Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Oct 2012 12:07:21 +0000 (21:07 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Oct 2012 12:07:21 +0000 (21:07 +0900)
Pull IMA bugfix (security subsystem) from James Morris.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  ima: fix bug in argument order

2669 files changed:
Documentation/CodingStyle
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/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-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/aoe/aoe.txt
Documentation/aoe/mkdevs.sh [deleted file]
Documentation/aoe/mkshelf.sh [deleted file]
Documentation/aoe/status.sh
Documentation/devicetree/bindings/arm/xen.txt [new file with mode: 0644]
Documentation/devicetree/bindings/crypto/fsl-sec4.txt
Documentation/devicetree/bindings/crypto/mv_cesa.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-fan.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-mvebu.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/88pm860x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/syscon.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/tps65910.txt
Documentation/devicetree/bindings/mfd/twl4030-audio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/twl6040.txt
Documentation/devicetree/bindings/misc/ifm-csi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
Documentation/devicetree/bindings/regulator/88pm860x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8907.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/tps6586x.txt
Documentation/devicetree/bindings/rtc/snvs-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/backlight/88pm860x.txt [new file with mode: 0644]
Documentation/dvb/README.dvb-usb
Documentation/dvb/get_dvb_firmware
Documentation/ioctl/ioctl-number.txt
Documentation/power/power_supply_class.txt
Documentation/printk-formats.txt
Documentation/ramoops.txt
Documentation/rtc.txt
Documentation/smsc_ece1099.txt [new file with mode: 0644]
Documentation/sysctl/kernel.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
MAINTAINERS
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-xp-db.dts
arch/arm/boot/dts/armada-xp-mv78230.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-mv78260.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-mv78460.dtsi [new file with mode: 0644]
arch/arm/boot/dts/dove-cm-a510.dts [new file with mode: 0644]
arch/arm/boot/dts/dove-cubox.dts [new file with mode: 0644]
arch/arm/boot/dts/dove-dove-db.dts [new file with mode: 0644]
arch/arm/boot/dts/dove.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/kirkwood-dnskw.dtsi
arch/arm/boot/dts/kirkwood-dockstar.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-km_kirkwood.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/pxa910-dkb.dts
arch/arm/boot/dts/pxa910.dtsi
arch/arm/boot/dts/xenvm-4.2.dts [new file with mode: 0644]
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/kirkwood_defconfig
arch/arm/configs/lpc32xx_defconfig
arch/arm/configs/marzen_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/mxs_defconfig
arch/arm/configs/s3c6400_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/hypervisor.h [new file with mode: 0644]
arch/arm/include/asm/sync_bitops.h [new file with mode: 0644]
arch/arm/include/asm/xen/events.h [new file with mode: 0644]
arch/arm/include/asm/xen/hypercall.h [new file with mode: 0644]
arch/arm/include/asm/xen/hypervisor.h [new file with mode: 0644]
arch/arm/include/asm/xen/interface.h [new file with mode: 0644]
arch/arm/include/asm/xen/page.h [new file with mode: 0644]
arch/arm/mach-at91/clock.c
arch/arm/mach-davinci/board-tnetv107x-evm.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-dove/Kconfig
arch/arm/mach-dove/Makefile
arch/arm/mach-dove/common.c
arch/arm/mach-dove/common.h
arch/arm/mach-dove/include/mach/bridge-regs.h
arch/arm/mach-dove/include/mach/dove.h
arch/arm/mach-dove/include/mach/pm.h
arch/arm/mach-dove/irq.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/Makefile
arch/arm/mach-kirkwood/addr-map.c
arch/arm/mach-kirkwood/board-dnskw.c
arch/arm/mach-kirkwood/board-dockstar.c [new file with mode: 0644]
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/board-iconnect.c
arch/arm/mach-kirkwood/board-iomega_ix2_200.c [new file with mode: 0644]
arch/arm/mach-kirkwood/board-km_kirkwood.c [new file with mode: 0644]
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/common.h
arch/arm/mach-kirkwood/include/mach/bridge-regs.h
arch/arm/mach-kirkwood/include/mach/kirkwood.h
arch/arm/mach-kirkwood/irq.c
arch/arm/mach-kirkwood/pcie.c
arch/arm/mach-kirkwood/ts41x-setup.c
arch/arm/mach-msm/board-qsd8x50.c
arch/arm/mach-mv78xx0/addr-map.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
arch/arm/mach-mv78xx0/irq.c
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-mvebu/Makefile
arch/arm/mach-mvebu/addr-map.c [new file with mode: 0644]
arch/arm/mach-mvebu/armada-370-xp.c
arch/arm/mach-mvebu/armada-370-xp.h
arch/arm/mach-mvebu/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/timer.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/clkt2xxx_apll.c
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clock3xxx.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
arch/arm/mach-omap2/clockdomain44xx.c
arch/arm/mach-omap2/clockdomains3xxx_data.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/cm-regbits-33xx.h
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm-regbits-44xx.h
arch/arm/mach-omap2/cm2xxx_3xxx.c
arch/arm/mach-omap2/cm2xxx_3xxx.h
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.h
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pmu.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomain44xx.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/usb-host.c
arch/arm/mach-orion5x/addr-map.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/include/mach/bridge-regs.h
arch/arm/mach-orion5x/include/mach/orion5x.h
arch/arm/mach-orion5x/irq.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-u300/i2c.c
arch/arm/mach-vexpress/v2m.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-omap/clock.c
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/iommu.h
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/usb.h
arch/arm/plat-omap/omap_device.c
arch/arm/plat-orion/Makefile
arch/arm/plat-orion/addr-map.c
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/addr-map.h
arch/arm/plat-orion/include/plat/common.h
arch/arm/plat-orion/include/plat/mpp.h
arch/arm/plat-orion/include/plat/time.h
arch/arm/plat-orion/mpp.c
arch/arm/plat-orion/time.c
arch/arm/xen/Makefile [new file with mode: 0644]
arch/arm/xen/enlighten.c [new file with mode: 0644]
arch/arm/xen/grant-table.c [new file with mode: 0644]
arch/arm/xen/hypercall.S [new file with mode: 0644]
arch/arm64/include/asm/compat.h
arch/arm64/include/asm/hwcap.h
arch/arm64/include/asm/stat.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/signal32.c
arch/avr32/include/asm/elf.h
arch/blackfin/include/asm/elf.h
arch/c6x/Makefile
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/elf.h
arch/c6x/include/asm/signal.h [deleted file]
arch/c6x/include/asm/unistd.h
arch/cris/include/asm/elf.h
arch/frv/include/asm/elf.h
arch/frv/kernel/pm.c
arch/frv/kernel/setup.c
arch/frv/mb93090-mb00/pci-irq.c
arch/h8300/include/asm/elf.h
arch/h8300/kernel/sys_h8300.c
arch/h8300/kernel/timer/itu.c
arch/h8300/kernel/timer/timer16.c
arch/h8300/kernel/timer/timer8.c
arch/h8300/kernel/timer/tpu.c
arch/h8300/platform/h8300h/irq.c
arch/h8300/platform/h8s/irq.c
arch/hexagon/include/asm/elf.h
arch/hexagon/include/asm/unistd.h
arch/ia64/include/asm/xen/interface.h
arch/ia64/xen/irq_xen.c
arch/ia64/xen/irq_xen.h
arch/m32r/include/asm/elf.h
arch/m68k/include/asm/cacheflush_no.h
arch/m68k/include/asm/elf.h
arch/m68k/include/asm/m5206sim.h
arch/m68k/include/asm/m523xsim.h
arch/m68k/include/asm/m5249sim.h
arch/m68k/include/asm/m525xsim.h
arch/m68k/include/asm/m5272sim.h
arch/m68k/include/asm/m527xsim.h
arch/m68k/include/asm/m528xsim.h
arch/m68k/include/asm/m5307sim.h
arch/m68k/include/asm/m532xsim.h
arch/m68k/include/asm/m5407sim.h
arch/m68k/include/asm/m54xxgpt.h
arch/m68k/include/asm/m54xxsim.h
arch/m68k/include/asm/mcfslt.h
arch/m68k/include/asm/nettel.h
arch/m68k/platform/68VZ328/Makefile
arch/m68k/platform/coldfire/device.c
arch/m68k/platform/coldfire/head.S
arch/m68k/platform/coldfire/intc-5249.c
arch/m68k/platform/coldfire/intc-5272.c
arch/m68k/platform/coldfire/intc.c
arch/m68k/platform/coldfire/m523x.c
arch/m68k/platform/coldfire/m5249.c
arch/m68k/platform/coldfire/m525x.c
arch/m68k/platform/coldfire/m5272.c
arch/m68k/platform/coldfire/m527x.c
arch/m68k/platform/coldfire/m528x.c
arch/m68k/platform/coldfire/m532x.c
arch/m68k/platform/coldfire/m54xx.c
arch/m68k/platform/coldfire/nettel.c
arch/m68k/platform/coldfire/pci.c
arch/m68k/platform/coldfire/reset.c
arch/m68k/platform/coldfire/sltimers.c
arch/m68k/platform/coldfire/timers.c
arch/microblaze/include/asm/elf.h
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/include/asm/compat-signal.h
arch/mips/include/asm/compat.h
arch/mips/pci/pci-octeon.c
arch/mn10300/Makefile
arch/mn10300/include/asm/elf.h
arch/openrisc/include/asm/elf.h
arch/openrisc/include/asm/unistd.h
arch/parisc/Kconfig
arch/parisc/include/asm/compat.h
arch/parisc/kernel/signal32.h
arch/powerpc/Kconfig
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi
arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi
arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi
arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi
arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi
arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi
arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi
arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi
arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi
arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi
arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi
arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi
arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi
arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi
arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
arch/powerpc/boot/dts/fsl/p5040si-post.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8536ds.dtsi
arch/powerpc/boot/dts/mpc8540ads.dts
arch/powerpc/boot/dts/mpc8541cds.dts
arch/powerpc/boot/dts/mpc8544ds.dts
arch/powerpc/boot/dts/mpc8544ds.dtsi
arch/powerpc/boot/dts/mpc8555cds.dts
arch/powerpc/boot/dts/mpc8560ads.dts
arch/powerpc/boot/dts/o2d.dts [new file with mode: 0644]
arch/powerpc/boot/dts/o2d.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/o2d300.dts [new file with mode: 0644]
arch/powerpc/boot/dts/o2dnt2.dts [new file with mode: 0644]
arch/powerpc/boot/dts/o2i.dts [new file with mode: 0644]
arch/powerpc/boot/dts/o2mnt.dts [new file with mode: 0644]
arch/powerpc/boot/dts/o3dnt.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1020rdb_camp_core0.dts [deleted file]
arch/powerpc/boot/dts/p1020rdb_camp_core1.dts [deleted file]
arch/powerpc/boot/dts/p1022ds.dtsi
arch/powerpc/boot/dts/p1022rdk.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p2020rdb_camp_core0.dts [deleted file]
arch/powerpc/boot/dts/p2020rdb_camp_core1.dts [deleted file]
arch/powerpc/boot/dts/p2041rdb.dts
arch/powerpc/boot/dts/p3041ds.dts
arch/powerpc/boot/dts/p4080ds.dts
arch/powerpc/boot/dts/p5020ds.dts
arch/powerpc/boot/dts/p5040ds.dts [new file with mode: 0644]
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/abs_addr.h [deleted file]
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/cacheflush.h
arch/powerpc/include/asm/compat.h
arch/powerpc/include/asm/debug.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/eeh_event.h
arch/powerpc/include/asm/exception-64e.h
arch/powerpc/include/asm/fsl_guts.h
arch/powerpc/include/asm/fsl_ifc.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/hw_breakpoint.h
arch/powerpc/include/asm/kprobes.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/mpc52xx.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/pgtable-ppc64-4k.h
arch/powerpc/include/asm/pgtable-ppc64-64k.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/ppc-pci.h
arch/powerpc/include/asm/probes.h [new file with mode: 0644]
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/siginfo.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/sparsemem.h
arch/powerpc/include/asm/swiotlb.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/tlbflush.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/include/asm/uprobes.h [new file with mode: 0644]
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fadump.c
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/ppc32.h
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/uprobes.c [new file with mode: 0644]
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vio.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/trace.h
arch/powerpc/lib/memcpy_power7.S
arch/powerpc/lib/sstep.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_context_hash64.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/slb_low.S
arch/powerpc/mm/slice.c
arch/powerpc/mm/stab.c
arch/powerpc/mm/subpage-prot.c
arch/powerpc/mm/tlb_hash64.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power7-pmu.c
arch/powerpc/platforms/40x/ppc40x_simple.c
arch/powerpc/platforms/44x/currituck.c
arch/powerpc/platforms/512x/Kconfig
arch/powerpc/platforms/512x/clock.c
arch/powerpc/platforms/512x/mpc5121_generic.c
arch/powerpc/platforms/512x/mpc512x_shared.c
arch/powerpc/platforms/52xx/lite5200.c
arch/powerpc/platforms/52xx/media5200.c
arch/powerpc/platforms/52xx/mpc5200_simple.c
arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
arch/powerpc/platforms/83xx/mpc837x_rdb.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/common.c
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/ge_imp3a.c
arch/powerpc/platforms/85xx/mpc8536_ds.c
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/p1010rdb.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p1022_rdk.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/p1023_rds.c
arch/powerpc/platforms/85xx/p2041_rdb.c
arch/powerpc/platforms/85xx/p3041_ds.c
arch/powerpc/platforms/85xx/p4080_ds.c
arch/powerpc/platforms/85xx/p5020_ds.c
arch/powerpc/platforms/85xx/p5040_ds.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/qemu_e500.c
arch/powerpc/platforms/85xx/sbc8548.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/85xx/socrates.c
arch/powerpc/platforms/85xx/stx_gp3.c
arch/powerpc/platforms/85xx/tqm85xx.c
arch/powerpc/platforms/85xx/xes_mpc85xx.c
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/sbc8641d.c
arch/powerpc/platforms/cell/beat.c
arch/powerpc/platforms/cell/beat.h
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/pasemi/iommu.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci-p5ioc2.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/ps3/htab.c
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_cache.c
arch/powerpc/platforms/pseries/eeh_dev.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/platforms/pseries/eeh_pe.c [new file with mode: 0644]
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/eeh_sysfs.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
arch/powerpc/sysdev/fsl_ifc.c
arch/powerpc/sysdev/fsl_mpic_err.c [new file with mode: 0644]
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_pci.h
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic.h
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/include/asm/compat.h
arch/s390/kernel/compat_linux.h
arch/score/Kconfig
arch/score/include/asm/elf.h
arch/score/include/asm/unistd.h
arch/score/kernel/sys_score.c
arch/sh/include/asm/elf.h
arch/sh/include/asm/io.h
arch/sh/kernel/ioport.c
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/elf_32.h
arch/sparc/include/asm/siginfo.h
arch/sparc/kernel/signal32.c
arch/tile/include/asm/compat.h
arch/tile/include/asm/elf.h
arch/tile/include/asm/unistd.h
arch/tile/kernel/compat_signal.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/unistd.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/compat.h
arch/x86/include/asm/ia32.h
arch/x86/include/asm/xen/interface.h
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/rtc.c
arch/x86/lguest/Kconfig
arch/x86/xen/enlighten.c
arch/x86/xen/irq.c
arch/x86/xen/xen-ops.h
arch/xtensa/include/asm/elf.h
drivers/atm/eni.c
drivers/block/aoe/aoe.h
drivers/block/aoe/aoeblk.c
drivers/block/aoe/aoechr.c
drivers/block/aoe/aoecmd.c
drivers/block/aoe/aoedev.c
drivers/block/aoe/aoemain.c
drivers/block/aoe/aoenet.c
drivers/block/nbd.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/blkback.c
drivers/char/hw_random/omap-rng.c
drivers/char/mbcs.c
drivers/char/virtio_console.c
drivers/crypto/mv_cesa.c
drivers/crypto/nx/nx.c
drivers/dma/dmaengine.c
drivers/edac/mpc85xx_edac.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-bt8xx.c
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-mvebu.c [new file with mode: 0644]
drivers/gpio/gpio-twl6040.c [new file with mode: 0644]
drivers/hwmon/gpio-fan.c
drivers/i2c/i2c-core.c
drivers/ide/aec62xx.c
drivers/ide/ali14xx.c
drivers/ide/alim15x3.c
drivers/ide/amd74xx.c
drivers/ide/atiixp.c
drivers/ide/cmd640.c
drivers/ide/cmd64x.c
drivers/ide/cs5520.c
drivers/ide/cs5530.c
drivers/ide/cs5535.c
drivers/ide/cy82c693.c
drivers/ide/dtc2278.c
drivers/ide/hpt366.c
drivers/ide/ht6560b.c
drivers/ide/icside.c
drivers/ide/ide-pci-generic.c
drivers/ide/it8172.c
drivers/ide/it8213.c
drivers/ide/it821x.c
drivers/ide/jmicron.c
drivers/ide/ns87415.c
drivers/ide/opti621.c
drivers/ide/pdc202xx_new.c
drivers/ide/pdc202xx_old.c
drivers/ide/piix.c
drivers/ide/qd65xx.c
drivers/ide/rz1000.c
drivers/ide/sc1200.c
drivers/ide/scc_pata.c
drivers/ide/serverworks.c
drivers/ide/siimage.c
drivers/ide/sis5513.c
drivers/ide/sl82c105.c
drivers/ide/slc90e66.c
drivers/ide/tc86c001.c
drivers/ide/triflex.c
drivers/ide/trm290.c
drivers/ide/tx4938ide.c
drivers/ide/tx4939ide.c
drivers/ide/umc8672.c
drivers/ide/via82cxxx.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_eq.c
drivers/infiniband/hw/ehca/ehca_mrmw.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/ehca_tools.h
drivers/infiniband/hw/ehca/hcp_if.c
drivers/infiniband/hw/ehca/ipz_pt_fn.c
drivers/infiniband/hw/mlx4/cm.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/misc/twl4030-vibra.c
drivers/input/touchscreen/88pm860x-ts.c
drivers/leds/leds-88pm860x.c
drivers/lguest/lguest_device.c
drivers/macintosh/macio_asic.c
drivers/macintosh/smu.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 87% 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 98% similarity]
drivers/media/i2c/m5mols/m5mols_capture.c [moved from drivers/media/video/m5mols/m5mols_capture.c with 100% 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 95% similarity]
drivers/media/i2c/m5mols/m5mols_reg.h [moved from drivers/media/video/m5mols/m5mols_reg.h with 100% 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 98% similarity]
drivers/media/i2c/mt9t001.c [moved from drivers/media/video/mt9t001.c with 100% 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 88% 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 100% 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 99% 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 100% similarity]
drivers/media/platform/davinci/vpbe_display.c [moved from drivers/media/video/davinci/vpbe_display.c with 98% 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 100% 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 99% 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 95% similarity]
drivers/media/platform/davinci/vpif_capture.h [moved from drivers/media/video/davinci/vpif_capture.h with 98% similarity]
drivers/media/platform/davinci/vpif_display.c [moved from drivers/media/video/davinci/vpif_display.c with 94% similarity]
drivers/media/platform/davinci/vpif_display.h [moved from drivers/media/video/davinci/vpif_display.h with 98% 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 97% similarity]
drivers/media/platform/s5p-fimc/fimc-core.c [moved from drivers/media/video/s5p-fimc/fimc-core.c with 100% similarity]
drivers/media/platform/s5p-fimc/fimc-core.h [moved from drivers/media/video/s5p-fimc/fimc-core.h with 99% 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 95% 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 99% similarity]
drivers/media/platform/s5p-fimc/fimc-reg.h [moved from drivers/media/video/s5p-fimc/fimc-reg.h with 100% similarity]
drivers/media/platform/s5p-fimc/mipi-csis.c [moved from drivers/media/video/s5p-fimc/mipi-csis.c with 82% 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 98% 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 100% 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 94% 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 98% 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/88pm860x-core.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab3100-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/anatop-mfd.c [deleted file]
drivers/mfd/arizona-irq.c
drivers/mfd/da9055-core.c [new file with mode: 0644]
drivers/mfd/da9055-i2c.c [new file with mode: 0644]
drivers/mfd/db8500-prcmu.c
drivers/mfd/lp8788-irq.c [new file with mode: 0644]
drivers/mfd/lp8788.c [new file with mode: 0644]
drivers/mfd/lpc_ich.c
drivers/mfd/max8907.c [new file with mode: 0644]
drivers/mfd/max8925-core.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/omap-usb-host.c
drivers/mfd/omap-usb-tll.c [new file with mode: 0644]
drivers/mfd/palmas.c
drivers/mfd/rc5t583-irq.c
drivers/mfd/rc5t583.c
drivers/mfd/smsc-ece1099.c [new file with mode: 0644]
drivers/mfd/syscon.c [new file with mode: 0644]
drivers/mfd/tc3589x.c
drivers/mfd/tps65090.c
drivers/mfd/tps65217.c
drivers/mfd/tps6586x.c
drivers/mfd/tps65910.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl6040-core.c
drivers/mfd/wm5110-tables.c
drivers/mfd/wm831x-core.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-regmap.c
drivers/mmc/host/sdhci-pci.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/net/bonding/bond_main.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/slcan.c
drivers/net/can/vcan.c
drivers/net/ethernet/8390/ne3210.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/dec/tulip/eeprom.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/winbond-840.c
drivers/net/ethernet/dlink/sundance.c
drivers/net/ethernet/fealnx.c
drivers/net/ethernet/ibm/ehea/ehea.h
drivers/net/ethernet/ibm/ehea/ehea_phyp.c
drivers/net/ethernet/ibm/ehea/ehea_qmr.c
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/mkiss.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/rionet.c
drivers/net/team/team.c
drivers/net/wan/z85230.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netfront.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/pinctrl-armada-370.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-armada-xp.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-dove.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-kirkwood.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-mvebu.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-mvebu.h [new file with mode: 0644]
drivers/platform/x86/amilo-rfkill.c
drivers/platform/x86/fujitsu-tablet.c
drivers/platform/x86/thinkpad_acpi.c
drivers/power/88pm860x_battery.c [new file with mode: 0644]
drivers/power/88pm860x_charger.c [new file with mode: 0644]
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/ab8500_btemp.c
drivers/power/ab8500_charger.c
drivers/power/ab8500_fg.c
drivers/power/bq27x00_battery.c
drivers/power/charger-manager.c
drivers/power/da9030_battery.c
drivers/power/da9052-battery.c
drivers/power/ds2781_battery.c
drivers/power/lp8727_charger.c
drivers/power/lp8788-charger.c [new file with mode: 0644]
drivers/power/pda_power.c
drivers/power/power_supply_sysfs.c
drivers/power/sbs-battery.c
drivers/power/smb347-charger.c
drivers/power/twl4030_charger.c
drivers/power/wm97xx_battery.c
drivers/pps/pps.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/pwm-twl6030.c [moved from drivers/mfd/twl6030-pwm.c with 55% similarity]
drivers/rapidio/devices/tsi721.c
drivers/rapidio/devices/tsi721.h
drivers/rapidio/rio-scan.c
drivers/rapidio/rio.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/ab3100.c
drivers/regulator/anatop-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/remoteproc/remoteproc_virtio.c
drivers/rpmsg/Kconfig
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/hctosys.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-coh901331.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds2404.c [new file with mode: 0644]
drivers/rtc/rtc-em3027.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-jz4740.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-max8907.c [new file with mode: 0644]
drivers/rtc/rtc-mxc.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-proc.c
drivers/rtc/rtc-rc5t583.c [new file with mode: 0644]
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-snvs.c [new file with mode: 0644]
drivers/rtc/rtc-spear.c
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-tps65910.c [new file with mode: 0644]
drivers/rtc/rtc-x1205.c
drivers/s390/kvm/kvm_virtio.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/atp870u.c
drivers/scsi/ipr.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.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/thermal/thermal_sys.c
drivers/tty/hvc/hvc_console.c
drivers/tty/hvc/hvc_vio.c
drivers/video/aty/aty128fb.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/da9052_bl.c
drivers/video/backlight/kb3886_bl.c
drivers/video/backlight/lm3630_bl.c [new file with mode: 0644]
drivers/video/backlight/lm3639_bl.c [new file with mode: 0644]
drivers/video/backlight/ltv350qv.c
drivers/video/backlight/max8925_bl.c
drivers/video/backlight/platform_lcd.c
drivers/video/backlight/progear_bl.c [deleted file]
drivers/video/backlight/tps65217_bl.c [new file with mode: 0644]
drivers/video/geode/gx1fb_core.c
drivers/video/gxt4500.c
drivers/video/i810/i810_main.c
drivers/video/jz4740_fb.c
drivers/video/ps3fb.c
drivers/virtio/Kconfig
drivers/virtio/Makefile
drivers/virtio/virtio.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/m54xx_wdt.c
drivers/xen/Makefile
drivers/xen/events.c
fs/Kconfig.binfmt
fs/Makefile
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/compat_binfmt_elf.c
fs/coredump.c
fs/coredump.h [new file with mode: 0644]
fs/eventpoll.c
fs/exec.c
fs/fat/Makefile
fs/fat/cache.c
fs/fat/dir.c
fs/fat/fat.h
fs/fat/fatent.c
fs/fat/inode.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fat/nfs.c [new file with mode: 0644]
fs/hpfs/anode.c
fs/hpfs/dnode.c
fs/omfs/file.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/pstore/Kconfig
fs/pstore/ftrace.c
fs/pstore/internal.h
fs/pstore/platform.c
fs/pstore/ram.c
fs/super.c
include/asm-generic/bitops/le.h
include/asm-generic/unistd.h
include/linux/Kbuild
include/linux/audit.h
include/linux/binfmts.h
include/linux/compat.h
include/linux/coredump.h
include/linux/dvb/frontend.h
include/linux/dvb/version.h
include/linux/elf.h
include/linux/eventpoll.h
include/linux/genalloc.h
include/linux/i2c/twl.h
include/linux/idr.h
include/linux/init.h
include/linux/ioport.h
include/linux/libfdt.h
include/linux/mfd/88pm860x.h
include/linux/mfd/ab3100.h [new file with mode: 0644]
include/linux/mfd/abx500.h
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/anatop.h [deleted file]
include/linux/mfd/da9055/core.h [new file with mode: 0644]
include/linux/mfd/da9055/pdata.h [new file with mode: 0644]
include/linux/mfd/da9055/reg.h [new file with mode: 0644]
include/linux/mfd/lp8788-isink.h [new file with mode: 0644]
include/linux/mfd/lp8788.h [new file with mode: 0644]
include/linux/mfd/lpc_ich.h
include/linux/mfd/max8907.h [new file with mode: 0644]
include/linux/mfd/max8925.h
include/linux/mfd/palmas.h
include/linux/mfd/rc5t583.h
include/linux/mfd/smsc.h [new file with mode: 0644]
include/linux/mfd/syscon.h [new file with mode: 0644]
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h [new file with mode: 0644]
include/linux/mfd/tc3589x.h
include/linux/mfd/tps65217.h
include/linux/mfd/tps6586x.h
include/linux/mfd/tps65910.h
include/linux/mfd/twl6040.h
include/linux/nbd.h
include/linux/of.h
include/linux/omap3isp.h
include/linux/percpu.h
include/linux/platform_data/lm3630_bl.h [new file with mode: 0644]
include/linux/platform_data/lm3639_bl.h [new file with mode: 0644]
include/linux/platform_data/lp855x.h
include/linux/platform_data/lp8727.h
include/linux/power/charger-manager.h
include/linux/power_supply.h
include/linux/pstore.h
include/linux/rio.h
include/linux/rio_drv.h
include/linux/rtc-ds2404.h [new file with mode: 0644]
include/linux/rtc.h
include/linux/sched.h
include/linux/slab.h
include/linux/slab_def.h
include/linux/slob_def.h
include/linux/v4l2-common.h
include/linux/v4l2-controls.h [new file with mode: 0644]
include/linux/v4l2-subdev.h
include/linux/videodev2.h
include/linux/virtio.h
include/linux/virtio_config.h
include/linux/virtio_ring.h
include/media/ad9389b.h [new file with mode: 0644]
include/media/adv7604.h [new file with mode: 0644]
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/ip_fib.h
include/net/net_namespace.h
include/net/sctp/structs.h
include/sound/tea575x-tuner.h
include/xen/events.h
include/xen/interface/features.h
include/xen/interface/io/protocols.h
include/xen/interface/memory.h
include/xen/interface/physdev.h
include/xen/interface/version.h
include/xen/xen.h
init/Kconfig
kernel/kexec.c
kernel/resource.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/taskstats.c
kernel/trace/trace.c
kernel/trace/trace_functions.c
lib/Kconfig.debug
lib/crc32.c
lib/decompress.c
lib/gcd.c
lib/gen_crc32table.c
lib/genalloc.c
lib/idr.c
lib/parser.c
lib/plist.c
lib/scatterlist.c
lib/spinlock_debug.c
lib/vsprintf.c
mm/percpu.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slob.c
mm/slub.c
mm/util.c
net/8021q/vlan_core.c
net/can/af_can.c
net/can/bcm.c
net/can/gw.c
net/can/raw.c
net/decnet/dn_rules.c
net/ipv4/fib_rules.c
net/ipv4/fib_semantics.c
net/ipv4/ipmr.c
net/ipv6/addrconf.c
net/ipv6/addrlabel.c
net/ipv6/fib6_rules.c
net/ipv6/ip6mr.c
net/ipv6/route.c
net/irda/af_irda.c
net/irda/irttp.c
net/nfc/llcp/sock.c
net/sctp/input.c
net/sctp/outqueue.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/tipc/socket.c
scripts/Kbuild.include
scripts/checkpatch.pl
scripts/kernel-doc
security/device_cgroup.c
sound/i2c/other/tea575x-tuner.c
sound/pci/Kconfig
sound/soc/codecs/wm5100.c
tools/lguest/lguest.c
tools/testing/selftests/Makefile
tools/testing/selftests/epoll/Makefile [new file with mode: 0644]
tools/testing/selftests/epoll/test_epoll.c [new file with mode: 0644]
tools/virtio/virtio-trace/Makefile [new file with mode: 0644]
tools/virtio/virtio-trace/README [new file with mode: 0644]
tools/virtio/virtio-trace/trace-agent-ctl.c [new file with mode: 0644]
tools/virtio/virtio-trace/trace-agent-rw.c [new file with mode: 0644]
tools/virtio/virtio-trace/trace-agent.c [new file with mode: 0644]
tools/virtio/virtio-trace/trace-agent.h [new file with mode: 0644]
virt/kvm/kvm_main.c

index cb9258b8fd35b25b8ac750b18b4237204213fbd4..495e5ba1634cac59350326485b07b7e902242ab3 100644 (file)
@@ -454,6 +454,16 @@ The preferred style for long (multi-line) comments is:
         * with beginning and ending almost-blank lines.
         */
 
+For files in net/ and drivers/net/ the preferred style for long (multi-line)
+comments is a little different.
+
+       /* The preferred comment style for files in net/ and drivers/net
+        * looks like this.
+        *
+        * It is nearly the same as the generally preferred comment style,
+        * but there is no initial almost-blank line.
+        */
+
 It's also important to comment data, whether they are basic types or derived
 types.  To this end, use just one data declaration per line (no commas for
 multiple data declarations).  This leaves you room for a small comment on each
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..c6ae4c9d0e0c6f0ae6f9661f916bb73e3d7fc89f 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>
@@ -2614,10 +2579,6 @@ ioctls.</para>
          <para>Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION;
          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>
-        </listitem>
         <listitem>
          <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
index b0964fb4e8348853619efd3296b7821d4e6b6803..272a5f71850934e23a3c6e7ca7b5d8cc60b9784c 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">
@@ -4274,4 +4273,165 @@ interface and may change in the future.</para>
       </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>
+      </table>
+
+    </section>
 </section>
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..97f785add841c602d179a2b131060994deeaa26d 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
@@ -685,18 +685,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
            <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 +823,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..1ddbfabe31953b34fa8f51a8dc7c515daca39a06 100644 (file)
@@ -708,6 +708,7 @@ information.</para>
     &sub-y41p;
     &sub-yuv420;
     &sub-yuv420m;
+    &sub-yvu420m;
     &sub-yuv410;
     &sub-yuv422p;
     &sub-yuv411p;
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 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..6a821a65a5aec9ce1e196261c5149b666f2e4c2e 100644 (file)
@@ -155,6 +155,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 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 5f5aa16047ff4f8f5a9680101572c8afc34e799c..bfc9cb19abcd56ca23f240c9854f67e0c9f3ec0f 100644 (file)
@@ -1,8 +1,16 @@
-The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
+ATA over Ethernet is a network protocol that provides simple access to
+block storage on the LAN.
 
-  http://www.coraid.com/SUPPORT/EtherDrive-HBA  
+  http://support.coraid.com/documents/AoEr11.txt
 
-  It has many tips and hints!
+The EtherDrive (R) HOWTO for 2.6 and 3.x kernels is found at ...
+
+  http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO.html
+
+It has many tips and hints!  Please see, especially, recommended
+tunings for virtual memory:
+
+  http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO-5.html#ss5.19
 
 The aoetools are userland programs that are designed to work with this
 driver.  The aoetools are on sourceforge.
@@ -23,20 +31,12 @@ CREATING DEVICE NODES
   There is a udev-install.sh script that shows how to install these
   rules on your system.
 
-  If you are not using udev, two scripts are provided in
-  Documentation/aoe as examples of static device node creation for
-  using the aoe driver.
-
-    rm -rf /dev/etherd
-    sh Documentation/aoe/mkdevs.sh /dev/etherd
-
-  ... or to make just one shelf's worth of block device nodes ...
-
-    sh Documentation/aoe/mkshelf.sh /dev/etherd 0
-
   There is also an autoload script that shows how to edit
   /etc/modprobe.d/aoe.conf to ensure that the aoe module is loaded when
-  necessary.
+  necessary.  Preloading the aoe module is preferable to autoloading,
+  however, because AoE discovery takes a few seconds.  It can be
+  confusing when an AoE device is not present the first time the a
+  command is run but appears a second later.
 
 USING DEVICE NODES
 
@@ -51,9 +51,9 @@ USING DEVICE NODES
   "echo > /dev/etherd/discover" tells the driver to find out what AoE
   devices are available.
 
-  These character devices may disappear and be replaced by sysfs
-  counterparts.  Using the commands in aoetools insulates users from
-  these implementation details.
+  In the future these character devices may disappear and be replaced
+  by sysfs counterparts.  Using the commands in aoetools insulates
+  users from these implementation details.
 
   The block devices are named like this:
 
@@ -76,8 +76,8 @@ USING SYSFS
   The netif attribute is the network interface on the localhost
   through which we are communicating with the remote AoE device.
 
-  There is a script in this directory that formats this information
-  in a convenient way.  Users with aoetools can use the aoe-stat
+  There is a script in this directory that formats this information in
+  a convenient way.  Users with aoetools should use the aoe-stat
   command.
 
   root@makki root# sh Documentation/aoe/status.sh 
@@ -121,3 +121,21 @@ DRIVER OPTIONS
   usage example for the module parameter.
 
     modprobe aoe_iflist="eth1 eth3"
+
+  The aoe_deadsecs module parameter determines the maximum number of
+  seconds that the driver will wait for an AoE device to provide a
+  response to an AoE command.  After aoe_deadsecs seconds have
+  elapsed, the AoE device will be marked as "down".
+
+  The aoe_maxout module parameter has a default of 128.  This is the
+  maximum number of unresponded packets that will be sent to an AoE
+  target at one time.
+
+  The aoe_dyndevs module parameter defaults to 1, meaning that the
+  driver will assign a block device minor number to a discovered AoE
+  target based on the order of its discovery.  With dynamic minor
+  device numbers in use, a greater range of AoE shelf and slot
+  addresses can be supported.  Users with udev will never have to
+  think about minor numbers.  Using aoe_dyndevs=0 allows device nodes
+  to be pre-created using a static minor-number scheme with the
+  aoe-mkshelf script in the aoetools.
diff --git a/Documentation/aoe/mkdevs.sh b/Documentation/aoe/mkdevs.sh
deleted file mode 100644 (file)
index 44c0ab7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-n_shelves=${n_shelves:-10}
-n_partitions=${n_partitions:-16}
-
-if test "$#" != "1"; then
-       echo "Usage: sh `basename $0` {dir}" 1>&2
-       echo "       n_partitions=16 sh `basename $0` {dir}" 1>&2
-       exit 1
-fi
-dir=$1
-
-MAJOR=152
-
-echo "Creating AoE devnode files in $dir ..."
-
-set -e
-
-mkdir -p $dir
-
-# (Status info is in sysfs.  See status.sh.)
-# rm -f $dir/stat
-# mknod -m 0400 $dir/stat c $MAJOR 1
-rm -f $dir/err
-mknod -m 0400 $dir/err c $MAJOR 2
-rm -f $dir/discover
-mknod -m 0200 $dir/discover c $MAJOR 3
-rm -f $dir/interfaces
-mknod -m 0200 $dir/interfaces c $MAJOR 4
-rm -f $dir/revalidate
-mknod -m 0200 $dir/revalidate c $MAJOR 5
-rm -f $dir/flush
-mknod -m 0200 $dir/flush c $MAJOR 6
-
-export n_partitions
-mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'`
-i=0
-while test $i -lt $n_shelves; do
-       sh -xc "sh $mkshelf $dir $i"
-       i=`expr $i + 1`
-done
diff --git a/Documentation/aoe/mkshelf.sh b/Documentation/aoe/mkshelf.sh
deleted file mode 100644 (file)
index 3261581..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/sh
-
-if test "$#" != "2"; then
-       echo "Usage: sh `basename $0` {dir} {shelfaddress}" 1>&2
-       echo "       n_partitions=16 sh `basename $0` {dir} {shelfaddress}" 1>&2
-       exit 1
-fi
-n_partitions=${n_partitions:-16}
-dir=$1
-shelf=$2
-nslots=16
-maxslot=`echo $nslots 1 - p | dc`
-MAJOR=152
-
-set -e
-
-minor=`echo $nslots \* $shelf \* $n_partitions | bc`
-endp=`echo $n_partitions - 1 | bc`
-for slot in `seq 0 $maxslot`; do
-       for part in `seq 0 $endp`; do
-               name=e$shelf.$slot
-               test "$part" != "0" && name=${name}p$part
-               rm -f $dir/$name
-               mknod -m 0660 $dir/$name b $MAJOR $minor
-
-               minor=`expr $minor + 1`
-       done
-done
index 751f3be514b831296b038fd343443c15d0aa5b32..eeec7baae57a8f3db9a0da1583c0e3c8e0e8408d 100644 (file)
@@ -1,5 +1,8 @@
 #! /bin/sh
 # collate and present sysfs information about AoE storage
+#
+# A more complete version of this script is aoe-stat, in the
+# aoetools.
 
 set -e
 format="%8s\t%8s\t%8s\n"
diff --git a/Documentation/devicetree/bindings/arm/xen.txt b/Documentation/devicetree/bindings/arm/xen.txt
new file mode 100644 (file)
index 0000000..0f7b9c2
--- /dev/null
@@ -0,0 +1,25 @@
+* Xen hypervisor device tree bindings
+
+Xen ARM virtual platforms shall have a top-level "hypervisor" node with
+the following properties:
+
+- compatible:
+       compatible = "xen,xen-<version>", "xen,xen";
+  where <version> is the version of the Xen ABI of the platform.
+
+- reg: specifies the base physical address and size of a region in
+  memory where the grant table should be mapped to, using an
+  HYPERVISOR_memory_op hypercall. The memory region is large enough to map
+  the whole grant table (it is larger or equal to gnttab_max_grant_frames()).
+
+- interrupts: the interrupt used by Xen to inject event notifications.
+  A GIC node is also required.
+
+
+Example (assuming #address-cells = <2> and #size-cells = <2>):
+
+hypervisor {
+       compatible = "xen,xen-4.3", "xen,xen";
+       reg = <0 0xb0000000 0 0x20000>;
+       interrupts = <1 15 0xf08>;
+};
index bf57ecd5d73a6218d1310da2695f4bb977710e57..bd7ce120bc135e9eccb9f2cbdb3a38fdc15f9702 100644 (file)
@@ -9,6 +9,7 @@ Copyright (C) 2008-2011 Freescale Semiconductor Inc.
    -Run Time Integrity Check (RTIC) Node
    -Run Time Integrity Check (RTIC) Memory Node
    -Secure Non-Volatile Storage (SNVS) Node
+   -Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
    -Full Example
 
 NOTE: the SEC 4 is also known as Freescale's Cryptographic Accelerator
@@ -294,6 +295,27 @@ Secure Non-Volatile Storage (SNVS) Node
           address and length of the SEC4 configuration
           registers.
 
+   - #address-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+           for representing physical addresses in child nodes.  Must
+           have a value of 1.
+
+   - #size-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+           for representing the size of physical addresses in
+           child nodes.  Must have a value of 1.
+
+   - ranges
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+           range of the SNVS register space.  A triplet that includes
+           the child address, parent address, & length.
+
    - interrupts
       Usage: required
       Value type: <prop_encoded-array>
@@ -314,10 +336,33 @@ EXAMPLE
        sec_mon@314000 {
                compatible = "fsl,sec-v4.0-mon";
                reg = <0x314000 0x1000>;
+               ranges = <0 0x314000 0x1000>;
                interrupt-parent = <&mpic>;
                interrupts = <93 2>;
        };
 
+=====================================================================
+Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
+
+  A SNVS child node that defines SNVS LP RTC.
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,sec-v4.0-mon-rtc-lp".
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  Specifies the physical
+          address and length of the SNVS LP configuration registers.
+
+EXAMPLE
+       sec_mon_rtc_lp@314000 {
+               compatible = "fsl,sec-v4.0-mon-rtc-lp";
+               reg = <0x34 0x58>;
+       };
+
 =====================================================================
 FULL EXAMPLE
 
@@ -390,8 +435,14 @@ FULL EXAMPLE
        sec_mon: sec_mon@314000 {
                compatible = "fsl,sec-v4.0-mon";
                reg = <0x314000 0x1000>;
+               ranges = <0 0x314000 0x1000>;
                interrupt-parent = <&mpic>;
                interrupts = <93 2>;
+
+               sec_mon_rtc_lp@34 {
+                       compatible = "fsl,sec-v4.0-mon-rtc-lp";
+                       reg = <0x34 0x58>;
+               };
        };
 
 =====================================================================
diff --git a/Documentation/devicetree/bindings/crypto/mv_cesa.txt b/Documentation/devicetree/bindings/crypto/mv_cesa.txt
new file mode 100644 (file)
index 0000000..47229b1
--- /dev/null
@@ -0,0 +1,20 @@
+Marvell Cryptographic Engines And Security Accelerator
+
+Required properties:
+- compatible : should be "marvell,orion-crypto"
+- reg : base physical address of the engine and length of memory mapped
+        region, followed by base physical address of sram and its memory
+        length
+- reg-names : "regs" , "sram";
+- interrupts : interrupt number
+
+Examples:
+
+       crypto@30000 {
+               compatible = "marvell,orion-crypto";
+               reg = <0x30000 0x10000>,
+                     <0x4000000 0x800>;
+               reg-names = "regs" , "sram";
+               interrupts = <22>;
+               status = "okay";
+       };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-fan.txt b/Documentation/devicetree/bindings/gpio/gpio-fan.txt
new file mode 100644 (file)
index 0000000..2dd457a
--- /dev/null
@@ -0,0 +1,25 @@
+Bindings for fan connected to GPIO lines
+
+Required properties:
+- compatible : "gpio-fan"
+- gpios: Specifies the pins that map to bits in the control value,
+  ordered MSB-->LSB.
+- gpio-fan,speed-map: A mapping of possible fan RPM speeds and the
+  control value that should be set to achieve them. This array
+  must have the RPM values in ascending order.
+
+Optional properties:
+- alarm-gpios: This pin going active indicates something is wrong with
+  the fan, and a udev event will be fired.
+
+Examples:
+
+       gpio_fan {
+               compatible = "gpio-fan";
+               gpios = <&gpio1 14 1
+                        &gpio1 13 1>;
+               gpio-fan,speed-map = <0    0
+                                     3000 1
+                                     6000 2>;
+               alarm-gpios = <&gpio1 15 1>;
+       };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
new file mode 100644 (file)
index 0000000..a6f3bec
--- /dev/null
@@ -0,0 +1,53 @@
+* Marvell EBU GPIO controller
+
+Required properties:
+
+- compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio"
+  or "marvell,armadaxp-gpio". "marvell,orion-gpio" should be used for
+  Orion, Kirkwood, Dove, Discovery (except MV78200) and Armada
+  370. "marvell,mv78200-gpio" should be used for the Discovery
+  MV78200. "marvel,armadaxp-gpio" should be used for all Armada XP
+  SoCs (MV78230, MV78260, MV78460).
+
+- reg: Address and length of the register set for the device. Only one
+  entry is expected, except for the "marvell,armadaxp-gpio" variant
+  for which two entries are expected: one for the general registers,
+  one for the per-cpu registers.
+
+- interrupts: The list of interrupts that are used for all the pins
+  managed by this GPIO bank. There can be more than one interrupt
+  (example: 1 interrupt per 8 pins on Armada XP, which means 4
+  interrupts per bank of 32 GPIOs).
+
+- interrupt-controller: identifies the node as an interrupt controller
+
+- #interrupt-cells: specifies the number of cells needed to encode an
+  interrupt source. Should be two.
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+
+- gpio-controller: marks the device node as a gpio controller
+
+- ngpios: number of GPIOs this controller has
+
+- #gpio-cells: Should be two. The first cell is the pin number. The
+  second cell is reserved for flags, unused at the moment.
+
+Example:
+
+               gpio0: gpio@d0018100 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018100 0x40>,
+                           <0xd0018800 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       interrupts = <16>, <17>, <18>, <19>;
+               };
diff --git a/Documentation/devicetree/bindings/mfd/88pm860x.txt b/Documentation/devicetree/bindings/mfd/88pm860x.txt
new file mode 100644 (file)
index 0000000..63f3ee3
--- /dev/null
@@ -0,0 +1,85 @@
+* Marvell 88PM860x Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm860x"
+- reg : the I2C slave address for the 88pm860x chip
+- interrupts : IRQ line for the 88pm860x chip
+- interrupt-controller: describes the 88pm860x as an interrupt controller (has its own domain)
+- #interrupt-cells : should be 1.
+               - The cell is the 88pm860x local IRQ number
+
+Optional parent device properties:
+- marvell,88pm860x-irq-read-clr: inicates whether interrupt status is cleared by read
+- marvell,88pm860x-slave-addr: 88pm860x are two chips solution. <reg> stores the I2C address
+                               of one chip, and this property stores the I2C address of
+                               another chip.
+
+88pm860x consists of a large and varied group of sub-devices:
+
+Device                  Supply Names    Description
+------                  ------------    -----------
+88pm860x-onkey         :               : On key
+88pm860x-rtc           :               : RTC
+88pm8607               :               : Regulators
+88pm860x-backlight     :               : Backlight
+88pm860x-led           :               : Led
+88pm860x-touch         :               : Touchscreen
+
+Example:
+
+       pmic: 88pm860x@34 {
+               compatible = "marvell,88pm860x";
+               reg = <0x34>;
+               interrupts = <4>;
+               interrupt-parent = <&intc>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               marvell,88pm860x-irq-read-clr;
+               marvell,88pm860x-slave-addr = <0x11>;
+
+               regulators {
+                       BUCK1 {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+                       LDO1 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+               rtc {
+                       marvell,88pm860x-vrtc = <1>;
+               };
+               touch {
+                       marvell,88pm860x-gpadc-prebias = <1>;
+                       marvell,88pm860x-gpadc-slot-cycle = <1>;
+                       marvell,88pm860x-tsi-prebias = <6>;
+                       marvell,88pm860x-pen-prebias = <16>;
+                       marvell,88pm860x-pen-prechg = <2>;
+                       marvell,88pm860x-resistor-X = <300>;
+               };
+               backlights {
+                       backlight-0 {
+                               marvell,88pm860x-iset = <4>;
+                               marvell,88pm860x-pwm = <3>;
+                       };
+                       backlight-2 {
+                       };
+               };
+               leds {
+                       led0-red {
+                               marvell,88pm860x-iset = <12>;
+                       };
+                       led0-green {
+                               marvell,88pm860x-iset = <12>;
+                       };
+                       led0-blue {
+                               marvell,88pm860x-iset = <12>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
new file mode 100644 (file)
index 0000000..fe8150b
--- /dev/null
@@ -0,0 +1,20 @@
+* System Controller Registers R/W driver
+
+System controller node represents a register region containing a set
+of miscellaneous registers. The registers are not cohesive enough to
+represent as any specific type of device. The typical use-case is for
+some other node's driver, or platform-specific code, to acquire a
+reference to the syscon node (e.g. by phandle, node path, or search
+using a specific compatible value), interrogate the node (or associated
+OS driver) to determine the location of the registers, and access the
+registers directly.
+
+Required properties:
+- compatible: Should contain "syscon".
+- reg: the register region can be accessed from syscon
+
+Examples:
+gpr: iomuxc-gpr@020e0000 {
+       compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+       reg = <0x020e0000 0x38>;
+};
index db03599ae4dcf268f0410d0b1373c3369f67351d..2e3304888ffc1c10e07b83fcec088d61dce6004d 100644 (file)
@@ -59,6 +59,8 @@ Optional properties:
   in TPS6591X datasheet)
 - ti,en-gpio-sleep: enable sleep control for gpios
   There should be 9 entries here, one for each gpio.
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
 
 Regulator Optional properties:
 - ti,regulator-ext-sleep-control: enable external sleep
@@ -79,6 +81,8 @@ Example:
                #interrupt-cells = <2>;
                interrupt-controller;
 
+               ti,system-power-controller;
+
                ti,vmbch-threshold = 0;
                ti,vmbch2-threshold = 0;
                ti,en-ck32k-xtal;
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-audio.txt b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
new file mode 100644 (file)
index 0000000..414d2ae
--- /dev/null
@@ -0,0 +1,46 @@
+Texas Instruments TWL family (twl4030) audio module
+
+The audio module inside the TWL family consist of an audio codec and a vibra
+driver.
+
+Required properties:
+- compatible : must be "ti,twl4030-audio"
+
+Optional properties, nodes:
+
+Audio functionality:
+- codec { }: Need to be present if the audio functionality is used. Within this
+            section the following options can be used:
+- ti,digimic_delay: Delay need after enabling the digimic to reduce artifacts
+                   from the start of the recorded sample (in ms)
+-ti,ramp_delay_value: HS ramp delay configuration to reduce pop noise
+-ti,hs_extmute: Use external mute for HS pop reduction
+-ti,hs_extmute_gpio: Use external GPIO to control the external mute
+-ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the
+                     valid values.
+
+Vibra functionality
+- ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if
+                  missing or it is 0, the vibra functionality is disabled.
+
+Example:
+&i2c1 {
+       clock-frequency = <2600000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+               interrupt-parent = <&intc>;
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+
+                       ti,enable-vibra = <1>;
+
+                       codec {
+                               ti,ramp_delay_value = <3>;
+                       };
+
+               };
+       };
+};
index c855240f3a0e0afec8fa3e6870f82dddde00ebcc..0f5dd709d752490815fab1a978b8c2ff1c1f383b 100644 (file)
@@ -1,7 +1,7 @@
 Texas Instruments TWL6040 family
 
-The TWL6040s are 8-channel high quality low-power audio codecs providing audio
-and vibra functionality on OMAP4+ platforms.
+The TWL6040s are 8-channel high quality low-power audio codecs providing audio,
+vibra and GPO functionality on OMAP4+ platforms.
 They are connected ot the host processor via i2c for commands, McPDM for audio
 data and commands.
 
@@ -10,6 +10,8 @@ Required properties:
 - reg: must be 0x4b for i2c address
 - interrupts: twl6040 has one interrupt line connecteded to the main SoC
 - interrupt-parent: The parent interrupt controller
+- gpio-controller:
+- #gpio-cells = <1>: twl6040 provides GPO lines.
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 
 - vio-supply: Regulator for the twl6040 VIO supply
@@ -37,7 +39,6 @@ Example:
 &i2c1 {
        twl6040: twl@4b {
                compatible = "ti,twl6040";
-               reg = <0x4b>;
 
                interrupts = <0 119 4>;
                interrupt-parent = <&gic>;
@@ -60,3 +61,5 @@ Example:
                };
        };
 };
+
+/include/ "twl6040.dtsi"
diff --git a/Documentation/devicetree/bindings/misc/ifm-csi.txt b/Documentation/devicetree/bindings/misc/ifm-csi.txt
new file mode 100644 (file)
index 0000000..5bdfffb
--- /dev/null
@@ -0,0 +1,41 @@
+IFM camera sensor interface on mpc5200 LocalPlus bus
+
+Required properties:
+- compatible: "ifm,o2d-csi"
+- reg: specifies sensor chip select number and associated address range
+- interrupts: external interrupt line number and interrupt sense mode
+  of the interrupt line signaling frame valid events
+- gpios: three gpio-specifiers for "capture", "reset" and "master enable"
+  GPIOs (strictly in this order).
+- ifm,csi-clk-handle: the phandle to a node in the DT describing the sensor
+  clock generator. This node is usually a general purpose timer controller.
+- ifm,csi-addr-bus-width: address bus width (valid values are 16, 24, 25)
+- ifm,csi-data-bus-width: data bus width (valid values are 8 and 16)
+- ifm,csi-wait-cycles: sensor bus wait cycles
+
+Optional properties:
+- ifm,csi-byte-swap: if this property is present, the byte swapping on
+  the bus will be enabled.
+
+Example:
+
+       csi@3,0 {
+               compatible = "ifm,o2d-csi";
+               reg = <3 0 0x00100000>;         /* CS 3, 1 MiB range */
+               interrupts = <1 1 2>;           /* IRQ1, edge falling */
+
+               ifm,csi-clk-handle = <&timer7>;
+               gpios = <&gpio_simple 23 0      /* image_capture */
+                        &gpio_simple 26 0      /* image_reset */
+                        &gpio_simple 29 0>;    /* image_master_en */
+
+               ifm,csi-addr-bus-width = <24>;
+               ifm,csi-data-bus-width = <8>;
+               ifm,csi-wait-cycles = <0>;
+       };
+
+The base address of the used chip select is specified in the
+ranges property of the parent localbus node, for example:
+
+       ranges = <0 0 0xff000000 0x01000000
+                 3 0 0xe3000000 0x00100000>;
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
new file mode 100644 (file)
index 0000000..01ef408
--- /dev/null
@@ -0,0 +1,95 @@
+* Marvell Armada 370 SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6710-pinctrl"
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, uart0(rxd)
+mpp1          1        gpo, uart0(txd)
+mpp2          2        gpio, i2c0(sck), uart0(txd)
+mpp3          3        gpio, i2c0(sda), uart0(rxd)
+mpp4          4        gpio, cpu_pd(vdd)
+mpp5          5        gpo, ge0(txclko), uart1(txd), spi1(clk), audio(mclk)
+mpp6          6        gpio, ge0(txd0), sata0(prsnt), tdm(rst), audio(sdo)
+mpp7          7        gpo, ge0(txd1), tdm(tdx), audio(lrclk)
+mpp8          8        gpio, ge0(txd2), uart0(rts), tdm(drx), audio(bclk)
+mpp9          9        gpo, ge0(txd3), uart1(txd), sd0(clk), audio(spdifo)
+mpp10         10       gpio, ge0(txctl), uart0(cts), tdm(fsync), audio(sdi)
+mpp11         11       gpio, ge0(rxd0), uart1(rxd), sd0(cmd), spi0(cs1),
+                       sata1(prsnt), spi1(cs1)
+mpp12         12       gpio, ge0(rxd1), i2c1(sda), sd0(d0), spi1(cs0),
+                       audio(spdifi)
+mpp13         13       gpio, ge0(rxd2), i2c1(sck), sd0(d1), tdm(pclk),
+                       audio(rmclk)
+mpp14         14       gpio, ge0(rxd3), pcie(clkreq0), sd0(d2), spi1(mosi),
+                       spi0(cs2)
+mpp15         15       gpio, ge0(rxctl), pcie(clkreq1), sd0(d3), spi1(miso),
+                       spi0(cs3)
+mpp16         16       gpio, ge0(rxclk), uart1(rxd), tdm(int), audio(extclk)
+mpp17         17       gpo, ge(mdc)
+mpp18         18       gpio, ge(mdio)
+mpp19         19       gpio, ge0(txclk), ge1(txclkout), tdm(pclk)
+mpp20         20       gpo, ge0(txd4), ge1(txd0)
+mpp21         21       gpo, ge0(txd5), ge1(txd1), uart1(txd)
+mpp22         22       gpo, ge0(txd6), ge1(txd2), uart0(rts)
+mpp23         23       gpo, ge0(txd7), ge1(txd3), spi1(mosi)
+mpp24         24       gpio, ge0(col), ge1(txctl), spi1(cs0)
+mpp25         25       gpio, ge0(rxerr), ge1(rxd0), uart1(rxd)
+mpp26         26       gpio, ge0(crs), ge1(rxd1), spi1(miso)
+mpp27         27       gpio, ge0(rxd4), ge1(rxd2), uart0(cts)
+mpp28         28       gpio, ge0(rxd5), ge1(rxd3)
+mpp29         29       gpio, ge0(rxd6), ge1(rxctl), i2c1(sda)
+mpp30         30       gpio, ge0(rxd7), ge1(rxclk), i2c1(sck)
+mpp31         31       gpio, tclk, ge0(txerr)
+mpp32         32       gpio, spi0(cs0)
+mpp33         33       gpio, dev(bootcs), spi0(cs0)
+mpp34         34       gpo, dev(wen0), spi0(mosi)
+mpp35         35       gpo, dev(oen), spi0(sck)
+mpp36         36       gpo, dev(a1), spi0(miso)
+mpp37         37       gpo, dev(a0), sata0(prsnt)
+mpp38         38       gpio, dev(ready), uart1(cts), uart0(cts)
+mpp39         39       gpo, dev(ad0), audio(spdifo)
+mpp40         40       gpio, dev(ad1), uart1(rts), uart0(rts)
+mpp41         41       gpio, dev(ad2), uart1(rxd)
+mpp42         42       gpo, dev(ad3), uart1(txd)
+mpp43         43       gpo, dev(ad4), audio(bclk)
+mpp44         44       gpo, dev(ad5), audio(mclk)
+mpp45         45       gpo, dev(ad6), audio(lrclk)
+mpp46         46       gpo, dev(ad7), audio(sdo)
+mpp47         47       gpo, dev(ad8), sd0(clk), audio(spdifo)
+mpp48         48       gpio, dev(ad9), uart0(rts), sd0(cmd), sata1(prsnt),
+                       spi0(cs1)
+mpp49         49       gpio, dev(ad10), pcie(clkreq1), sd0(d0), spi1(cs0),
+                       audio(spdifi)
+mpp50         50       gpio, dev(ad11), uart0(cts), sd0(d1), spi1(miso),
+                       audio(rmclk)
+mpp51         51       gpio, dev(ad12), i2c1(sda), sd0(d2), spi1(mosi)
+mpp52         52       gpio, dev(ad13), i2c1(sck), sd0(d3), spi1(sck)
+mpp53         53       gpio, dev(ad14), sd0(clk), tdm(pclk), spi0(cs2),
+                       pcie(clkreq1)
+mpp54         54       gpo, dev(ad15), tdm(dtx)
+mpp55         55       gpio, dev(cs1), uart1(txd), tdm(rst), sata1(prsnt),
+                       sata0(prsnt)
+mpp56         56       gpio, dev(cs2), uart1(cts), uart0(cts), spi0(cs3),
+                       pcie(clkreq0), spi1(cs1)
+mpp57         57       gpio, dev(cs3), uart1(rxd), tdm(fsync), sata0(prsnt),
+                       audio(sdo)
+mpp58         58       gpio, dev(cs0), uart1(rts), tdm(int), audio(extclk),
+                       uart0(rts)
+mpp59         59       gpo, dev(ale0), uart1(rts), uart0(rts), audio(bclk)
+mpp60         60       gpio, dev(ale1), uart1(rxd), sata0(prsnt), pcie(rst-out),
+                       audio(sdi)
+mpp61         61       gpo, dev(wen1), uart1(txd), audio(rclk)
+mpp62         62       gpio, dev(a2), uart1(cts), tdm(drx), pcie(clkreq0),
+                       audio(mclk), uart0(cts)
+mpp63         63       gpo, spi0(sck), tclk
+mpp64         64       gpio, spi0(miso), spi0-1(cs1)
+mpp65         65       gpio, spi0(mosi), spi0-1(cs2)
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
new file mode 100644 (file)
index 0000000..bfa0a2e
--- /dev/null
@@ -0,0 +1,100 @@
+* Marvell Armada XP SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl",
+              "marvell,mv78460-pinctrl"
+
+This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+* Marvell Armada XP (all variants)
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, ge0(txclko), lcd(d0)
+mpp1          1        gpio, ge0(txd0), lcd(d1)
+mpp2          2        gpio, ge0(txd1), lcd(d2)
+mpp3          3        gpio, ge0(txd2), lcd(d3)
+mpp4          4        gpio, ge0(txd3), lcd(d4)
+mpp5          5        gpio, ge0(txctl), lcd(d5)
+mpp6          6        gpio, ge0(rxd0), lcd(d6)
+mpp7          7        gpio, ge0(rxd1), lcd(d7)
+mpp8          8        gpio, ge0(rxd2), lcd(d8)
+mpp9          9        gpio, ge0(rxd3), lcd(d9)
+mpp10         10       gpio, ge0(rxctl), lcd(d10)
+mpp11         11       gpio, ge0(rxclk), lcd(d11)
+mpp12         12       gpio, ge0(txd4), ge1(txd0), lcd(d12)
+mpp13         13       gpio, ge0(txd5), ge1(txd1), lcd(d13)
+mpp14         14       gpio, ge0(txd6), ge1(txd2), lcd(d15)
+mpp15         15       gpio, ge0(txd7), ge1(txd3), lcd(d16)
+mpp16         16       gpio, ge0(txd7), ge1(txd3), lcd(d16)
+mpp17         17       gpio, ge0(col), ge1(txctl), lcd(d17)
+mpp18         18       gpio, ge0(rxerr), ge1(rxd0), lcd(d18), ptp(trig)
+mpp19         19       gpio, ge0(crs), ge1(rxd1), lcd(d19), ptp(evreq)
+mpp20         20       gpio, ge0(rxd4), ge1(rxd2), lcd(d20), ptp(clk)
+mpp21         21       gpio, ge0(rxd5), ge1(rxd3), lcd(d21), mem(bat)
+mpp22         22       gpio, ge0(rxd6), ge1(rxctl), lcd(d22), sata0(prsnt)
+mpp23         23       gpio, ge0(rxd7), ge1(rxclk), lcd(d23), sata1(prsnt)
+mpp24         24       gpio, lcd(hsync), sata1(prsnt), nf(bootcs-re), tdm(rst)
+mpp25         25       gpio, lcd(vsync), sata0(prsnt), nf(bootcs-we), tdm(pclk)
+mpp26         26       gpio, lcd(clk), tdm(fsync), vdd(cpu1-pd)
+mpp27         27       gpio, lcd(e), tdm(dtx), ptp(trig)
+mpp28         28       gpio, lcd(pwm), tdm(drx), ptp(evreq)
+mpp29         29       gpio, lcd(ref-clk), tdm(int0), ptp(clk), vdd(cpu0-pd)
+mpp30         30       gpio, tdm(int1), sd0(clk)
+mpp31         31       gpio, tdm(int2), sd0(cmd), vdd(cpu0-pd)
+mpp32         32       gpio, tdm(int3), sd0(d0), vdd(cpu1-pd)
+mpp33         33       gpio, tdm(int4), sd0(d1), mem(bat)
+mpp34         34       gpio, tdm(int5), sd0(d2), sata0(prsnt)
+mpp35         35       gpio, tdm(int6), sd0(d3), sata1(prsnt)
+mpp36         36       gpio, spi(mosi)
+mpp37         37       gpio, spi(miso)
+mpp38         38       gpio, spi(sck)
+mpp39         39       gpio, spi(cs0)
+mpp40         40       gpio, spi(cs1), uart2(cts), lcd(vga-hsync), vdd(cpu1-pd),
+                       pcie(clkreq0)
+mpp41         41       gpio, spi(cs2), uart2(rts), lcd(vga-vsync), sata1(prsnt),
+                       pcie(clkreq1)
+mpp42         42       gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer),
+                       vdd(cpu0-pd)
+mpp43         43       gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout),
+                       vdd(cpu2-3-pd){1}
+mpp44         44       gpio, uart2(cts), uart3(rxd), spi(cs4), pcie(clkreq2),
+                       mem(bat)
+mpp45         45       gpio, uart2(rts), uart3(txd), spi(cs5), sata1(prsnt)
+mpp46         46       gpio, uart3(rts), uart1(rts), spi(cs6), sata0(prsnt)
+mpp47         47       gpio, uart3(cts), uart1(cts), spi(cs7), pcie(clkreq3),
+                       ref(clkout)
+mpp48         48       gpio, tclk, dev(burst/last)
+
+* Marvell Armada XP (mv78260 and mv78460 only)
+
+name          pins     functions
+================================================================================
+mpp49         49       gpio, dev(we3)
+mpp50         50       gpio, dev(we2)
+mpp51         51       gpio, dev(ad16)
+mpp52         52       gpio, dev(ad17)
+mpp53         53       gpio, dev(ad18)
+mpp54         54       gpio, dev(ad19)
+mpp55         55       gpio, dev(ad20), vdd(cpu0-pd)
+mpp56         56       gpio, dev(ad21), vdd(cpu1-pd)
+mpp57         57       gpio, dev(ad22), vdd(cpu2-3-pd){1}
+mpp58         58       gpio, dev(ad23)
+mpp59         59       gpio, dev(ad24)
+mpp60         60       gpio, dev(ad25)
+mpp61         61       gpio, dev(ad26)
+mpp62         62       gpio, dev(ad27)
+mpp63         63       gpio, dev(ad28)
+mpp64         64       gpio, dev(ad29)
+mpp65         65       gpio, dev(ad30)
+mpp66         66       gpio, dev(ad31)
+
+Notes:
+* {1} vdd(cpu2-3-pd) only available on mv78460.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
new file mode 100644 (file)
index 0000000..a648aaa
--- /dev/null
@@ -0,0 +1,72 @@
+* Marvell Dove SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,dove-pinctrl"
+- clocks: (optional) phandle of pdma clock
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, pmu, uart2(rts), sdio0(cd), lcd0(pwm)
+mpp1          1        gpio, pmu, uart2(cts), sdio0(wp), lcd1(pwm)
+mpp2          2        gpio, pmu, uart2(txd), sdio0(buspwr), sata(prsnt),
+                       uart1(rts)
+mpp3          3        gpio, pmu, uart2(rxd), sdio0(ledctrl), sata(act),
+                       uart1(cts), lcd-spi(cs1)
+mpp4          4        gpio, pmu, uart3(rts), sdio1(cd), spi1(miso)
+mpp5          5        gpio, pmu, uart3(cts), sdio1(wp), spi1(cs)
+mpp6          6        gpio, pmu, uart3(txd), sdio1(buspwr), spi1(mosi)
+mpp7          7        gpio, pmu, uart3(rxd), sdio1(ledctrl), spi1(sck)
+mpp8          8        gpio, pmu, watchdog(rstout)
+mpp9          9        gpio, pmu, pex1(clkreq)
+mpp10         10       gpio, pmu, ssp(sclk)
+mpp11         11       gpio, pmu, sata(prsnt), sata-1(act), sdio0(ledctrl),
+                       sdio1(ledctrl), pex0(clkreq)
+mpp12         12       gpio, pmu, uart2(rts), audio0(extclk), sdio1(cd), sata(act)
+mpp13         13       gpio, pmu, uart2(cts), audio1(extclk), sdio1(wp),
+                       ssp(extclk)
+mpp14         14       gpio, pmu, uart2(txd), sdio1(buspwr), ssp(rxd)
+mpp15         15       gpio, pmu, uart2(rxd), sdio1(ledctrl), ssp(sfrm)
+mpp16         16       gpio, uart3(rts), sdio0(cd), ac97(sdi1), lcd-spi(cs1)
+mpp17         17       gpio, uart3(cts), sdio0(wp), ac97(sdi2), twsi(sda),
+                       ac97-1(sysclko)
+mpp18         18       gpio, uart3(txd), sdio0(buspwr), ac97(sdi3), lcd0(pwm)
+mpp19         19       gpio, uart3(rxd), sdio0(ledctrl), twsi(sck)
+mpp20         20       gpio, sdio0(cd), sdio1(cd), spi1(miso), lcd-spi(miso),
+                       ac97(sysclko)
+mpp21         21       gpio, sdio0(wp), sdio1(wp), spi1(cs), lcd-spi(cs0),
+                       uart1(cts), ssp(sfrm)
+mpp22         22       gpio, sdio0(buspwr), sdio1(buspwr), spi1(mosi),
+                       lcd-spi(mosi), uart1(cts), ssp(txd)
+mpp23         23       gpio, sdio0(ledctrl), sdio1(ledctrl), spi1(sck),
+                       lcd-spi(sck), ssp(sclk)
+mpp_camera    24-39    gpio, camera
+mpp_sdio0     40-45    gpio, sdio0
+mpp_sdio1     46-51    gpio, sdio1
+mpp_audio1    52-57    gpio, i2s1/spdifo, i2s1, spdifo, twsi, ssp/spdifo, ssp,
+                       ssp/twsi
+mpp_spi0      58-61    gpio, spi0
+mpp_uart1     62-63    gpio, uart1
+mpp_nand      64-71    gpo, nand
+audio0        -        i2s, ac97
+twsi          -        none, opt1, opt2, opt3
+
+Notes:
+* group "mpp_audio1" allows the following functions and gpio pins:
+  - gpio          : gpio on pins 52-57
+  - i2s1/spdifo   : audio1 i2s on pins 52-55 and spdifo on 57, no gpios
+  - i2s1          : audio1 i2s on pins 52-55, gpio on pins 56,57
+  - spdifo        : spdifo on pin 57, gpio on pins 52-55
+  - twsi          : twsi on pins 56,57, gpio on pins 52-55
+  - ssp/spdifo    : ssp on pins 52-55, spdifo on pin 57, no gpios
+  - ssp           : ssp on pins 52-55, gpio on pins 56,57
+  - ssp/twsi      : ssp on pins 52-55, twsi on pins 56,57, no gpios
+* group "audio0" internally muxes i2s0 or ac97 controller to the dedicated
+  audio0 pins.
+* group "twsi" internally muxes twsi controller to the dedicated or option pins.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
new file mode 100644 (file)
index 0000000..361bccb
--- /dev/null
@@ -0,0 +1,279 @@
+* Marvell Kirkwood SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6180-pinctrl",
+              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
+              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
+
+This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+* Marvell Kirkwood 88f6180
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, mii(rxerr)
+mpp21         21       gpio, audio(spdifi)
+mpp22         22       gpio, audio(spdifo)
+mpp23         23       gpio, audio(rmclk)
+mpp24         24       gpio, audio(bclk)
+mpp25         25       gpio, audio(sdo)
+mpp26         26       gpio, audio(lrclk)
+mpp27         27       gpio, audio(mclk)
+mpp28         28       gpio, audio(sdi)
+mpp29         29       gpio, audio(extclk)
+
+* Marvell Kirkwood 88f6190
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0)
+mpp21         21       gpio, ge1(txd1), sata0(act)
+mpp22         22       gpio, ge1(txd2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt)
+mpp24         24       gpio, ge1(rxd0)
+mpp25         25       gpio, ge1(rxd1)
+mpp26         26       gpio, ge1(rxd2)
+mpp27         27       gpio, ge1(rxd3)
+mpp28         28       gpio, ge1(col)
+mpp29         29       gpio, ge1(txclk)
+mpp30         30       gpio, ge1(rxclk)
+mpp31         31       gpio, ge1(rxclk)
+mpp32         32       gpio, ge1(txclko)
+mpp33         33       gpo, ge1(txclk)
+mpp34         34       gpio, ge1(txen)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr)
+
+* Marvell Kirkwood 88f6192
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+
+* Marvell Kirkwood 88f6281
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpio, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk)
+mpp45         45       gpio, ts(mp9), tdm(pclk)
+mpp46         46       gpio, ts(mp10), tdm(fs)
+mpp47         47       gpio, ts(mp11), tdm(drx)
+mpp48         48       gpio, ts(mp12), tdm(dtx)
+mpp49         49       gpio, ts(mp9), tdm(rx0ql), ptp(clk)
+
+* Marvell Kirkwood 88f6282
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), sata1(act), lcd(hsync)
+mpp5          5        gpo, nand(io7), uart0(txd), sata0(act), lcd(vsync)
+mpp6          6        sysrst(out), spi(mosi)
+mpp7          7        gpo, spi(cs), lcd(pwm)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), mii(col),
+                       mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), mii(crs),
+                       sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), sata0(act)
+mpp12         12       gpo, sdio(clk), audio(spdifo), spi(mosi), twsi(sda)
+mpp13         13       gpio, sdio(cmd), uart1(txd), audio(rmclk), lcd(pwm)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt),
+                       audio(spdifi), audio-1(sdi)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act),
+                       spi(cs)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act), lcd(extclk)
+mpp17         17       gpio, sdio(d3), sata0(prsnt), sata1(act), twsi1(sck)
+mpp18         18       gpo, nand(io0), pex(clkreq)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act), lcd(d0)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo), lcd(d1)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt), lcd(d2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk), lcd(d3)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo),
+                       lcd(d4)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk),
+                       lcd(d5)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk),
+                       lcd(d6)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi),
+                       lcd(d7)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk),
+                       lcd(d8)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst), lcd(d9)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk), lcd(d10)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs), lcd(d11)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx), lcd(d12)
+mpp33         33       gpo, ge1(txclk), tdm(drx), lcd(d13)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act), lcd(d14)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql),
+                       lcd(d15)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi), twsi1(sda)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo), twsi1(sck)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk), lcd(d18)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk), lcd(d19)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo), lcd(d20)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk), lcd(d21)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk), lcd(d22)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi), lcd(d23)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk), lcd(clk)
+mpp45         45       gpio, ts(mp9), tdm(pclk), lcd(e)
+mpp46         46       gpio, ts(mp10), tdm(fs), lcd(hsync)
+mpp47         47       gpio, ts(mp11), tdm(drx), lcd(vsync)
+mpp48         48       gpio, ts(mp12), tdm(dtx), lcd(d16)
+mpp49         49       gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
new file mode 100644 (file)
index 0000000..0a26c3a
--- /dev/null
@@ -0,0 +1,46 @@
+* Marvell SoC pinctrl core driver for mpp
+
+The pinctrl driver enables Marvell SoCs to configure the multi-purpose pins
+(mpp) to a specific function. For each SoC family there is a SoC specific
+driver using this core driver.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+A Marvell SoC pin configuration node is a node of a group of pins which can
+be used for a specific device or function. Each node requires one or more
+mpp pins or group of pins and a mpp function common to all pins.
+
+Required properties for pinctrl driver:
+- compatible: "marvell,<soc>-pinctrl"
+  Please refer to each marvell,<soc>-pinctrl.txt binding doc for supported SoCs.
+
+Required properties for pin configuration node:
+- marvell,pins: string array of mpp pins or group of pins to be muxed.
+- marvell,function: string representing a function to mux to for all
+    marvell,pins given in this pin configuration node. The function has to be
+    common for all marvell,pins. Please refer to marvell,<soc>-pinctrl.txt for
+    valid pin/pin group names and available function names for each SoC.
+
+Examples:
+
+uart1: serial@12100 {
+       compatible = "ns16550a";
+       reg = <0x12100 0x100>;
+       reg-shift = <2>;
+       interrupts = <7>;
+
+       pinctrl-0 = <&pmx_uart1_sw>;
+       pinctrl-names = "default";
+};
+
+pinctrl: pinctrl@d0200 {
+       compatible = "marvell,dove-pinctrl";
+       reg = <0xd0200 0x20>;
+
+       pmx_uart1_sw: pmx-uart1-sw {
+               marvell,pins = "mpp_uart1";
+               marvell,function = "uart1";
+       };
+};
index 939a26d541f64251252a652c04270e82c96b377b..d5e370450ac0b265540f092a6e3dd9c6315c6c74 100644 (file)
@@ -12,9 +12,12 @@ Properties:
 - #size-cells : Either one or two, depending on how large each chipselect
                 can be.
 - reg : Offset and length of the register set for the device
-- interrupts : IFC has two interrupts. The first one is the "common"
-               interrupt(CM_EVTER_STAT), and second is the NAND interrupt
-               (NAND_EVTER_STAT).
+- interrupts: IFC may have one or two interrupts.  If two interrupt
+              specifiers are present, the first is the "common"
+              interrupt (CM_EVTER_STAT), and the second is the NAND
+              interrupt (NAND_EVTER_STAT).  If there is only one,
+              that interrupt reports both types of event.
+
 
 - ranges : Each range corresponds to a single chipselect, and covers
            the entire access window as configured.
diff --git a/Documentation/devicetree/bindings/regulator/88pm860x.txt b/Documentation/devicetree/bindings/regulator/88pm860x.txt
new file mode 100644 (file)
index 0000000..1267b3e
--- /dev/null
@@ -0,0 +1,30 @@
+Marvell 88PM860x regulator
+
+Required properties:
+- compatible: "marvell,88pm860x"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the regulator-compatible
+  property, with valid values listed below.
+
+Example:
+
+       pmic: 88pm860x@34 {
+               compatible = "marvell,88pm860x";
+               reg = <0x34>;
+
+               regulators {
+                       BUCK1 {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+                       BUCK3 {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/max8907.txt b/Documentation/devicetree/bindings/regulator/max8907.txt
new file mode 100644 (file)
index 0000000..371eccd
--- /dev/null
@@ -0,0 +1,69 @@
+MAX8907 regulator
+
+Required properties:
+- compatible: "maxim,max8907"
+- reg: I2C slave address
+- interrupts: The interrupt output of the controller
+- mbatt-supply: The input supply for MBATT, BBAT, SDBY, VRTC.
+- in-v1-supply: The input supply for SD1.
+- in-v2-supply: The input supply for SD2.
+- in-v3-supply: The input supply for SD3.
+- in1-supply: The input supply for LDO1.
+...
+- in20-supply: The input supply for LDO20.
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+Optional properties:
+- maxim,system-power-controller: Boolean property indicating that the PMIC
+  controls the overall system power.
+
+The valid names for regulators are:
+
+  sd1, sd2, sd3, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8, ldo9, ldo10,
+  ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19, ldo20, out5v,
+  out33v, bbat, sdby, vrtc.
+
+Example:
+
+               max8907@3c {
+                       compatible = "maxim,max8907";
+                       reg = <0x3c>;
+                       interrupts = <0 86 0x4>;
+
+                       maxim,system-power-controller;
+
+                       mbatt-supply = <&some_reg>;
+                       in-v1-supply = <&mbatt_reg>;
+                       ...
+                       in1-supply = <&mbatt_reg>;
+                       ...
+
+                       regulators {
+                               mbatt_reg: mbatt {
+                                       regulator-name = "vbat_pmu";
+                                       regulator-min-microvolt = <5000000>;
+                                       regulator-max-microvolt = <5000000>;
+                                       regulator-always-on;
+                               };
+
+                               sd1 {
+                                       regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               sd2 {
+                                       regulator-name = "nvvdd_sv2,vdd_core";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+...
+                       };
+               };
+       };
index 07b9ef6e49d5a82fb3b8026947eae0d4411e5d98..8b40cac24d93959740b828f8614736177028f066 100644 (file)
@@ -22,6 +22,10 @@ Required properties:
 - vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
 - vinldo9-supply: The input supply for the LDO9
 
+Optional properties:
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
+
 Each regulator is defined using the standard binding for regulators.
 
 Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver
@@ -37,6 +41,8 @@ Example:
                #gpio-cells = <2>;
                gpio-controller;
 
+               ti,system-power-controller;
+
                sys-supply = <&some_reg>;
                vin-sm0-supply = <&some_reg>;
                vin-sm1-supply = <&some_reg>;
diff --git a/Documentation/devicetree/bindings/rtc/snvs-rtc.txt b/Documentation/devicetree/bindings/rtc/snvs-rtc.txt
new file mode 100644 (file)
index 0000000..fb61ed7
--- /dev/null
@@ -0,0 +1 @@
+See Documentation/devicetree/bindings/crypto/fsl-sec4.txt for details.
diff --git a/Documentation/devicetree/bindings/video/backlight/88pm860x.txt b/Documentation/devicetree/bindings/video/backlight/88pm860x.txt
new file mode 100644 (file)
index 0000000..261df27
--- /dev/null
@@ -0,0 +1,15 @@
+88pm860x-backlight bindings
+
+Optional properties:
+  - marvell,88pm860x-iset: Current supplies on backlight device.
+  - marvell,88pm860x-pwm: PWM frequency on backlight device.
+
+Example:
+
+       backlights {
+               backlight-0 {
+                       marvell,88pm860x-iset = <4>;
+                       marvell,88pm860x-pwm = <3>;
+               };
+               backlight-2 {
+               };
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 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 2f0ddc15b5ac3621a4caaa7933cfbc656b47016b..9c647bd7c5a9cf108746647b8f97ec4b70afe1ab 100644 (file)
@@ -81,6 +81,9 @@ This defines trickle and fast charges.  For batteries that
 are already charged or discharging, 'n/a' can be displayed (or
 'unknown', if the status is not known).
 
+AUTHENTIC - indicates the power supply (battery or charger) connected
+to the platform is authentic(1) or non authentic(0).
+
 HEALTH - represents health of the battery, values corresponds to
 POWER_SUPPLY_HEALTH_*, defined in battery.h.
 
@@ -113,8 +116,12 @@ be negative; there is no empty or full value.  It is only useful for
 relative, time-based measurements.
 
 CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger.
+CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the
+power supply object.
 
 CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
+CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
+power supply object.
 
 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
 
index 7561d7ed8e11ef25a9a1fb479492148b6f038d5d..8ffb274367c7a4867b1930c9c5bd60ff475bfffb 100644 (file)
@@ -69,6 +69,7 @@ MAC/FDDI addresses:
        %pMR    05:04:03:02:01:00
        %pMF    00-01-02-03-04-05
        %pm     000102030405
+       %pmR    050403020100
 
        For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm'
        specifiers result in a printed address with ('M') or without ('m') byte
index 197ad59ab9bf71cbcfbec783680105967ead06a7..69b3cac4749d76811be9c39a6e3605023a7639fd 100644 (file)
@@ -102,9 +102,7 @@ related hangs. The functions call chain log is stored in a "ftrace-ramoops"
 file. Here is an example of usage:
 
  # mount -t debugfs debugfs /sys/kernel/debug/
- # cd /sys/kernel/debug/tracing
- # echo function > current_tracer
- # echo 1 > options/func_pstore
+ # echo 1 > /sys/kernel/debug/pstore/record_ftrace
  # reboot -f
  [...]
  # mount -t pstore pstore /mnt/
index 250160469d83e65c3a5235ee7b00b83b40abb68d..32aa4002de4a9fbd9fe64045119f811df47886ae 100644 (file)
@@ -119,8 +119,9 @@ three different userspace interfaces:
     *  /sys/class/rtc/rtcN ... sysfs attributes support readonly
        access to some RTC attributes.
 
-    *  /proc/driver/rtc ... the first RTC (rtc0) may expose itself
-       using a procfs interface.  More information is (currently) shown
+    *  /proc/driver/rtc ... the system clock RTC may expose itself
+       using a procfs interface. If there is no RTC for the system clock,
+       rtc0 is used by default. More information is (currently) shown
        here than through sysfs.
 
 The RTC Class framework supports a wide variety of RTCs, ranging from those
diff --git a/Documentation/smsc_ece1099.txt b/Documentation/smsc_ece1099.txt
new file mode 100644 (file)
index 0000000..6b492e8
--- /dev/null
@@ -0,0 +1,56 @@
+What is smsc-ece1099?
+----------------------
+
+The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
+or GPIO Expansion device. The device supports a keyboard
+scan matrix of 23x8. The device is connected to a Master
+via the SMSC BC-Link interface or via the SMBus.
+Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
+are multiplexed with GPIOs.
+
+Interrupt generation
+--------------------
+
+Interrupts can be generated by an edge detection on a GPIO
+pin or an edge detection on one of the bus interface pins.
+Interrupts can also be detected on the keyboard scan interface.
+The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
+any bit in one of the Interrupt Status registers is 1 and
+the corresponding Interrupt Mask bit is also 1.
+
+In order for software to determine which device is the source
+of an interrupt, it should first read the Group Interrupt Status Register
+to determine which Status register group is a source for the interrupt.
+Software should read both the Status register and the associated Mask register,
+then AND the two values together. Bits that are 1 in the result of the AND
+are active interrupts. Software clears an interrupt by writing a 1 to the
+corresponding bit in the Status register.
+
+Communication Protocol
+----------------------
+
+- SMbus slave Interface
+       The host processor communicates with the ECE1099 device
+       through a series of read/write registers via the SMBus
+       interface. SMBus is a serial communication protocol between
+       a computer host and its peripheral devices. The SMBus data
+       rate is 10KHz minimum to 400 KHz maximum
+
+- Slave Bus Interface
+       The ECE1099 device SMBus implementation is a subset of the
+       SMBus interface to the host. The device is a slave-only SMBus device.
+       The implementation in the device is a subset of SMBus since it
+       only supports four protocols.
+
+       The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
+       only valid SMBus protocols for the device.
+
+- BC-LinkTM Interface
+       The BC-Link is a proprietary bus that allows communication
+       between a Master device and a Companion device. The Master
+       device uses this serial bus to read and write registers
+       located on the Companion device. The bus comprises three signals,
+       BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
+       clock, BC_CLK, and the Companion device is the source for an
+       independent asynchronous interrupt signal, BC_INT#. The ECE1099
+       supports BC-Link speeds up to 24MHz.
index 6d78841fd41677d4f81dbcb53eed7ab8602cddb4..2907ba6c3607dfd557e3e4533413b0bea8518a60 100644 (file)
@@ -181,6 +181,8 @@ core_pattern is used to specify a core dumpfile pattern name.
        %p      pid
        %u      uid
        %g      gid
+       %d      dump mode, matches PR_SET_DUMPABLE and
+               /proc/sys/fs/suid_dumpable
        %s      signal number
        %t      UNIX time of dump
        %h      hostname
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..54270df99d5c2f1794c4fcd537eec05fd525d031 100644 (file)
@@ -594,7 +594,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 f883fc1b1b46aeee041dbd0ab4db221ec41311c6..84ee86719bd9100174e2fcd0f4ffc6d475dcdce6 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
@@ -572,7 +602,7 @@ F:  drivers/net/appletalk/
 F:     net/appletalk/
 
 ARASAN COMPACT FLASH PATA CONTROLLER
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     include/linux/pata_arasan_cf_data.h
@@ -760,6 +790,7 @@ S:  Maintained
 T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:     arch/arm/mach-imx/
 F:     arch/arm/plat-mxc/
+F:     arch/arm/configs/imx*_defconfig
 
 ARM/FREESCALE IMX6
 M:     Shawn Guo <shawn.guo@linaro.org>
@@ -1062,7 +1093,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>
@@ -1072,7 +1103,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>
@@ -1080,7 +1111,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>
@@ -1245,7 +1276,7 @@ F:        include/linux/i2c/at24.h
 
 ATA OVER ETHERNET (AOE) DRIVER
 M:     "Ed L. Cashin" <ecashin@coraid.com>
-W:     http://www.coraid.com/support/linux
+W:     http://support.coraid.com/support/linux
 S:     Supported
 F:     Documentation/aoe/
 F:     drivers/block/aoe/
@@ -1352,7 +1383,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
@@ -1699,7 +1730,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>
@@ -1729,7 +1760,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>
@@ -2118,7 +2149,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>
@@ -2473,6 +2514,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
@@ -2484,6 +2636,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
@@ -2512,6 +2674,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>
@@ -2794,8 +2966,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>
@@ -3025,7 +3207,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
@@ -3123,6 +3305,7 @@ T:        git git://git.secretlab.ca/git/linux-2.6.git
 F:     Documentation/gpio.txt
 F:     drivers/gpio/
 F:     include/linux/gpio*
+F:     include/asm-generic/gpio.h
 
 GRE DEMULTIPLEXER DRIVER
 M:     Dmitry Kozlov <xeb@mail.ru>
@@ -3142,49 +3325,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>
@@ -3238,6 +3428,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
@@ -3904,7 +4104,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
@@ -4198,6 +4398,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
@@ -4600,7 +4820,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
@@ -4664,6 +4884,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
@@ -5004,7 +5234,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>
@@ -5045,7 +5275,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>
@@ -5265,7 +5495,7 @@ F:        include/linux/i2c-algo-pca.h
 F:     include/linux/i2c-pca-platform.h
 
 PCDP - PRIMARY CONSOLE AND DEBUG PORT
-M:     Khalid Aziz <khalid.aziz@hp.com>
+M:     Khalid Aziz <khalid@gonehiking.org>
 S:     Maintained
 F:     drivers/firmware/pcdp.*
 
@@ -5548,13 +5778,25 @@ L:      cbe-oss-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/block/ps3vram.c
 
+PSTORE FILESYSTEM
+M:     Anton Vorontsov <cbouatmailru@gmail.com>
+M:     Colin Cross <ccross@android.com>
+M:     Kees Cook <keescook@chromium.org>
+M:     Tony Luck <tony.luck@intel.com>
+S:     Maintained
+T:     git git://git.infradead.org/users/cbou/linux-pstore.git
+F:     fs/pstore/
+F:     include/linux/pstore*
+F:     drivers/firmware/efivars.c
+F:     drivers/acpi/apei/erst.c
+
 PTP HARDWARE CLOCK SUPPORT
 M:     Richard Cochran <richardcochran@gmail.com>
 S:     Maintained
 W:     http://linuxptp.sourceforge.net/
 F:     Documentation/ABI/testing/sysfs-ptp
 F:     Documentation/ptp/*
-F:     drivers/net/gianfar_ptp.c
+F:     drivers/net/ethernet/freescale/gianfar_ptp.c
 F:     drivers/net/phy/dp83640*
 F:     drivers/ptp/*
 F:     include/linux/ptp_cl*
@@ -5577,7 +5819,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>
@@ -5687,6 +5929,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
@@ -5853,6 +6105,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
@@ -5947,9 +6209,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>
@@ -5986,7 +6248,7 @@ S:        Maintained
 F:     drivers/tty/serial
 
 SYNOPSYS DESIGNWARE DMAC DRIVER
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 S:     Maintained
 F:     include/linux/dw_dmac.h
 F:     drivers/dma/dw_dmac_regs.h
@@ -6010,7 +6272,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>
@@ -6134,7 +6396,7 @@ S:        Maintained
 F:     drivers/mmc/host/sdhci-s3c.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 L:     spear-devel@list.st.com
 L:     linux-mmc@vger.kernel.org
 S:     Maintained
@@ -6398,8 +6660,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>
@@ -6499,7 +6762,7 @@ S:        Maintained
 F:     include/linux/compiler.h
 
 SPEAR PLATFORM SUPPORT
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 M:     Shiraz Hashim <shiraz.hashim@st.com>
 L:     spear-devel@list.st.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -6508,7 +6771,7 @@ S:        Maintained
 F:     arch/arm/plat-spear/
 
 SPEAR13XX MACHINE SUPPORT
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 M:     Shiraz Hashim <shiraz.hashim@st.com>
 L:     spear-devel@list.st.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -6517,7 +6780,7 @@ S:        Maintained
 F:     arch/arm/mach-spear13xx/
 
 SPEAR3XX MACHINE SUPPORT
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 M:     Shiraz Hashim <shiraz.hashim@st.com>
 L:     spear-devel@list.st.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -6528,7 +6791,7 @@ F:        arch/arm/mach-spear3xx/
 SPEAR6XX MACHINE SUPPORT
 M:     Rajeev Kumar <rajeev-dlh.kumar@st.com>
 M:     Shiraz Hashim <shiraz.hashim@st.com>
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 L:     spear-devel@list.st.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.st.com/spear
@@ -6536,7 +6799,7 @@ S:        Maintained
 F:     arch/arm/mach-spear6xx/
 
 SPEAR CLOCK FRAMEWORK SUPPORT
-M:     Viresh Kumar <viresh.linux@gmail.com>
+M:     Viresh Kumar <viresh.linux@gmail.com>
 L:     spear-devel@list.st.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.st.com/spear
@@ -6817,6 +7080,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
@@ -7007,6 +7330,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
@@ -7179,15 +7512,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
@@ -7357,7 +7681,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>
@@ -7392,17 +7716,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>
@@ -7431,7 +7745,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>
@@ -7489,7 +7803,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
@@ -7801,6 +8115,13 @@ F:       drivers/xen/
 F:     arch/x86/include/asm/xen/
 F:     include/xen/
 
+XEN HYPERVISOR ARM
+M:     Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
+S:     Supported
+F:     arch/arm/xen/
+F:     arch/arm/include/asm/xen/
+
 XEN NETWORK BACKEND DRIVER
 M:     Ian Campbell <ian.campbell@citrix.com>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
@@ -7891,7 +8212,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 7bab17ed29729b84c464be57d6aa9e76a9c7369d..8ac460a8f4ca64dfd33238af132775bac1a6d6dd 100644 (file)
@@ -529,10 +529,11 @@ config ARCH_IXP4XX
 config ARCH_DOVE
        bool "Marvell Dove"
        select CPU_V7
-       select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
-       select PLAT_ORION
+       select MIGHT_HAVE_PCI
+       select PLAT_ORION_LEGACY
+       select USB_ARCH_HAS_EHCI
        help
          Support for the Marvell Dove SoC 88AP510
 
@@ -542,7 +543,7 @@ config ARCH_KIRKWOOD
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
-       select PLAT_ORION
+       select PLAT_ORION_LEGACY
        help
          Support for the following Marvell Kirkwood series SoCs:
          88F6180, 88F6192 and 88F6281.
@@ -568,7 +569,7 @@ config ARCH_MV78XX0
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
-       select PLAT_ORION
+       select PLAT_ORION_LEGACY
        help
          Support for the following Marvell MV78xx0 series SoCs:
          MV781x0, MV782x0.
@@ -580,7 +581,7 @@ config ARCH_ORION5X
        select PCI
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
-       select PLAT_ORION
+       select PLAT_ORION_LEGACY
        help
          Support for the following Marvell Orion 5x series SoCs:
          Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
@@ -1138,6 +1139,10 @@ config PLAT_ORION
        select IRQ_DOMAIN
        select COMMON_CLK
 
+config PLAT_ORION_LEGACY
+       bool
+       select PLAT_ORION
+
 config PLAT_PXA
        bool
 
@@ -1829,6 +1834,16 @@ config DEPRECATED_PARAM_STRUCT
          This was deprecated in 2001 and announced to live on for 5 years.
          Some old boot loaders still use this way.
 
+config XEN_DOM0
+       def_bool y
+       depends on XEN
+
+config XEN
+       bool "Xen guest support on ARM (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && ARM && OF
+       help
+         Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
+
 endmenu
 
 menu "Boot options"
index b86e57ef146b0de3af0b41b0e21a8b5834dd0a65..40ea991b67824e73b3409191e0f8767ad594f83e 100644 (file)
@@ -250,6 +250,7 @@ endif
 core-$(CONFIG_FPE_NWFPE)       += arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)     += $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)             += arch/arm/vfp/
+core-$(CONFIG_XEN)             += arch/arm/xen/
 
 # If we have a machine-specific directory, then include it in the build.
 core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
index 43c084c2cd6682074e45c57090c0d3ee4a2e38d0..29f541f0e6530dde50cea5006cd2bbffc99ccfbf 100644 (file)
@@ -17,6 +17,9 @@ dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \
        usb_a9263.dtb \
        usb_a9g20.dtb
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
+dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
+       dove-cubox.dtb \
+       dove-dove-db.dtb
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-smdkv310.dtb \
        exynos4210-trats.dtb \
@@ -33,10 +36,13 @@ dtb-$(CONFIG_SOC_IMX6Q) += imx6q-arm2.dtb \
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
        kirkwood-dns325.dtb \
+       kirkwood-dockstar.dtb \
        kirkwood-dreamplug.dtb \
        kirkwood-goflexnet.dtb \
        kirkwood-ib62x0.dtb \
        kirkwood-iconnect.dtb \
+       kirkwood-iomega_ix2_200.dtb \
+       kirkwood-km_kirkwood.dtb \
        kirkwood-lschlv2.dtb \
        kirkwood-lsxhl.dtb \
        kirkwood-ts219-6281.dtb \
@@ -96,6 +102,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
        vexpress-v2p-ca9.dtb \
        vexpress-v2p-ca15-tc1.dtb \
-       vexpress-v2p-ca15_a7.dtb
+       vexpress-v2p-ca15_a7.dtb \
+       xenvm-4.2.dtb
 
 endif
index 6b6b932a5a7dc291c4414ef1fc01404bfff06724..16cc82cdaa817aef1cb2e235c93b8412ddfb7af8 100644 (file)
                               reg = <0xd0020300 0x30>;
                               interrupts = <37>, <38>, <39>, <40>;
                };
+
+               addr-decoding@d0020000 {
+                       compatible = "marvell,armada-addr-decoding-controller";
+                       reg = <0xd0020000 0x258>;
+               };
        };
 };
 
index 3228ccc83332f4e0bbe2bb94d4ed750afcea4fa2..2069151afe01583ecb07c07f7f3cb91477a889d9 100644 (file)
        model = "Marvell Armada 370 family SoC";
        compatible = "marvell,armada370", "marvell,armada-370-xp";
 
+       aliases {
+               gpio0 = &gpio0;
+               gpio1 = &gpio1;
+               gpio2 = &gpio2;
+       };
+
        mpic: interrupt-controller@d0020000 {
              reg = <0xd0020a00 0x1d0>,
                    <0xd0021870 0x58>;
                                compatible = "marvell,armada-370-xp-system-controller";
                                reg = <0xd0018200 0x100>;
                };
+
+               pinctrl {
+                       compatible = "marvell,mv88f6710-pinctrl";
+                       reg = <0xd0018000 0x38>;
+               };
+
+               gpio0: gpio@d0018100 {
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018100 0x40>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <82>, <83>, <84>, <85>;
+               };
+
+               gpio1: gpio@d0018140 {
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018140 0x40>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <87>, <88>, <89>, <90>;
+               };
+
+               gpio2: gpio@d0018180 {
+                       compatible = "marvell,orion-gpio";
+                       reg = <0xd0018180 0x40>;
+                       ngpios = <2>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <91>;
+               };
        };
 };
index f97040d4258d97bc81bd2608d8faf320eed3e37c..b1fc728515e9c739ae272004c86a5e6ec1de393e 100644 (file)
  */
 
 /dts-v1/;
-/include/ "armada-xp.dtsi"
+/include/ "armada-xp-mv78460.dtsi"
 
 / {
        model = "Marvell Armada XP Evaluation Board";
-       compatible = "marvell,axp-db", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,axp-db", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
                bootargs = "console=ttyS0,115200 earlyprintk";
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
new file mode 100644 (file)
index 0000000..ea35519
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78230 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP MV78230 SoC";
+       compatible = "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       aliases {
+               gpio0 = &gpio0;
+               gpio1 = &gpio1;
+       };
+
+       soc {
+               pinctrl {
+                       compatible = "marvell,mv78230-pinctrl";
+                       reg = <0xd0018000 0x38>;
+               };
+
+               gpio0: gpio@d0018100 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018100 0x40>,
+                           <0xd0018800 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <16>, <17>, <18>, <19>;
+               };
+
+               gpio1: gpio@d0018140 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018140 0x40>,
+                           <0xd0018840 0x30>;
+                       ngpios = <17>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <20>, <21>, <22>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
new file mode 100644 (file)
index 0000000..2057863
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78260 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP MV78260 SoC";
+       compatible = "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       aliases {
+               gpio0 = &gpio0;
+               gpio1 = &gpio1;
+               gpio2 = &gpio2;
+       };
+
+       soc {
+               pinctrl {
+                       compatible = "marvell,mv78260-pinctrl";
+                       reg = <0xd0018000 0x38>;
+               };
+
+               gpio0: gpio@d0018100 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018100 0x40>,
+                           <0xd0018800 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <16>, <17>, <18>, <19>;
+               };
+
+               gpio1: gpio@d0018140 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018140 0x40>,
+                           <0xd0018840 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <20>, <21>, <22>, <23>;
+               };
+
+               gpio2: gpio@d0018180 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018180 0x40>,
+                           <0xd0018870 0x30>;
+                       ngpios = <3>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <24>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
new file mode 100644 (file)
index 0000000..ffac983
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78460 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP MV78460 SoC";
+       compatible = "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       aliases {
+               gpio0 = &gpio0;
+               gpio1 = &gpio1;
+               gpio2 = &gpio2;
+       };
+
+       soc {
+               pinctrl {
+                       compatible = "marvell,mv78460-pinctrl";
+                       reg = <0xd0018000 0x38>;
+               };
+
+               gpio0: gpio@d0018100 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018100 0x40>,
+                           <0xd0018800 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <16>, <17>, <18>, <19>;
+               };
+
+               gpio1: gpio@d0018140 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018140 0x40>,
+                           <0xd0018840 0x30>;
+                       ngpios = <32>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <20>, <21>, <22>, <23>;
+               };
+
+               gpio2: gpio@d0018180 {
+                       compatible = "marvell,armadaxp-gpio";
+                       reg = <0xd0018180 0x40>,
+                           <0xd0018870 0x30>;
+                       ngpios = <3>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupts-cells = <2>;
+                       interrupts = <24>;
+               };
+       };
+ };
diff --git a/arch/arm/boot/dts/dove-cm-a510.dts b/arch/arm/boot/dts/dove-cm-a510.dts
new file mode 100644 (file)
index 0000000..61a8062
--- /dev/null
@@ -0,0 +1,38 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+       model = "Compulab CM-A510";
+       compatible = "compulab,cm-a510", "marvell,dove";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x40000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+};
+
+&uart0 { status = "okay"; };
+&uart1 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sdio1 { status = "okay"; };
+&sata0 { status = "okay"; };
+
+&spi0 {
+       status = "okay";
+
+       /* spi0.0: 4M Flash Winbond W25Q32BV */
+       spi-flash@0 {
+               compatible = "st,w25q32";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+         status = "okay";
+};
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
new file mode 100644 (file)
index 0000000..0adbd5a
--- /dev/null
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+       model = "SolidRun CuBox";
+       compatible = "solidrun,cubox", "marvell,dove";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x40000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               power {
+                       label = "Power";
+                       gpios = <&gpio0 18 1>;
+                       linux,default-trigger = "default-on";
+               };
+       };
+};
+
+&uart0 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sata0 { status = "okay"; };
+&i2c0 { status = "okay"; };
+
+&spi0 {
+       status = "okay";
+
+       /* spi0.0: 4M Flash Winbond W25Q32BV */
+       spi-flash@0 {
+               compatible = "st,w25q32";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/dove-dove-db.dts
new file mode 100644 (file)
index 0000000..e5a920b
--- /dev/null
@@ -0,0 +1,38 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+       model = "Marvell DB-MV88AP510-BP Development Board";
+       compatible = "marvell,dove-db", "marvell,dove";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x40000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+};
+
+&uart0 { status = "okay"; };
+&uart1 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sdio1 { status = "okay"; };
+&sata0 { status = "okay"; };
+
+&spi0 {
+       status = "okay";
+
+       /* spi0.0: 4M Flash ST-M25P32-VMF6P */
+       spi-flash@0 {
+               compatible = "st,m25p32";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+         status = "okay";
+};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
new file mode 100644 (file)
index 0000000..96fb824
--- /dev/null
@@ -0,0 +1,143 @@
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "marvell,dove";
+       model = "Marvell Armada 88AP510 SoC";
+
+       interrupt-parent = <&intc>;
+
+       intc: interrupt-controller {
+               compatible = "marvell,orion-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = <0xf1020204 0x04>,
+                     <0xf1020214 0x04>;
+       };
+
+       mbus@f1000000 {
+               compatible = "simple-bus";
+               ranges = <0 0xf1000000 0x4000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               uart0: serial@12000 {
+                       compatible = "ns16550a";
+                       reg = <0x12000 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <7>;
+                       clock-frequency = <166666667>;
+                       status = "disabled";
+               };
+
+               uart1: serial@12100 {
+                       compatible = "ns16550a";
+                       reg = <0x12100 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <8>;
+                       clock-frequency = <166666667>;
+                       status = "disabled";
+               };
+
+               uart2: serial@12200 {
+                       compatible = "ns16550a";
+                       reg = <0x12000 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <9>;
+                       clock-frequency = <166666667>;
+                       status = "disabled";
+               };
+
+               uart3: serial@12300 {
+                       compatible = "ns16550a";
+                       reg = <0x12100 0x100>;
+                       reg-shift = <2>;
+                       interrupts = <10>;
+                       clock-frequency = <166666667>;
+                       status = "disabled";
+               };
+
+               wdt: wdt@20300 {
+                       compatible = "marvell,orion-wdt";
+                       reg = <0x20300 0x28>;
+               };
+
+               gpio0: gpio@d0400 {
+                       compatible = "marvell,orion-gpio";
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       reg = <0xd0400 0x20>;
+                       ngpio = <32>;
+                       interrupts = <12>, <13>, <14>, <60>;
+               };
+
+               gpio1: gpio@d0420 {
+                       compatible = "marvell,orion-gpio";
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       reg = <0xd0420 0x20>;
+                       ngpio = <32>;
+                       interrupts = <61>;
+               };
+
+               gpio2: gpio@e8400 {
+                       compatible = "marvell,orion-gpio";
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       reg = <0xe8400 0x0c>;
+                       ngpio = <8>;
+               };
+
+               spi0: spi@10600 {
+                       compatible = "marvell,orion-spi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+                       interrupts = <6>;
+                       reg = <0x10600 0x28>;
+                       status = "disabled";
+               };
+
+               spi1: spi@14600 {
+                       compatible = "marvell,orion-spi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       interrupts = <5>;
+                       reg = <0x14600 0x28>;
+                       status = "disabled";
+               };
+
+               i2c0: i2c@11000 {
+                       compatible = "marvell,mv64xxx-i2c";
+                       reg = <0x11000 0x20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <11>;
+                       clock-frequency = <400000>;
+                       timeout-ms = <1000>;
+                       status = "disabled";
+               };
+
+               sdio0: sdio@92000 {
+                       compatible = "marvell,dove-sdhci";
+                       reg = <0x92000 0x100>;
+                       interrupts = <35>, <37>;
+                       status = "disabled";
+               };
+
+               sdio1: sdio@90000 {
+                       compatible = "marvell,dove-sdhci";
+                       reg = <0x90000 0x100>;
+                       interrupts = <36>, <38>;
+                       status = "disabled";
+               };
+
+               sata0: sata@a0000 {
+                       compatible = "marvell,orion-sata";
+                       reg = <0xa0000 0x2400>;
+                       interrupts = <62>;
+                       nr-ports = <1>;
+                       status = "disabled";
+               };
+       };
+};
index 35e5895ba3df31856c73193a6bf79f791d54f985..f3990b04fecf4661216c9cf321dc817c72e1a0b7 100644 (file)
                                #clock-cells = <1>;
                        };
 
-                       anatop@020c8000 {
-                               compatible = "fsl,imx6q-anatop";
+                       anatop: anatop@020c8000 {
+                               compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
                                reg = <0x020c8000 0x1000>;
                                interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 
                                interrupts = <0 89 0x04 0 90 0x04>;
                        };
 
+                       gpr: iomuxc-gpr@020e0000 {
+                               compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+                               reg = <0x020e0000 0x38>;
+                       };
+
                        iomuxc@020e0000 {
                                compatible = "fsl,imx6q-iomuxc";
                                reg = <0x020e0000 0x4000>;
index 7408655f91b500cc5f4a4fc283c6bb30c7c43eac..9b32d0272825fcb172c0ef720c30f74c4202e0f5 100644 (file)
                };
        };
 
+       gpio_fan {
+               /* Fan: ADDA AD045HB-G73 40mm 6000rpm@5v */
+               compatible = "gpio-fan";
+               gpios = <&gpio1 14 1
+                        &gpio1 13 1>;
+               gpio-fan,speed-map = <0    0
+                                     3000 1
+                                     6000 2>;
+       };
+
        ocp@f1000000 {
                sata@80000 {
                        status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
new file mode 100644 (file)
index 0000000..08a5824
--- /dev/null
@@ -0,0 +1,57 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+       model = "Seagate FreeAgent Dockstar";
+       compatible = "seagate,dockstar", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk root=/dev/sda1 rootdelay=10";
+       };
+
+       ocp@f1000000 {
+               serial@12000 {
+                       clock-frequency = <200000000>;
+                       status = "ok";
+               };
+
+               nand@3000000 {
+                       status = "okay";
+
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x0000000 0x100000>;
+                               read-only;
+                       };
+
+                       partition@100000 {
+                               label = "uImage";
+                               reg = <0x0100000 0x400000>;
+                       };
+
+                       partition@500000 {
+                               label = "data";
+                               reg = <0x0500000 0xfb00000>;
+                       };
+               };
+       };
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               health {
+                       label = "status:green:health";
+                       gpios = <&gpio1 14 1>;
+                       linux,default-trigger = "default-on";
+               };
+               fault {
+                       label = "status:orange:fault";
+                       gpios = <&gpio1 15 1>;
+               };
+       };
+};
index f8ca6fa88192a5d36edb0c484a7a13c7c11e6e7c..d97cd9d4753e298689f3e9331eb7945569b416cd 100644 (file)
@@ -12,7 +12,7 @@
        };
 
        chosen {
-               bootargs = "console=ttyS0,115200n8 earlyprintk mtdparts=orion_nand:0xc0000@0x0(uboot),0x20000@0xa0000(env),0x300000@0x100000(zImage),0x300000@0x540000(initrd),0x1f400000@0x980000(boot)";
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
                linux,initrd-start = <0x4500040>;
                linux,initrd-end   = <0x4800000>;
        };
                        clock-frequency = <200000000>;
                        status = "ok";
                };
+
+               nand@3000000 {
+                       status = "okay";
+
+                       partition@0 {
+                               label = "uboot";
+                               reg = <0x0000000 0xc0000>;
+                       };
+
+                       partition@a0000 {
+                               label = "env";
+                               reg = <0xa0000 0x20000>;
+                       };
+
+                       partition@100000 {
+                               label = "zImage";
+                               reg = <0x100000 0x300000>;
+                       };
+
+                       partition@540000 {
+                               label = "initrd";
+                               reg = <0x540000 0x300000>;
+                       };
+
+                       partition@980000 {
+                               label = "boot";
+                               reg = <0x980000 0x1f400000>;
+                       };
+               };
        };
+
        gpio-leds {
                compatible = "gpio-leds";
 
                        gpios = <&gpio1 16 0>;
                };
        };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               button@1 {
+                       label = "OTB Button";
+                       linux,code = <133>;
+                       gpios = <&gpio1 3 1>;
+                       debounce-interval = <100>;
+               };
+               button@2 {
+                       label = "Reset";
+                       linux,code = <0x198>;
+                       gpios = <&gpio0 12 1>;
+                       debounce-interval = <100>;
+               };
+       };
 };
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
new file mode 100644 (file)
index 0000000..865aeec
--- /dev/null
@@ -0,0 +1,105 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+       model = "Iomega StorCenter ix2-200";
+       compatible = "iom,ix2-200", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+
+       ocp@f1000000 {
+               i2c@11000 {
+                       status = "okay";
+
+                       lm63: lm63@4c {
+                               compatible = "national,lm63";
+                               reg = <0x4c>;
+                       };
+               };
+
+               serial@12000 {
+                       clock-frequency = <200000000>;
+                       status = "ok";
+               };
+
+               nand@3000000 {
+                       status = "okay";
+
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x0000000 0x100000>;
+                               read-only;
+                       };
+
+                       partition@a0000 {
+                               label = "env";
+                               reg = <0xa0000 0x20000>;
+                               read-only;
+                       };
+
+                       partition@100000 {
+                               label = "uImage";
+                               reg = <0x100000 0x300000>;
+                       };
+
+                       partition@400000 {
+                               label = "uInitrd";
+                               reg = <0x540000 0x1000000>;
+                       };
+               };
+               sata@80000 {
+                       status = "okay";
+                       nr-ports = <2>;
+               };
+
+       };
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               power_led {
+                       label = "status:white:power_led";
+                       gpios = <&gpio0 16 0>;
+                       linux,default-trigger = "default-on";
+               };
+               health_led1 {
+                       label = "status:red:health_led";
+                       gpios = <&gpio1 5 0>;
+               };
+               health_led2 {
+                       label = "status:white:health_led";
+                       gpios = <&gpio1 4 0>;
+               };
+               backup_led {
+                       label = "status:blue:backup_led";
+                       gpios = <&gpio0 15 0>;
+               };
+       };
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               Power {
+                       label = "Power Button";
+                       linux,code = <116>;
+                       gpios = <&gpio0 14 1>;
+               };
+               Reset {
+                       label = "Reset Button";
+                       linux,code = <0x198>;
+                       gpios = <&gpio0 12 1>;
+               };
+               OTB {
+                       label = "OTB Button";
+                       linux,code = <133>;
+                       gpios = <&gpio1 3 1>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
new file mode 100644 (file)
index 0000000..75bdb93
--- /dev/null
@@ -0,0 +1,29 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+       model = "Keymile Kirkwood Reference Design";
+       compatible = "keymile,km_kirkwood", "marvell,kirkwood-98DX4122", "marvell,kirkwood";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x08000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+
+       ocp@f1000000 {
+               serial@12000 {
+                       clock-frequency = <200000000>;
+                       status = "ok";
+               };
+
+               nand@3000000 {
+                       status = "ok";
+                       chip-delay = <25>;
+               };
+       };
+};
index cef9616f330aa06fc75769a79fbcf62211b3fea7..4e5b8154a5be5d95535cd5eb9d66f894670c0946 100644 (file)
@@ -14,7 +14,8 @@
 
        ocp@f1000000 {
                compatible = "simple-bus";
-               ranges = <0 0xf1000000 0x4000000>;
+               ranges = <0x00000000 0xf1000000 0x4000000
+                         0xf5000000 0xf5000000 0x0000400>;
                #address-cells = <1>;
                #size-cells = <1>;
 
                        clock-frequency = <100000>;
                        status = "disabled";
                };
+
+               crypto@30000 {
+                       compatible = "marvell,orion-crypto";
+                       reg = <0x30000 0x10000>,
+                             <0xf5000000 0x800>;
+                       reg-names = "regs", "sram";
+                       interrupts = <22>;
+                       status = "okay";
+               };
        };
 };
index e92be5a474e76f9bff3bb98e93682bc0c431a7d1..595492aa505372047aab605aff58b043f16896f6 100644 (file)
                        };
                        twsi1: i2c@d4011000 {
                                status = "okay";
+
+                               pmic: 88pm860x@34 {
+                                       compatible = "marvell,88pm860x";
+                                       reg = <0x34>;
+                                       interrupts = <4>;
+                                       interrupt-parent = <&intc>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <1>;
+
+                                       marvell,88pm860x-irq-read-clr;
+                                       marvell,88pm860x-slave-addr = <0x11>;
+
+                                       regulators {
+                                               BUCK1 {
+                                                       regulator-min-microvolt = <1000000>;
+                                                       regulator-max-microvolt = <1500000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               BUCK2 {
+                                                       regulator-min-microvolt = <1000000>;
+                                                       regulator-max-microvolt = <1500000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               BUCK3 {
+                                                       regulator-min-microvolt = <1000000>;
+                                                       regulator-max-microvolt = <3000000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO1 {
+                                                       regulator-min-microvolt = <1200000>;
+                                                       regulator-max-microvolt = <2800000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO2 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO3 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO4 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-always-on;
+                                               };
+                                               LDO5 {
+                                                       regulator-min-microvolt = <2900000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO6 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO7 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <2900000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO8 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <2900000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO9 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO10 {
+                                                       regulator-min-microvolt = <1200000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-boot-on;
+                                                       regulator-always-on;
+                                               };
+                                               LDO12 {
+                                                       regulator-min-microvolt = <1200000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-always-on;
+                                               };
+                                               LDO13 {
+                                                       regulator-min-microvolt = <1200000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-always-on;
+                                               };
+                                               LDO14 {
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3300000>;
+                                                       regulator-always-on;
+                                               };
+                                       };
+                                       rtc {
+                                               marvell,88pm860x-vrtc = <1>;
+                                       };
+                                       touch {
+                                               marvell,88pm860x-gpadc-prebias = <1>;
+                                               marvell,88pm860x-gpadc-slot-cycle = <1>;
+                                               marvell,88pm860x-tsi-prebias = <6>;
+                                               marvell,88pm860x-pen-prebias = <16>;
+                                               marvell,88pm860x-pen-prechg = <2>;
+                                               marvell,88pm860x-resistor-X = <300>;
+                                       };
+                                       backlights {
+                                               backlight-0 {
+                                                       marvell,88pm860x-iset = <4>;
+                                                       marvell,88pm860x-pwm = <3>;
+                                               };
+                                               backlight-2 {
+                                               };
+                                       };
+                                       leds {
+                                               led0-red {
+                                                       marvell,88pm860x-iset = <12>;
+                                               };
+                                               led0-green {
+                                                       marvell,88pm860x-iset = <12>;
+                                               };
+                                               led0-blue {
+                                                       marvell,88pm860x-iset = <12>;
+                                               };
+                                       };
+                               };
                        };
                        rtc: rtc@d4010000 {
                                status = "okay";
index a3be44d86bcd5a3f9bd4938364bb76cedf85c5ac..825aaca33034d9f23e63ade23bd611a38c3a6f9d 100644 (file)
 
                        twsi1: i2c@d4011000 {
                                compatible = "mrvl,mmp-twsi";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                reg = <0xd4011000 0x1000>;
                                interrupts = <7>;
                                mrvl,i2c-fast-mode;
 
                        twsi2: i2c@d4037000 {
                                compatible = "mrvl,mmp-twsi";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                reg = <0xd4037000 0x1000>;
                                interrupts = <54>;
                                status = "disabled";
diff --git a/arch/arm/boot/dts/xenvm-4.2.dts b/arch/arm/boot/dts/xenvm-4.2.dts
new file mode 100644 (file)
index 0000000..ec3f952
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Xen Virtual Machine for unprivileged guests
+ *
+ * Based on ARM Ltd. Versatile Express CoreTile Express (single CPU)
+ * Cortex-A15 MPCore (V2P-CA15)
+ *
+ */
+
+/dts-v1/;
+
+/ {
+       model = "XENVM-4.2";
+       compatible = "xen,xenvm-4.2", "xen,xenvm";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen {
+               /* this field is going to be adjusted by the hypervisor */
+               bootargs = "console=hvc0 root=/dev/xvda";
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <0>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               /* this field is going to be adjusted by the hypervisor */
+               reg = <0 0x80000000 0 0x08000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0 0x2c001000 0 0x1000>,
+                     <0 0x2c002000 0 0x100>;
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+       };
+
+       hypervisor {
+               compatible = "xen,xen-4.2", "xen,xen";
+               /* this field is going to be adjusted by the hypervisor */
+               reg = <0 0xb0000000 0 0x20000>;
+               /* this field is going to be adjusted by the hypervisor */
+               interrupts = <1 15 0xf08>;
+       };
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+       };
+};
index 565132d02105c7566f76800558d9008b46182b8d..66aa7a6db884c14668be9f20a6d27166c85a8c1f 100644 (file)
@@ -40,7 +40,6 @@ CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -177,6 +176,9 @@ CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_MXS_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
index aeb3af541fedc8bf1b31f25a712426bb38ed5af8..74eee0c78f283dddb7ef36e37d95baf849860870 100644 (file)
@@ -1,5 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=19
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -15,9 +17,19 @@ CONFIG_MACH_MV88F6281GTW_GE=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_ESATA_SHEEVAPLUG=y
 CONFIG_MACH_GURUPLUG=y
-CONFIG_MACH_DOCKSTAR=y
+CONFIG_MACH_DREAMPLUG_DT=y
+CONFIG_MACH_ICONNECT_DT=y
+CONFIG_MACH_DLINK_KIRKWOOD_DT=y
+CONFIG_MACH_IB62X0_DT=y
+CONFIG_MACH_TS219_DT=y
+CONFIG_MACH_DOCKSTAR_DT=y
+CONFIG_MACH_GOFLEXNET_DT=y
+CONFIG_MACH_LSXL_DT=y
+CONFIG_MACH_IOMEGA_IX2_200_DT=y
+CONFIG_MACH_KM_KIRKWOOD_DT=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
+CONFIG_MACH_DOCKSTAR=y
 CONFIG_MACH_OPENRD_BASE=y
 CONFIG_MACH_OPENRD_CLIENT=y
 CONFIG_MACH_OPENRD_ULTIMATE=y
@@ -29,8 +41,6 @@ CONFIG_MACH_NET2BIG_V2=y
 CONFIG_MACH_NET5BIG_V2=y
 CONFIG_MACH_T5325=y
 # CONFIG_CPU_FEROCEON_OLD_ID is not set
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
@@ -47,13 +57,11 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_NET_DSA=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_NET_PKTGEN=m
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -69,7 +77,6 @@ CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -78,22 +85,21 @@ CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_NET_PCI=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_MV643XX_ETH=y
-# CONFIG_NETDEV_10000 is not set
+CONFIG_MARVELL_PHY=y
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
@@ -103,7 +109,8 @@ CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
@@ -119,10 +126,8 @@ CONFIG_HID_TOPSEED=y
 CONFIG_HID_THRUSTMASTER=y
 CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_PRINTER=m
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -148,7 +153,6 @@ CONFIG_MV_XOR=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
@@ -158,7 +162,6 @@ CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_850=y
@@ -171,11 +174,8 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_PCBC=m
index e42a0e3d4c3a6466375e492eaf5759c0cc0bff30..92386b20bd096cf27a9410c29e8e8822d2554964 100644 (file)
@@ -133,7 +133,6 @@ CONFIG_SND_DEBUG_VERBOSE=y
 # CONFIG_SND_ARM is not set
 # CONFIG_SND_SPI is not set
 CONFIG_SND_SOC=y
-# CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
@@ -149,6 +148,7 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_PCA9532=y
 CONFIG_LEDS_PCA9532_GPIO=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -161,10 +161,13 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_LPC32XX=y
 CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
 CONFIG_STAGING=y
 CONFIG_LPC32XX_ADC=y
-CONFIG_MAX517=y
 CONFIG_IIO=y
+CONFIG_MAX517=y
+CONFIG_PWM=y
+CONFIG_PWM_LPC32XX=y
 CONFIG_EXT2_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
index f513acedc10a57ee67099773019e2c4c54ab252e..53382b6c8bb43345ae75b8f1ea39ab509d161980 100644 (file)
@@ -1,13 +1,14 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_KERNEL_LZMA=y
+CONFIG_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
-# CONFIG_BLOCK is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_SHMOBILE=y
 CONFIG_ARCH_R8A7779=y
 CONFIG_MACH_MARZEN=y
@@ -21,7 +22,6 @@ CONFIG_ARM_ERRATA_458693=y
 CONFIG_ARM_ERRATA_460075=y
 CONFIG_ARM_ERRATA_743622=y
 CONFIG_ARM_ERRATA_754322=y
-CONFIG_NO_HZ=y
 CONFIG_SMP=y
 # CONFIG_ARM_CPU_TOPOLOGY is not set
 CONFIG_AEABI=y
@@ -29,13 +29,16 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
+CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -71,16 +74,18 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_SSB=y
-# CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_REDUCED=y
index 2e86b31c33cf1cab3afe20243c085e26104e574a..7bcf850eddcd7f2c843c0b297eda1f24125cc03c 100644 (file)
@@ -21,6 +21,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
index 36d60dda310c70844c22260a3f1b90ab9800a1df..048aaca60814c99d2143edee134d128ba9264a08 100644 (file)
@@ -53,6 +53,9 @@ CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_M25P80
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_NETDEVICES=y
@@ -82,13 +85,13 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MXS=y
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=m
+CONFIG_SPI_MXS=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
 CONFIG_DISPLAY_SUPPORT=m
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
@@ -103,14 +106,45 @@ CONFIG_SND_SOC_I2C_AND_SPI=y
 CONFIG_SND_SOC_SGTL5000=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_MXS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_MMC=y
 CONFIG_MMC_MXS=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_RTC_DRV_STMP=y
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
+CONFIG_STAGING=y
+CONFIG_MXS_LRADC=y
+CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_COMMON_CLK_DEBUG=y
+CONFIG_IIO=y
+CONFIG_PWM=y
+CONFIG_PWM_MXS=y
 CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_FSCACHE=m
index ba6a515086b56b7b05deecc1ea91cb6d61fd6275..3a186d653dac2e7e5feaebe745ab15e1c65c0fea 100644 (file)
@@ -9,11 +9,14 @@ CONFIG_ARCH_S3C64XX=y
 CONFIG_S3C_BOOT_ERROR_RESET=y
 CONFIG_MACH_SMDK6400=y
 CONFIG_MACH_ANW6410=y
+CONFIG_MACH_MINI6410=y
+CONFIG_MACH_REAL6410=y
 CONFIG_MACH_SMDK6410=y
 CONFIG_MACH_NCP=y
 CONFIG_MACH_HMT=y
 CONFIG_MACH_SMARTQ5=y
 CONFIG_MACH_SMARTQ7=y
+CONFIG_MACH_WLF_CRAGG_6410=y
 CONFIG_CPU_32v6K=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/linuxrc initrd=0x51000000,6M ramdisk_size=6144"
index 0d6bb738c6de370e6d13462ca398c262749aa50f..e2184f6c20b3d3e6eeb9338794fb37375a7d9709 100644 (file)
@@ -24,11 +24,11 @@ CONFIG_EFI_PARTITION=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_TEGRA=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
-CONFIG_MACH_HARMONY=y
-CONFIG_MACH_PAZ00=y
-CONFIG_MACH_TRIMSLICE=y
+CONFIG_TEGRA_PCI=y
+CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -67,7 +67,18 @@ CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_TUNNEL=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
-# CONFIG_WIRELESS is not set
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=m
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
@@ -87,7 +98,8 @@ CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
-# CONFIG_WLAN is not set
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
@@ -105,25 +117,31 @@ CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
 CONFIG_SPI_TEGRA=y
-CONFIG_GPIO_TPS65910=y
+CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_TPS6586X=y
+CONFIG_GPIO_TPS65910=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_MFD_TPS65910=y
+CONFIG_MFD_MAX8907=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8907=y
 CONFIG_REGULATOR_TPS62360=y
 CONFIG_REGULATOR_TPS6586X=y
 CONFIG_REGULATOR_TPS65910=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
 # CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_PCI is not set
 # CONFIG_SND_ARM is not set
 # CONFIG_SND_SPI is not set
 # CONFIG_SND_USB is not set
@@ -136,13 +154,25 @@ CONFIG_SND_SOC_TEGRA_ALC5632=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_TPS65910=y
 CONFIG_RTC_DRV_EM3027=y
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_DMADEVICES=y
@@ -154,10 +184,14 @@ CONFIG_SENSORS_AK8975=y
 CONFIG_MFD_NVEC=y
 CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
+CONFIG_NVEC_POWER=y
+CONFIG_NVEC_PAZ00=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_MEMORY=y
 CONFIG_IIO=y
+CONFIG_PWM=y
+CONFIG_PWM_TEGRA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -170,6 +204,7 @@ CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
@@ -188,8 +223,6 @@ CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_TEGRA_AES=y
diff --git a/arch/arm/include/asm/hypervisor.h b/arch/arm/include/asm/hypervisor.h
new file mode 100644 (file)
index 0000000..b90d9e5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_ARM_HYPERVISOR_H
+#define _ASM_ARM_HYPERVISOR_H
+
+#include <asm/xen/hypervisor.h>
+
+#endif
diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h
new file mode 100644 (file)
index 0000000..63479ee
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __ASM_SYNC_BITOPS_H__
+#define __ASM_SYNC_BITOPS_H__
+
+#include <asm/bitops.h>
+#include <asm/system.h>
+
+/* sync_bitops functions are equivalent to the SMP implementation of the
+ * original functions, independently from CONFIG_SMP being defined.
+ *
+ * We need them because _set_bit etc are not SMP safe if !CONFIG_SMP. But
+ * under Xen you might be communicating with a completely external entity
+ * who might be on another CPU (e.g. two uniprocessor guests communicating
+ * via event channels and grant tables). So we need a variant of the bit
+ * ops which are SMP safe even on a UP kernel.
+ */
+
+#define sync_set_bit(nr, p)            _set_bit(nr, p)
+#define sync_clear_bit(nr, p)          _clear_bit(nr, p)
+#define sync_change_bit(nr, p)         _change_bit(nr, p)
+#define sync_test_and_set_bit(nr, p)   _test_and_set_bit(nr, p)
+#define sync_test_and_clear_bit(nr, p) _test_and_clear_bit(nr, p)
+#define sync_test_and_change_bit(nr, p)        _test_and_change_bit(nr, p)
+#define sync_test_bit(nr, addr)                test_bit(nr, addr)
+#define sync_cmpxchg                   cmpxchg
+
+
+#endif
diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h
new file mode 100644 (file)
index 0000000..94b4e90
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_ARM_XEN_EVENTS_H
+#define _ASM_ARM_XEN_EVENTS_H
+
+#include <asm/ptrace.h>
+
+enum ipi_vector {
+       XEN_PLACEHOLDER_VECTOR,
+
+       /* Xen IPIs go here */
+       XEN_NR_IPIS,
+};
+
+static inline int xen_irqs_disabled(struct pt_regs *regs)
+{
+       return raw_irqs_disabled_flags(regs->ARM_cpsr);
+}
+
+#endif /* _ASM_ARM_XEN_EVENTS_H */
diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
new file mode 100644 (file)
index 0000000..8a82325
--- /dev/null
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 _ASM_ARM_XEN_HYPERCALL_H
+#define _ASM_ARM_XEN_HYPERCALL_H
+
+#include <xen/interface/xen.h>
+
+long privcmd_call(unsigned call, unsigned long a1,
+               unsigned long a2, unsigned long a3,
+               unsigned long a4, unsigned long a5);
+int HYPERVISOR_xen_version(int cmd, void *arg);
+int HYPERVISOR_console_io(int cmd, int count, char *str);
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+int HYPERVISOR_sched_op(int cmd, void *arg);
+int HYPERVISOR_event_channel_op(int cmd, void *arg);
+unsigned long HYPERVISOR_hvm_op(int op, void *arg);
+int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
+int HYPERVISOR_physdev_op(int cmd, void *arg);
+
+static inline void
+MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
+                       unsigned int new_val, unsigned long flags)
+{
+       BUG();
+}
+
+static inline void
+MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
+                int count, int *success_count, domid_t domid)
+{
+       BUG();
+}
+
+static inline int
+HYPERVISOR_multicall(void *call_list, int nr_calls)
+{
+       BUG();
+}
+#endif /* _ASM_ARM_XEN_HYPERCALL_H */
diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h
new file mode 100644 (file)
index 0000000..d7ab99a
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _ASM_ARM_XEN_HYPERVISOR_H
+#define _ASM_ARM_XEN_HYPERVISOR_H
+
+extern struct shared_info *HYPERVISOR_shared_info;
+extern struct start_info *xen_start_info;
+
+/* Lazy mode for batching updates / context switch */
+enum paravirt_lazy_mode {
+       PARAVIRT_LAZY_NONE,
+       PARAVIRT_LAZY_MMU,
+       PARAVIRT_LAZY_CPU,
+};
+
+static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
+{
+       return PARAVIRT_LAZY_NONE;
+}
+
+#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
new file mode 100644 (file)
index 0000000..ae05e56
--- /dev/null
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * Guest OS interface to ARM Xen.
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ */
+
+#ifndef _ASM_ARM_XEN_INTERFACE_H
+#define _ASM_ARM_XEN_INTERFACE_H
+
+#include <linux/types.h>
+
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+
+#define __DEFINE_GUEST_HANDLE(name, type) \
+       typedef struct { union { type *p; uint64_aligned_t q; }; }  \
+        __guest_handle_ ## name
+
+#define DEFINE_GUEST_HANDLE_STRUCT(name) \
+       __DEFINE_GUEST_HANDLE(name, struct name)
+#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
+#define GUEST_HANDLE(name)        __guest_handle_ ## name
+
+#define set_xen_guest_handle(hnd, val)                 \
+       do {                                            \
+               if (sizeof(hnd) == 8)                   \
+                       *(uint64_t *)&(hnd) = 0;        \
+               (hnd).p = val;                          \
+       } while (0)
+
+#ifndef __ASSEMBLY__
+/* Explicitly size integers that represent pfns in the interface with
+ * Xen so that we can have one ABI that works for 32 and 64 bit guests. */
+typedef uint64_t xen_pfn_t;
+typedef uint64_t xen_ulong_t;
+/* Guest handles for primitive C types. */
+__DEFINE_GUEST_HANDLE(uchar, unsigned char);
+__DEFINE_GUEST_HANDLE(uint,  unsigned int);
+__DEFINE_GUEST_HANDLE(ulong, unsigned long);
+DEFINE_GUEST_HANDLE(char);
+DEFINE_GUEST_HANDLE(int);
+DEFINE_GUEST_HANDLE(long);
+DEFINE_GUEST_HANDLE(void);
+DEFINE_GUEST_HANDLE(uint64_t);
+DEFINE_GUEST_HANDLE(uint32_t);
+DEFINE_GUEST_HANDLE(xen_pfn_t);
+
+/* Maximum number of virtual CPUs in multi-processor guests. */
+#define MAX_VIRT_CPUS 1
+
+struct arch_vcpu_info { };
+struct arch_shared_info { };
+
+/* TODO: Move pvclock definitions some place arch independent */
+struct pvclock_vcpu_time_info {
+       u32   version;
+       u32   pad0;
+       u64   tsc_timestamp;
+       u64   system_time;
+       u32   tsc_to_system_mul;
+       s8    tsc_shift;
+       u8    flags;
+       u8    pad[2];
+} __attribute__((__packed__)); /* 32 bytes */
+
+/* It is OK to have a 12 bytes struct with no padding because it is packed */
+struct pvclock_wall_clock {
+       u32   version;
+       u32   sec;
+       u32   nsec;
+} __attribute__((__packed__));
+#endif
+
+#endif /* _ASM_ARM_XEN_INTERFACE_H */
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
new file mode 100644 (file)
index 0000000..1742023
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef _ASM_ARM_XEN_PAGE_H
+#define _ASM_ARM_XEN_PAGE_H
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/pfn.h>
+#include <linux/types.h>
+
+#include <xen/interface/grant_table.h>
+
+#define pfn_to_mfn(pfn)                        (pfn)
+#define phys_to_machine_mapping_valid  (1)
+#define mfn_to_pfn(mfn)                        (mfn)
+#define mfn_to_virt(m)                 (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#define pte_mfn            pte_pfn
+#define mfn_pte            pfn_pte
+
+/* Xen machine address */
+typedef struct xmaddr {
+       phys_addr_t maddr;
+} xmaddr_t;
+
+/* Xen pseudo-physical address */
+typedef struct xpaddr {
+       phys_addr_t paddr;
+} xpaddr_t;
+
+#define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
+#define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
+
+static inline xmaddr_t phys_to_machine(xpaddr_t phys)
+{
+       unsigned offset = phys.paddr & ~PAGE_MASK;
+       return XMADDR(PFN_PHYS(pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
+}
+
+static inline xpaddr_t machine_to_phys(xmaddr_t machine)
+{
+       unsigned offset = machine.maddr & ~PAGE_MASK;
+       return XPADDR(PFN_PHYS(mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
+}
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)     (phys_to_machine(XPADDR(__pa(v))))
+#define virt_to_pfn(v)          (PFN_DOWN(__pa(v)))
+#define virt_to_mfn(v)         (pfn_to_mfn(virt_to_pfn(v)))
+#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr)
+{
+       /* TODO: assuming it is mapped in the kernel 1:1 */
+       return virt_to_machine(vaddr);
+}
+
+/* TODO: this shouldn't be here but it is because the frontend drivers
+ * are using it (its rolled in headers) even though we won't hit the code path.
+ * So for right now just punt with this.
+ */
+static inline pte_t *lookup_address(unsigned long address, unsigned int *level)
+{
+       BUG();
+       return NULL;
+}
+
+static inline int m2p_add_override(unsigned long mfn, struct page *page,
+               struct gnttab_map_grant_ref *kmap_op)
+{
+       return 0;
+}
+
+static inline int m2p_remove_override(struct page *page, bool clear_pte)
+{
+       return 0;
+}
+
+static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG();
+       return false;
+}
+#endif /* _ASM_ARM_XEN_PAGE_H */
index 188c82971ebd069ac890f90726660e8181e6848b..33361505c0cd70cc3171f64ec4d5306670b2cd4b 100644 (file)
@@ -625,7 +625,7 @@ fail:
        return 0;
 }
 
-static struct clk *const standard_pmc_clocks[] __initdata = {
+static struct clk *const standard_pmc_clocks[] __initconst = {
        /* four primary clocks */
        &clk32k,
        &main_clk,
index ac4e003ad86336e61cb4774a0934f437bbfdfaca..be3099733b1fb2ab6eb857998cb4a2838a49ff70 100644 (file)
@@ -88,7 +88,7 @@ static struct davinci_mmc_config mmc_config = {
        .version        = MMC_CTLR_VERSION_1,
 };
 
-static const short sdio1_pins[] __initdata = {
+static const short sdio1_pins[] __initconst = {
        TNETV107X_SDIO1_CLK_1,          TNETV107X_SDIO1_CMD_1,
        TNETV107X_SDIO1_DATA0_1,        TNETV107X_SDIO1_DATA1_1,
        TNETV107X_SDIO1_DATA2_1,        TNETV107X_SDIO1_DATA3_1,
@@ -96,12 +96,12 @@ static const short sdio1_pins[] __initdata = {
        -1
 };
 
-static const short uart1_pins[] __initdata = {
+static const short uart1_pins[] __initconst = {
        TNETV107X_UART1_RD,             TNETV107X_UART1_TD,
        -1
 };
 
-static const short ssp_pins[] __initdata = {
+static const short ssp_pins[] __initconst = {
        TNETV107X_SSP0_0, TNETV107X_SSP0_1, TNETV107X_SSP0_2,
        TNETV107X_SSP1_0, TNETV107X_SSP1_1, TNETV107X_SSP1_2,
        TNETV107X_SSP1_3, -1
index deee5c2da7546b987be46b596b00bef4bbf04d1f..510648e0394b80d4f6186f93ae4516f7624d7dbb 100644 (file)
@@ -838,7 +838,7 @@ static const struct mux_config da830_pins[] = {
 #endif
 };
 
-const short da830_emif25_pins[] __initdata = {
+const short da830_emif25_pins[] __initconst = {
        DA830_EMA_D_0, DA830_EMA_D_1, DA830_EMA_D_2, DA830_EMA_D_3,
        DA830_EMA_D_4, DA830_EMA_D_5, DA830_EMA_D_6, DA830_EMA_D_7,
        DA830_EMA_D_8, DA830_EMA_D_9, DA830_EMA_D_10, DA830_EMA_D_11,
@@ -853,19 +853,19 @@ const short da830_emif25_pins[] __initdata = {
        -1
 };
 
-const short da830_spi0_pins[] __initdata = {
+const short da830_spi0_pins[] __initconst = {
        DA830_SPI0_SOMI_0, DA830_SPI0_SIMO_0, DA830_SPI0_CLK, DA830_NSPI0_ENA,
        DA830_NSPI0_SCS_0,
        -1
 };
 
-const short da830_spi1_pins[] __initdata = {
+const short da830_spi1_pins[] __initconst = {
        DA830_SPI1_SOMI_0, DA830_SPI1_SIMO_0, DA830_SPI1_CLK, DA830_NSPI1_ENA,
        DA830_NSPI1_SCS_0,
        -1
 };
 
-const short da830_mmc_sd_pins[] __initdata = {
+const short da830_mmc_sd_pins[] __initconst = {
        DA830_MMCSD_DAT_0, DA830_MMCSD_DAT_1, DA830_MMCSD_DAT_2,
        DA830_MMCSD_DAT_3, DA830_MMCSD_DAT_4, DA830_MMCSD_DAT_5,
        DA830_MMCSD_DAT_6, DA830_MMCSD_DAT_7, DA830_MMCSD_CLK,
@@ -873,32 +873,32 @@ const short da830_mmc_sd_pins[] __initdata = {
        -1
 };
 
-const short da830_uart0_pins[] __initdata = {
+const short da830_uart0_pins[] __initconst = {
        DA830_NUART0_CTS, DA830_NUART0_RTS, DA830_UART0_RXD, DA830_UART0_TXD,
        -1
 };
 
-const short da830_uart1_pins[] __initdata = {
+const short da830_uart1_pins[] __initconst = {
        DA830_UART1_RXD, DA830_UART1_TXD,
        -1
 };
 
-const short da830_uart2_pins[] __initdata = {
+const short da830_uart2_pins[] __initconst = {
        DA830_UART2_RXD, DA830_UART2_TXD,
        -1
 };
 
-const short da830_usb20_pins[] __initdata = {
+const short da830_usb20_pins[] __initconst = {
        DA830_USB0_DRVVBUS, DA830_USB_REFCLKIN,
        -1
 };
 
-const short da830_usb11_pins[] __initdata = {
+const short da830_usb11_pins[] __initconst = {
        DA830_USB_REFCLKIN,
        -1
 };
 
-const short da830_uhpi_pins[] __initdata = {
+const short da830_uhpi_pins[] __initconst = {
        DA830_UHPI_HD_0, DA830_UHPI_HD_1, DA830_UHPI_HD_2, DA830_UHPI_HD_3,
        DA830_UHPI_HD_4, DA830_UHPI_HD_5, DA830_UHPI_HD_6, DA830_UHPI_HD_7,
        DA830_UHPI_HD_8, DA830_UHPI_HD_9, DA830_UHPI_HD_10, DA830_UHPI_HD_11,
@@ -909,14 +909,14 @@ const short da830_uhpi_pins[] __initdata = {
        -1
 };
 
-const short da830_cpgmac_pins[] __initdata = {
+const short da830_cpgmac_pins[] __initconst = {
        DA830_RMII_TXD_0, DA830_RMII_TXD_1, DA830_RMII_TXEN, DA830_RMII_CRS_DV,
        DA830_RMII_RXD_0, DA830_RMII_RXD_1, DA830_RMII_RXER, DA830_MDIO_CLK,
        DA830_MDIO_D,
        -1
 };
 
-const short da830_emif3c_pins[] __initdata = {
+const short da830_emif3c_pins[] __initconst = {
        DA830_EMB_SDCKE, DA830_EMB_CLK_GLUE, DA830_EMB_CLK, DA830_NEMB_CS_0,
        DA830_NEMB_CAS, DA830_NEMB_RAS, DA830_NEMB_WE, DA830_EMB_BA_1,
        DA830_EMB_BA_0, DA830_EMB_A_0, DA830_EMB_A_1, DA830_EMB_A_2,
@@ -935,7 +935,7 @@ const short da830_emif3c_pins[] __initdata = {
        -1
 };
 
-const short da830_mcasp0_pins[] __initdata = {
+const short da830_mcasp0_pins[] __initconst = {
        DA830_AHCLKX0, DA830_ACLKX0, DA830_AFSX0,
        DA830_AHCLKR0, DA830_ACLKR0, DA830_AFSR0, DA830_AMUTE0,
        DA830_AXR0_0, DA830_AXR0_1, DA830_AXR0_2, DA830_AXR0_3,
@@ -945,7 +945,7 @@ const short da830_mcasp0_pins[] __initdata = {
        -1
 };
 
-const short da830_mcasp1_pins[] __initdata = {
+const short da830_mcasp1_pins[] __initconst = {
        DA830_AHCLKX1, DA830_ACLKX1, DA830_AFSX1,
        DA830_AHCLKR1, DA830_ACLKR1, DA830_AFSR1, DA830_AMUTE1,
        DA830_AXR1_0, DA830_AXR1_1, DA830_AXR1_2, DA830_AXR1_3,
@@ -954,24 +954,24 @@ const short da830_mcasp1_pins[] __initdata = {
        -1
 };
 
-const short da830_mcasp2_pins[] __initdata = {
+const short da830_mcasp2_pins[] __initconst = {
        DA830_AHCLKX2, DA830_ACLKX2, DA830_AFSX2,
        DA830_AHCLKR2, DA830_ACLKR2, DA830_AFSR2, DA830_AMUTE2,
        DA830_AXR2_0, DA830_AXR2_1, DA830_AXR2_2, DA830_AXR2_3,
        -1
 };
 
-const short da830_i2c0_pins[] __initdata = {
+const short da830_i2c0_pins[] __initconst = {
        DA830_I2C0_SDA, DA830_I2C0_SCL,
        -1
 };
 
-const short da830_i2c1_pins[] __initdata = {
+const short da830_i2c1_pins[] __initconst = {
        DA830_I2C1_SCL, DA830_I2C1_SDA,
        -1
 };
 
-const short da830_lcdcntl_pins[] __initdata = {
+const short da830_lcdcntl_pins[] __initconst = {
        DA830_LCD_D_0, DA830_LCD_D_1, DA830_LCD_D_2, DA830_LCD_D_3,
        DA830_LCD_D_4, DA830_LCD_D_5, DA830_LCD_D_6, DA830_LCD_D_7,
        DA830_LCD_D_8, DA830_LCD_D_9, DA830_LCD_D_10, DA830_LCD_D_11,
@@ -981,34 +981,34 @@ const short da830_lcdcntl_pins[] __initdata = {
        -1
 };
 
-const short da830_pwm_pins[] __initdata = {
+const short da830_pwm_pins[] __initconst = {
        DA830_ECAP0_APWM0, DA830_ECAP1_APWM1, DA830_EPWM0B, DA830_EPWM0A,
        DA830_EPWMSYNCI, DA830_EPWMSYNC0, DA830_ECAP2_APWM2, DA830_EHRPWMGLUETZ,
        DA830_EPWM2B, DA830_EPWM2A, DA830_EPWM1B, DA830_EPWM1A,
        -1
 };
 
-const short da830_ecap0_pins[] __initdata = {
+const short da830_ecap0_pins[] __initconst = {
        DA830_ECAP0_APWM0,
        -1
 };
 
-const short da830_ecap1_pins[] __initdata = {
+const short da830_ecap1_pins[] __initconst = {
        DA830_ECAP1_APWM1,
        -1
 };
 
-const short da830_ecap2_pins[] __initdata = {
+const short da830_ecap2_pins[] __initconst = {
        DA830_ECAP2_APWM2,
        -1
 };
 
-const short da830_eqep0_pins[] __initdata = {
+const short da830_eqep0_pins[] __initconst = {
        DA830_EQEP0I, DA830_EQEP0S, DA830_EQEP0A, DA830_EQEP0B,
        -1
 };
 
-const short da830_eqep1_pins[] __initdata = {
+const short da830_eqep1_pins[] __initconst = {
        DA830_EQEP1I, DA830_EQEP1S, DA830_EQEP1A, DA830_EQEP1B,
        -1
 };
index b44dc844e15e0c2ce8c404486c75494749dfec51..6676dee7104ec6abdbc1b31fa82ae801a119a492 100644 (file)
@@ -576,17 +576,17 @@ static const struct mux_config da850_pins[] = {
 #endif
 };
 
-const short da850_i2c0_pins[] __initdata = {
+const short da850_i2c0_pins[] __initconst = {
        DA850_I2C0_SDA, DA850_I2C0_SCL,
        -1
 };
 
-const short da850_i2c1_pins[] __initdata = {
+const short da850_i2c1_pins[] __initconst = {
        DA850_I2C1_SCL, DA850_I2C1_SDA,
        -1
 };
 
-const short da850_lcdcntl_pins[] __initdata = {
+const short da850_lcdcntl_pins[] __initconst = {
        DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3,
        DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7,
        DA850_LCD_D_8, DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11,
index dd937c526a458980eac6ac03b352f8f548f070dd..00154e74ce6b11d892840315ddedd9366b73e86d 100644 (file)
@@ -15,6 +15,13 @@ config MACH_CM_A510
          Say 'Y' here if you want your kernel to support the
          CompuLab CM-A510 Board.
 
+config MACH_DOVE_DT
+       bool "Marvell Dove Flattened Device Tree"
+       select USE_OF
+       help
+         Say 'Y' here if you want your kernel to support the
+         Marvell Dove using flattened device tree.
+
 endmenu
 
 endif
index fa0f018560600b0e4a3d335240e805db4b482d7c..5e683baf96cffc53e0ac8410be6e7505d4fb8557 100644 (file)
@@ -1,4 +1,4 @@
-obj-y                          += common.o addr-map.o irq.o pcie.o mpp.o
-
+obj-y                          += common.o addr-map.o irq.o mpp.o
+obj-$(CONFIG_PCI)              += pcie.o
 obj-$(CONFIG_MACH_DOVE_DB)     += dove-db-setup.o
 obj-$(CONFIG_MACH_CM_A510)     += cm-a510.o
index 950ad9533d19ea88ab7c9651f80cfcb9c0a04887..b37bef1d5ffad9828f6734eb9a50262327ea950d 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/clk-provider.h>
 #include <linux/ata_platform.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/timex.h>
@@ -24,6 +26,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/pci.h>
 #include <mach/dove.h>
+#include <mach/pm.h>
 #include <mach/bridge-regs.h>
 #include <asm/mach/arch.h>
 #include <linux/irq.h>
 #include <plat/addr-map.h>
 #include "common.h"
 
-static int get_tclk(void);
-
 /*****************************************************************************
  * I/O Address Mapping
  ****************************************************************************/
 static struct map_desc dove_io_desc[] __initdata = {
        {
-               .virtual        = DOVE_SB_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) DOVE_SB_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(DOVE_SB_REGS_PHYS_BASE),
                .length         = DOVE_SB_REGS_SIZE,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = DOVE_NB_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) DOVE_NB_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(DOVE_NB_REGS_PHYS_BASE),
                .length         = DOVE_NB_REGS_SIZE,
                .type           = MT_DEVICE,
@@ -60,14 +61,69 @@ void __init dove_map_io(void)
 /*****************************************************************************
  * CLK tree
  ****************************************************************************/
+static int dove_tclk;
+
+static DEFINE_SPINLOCK(gating_lock);
 static struct clk *tclk;
 
-static void __init clk_init(void)
+static struct clk __init *dove_register_gate(const char *name,
+                                            const char *parent, u8 bit_idx)
 {
-       tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
-                                      get_tclk());
+       return clk_register_gate(NULL, name, parent, 0,
+                                (void __iomem *)CLOCK_GATING_CONTROL,
+                                bit_idx, 0, &gating_lock);
+}
+
+static void __init dove_clk_init(void)
+{
+       struct clk *usb0, *usb1, *sata, *pex0, *pex1, *sdio0, *sdio1;
+       struct clk *nand, *camera, *i2s0, *i2s1, *crypto, *ac97, *pdma;
+       struct clk *xor0, *xor1, *ge, *gephy;
 
-       orion_clkdev_init(tclk);
+       tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
+                                      dove_tclk);
+
+       usb0 = dove_register_gate("usb0", "tclk", CLOCK_GATING_BIT_USB0);
+       usb1 = dove_register_gate("usb1", "tclk", CLOCK_GATING_BIT_USB1);
+       sata = dove_register_gate("sata", "tclk", CLOCK_GATING_BIT_SATA);
+       pex0 = dove_register_gate("pex0", "tclk", CLOCK_GATING_BIT_PCIE0);
+       pex1 = dove_register_gate("pex1", "tclk", CLOCK_GATING_BIT_PCIE1);
+       sdio0 = dove_register_gate("sdio0", "tclk", CLOCK_GATING_BIT_SDIO0);
+       sdio1 = dove_register_gate("sdio1", "tclk", CLOCK_GATING_BIT_SDIO1);
+       nand = dove_register_gate("nand", "tclk", CLOCK_GATING_BIT_NAND);
+       camera = dove_register_gate("camera", "tclk", CLOCK_GATING_BIT_CAMERA);
+       i2s0 = dove_register_gate("i2s0", "tclk", CLOCK_GATING_BIT_I2S0);
+       i2s1 = dove_register_gate("i2s1", "tclk", CLOCK_GATING_BIT_I2S1);
+       crypto = dove_register_gate("crypto", "tclk", CLOCK_GATING_BIT_CRYPTO);
+       ac97 = dove_register_gate("ac97", "tclk", CLOCK_GATING_BIT_AC97);
+       pdma = dove_register_gate("pdma", "tclk", CLOCK_GATING_BIT_PDMA);
+       xor0 = dove_register_gate("xor0", "tclk", CLOCK_GATING_BIT_XOR0);
+       xor1 = dove_register_gate("xor1", "tclk", CLOCK_GATING_BIT_XOR1);
+       gephy = dove_register_gate("gephy", "tclk", CLOCK_GATING_BIT_GIGA_PHY);
+       ge = dove_register_gate("ge", "gephy", CLOCK_GATING_BIT_GBE);
+
+       orion_clkdev_add(NULL, "orion_spi.0", tclk);
+       orion_clkdev_add(NULL, "orion_spi.1", tclk);
+       orion_clkdev_add(NULL, "orion_wdt", tclk);
+       orion_clkdev_add(NULL, "mv64xxx_i2c.0", tclk);
+
+       orion_clkdev_add(NULL, "orion-ehci.0", usb0);
+       orion_clkdev_add(NULL, "orion-ehci.1", usb1);
+       orion_clkdev_add(NULL, "mv643xx_eth.0", ge);
+       orion_clkdev_add("0", "sata_mv.0", sata);
+       orion_clkdev_add("0", "pcie", pex0);
+       orion_clkdev_add("1", "pcie", pex1);
+       orion_clkdev_add(NULL, "sdhci-dove.0", sdio0);
+       orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
+       orion_clkdev_add(NULL, "orion_nand", nand);
+       orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
+       orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0);
+       orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1);
+       orion_clkdev_add(NULL, "mv_crypto", crypto);
+       orion_clkdev_add(NULL, "dove-ac97", ac97);
+       orion_clkdev_add(NULL, "dove-pdma", pdma);
+       orion_clkdev_add(NULL, "mv_xor_shared.0", xor0);
+       orion_clkdev_add(NULL, "mv_xor_shared.1", xor1);
 }
 
 /*****************************************************************************
@@ -178,22 +234,31 @@ void __init dove_init_early(void)
        orion_time_set_base(TIMER_VIRT_BASE);
 }
 
-static int get_tclk(void)
+static int __init dove_find_tclk(void)
 {
-       /* use DOVE_RESET_SAMPLE_HI/LO to detect tclk */
        return 166666667;
 }
 
 static void __init dove_timer_init(void)
 {
+       dove_tclk = dove_find_tclk();
        orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
-                       IRQ_DOVE_BRIDGE, get_tclk());
+                       IRQ_DOVE_BRIDGE, dove_tclk);
 }
 
 struct sys_timer dove_timer = {
        .init = dove_timer_init,
 };
 
+/*****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+ ****************************************************************************/
+void __init dove_crypto_init(void)
+{
+       orion_crypto_init(DOVE_CRYPT_PHYS_BASE, DOVE_CESA_PHYS_BASE,
+                         DOVE_CESA_SIZE, IRQ_DOVE_CRYPTO);
+}
+
 /*****************************************************************************
  * XOR 0
  ****************************************************************************/
@@ -275,8 +340,8 @@ void __init dove_sdio1_init(void)
 
 void __init dove_init(void)
 {
-       printk(KERN_INFO "Dove 88AP510 SoC, ");
-       printk(KERN_INFO "TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
+       pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
+               (dove_tclk + 499999) / 1000000);
 
 #ifdef CONFIG_CACHE_TAUROS2
        tauros2_init(0);
@@ -284,7 +349,7 @@ void __init dove_init(void)
        dove_setup_cpu_mbus();
 
        /* Setup root of clk tree */
-       clk_init();
+       dove_clk_init();
 
        /* internal devices that every board has */
        dove_rtc_init();
@@ -307,3 +372,67 @@ void dove_restart(char mode, const char *cmd)
        while (1)
                ;
 }
+
+#if defined(CONFIG_MACH_DOVE_DT)
+/*
+ * Auxdata required until real OF clock provider
+ */
+struct of_dev_auxdata dove_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
+       OF_DEV_AUXDATA("marvell,orion-spi", 0xf1014600, "orion_spi.1", NULL),
+       OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
+       OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
+                      NULL),
+       OF_DEV_AUXDATA("marvell,orion-sata", 0xf10a0000, "sata_mv.0", NULL),
+       OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1092000, "sdhci-dove.0", NULL),
+       OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1090000, "sdhci-dove.1", NULL),
+       {},
+};
+
+static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
+       .phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
+};
+
+static void __init dove_dt_init(void)
+{
+       pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
+               (dove_tclk + 499999) / 1000000);
+
+#ifdef CONFIG_CACHE_TAUROS2
+       tauros2_init();
+#endif
+       dove_setup_cpu_mbus();
+
+       /* Setup root of clk tree */
+       dove_clk_init();
+
+       /* Internal devices not ported to DT yet */
+       dove_rtc_init();
+       dove_xor0_init();
+       dove_xor1_init();
+
+       dove_ge00_init(&dove_dt_ge00_data);
+       dove_ehci0_init();
+       dove_ehci1_init();
+       dove_pcie_init(1, 1);
+       dove_crypto_init();
+
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            dove_auxdata_lookup, NULL);
+}
+
+static const char * const dove_dt_board_compat[] = {
+       "marvell,dove",
+       NULL
+};
+
+DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
+       .map_io         = dove_map_io,
+       .init_early     = dove_init_early,
+       .init_irq       = orion_dt_init_irq,
+       .timer          = &dove_timer,
+       .init_machine   = dove_dt_init,
+       .restart        = dove_restart,
+       .dt_compat      = dove_dt_board_compat,
+MACHINE_END
+#endif
index 6432a3ba864b7058ecc81dcc3df5b90f897bb4d5..1a233404b7355990fd1158da7e598e8f3125c541 100644 (file)
@@ -26,7 +26,11 @@ void dove_init_irq(void);
 void dove_setup_cpu_mbus(void);
 void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data);
 void dove_sata_init(struct mv_sata_platform_data *sata_data);
+#ifdef CONFIG_PCI
 void dove_pcie_init(int init_port0, int init_port1);
+#else
+static inline void dove_pcie_init(int init_port0, int init_port1) { }
+#endif
 void dove_ehci0_init(void);
 void dove_ehci1_init(void);
 void dove_uart0_init(void);
index f953bb54aa9d31d590791d97aaaf770aaaecfd93..99f259e8cf33133b73f2b9712746cf7ade80fcbb 100644 (file)
 
 #include <mach/dove.h>
 
-#define CPU_CONFIG             (BRIDGE_VIRT_BASE | 0x0000)
+#define CPU_CONFIG             (BRIDGE_VIRT_BASE + 0x0000)
 
-#define CPU_CONTROL            (BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL            (BRIDGE_VIRT_BASE + 0x0104)
 #define  CPU_CTRL_PCIE0_LINK   0x00000001
 #define  CPU_RESET             0x00000002
 #define  CPU_CTRL_PCIE1_LINK   0x00000008
 
-#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE + 0x0108)
 #define  SOFT_RESET_OUT_EN     0x00000004
 
-#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE + 0x010c)
 #define  SOFT_RESET            0x00000001
 
 #define  BRIDGE_INT_TIMER1_CLR (~0x0004)
 
-#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_LOW_OFF      0x0000
 #define IRQ_MASK_LOW_OFF       0x0004
 #define FIQ_MASK_LOW_OFF       0x0008
@@ -47,9 +47,9 @@
 #define ENDPOINT_MASK_HIGH     (IRQ_VIRT_BASE + ENDPOINT_MASK_HIGH_OFF)
 #define PCIE_INTERRUPT_MASK    (IRQ_VIRT_BASE + PCIE_INTERRUPT_MASK_OFF)
 
-#define POWER_MANAGEMENT       (BRIDGE_VIRT_BASE | 0x011c)
+#define POWER_MANAGEMENT       (BRIDGE_VIRT_BASE + 0x011c)
 
-#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE         (BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE         (BRIDGE_PHYS_BASE + 0x0300)
 
 #endif
index c91e3004a47bc01f60f470be1d38904b94c13ca6..661725e3115a5d37433aabb93cbf0be37a5049a8 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #define DOVE_CESA_PHYS_BASE            0xc8000000
-#define DOVE_CESA_VIRT_BASE            0xfdb00000
+#define DOVE_CESA_VIRT_BASE            IOMEM(0xfdb00000)
 #define DOVE_CESA_SIZE                 SZ_1M
 
 #define DOVE_PCIE0_MEM_PHYS_BASE       0xe0000000
 #define DOVE_BOOTROM_SIZE              SZ_128M
 
 #define DOVE_SCRATCHPAD_PHYS_BASE      0xf0000000
-#define DOVE_SCRATCHPAD_VIRT_BASE      0xfdd00000
+#define DOVE_SCRATCHPAD_VIRT_BASE      IOMEM(0xfdd00000)
 #define DOVE_SCRATCHPAD_SIZE           SZ_1M
 
 #define DOVE_SB_REGS_PHYS_BASE         0xf1000000
-#define DOVE_SB_REGS_VIRT_BASE         0xfde00000
+#define DOVE_SB_REGS_VIRT_BASE         IOMEM(0xfde00000)
 #define DOVE_SB_REGS_SIZE              SZ_8M
 
 #define DOVE_NB_REGS_PHYS_BASE         0xf1800000
-#define DOVE_NB_REGS_VIRT_BASE         0xfe600000
+#define DOVE_NB_REGS_VIRT_BASE         IOMEM(0xfe600000)
 #define DOVE_NB_REGS_SIZE              SZ_8M
 
 #define DOVE_PCIE0_IO_PHYS_BASE                0xf2000000
  */
 
 /* SPI, I2C, UART */
-#define DOVE_I2C_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0x11000)
-#define DOVE_UART0_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x12000)
-#define DOVE_UART0_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x12000)
-#define DOVE_UART1_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x12100)
-#define DOVE_UART1_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x12100)
-#define DOVE_UART2_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x12200)
-#define DOVE_UART2_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x12200)
-#define DOVE_UART3_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x12300)
-#define DOVE_UART3_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x12300)
-#define DOVE_SPI0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x10600)
-#define DOVE_SPI1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x14600)
+#define DOVE_I2C_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE + 0x11000)
+#define DOVE_UART0_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x12000)
+#define DOVE_UART0_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x12000)
+#define DOVE_UART1_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x12100)
+#define DOVE_UART1_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x12100)
+#define DOVE_UART2_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x12200)
+#define DOVE_UART2_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x12200)
+#define DOVE_UART3_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x12300)
+#define DOVE_UART3_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x12300)
+#define DOVE_SPI0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x10600)
+#define DOVE_SPI1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x14600)
 
 /* North-South Bridge */
-#define BRIDGE_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE | 0x20000)
-#define BRIDGE_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE | 0x20000)
+#define BRIDGE_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE + 0x20000)
+#define BRIDGE_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE + 0x20000)
 
 /* Cryptographic Engine */
-#define DOVE_CRYPT_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x30000)
+#define DOVE_CRYPT_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x30000)
 
 /* PCIe 0 */
-#define DOVE_PCIE0_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x40000)
+#define DOVE_PCIE0_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x40000)
 
 /* USB */
-#define DOVE_USB0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x50000)
-#define DOVE_USB1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x51000)
+#define DOVE_USB0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x50000)
+#define DOVE_USB1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x51000)
 
 /* XOR 0 Engine */
-#define DOVE_XOR0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x60800)
-#define DOVE_XOR0_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0x60800)
-#define DOVE_XOR0_HIGH_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE | 0x60A00)
-#define DOVE_XOR0_HIGH_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE | 0x60A00)
+#define DOVE_XOR0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x60800)
+#define DOVE_XOR0_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0x60800)
+#define DOVE_XOR0_HIGH_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE + 0x60A00)
+#define DOVE_XOR0_HIGH_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE + 0x60A00)
 
 /* XOR 1 Engine */
-#define DOVE_XOR1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x60900)
-#define DOVE_XOR1_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0x60900)
-#define DOVE_XOR1_HIGH_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE | 0x60B00)
-#define DOVE_XOR1_HIGH_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE | 0x60B00)
+#define DOVE_XOR1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x60900)
+#define DOVE_XOR1_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0x60900)
+#define DOVE_XOR1_HIGH_PHYS_BASE       (DOVE_SB_REGS_PHYS_BASE + 0x60B00)
+#define DOVE_XOR1_HIGH_VIRT_BASE       (DOVE_SB_REGS_VIRT_BASE + 0x60B00)
 
 /* Gigabit Ethernet */
-#define DOVE_GE00_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0x70000)
+#define DOVE_GE00_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0x70000)
 
 /* PCIe 1 */
-#define DOVE_PCIE1_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE | 0x80000)
+#define DOVE_PCIE1_VIRT_BASE   (DOVE_SB_REGS_VIRT_BASE + 0x80000)
 
 /* CAFE */
-#define DOVE_SDIO0_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x92000)
-#define DOVE_SDIO1_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE | 0x90000)
-#define DOVE_CAM_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0x94000)
-#define DOVE_CAFE_WIN_PHYS_BASE        (DOVE_SB_REGS_PHYS_BASE | 0x98000)
+#define DOVE_SDIO0_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x92000)
+#define DOVE_SDIO1_PHYS_BASE   (DOVE_SB_REGS_PHYS_BASE + 0x90000)
+#define DOVE_CAM_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE + 0x94000)
+#define DOVE_CAFE_WIN_PHYS_BASE        (DOVE_SB_REGS_PHYS_BASE + 0x98000)
 
 /* SATA */
-#define DOVE_SATA_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0xa0000)
+#define DOVE_SATA_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0xa0000)
 
 /* I2S/SPDIF */
-#define DOVE_AUD0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0xb0000)
-#define DOVE_AUD1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0xb4000)
+#define DOVE_AUD0_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0xb0000)
+#define DOVE_AUD1_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0xb4000)
 
 /* NAND Flash Controller */
-#define DOVE_NFC_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0xc0000)
+#define DOVE_NFC_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE + 0xc0000)
 
 /* MPP, GPIO, Reset Sampling */
-#define DOVE_MPP_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_MPP_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE + 0xd0200)
 #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
-#define DOVE_RESET_SAMPLE_LO   (DOVE_MPP_VIRT_BASE | 0x014)
-#define DOVE_RESET_SAMPLE_HI   (DOVE_MPP_VIRT_BASE | 0x018)
-#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
-#define DOVE_GPIO_HI_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0420)
-#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
-#define DOVE_MPP_GENERAL_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define DOVE_RESET_SAMPLE_LO   (DOVE_MPP_VIRT_BASE + 0x014)
+#define DOVE_RESET_SAMPLE_HI   (DOVE_MPP_VIRT_BASE + 0x018)
+#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0400)
+#define DOVE_GPIO_HI_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0xd0420)
+#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0xe8400)
+#define DOVE_MPP_GENERAL_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE + 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN       (1 << 1)
 #define  DOVE_NAND_GPIO_EN             (1 << 0)
 #define DOVE_MPP_CTRL4_VIRT_BASE       (DOVE_GPIO_LO_VIRT_BASE + 0x40)
 #define  DOVE_SD0_GPIO_SEL             (1 << 0)
 
 /* Power Management */
-#define DOVE_PMU_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xd0000)
+#define DOVE_PMU_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE + 0xd0000)
 #define DOVE_PMU_SIG_CTRL      (DOVE_PMU_VIRT_BASE + 0x802c)
 
 /* Real Time Clock */
-#define DOVE_RTC_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0xd8500)
+#define DOVE_RTC_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE + 0xd8500)
 
 /* AC97 */
-#define DOVE_AC97_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0xe0000)
-#define DOVE_AC97_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe0000)
+#define DOVE_AC97_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0xe0000)
+#define DOVE_AC97_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0xe0000)
 
 /* Peripheral DMA */
-#define DOVE_PDMA_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE | 0xe4000)
-#define DOVE_PDMA_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe4000)
+#define DOVE_PDMA_PHYS_BASE    (DOVE_SB_REGS_PHYS_BASE + 0xe4000)
+#define DOVE_PDMA_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0xe4000)
 
-#define DOVE_GLOBAL_CONFIG_1   (DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define DOVE_GLOBAL_CONFIG_1   (DOVE_SB_REGS_VIRT_BASE + 0xe802C)
 #define  DOVE_TWSI_ENABLE_OPTION1      (1 << 7)
-#define DOVE_GLOBAL_CONFIG_2   (DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define DOVE_GLOBAL_CONFIG_2   (DOVE_SB_REGS_VIRT_BASE + 0xe8030)
 #define  DOVE_TWSI_ENABLE_OPTION2      (1 << 20)
 #define  DOVE_TWSI_ENABLE_OPTION3      (1 << 21)
 #define  DOVE_TWSI_OPTION3_GPIO                (1 << 22)
-#define DOVE_SSP_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE | 0xec000)
-#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define DOVE_SSP_PHYS_BASE     (DOVE_SB_REGS_PHYS_BASE + 0xec000)
+#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE + 0xe8034)
 #define  DOVE_SSP_ON_AU1               (1 << 0)
 #define  DOVE_SSP_CLOCK_ENABLE         (1 << 1)
 #define  DOVE_SSP_BPB_CLOCK_SRC_SSP    (1 << 11)
 /* Memory Controller */
-#define DOVE_MC_VIRT_BASE      (DOVE_NB_REGS_VIRT_BASE | 0x00000)
+#define DOVE_MC_VIRT_BASE      (DOVE_NB_REGS_VIRT_BASE + 0x00000)
 
 /* LCD Controller */
-#define DOVE_LCD_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE | 0x10000)
-#define DOVE_LCD1_PHYS_BASE    (DOVE_NB_REGS_PHYS_BASE | 0x20000)
-#define DOVE_LCD2_PHYS_BASE    (DOVE_NB_REGS_PHYS_BASE | 0x10000)
-#define DOVE_LCD_DCON_PHYS_BASE        (DOVE_NB_REGS_PHYS_BASE | 0x30000)
+#define DOVE_LCD_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE + 0x10000)
+#define DOVE_LCD1_PHYS_BASE    (DOVE_NB_REGS_PHYS_BASE + 0x20000)
+#define DOVE_LCD2_PHYS_BASE    (DOVE_NB_REGS_PHYS_BASE + 0x10000)
+#define DOVE_LCD_DCON_PHYS_BASE        (DOVE_NB_REGS_PHYS_BASE + 0x30000)
 
 /* Graphic Engine */
-#define DOVE_GPU_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE | 0x40000)
+#define DOVE_GPU_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE + 0x40000)
 
 /* Video Engine */
-#define DOVE_VPU_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE | 0x400000)
+#define DOVE_VPU_PHYS_BASE     (DOVE_NB_REGS_PHYS_BASE + 0x400000)
 
 #endif
index 3ad9f946a9e8f8ef416aee2c4e8f5f29eb757c8c..7bcd0dfce4b1ce51b8b0e1bfc96ebcf9a0167d12 100644 (file)
 #include <mach/irqs.h>
 
 #define CLOCK_GATING_CONTROL   (DOVE_PMU_VIRT_BASE + 0x38)
-#define  CLOCK_GATING_USB0_MASK                (1 << 0)
-#define  CLOCK_GATING_USB1_MASK                (1 << 1)
-#define  CLOCK_GATING_GBE_MASK         (1 << 2)
-#define  CLOCK_GATING_SATA_MASK                (1 << 3)
-#define  CLOCK_GATING_PCIE0_MASK       (1 << 4)
-#define  CLOCK_GATING_PCIE1_MASK       (1 << 5)
-#define  CLOCK_GATING_SDIO0_MASK       (1 << 8)
-#define  CLOCK_GATING_SDIO1_MASK       (1 << 9)
-#define  CLOCK_GATING_NAND_MASK                (1 << 10)
-#define  CLOCK_GATING_CAMERA_MASK      (1 << 11)
-#define  CLOCK_GATING_I2S0_MASK                (1 << 12)
-#define  CLOCK_GATING_I2S1_MASK                (1 << 13)
-#define  CLOCK_GATING_CRYPTO_MASK      (1 << 15)
-#define  CLOCK_GATING_AC97_MASK                (1 << 21)
-#define  CLOCK_GATING_PDMA_MASK                (1 << 22)
-#define  CLOCK_GATING_XOR0_MASK                (1 << 23)
-#define  CLOCK_GATING_XOR1_MASK                (1 << 24)
-#define  CLOCK_GATING_GIGA_PHY_MASK    (1 << 30)
+#define  CLOCK_GATING_BIT_USB0         0
+#define  CLOCK_GATING_BIT_USB1         1
+#define  CLOCK_GATING_BIT_GBE          2
+#define  CLOCK_GATING_BIT_SATA         3
+#define  CLOCK_GATING_BIT_PCIE0                4
+#define  CLOCK_GATING_BIT_PCIE1                5
+#define  CLOCK_GATING_BIT_SDIO0                8
+#define  CLOCK_GATING_BIT_SDIO1                9
+#define  CLOCK_GATING_BIT_NAND         10
+#define  CLOCK_GATING_BIT_CAMERA       11
+#define  CLOCK_GATING_BIT_I2S0         12
+#define  CLOCK_GATING_BIT_I2S1         13
+#define  CLOCK_GATING_BIT_CRYPTO       15
+#define  CLOCK_GATING_BIT_AC97         21
+#define  CLOCK_GATING_BIT_PDMA         22
+#define  CLOCK_GATING_BIT_XOR0         23
+#define  CLOCK_GATING_BIT_XOR1         24
+#define  CLOCK_GATING_BIT_GIGA_PHY     30
+#define  CLOCK_GATING_USB0_MASK                (1 << CLOCK_GATING_BIT_USB0)
+#define  CLOCK_GATING_USB1_MASK                (1 << CLOCK_GATING_BIT_USB1)
+#define  CLOCK_GATING_GBE_MASK         (1 << CLOCK_GATING_BIT_GBE)
+#define  CLOCK_GATING_SATA_MASK                (1 << CLOCK_GATING_BIT_SATA)
+#define  CLOCK_GATING_PCIE0_MASK       (1 << CLOCK_GATING_BIT_PCIE0)
+#define  CLOCK_GATING_PCIE1_MASK       (1 << CLOCK_GATING_BIT_PCIE1)
+#define  CLOCK_GATING_SDIO0_MASK       (1 << CLOCK_GATING_BIT_SDIO0)
+#define  CLOCK_GATING_SDIO1_MASK       (1 << CLOCK_GATING_BIT_SDIO1)
+#define  CLOCK_GATING_NAND_MASK                (1 << CLOCK_GATING_BIT_NAND)
+#define  CLOCK_GATING_CAMERA_MASK      (1 << CLOCK_GATING_BIT_CAMERA)
+#define  CLOCK_GATING_I2S0_MASK                (1 << CLOCK_GATING_BIT_I2S0)
+#define  CLOCK_GATING_I2S1_MASK                (1 << CLOCK_GATING_BIT_I2S1)
+#define  CLOCK_GATING_CRYPTO_MASK      (1 << CLOCK_GATING_BIT_CRYPTO)
+#define  CLOCK_GATING_AC97_MASK                (1 << CLOCK_GATING_BIT_AC97)
+#define  CLOCK_GATING_PDMA_MASK                (1 << CLOCK_GATING_BIT_PDMA)
+#define  CLOCK_GATING_XOR0_MASK                (1 << CLOCK_GATING_BIT_XOR0)
+#define  CLOCK_GATING_XOR1_MASK                (1 << CLOCK_GATING_BIT_XOR1)
+#define  CLOCK_GATING_GIGA_PHY_MASK    (1 << CLOCK_GATING_BIT_GIGA_PHY)
 
 #define PMU_INTERRUPT_CAUSE    (DOVE_PMU_VIRT_BASE + 0x50)
 #define PMU_INTERRUPT_MASK     (DOVE_PMU_VIRT_BASE + 0x54)
index 186357f3b4db54e2b4141f149ec1920628b35d66..087711524e8a29d1e0d2de7c919bd705976ddbd7 100644 (file)
@@ -100,19 +100,19 @@ void __init dove_init_irq(void)
 {
        int i;
 
-       orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-       orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
+       orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+       orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
 
        /*
         * Initialize gpiolib for GPIOs 0-71.
         */
-       orion_gpio_init(NULL, 0, 32, (void __iomem *)DOVE_GPIO_LO_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START, gpio0_irqs);
 
-       orion_gpio_init(NULL, 32, 32, (void __iomem *)DOVE_GPIO_HI_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START + 32, gpio1_irqs);
 
-       orion_gpio_init(NULL, 64, 8, (void __iomem *)DOVE_GPIO2_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
                        IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
 
        /*
index 355332d502cb538cdec53e796bdf70b993f381ae..bb15b26041cb7d6bd13a5ca4d5532cb66632e2cc 100644 (file)
@@ -182,18 +182,18 @@ static struct hw_pci dove_pci __initdata = {
        .map_irq        = dove_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int index, unsigned long base)
+static void __init add_pcie_port(int index, void __iomem *base)
 {
        printk(KERN_INFO "Dove PCIe port %d: ", index);
 
-       if (orion_pcie_link_up((void __iomem *)base)) {
+       if (orion_pcie_link_up(base)) {
                struct pcie_port *pp = &pcie_port[num_pcie_ports++];
 
                printk(KERN_INFO "link up\n");
 
                pp->index = index;
                pp->root_bus_nr = -1;
-               pp->base = (void __iomem *)base;
+               pp->base = base;
                spin_lock_init(&pp->conf_lock);
                memset(&pp->res, 0, sizeof(pp->res));
        } else {
index 3a2042fb97127d780fd2ecda6a1fa78a67523d21..32197c117afe0b3c80656325ddafbdfdfc4f3e68 100644 (file)
@@ -758,7 +758,7 @@ config SOC_IMX6Q
        select HAVE_IMX_MMDC
        select HAVE_IMX_SRC
        select HAVE_SMP
-       select MFD_ANATOP
+       select MFD_SYSCON
        select PINCTRL
        select PINCTRL_IMX6Q
 
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 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 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 36979d3dfe341aa2cc3d41d0b1742bd1ef261a1a..47c91f7185d2fb7cdef048388e5cf82620e68a87 100644 (file)
@@ -23,8 +23,9 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
+#include <linux/regmap.h>
 #include <linux/micrel_phy.h>
-#include <linux/mfd/anatop.h>
+#include <linux/mfd/syscon.h>
 #include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -118,20 +119,7 @@ static void __init imx6q_sabrelite_init(void)
 
 static void __init imx6q_usb_init(void)
 {
-       struct device_node *np;
-       struct platform_device *pdev = NULL;
-       struct anatop *adata = NULL;
-
-       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-       if (np)
-               pdev = of_find_device_by_node(np);
-       if (pdev)
-               adata = platform_get_drvdata(pdev);
-       if (!adata) {
-               if (np)
-                       of_node_put(np);
-               return;
-       }
+       struct regmap *anatop;
 
 #define HW_ANADIG_USB1_CHRG_DETECT             0x000001b0
 #define HW_ANADIG_USB2_CHRG_DETECT             0x00000210
@@ -139,20 +127,21 @@ static void __init imx6q_usb_init(void)
 #define BM_ANADIG_USB_CHRG_DETECT_EN_B         0x00100000
 #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B   0x00080000
 
-       /*
-        * The external charger detector needs to be disabled,
-        * or the signal at DP will be poor
-        */
-       anatop_write_reg(adata, HW_ANADIG_USB1_CHRG_DETECT,
-                       BM_ANADIG_USB_CHRG_DETECT_EN_B
-                       | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-                       ~0);
-       anatop_write_reg(adata, HW_ANADIG_USB2_CHRG_DETECT,
-                       BM_ANADIG_USB_CHRG_DETECT_EN_B |
-                       BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-                       ~0);
-
-       of_node_put(np);
+       anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
+       if (!IS_ERR(anatop)) {
+               /*
+                * The external charger detector needs to be disabled,
+                * or the signal at DP will be poor
+                */
+               regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT,
+                               BM_ANADIG_USB_CHRG_DETECT_EN_B
+                               | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+               regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT,
+                               BM_ANADIG_USB_CHRG_DETECT_EN_B |
+                               BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+       } else {
+               pr_warn("failed to find fsl,imx6q-anatop regmap\n");
+       }
 }
 
 static void __init imx6q_init_machine(void)
index ca5c15a4e626fa4bc9fdb9ead0c4b45da4be3cec..50bca5032b7e0c00bf0871bb52b75ec7309911d7 100644 (file)
@@ -94,6 +94,13 @@ config MACH_TS219_DT
          or MV6282. If you have the wrong one, the buttons will not
          work.
 
+config MACH_DOCKSTAR_DT
+       bool "Seagate FreeAgent Dockstar (Flattened Device Tree)"
+       select ARCH_KIRKWOOD_DT
+       help
+         Say 'Y' here if you want your kernel to support the
+         Seagate FreeAgent Dockstar (Flattened Device Tree).
+
 config MACH_GOFLEXNET_DT
        bool "Seagate GoFlex Net (Flattened Device Tree)"
        select ARCH_KIRKWOOD_DT
@@ -109,6 +116,20 @@ config MACH_LSXL_DT
          Buffalo Linkstation LS-XHL & LS-CHLv2 devices, using
          Flattened Device Tree.
 
+config MACH_IOMEGA_IX2_200_DT
+       bool "Iomega StorCenter ix2-200 (Flattened Device Tree)"
+       select ARCH_KIRKWOOD_DT
+       help
+         Say 'Y' here if you want your kernel to support the
+         Iomega StorCenter ix2-200 (Flattened Device Tree).
+
+config MACH_KM_KIRKWOOD_DT
+       bool "Keymile Kirkwood Reference Design (Flattened Device Tree)"
+       select ARCH_KIRKWOOD_DT
+       help
+         Say 'Y' here if you want your kernel to support the
+         Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
+
 config MACH_TS219
        bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
        help
index 055c85a1cc46336de83e79797b5d66db1b1682b1..294779f892d9fc3f1f46a48981f9c2ede88e1ae8 100644 (file)
@@ -26,5 +26,8 @@ obj-$(CONFIG_MACH_ICONNECT_DT)                += board-iconnect.o
 obj-$(CONFIG_MACH_DLINK_KIRKWOOD_DT)   += board-dnskw.o
 obj-$(CONFIG_MACH_IB62X0_DT)           += board-ib62x0.o
 obj-$(CONFIG_MACH_TS219_DT)            += board-ts219.o tsx1x-common.o
+obj-$(CONFIG_MACH_DOCKSTAR_DT)         += board-dockstar.o
 obj-$(CONFIG_MACH_GOFLEXNET_DT)                += board-goflexnet.o
 obj-$(CONFIG_MACH_LSXL_DT)             += board-lsxl.o
+obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT)   += board-iomega_ix2_200.o
+obj-$(CONFIG_MACH_KM_KIRKWOOD_DT)      += board-km_kirkwood.o
index e9a7180863d9916cfe5e5439cbd712cb1ef1e0d4..8f0d162a1e1d146de8bd2793d6188cdbaac63429 100644 (file)
@@ -86,5 +86,6 @@ void __init kirkwood_setup_cpu_mbus(void)
        /*
         * Setup MBUS dram target info.
         */
-       orion_setup_cpu_mbus_target(&addr_map_cfg, DDR_WINDOW_CPU_BASE);
+       orion_setup_cpu_mbus_target(&addr_map_cfg,
+                                   (void __iomem *) DDR_WINDOW_CPU_BASE);
 }
index 4ab35065a144919ac264bd972f125dbf657120de..43d16d6714b82bed34aeff6ffa9240032b5560a2 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
-#include <linux/of.h>
 #include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio-fan.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
 #include "common.h"
 #include "mpp.h"
 
@@ -67,29 +57,6 @@ static unsigned int dnskw_mpp_config[] __initdata = {
        0
 };
 
-/* Fan: ADDA AD045HB-G73 40mm 6000rpm@5v */
-static struct gpio_fan_speed dnskw_fan_speed[] = {
-       {    0,  0 },
-       { 3000,  1 },
-       { 6000,  2 },
-};
-static unsigned dnskw_fan_pins[] = {46, 45};
-
-static struct gpio_fan_platform_data dnskw_fan_data = {
-       .num_ctrl       = ARRAY_SIZE(dnskw_fan_pins),
-       .ctrl           = dnskw_fan_pins,
-       .num_speed      = ARRAY_SIZE(dnskw_fan_speed),
-       .speed          = dnskw_fan_speed,
-};
-
-static struct platform_device dnskw_fan_device = {
-       .name   = "gpio-fan",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &dnskw_fan_data,
-       },
-};
-
 static void dnskw_power_off(void)
 {
        gpio_set_value(36, 1);
@@ -114,8 +81,6 @@ void __init dnskw_init(void)
        kirkwood_ehci_init();
        kirkwood_ge00_init(&dnskw_ge00_data);
 
-       platform_device_register(&dnskw_fan_device);
-
        /* Register power-off GPIO. */
        if (gpio_request(36, "dnskw:power:off") == 0
            && gpio_direction_output(36, 0) == 0)
diff --git a/arch/arm/mach-kirkwood/board-dockstar.c b/arch/arm/mach-kirkwood/board-dockstar.c
new file mode 100644 (file)
index 0000000..f2fbb02
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-kirkwood/board-dockstar.c
+ *
+ * Seagate FreeAgent Dockstar Board Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Copied and modified for Seagate GoFlex Net support by
+ * Joshua Coombs <josh.coombs@gmail.com> based on ArchLinux ARM's
+ * GoFlex kernel patches.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data dockstar_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static unsigned int dockstar_mpp_config[] __initdata = {
+       MPP29_GPIO,     /* USB Power Enable */
+       MPP46_GPIO,     /* LED green */
+       MPP47_GPIO,     /* LED orange */
+       0
+};
+
+void __init dockstar_dt_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_mpp_conf(dockstar_mpp_config);
+
+       if (gpio_request(29, "USB Power Enable") != 0 ||
+           gpio_direction_output(29, 1) != 0)
+               pr_err("can't setup GPIO 29 (USB Power Enable)\n");
+       kirkwood_ehci_init();
+
+       kirkwood_ge00_init(&dockstar_ge00_data);
+}
index e4eb450de301ef5231abfb54b000bef885a4ee2f..70c5a28824093f675880aab0c5c595206ac7e1d6 100644 (file)
@@ -33,6 +33,7 @@ struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
        OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
        OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL),
+       OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1030000, "mv_crypto", NULL),
        {},
 };
 
@@ -60,7 +61,6 @@ static void __init kirkwood_dt_init(void)
        /* internal devices that every board has */
        kirkwood_xor0_init();
        kirkwood_xor1_init();
-       kirkwood_crypto_init();
 
 #ifdef CONFIG_KEXEC
        kexec_reinit = kirkwood_enable_pcie;
@@ -81,12 +81,21 @@ static void __init kirkwood_dt_init(void)
        if (of_machine_is_compatible("qnap,ts219"))
                qnap_dt_ts219_init();
 
+       if (of_machine_is_compatible("seagate,dockstar"))
+               dockstar_dt_init();
+
        if (of_machine_is_compatible("seagate,goflexnet"))
                goflexnet_init();
 
        if (of_machine_is_compatible("buffalo,lsxl"))
                lsxl_init();
 
+       if (of_machine_is_compatible("iom,ix2-200"))
+               iomega_ix2_200_init();
+
+       if (of_machine_is_compatible("keymile,km_kirkwood"))
+               km_kirkwood_init();
+
        of_platform_populate(NULL, kirkwood_dt_match_table,
                             kirkwood_auxdata_lookup, NULL);
 }
@@ -98,8 +107,11 @@ static const char *kirkwood_dt_board_compat[] = {
        "iom,iconnect",
        "raidsonic,ib-nas62x0",
        "qnap,ts219",
+       "seagate,dockstar",
        "seagate,goflexnet",
        "buffalo,lsxl",
+       "iom,ix2-200",
+       "keymile,km_kirkwood",
        NULL
 };
 
index d7a9198ed300fd5c5f97a38b6a7ecd7868ed325f..d084b1e2943ac0bb74704eb69ed9016186b4baeb 100644 (file)
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/mtd/partitions.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
 #include "common.h"
@@ -44,57 +41,12 @@ static unsigned int iconnect_mpp_config[] __initdata = {
        0
 };
 
-static struct mtd_partition iconnect_nand_parts[] = {
-       {
-               .name = "flash",
-               .offset = 0,
-               .size = MTDPART_SIZ_FULL,
-       },
-};
-
-/* yikes... theses are the original input buttons */
-/* but I'm not convinced by the sw event choices  */
-static struct gpio_keys_button iconnect_buttons[] = {
-       {
-               .type           = EV_SW,
-               .code           = SW_LID,
-               .gpio           = 12,
-               .desc           = "Reset Button",
-               .active_low     = 1,
-               .debounce_interval = 100,
-       }, {
-               .type           = EV_SW,
-               .code           = SW_TABLET_MODE,
-               .gpio           = 35,
-               .desc           = "OTB Button",
-               .active_low     = 1,
-               .debounce_interval = 100,
-       },
-};
-
-static struct gpio_keys_platform_data iconnect_button_data = {
-       .buttons        = iconnect_buttons,
-       .nbuttons       = ARRAY_SIZE(iconnect_buttons),
-};
-
-static struct platform_device iconnect_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev        = {
-               .platform_data  = &iconnect_button_data,
-       },
-};
-
 void __init iconnect_init(void)
 {
        kirkwood_mpp_conf(iconnect_mpp_config);
-       kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 25);
 
        kirkwood_ehci_init();
        kirkwood_ge00_init(&iconnect_ge00_data);
-
-       platform_device_register(&iconnect_button_device);
 }
 
 static int __init iconnect_pci_init(void)
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
new file mode 100644 (file)
index 0000000..158fb97
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+ *
+ * Iomega StorCenter ix2-200
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_NONE,
+       .speed          = SPEED_1000,
+       .duplex         = DUPLEX_FULL,
+};
+
+static unsigned int iomega_ix2_200_mpp_config[] __initdata = {
+       MPP12_GPIO,                     /* Reset Button */
+       MPP14_GPIO,                     /* Power Button */
+       MPP15_GPIO,                     /* Backup LED (blue) */
+       MPP16_GPIO,                     /* Power LED (white) */
+       MPP35_GPIO,                     /* OTB Button */
+       MPP36_GPIO,                     /* Rebuild LED (white) */
+       MPP37_GPIO,                     /* Health LED (red) */
+       MPP38_GPIO,                     /* SATA LED brightness control 1 */
+       MPP39_GPIO,                     /* SATA LED brightness control 2 */
+       MPP40_GPIO,                     /* Backup LED brightness control 1 */
+       MPP41_GPIO,                     /* Backup LED brightness control 2 */
+       MPP42_GPIO,                     /* Power LED brightness control 1 */
+       MPP43_GPIO,                     /* Power LED brightness control 2 */
+       MPP44_GPIO,                     /* Health LED brightness control 1 */
+       MPP45_GPIO,                     /* Health LED brightness control 2 */
+       MPP46_GPIO,                     /* Rebuild LED brightness control 1 */
+       MPP47_GPIO,                     /* Rebuild LED brightness control 2 */
+       0
+};
+
+void __init iomega_ix2_200_init(void)
+{
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_mpp_conf(iomega_ix2_200_mpp_config);
+
+       kirkwood_ehci_init();
+
+       kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/board-km_kirkwood.c b/arch/arm/mach-kirkwood/board-km_kirkwood.c
new file mode 100644 (file)
index 0000000..f7d3283
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 2012 KEYMILE AG, CH-3097 Bern
+ * Valentin Longchamp <valentin.longchamp@keymile.com>
+ *
+ * arch/arm/mach-kirkwood/board-km_kirkwood.c
+ *
+ * Keymile km_kirkwood Reference Desing Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data km_kirkwood_ge00_data = {
+       .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
+};
+
+static unsigned int km_kirkwood_mpp_config[] __initdata = {
+       MPP8_GPIO,      /* I2C SDA */
+       MPP9_GPIO,      /* I2C SCL */
+       0
+};
+
+void __init km_kirkwood_init(void)
+{
+       struct clk *sata_clk;
+       /*
+        * Basic setup. Needs to be called early.
+        */
+       kirkwood_mpp_conf(km_kirkwood_mpp_config);
+
+       /*
+        * Our variant of kirkwood (integrated in the Bobcat) hangs on accessing
+        * SATA bits (14-15) of the Clock Gating Control Register. Since these
+        * devices are also not present in this variant, their clocks get
+        * disabled because unused when clk_disable_unused() gets called.
+        * That's why we change the flags to these clocks to CLK_IGNORE_UNUSED
+        */
+       sata_clk = clk_get_sys("sata_mv.0", "0");
+       if (!IS_ERR(sata_clk))
+               sata_clk->flags |= CLK_IGNORE_UNUSED;
+       sata_clk = clk_get_sys("sata_mv.0", "1");
+       if (!IS_ERR(sata_clk))
+               sata_clk->flags |= CLK_IGNORE_UNUSED;
+
+       kirkwood_ehci_init();
+       kirkwood_ge00_init(&km_kirkwood_ge00_data);
+}
index 5c38c94b79a291ef1e220566e2c8e6c10ac410f2..3991077f58a26aa5f3a77c2ff005e7c7838a1edb 100644 (file)
@@ -42,7 +42,7 @@
  ****************************************************************************/
 static struct map_desc kirkwood_io_desc[] __initdata = {
        {
-               .virtual        = KIRKWOOD_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
                .length         = KIRKWOOD_REGS_SIZE,
                .type           = MT_DEVICE,
@@ -205,8 +205,7 @@ static struct clk *tclk;
 
 static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
 {
-       return clk_register_gate(NULL, name, "tclk", 0,
-                                (void __iomem *)CLOCK_GATING_CTRL,
+       return clk_register_gate(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
                                 bit_idx, 0, &gating_lock);
 }
 
@@ -215,8 +214,7 @@ static struct clk __init *kirkwood_register_gate_fn(const char *name,
                                                    void (*fn_en)(void),
                                                    void (*fn_dis)(void))
 {
-       return clk_register_gate_fn(NULL, name, "tclk", 0,
-                                   (void __iomem *)CLOCK_GATING_CTRL,
+       return clk_register_gate_fn(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
                                    bit_idx, 0, &gating_lock, fn_en, fn_dis);
 }
 
index 304dd1abfdcaf8a9d74071550d59b9dd9a8ba2f9..bcffd7ca1ca21d13921c388bdfb19ec3a1a5e21f 100644 (file)
@@ -82,6 +82,12 @@ void ib62x0_init(void);
 static inline void ib62x0_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_DOCKSTAR_DT
+void dockstar_dt_init(void);
+#else
+static inline void dockstar_dt_init(void) {};
+#endif
+
 #ifdef CONFIG_MACH_GOFLEXNET_DT
 void goflexnet_init(void);
 #else
@@ -94,6 +100,18 @@ void lsxl_init(void);
 static inline void lsxl_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_IOMEGA_IX2_200_DT
+void iomega_ix2_200_init(void);
+#else
+static inline void iomega_ix2_200_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_KM_KIRKWOOD_DT
+void km_kirkwood_init(void);
+#else
+static inline void km_kirkwood_init(void) {};
+#endif
+
 /* early init functions not converted to fdt yet */
 char *kirkwood_id(void);
 void kirkwood_l2_init(void);
index a115142f8690bedf3bde2f10ad6f868b400a85dd..5c82b7dce4e2377b7dc84c55c03b5db8aa0c9784 100644 (file)
 
 #include <mach/kirkwood.h>
 
-#define CPU_CONFIG             (BRIDGE_VIRT_BASE | 0x0100)
+#define CPU_CONFIG             (BRIDGE_VIRT_BASE + 0x0100)
 #define CPU_CONFIG_ERROR_PROP  0x00000004
 
-#define CPU_CONTROL            (BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL            (BRIDGE_VIRT_BASE + 0x0104)
 #define CPU_RESET              0x00000002
 
-#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE + 0x0108)
 #define WDT_RESET_OUT_EN       0x00000002
 #define SOFT_RESET_OUT_EN      0x00000004
 
-#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE + 0x010c)
 #define SOFT_RESET             0x00000001
 
-#define BRIDGE_CAUSE           (BRIDGE_VIRT_BASE | 0x0110)
+#define BRIDGE_CAUSE           (BRIDGE_VIRT_BASE + 0x0110)
 #define WDT_INT_REQ            0x0008
 
 #define BRIDGE_INT_TIMER1_CLR  (~0x0004)
 
-#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_LOW_OFF      0x0000
 #define IRQ_MASK_LOW_OFF       0x0004
 #define IRQ_CAUSE_HIGH_OFF     0x0010
 #define IRQ_MASK_HIGH_OFF      0x0014
 
-#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE                (BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE                (BRIDGE_PHYS_BASE + 0x0300)
 
-#define L2_CONFIG_REG          (BRIDGE_VIRT_BASE | 0x0128)
+#define L2_CONFIG_REG          (BRIDGE_VIRT_BASE + 0x0128)
 #define L2_WRITETHROUGH                0x00000010
 
-#define CLOCK_GATING_CTRL      (BRIDGE_VIRT_BASE | 0x11c)
+#define CLOCK_GATING_CTRL      (BRIDGE_VIRT_BASE + 0x11c)
 #define CGC_BIT_GE0            (0)
 #define CGC_BIT_PEX0           (2)
 #define CGC_BIT_USB0           (3)
index af4f0000dcef31adf260e4c1def6365e4158a002..041653a04a9ccd0db3e8b99cbff4da6ea135f96b 100644 (file)
@@ -45,7 +45,7 @@
 #define KIRKWOOD_PCIE_IO_SIZE          SZ_64K
 
 #define KIRKWOOD_REGS_PHYS_BASE                0xf1000000
-#define KIRKWOOD_REGS_VIRT_BASE                0xfed00000
+#define KIRKWOOD_REGS_VIRT_BASE                IOMEM(0xfed00000)
 #define KIRKWOOD_REGS_SIZE             SZ_1M
 
 #define KIRKWOOD_PCIE_MEM_PHYS_BASE    0xe0000000
 /*
  * Register Map
  */
-#define DDR_VIRT_BASE          (KIRKWOOD_REGS_VIRT_BASE | 0x00000)
-#define  DDR_WINDOW_CPU_BASE   (DDR_VIRT_BASE | 0x1500)
-#define DDR_OPERATION_BASE     (DDR_VIRT_BASE | 0x1418)
-
-#define DEV_BUS_PHYS_BASE      (KIRKWOOD_REGS_PHYS_BASE | 0x10000)
-#define DEV_BUS_VIRT_BASE      (KIRKWOOD_REGS_VIRT_BASE | 0x10000)
-#define  SAMPLE_AT_RESET       (DEV_BUS_VIRT_BASE | 0x0030)
-#define  DEVICE_ID             (DEV_BUS_VIRT_BASE | 0x0034)
-#define  GPIO_LOW_VIRT_BASE    (DEV_BUS_VIRT_BASE | 0x0100)
-#define  GPIO_HIGH_VIRT_BASE   (DEV_BUS_VIRT_BASE | 0x0140)
-#define  RTC_PHYS_BASE         (DEV_BUS_PHYS_BASE | 0x0300)
-#define  SPI_PHYS_BASE         (DEV_BUS_PHYS_BASE | 0x0600)
-#define  I2C_PHYS_BASE         (DEV_BUS_PHYS_BASE | 0x1000)
-#define  UART0_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2000)
-#define  UART0_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2000)
-#define  UART1_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2100)
-#define  UART1_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2100)
-
-#define BRIDGE_VIRT_BASE       (KIRKWOOD_REGS_VIRT_BASE | 0x20000)
-#define BRIDGE_PHYS_BASE       (KIRKWOOD_REGS_PHYS_BASE | 0x20000)
-
-#define CRYPTO_PHYS_BASE       (KIRKWOOD_REGS_PHYS_BASE | 0x30000)
-
-#define PCIE_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE | 0x40000)
-#define PCIE_LINK_CTRL         (PCIE_VIRT_BASE | 0x70)
-#define PCIE_STATUS            (PCIE_VIRT_BASE | 0x1a04)
-#define PCIE1_VIRT_BASE                (KIRKWOOD_REGS_VIRT_BASE | 0x44000)
-#define PCIE1_LINK_CTRL                (PCIE1_VIRT_BASE | 0x70)
-#define PCIE1_STATUS           (PCIE1_VIRT_BASE | 0x1a04)
-
-#define USB_PHYS_BASE          (KIRKWOOD_REGS_PHYS_BASE | 0x50000)
-
-#define XOR0_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x60800)
-#define XOR0_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE | 0x60800)
-#define XOR1_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x60900)
-#define XOR1_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE | 0x60900)
-#define XOR0_HIGH_PHYS_BASE    (KIRKWOOD_REGS_PHYS_BASE | 0x60A00)
-#define XOR0_HIGH_VIRT_BASE    (KIRKWOOD_REGS_VIRT_BASE | 0x60A00)
-#define XOR1_HIGH_PHYS_BASE    (KIRKWOOD_REGS_PHYS_BASE | 0x60B00)
-#define XOR1_HIGH_VIRT_BASE    (KIRKWOOD_REGS_VIRT_BASE | 0x60B00)
-
-#define GE00_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x70000)
-#define GE01_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x74000)
-
-#define SATA_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x80000)
-#define SATA_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE | 0x80000)
-#define SATA0_IF_CTRL          (SATA_VIRT_BASE | 0x2050)
-#define SATA0_PHY_MODE_2       (SATA_VIRT_BASE | 0x2330)
-#define SATA1_IF_CTRL          (SATA_VIRT_BASE | 0x4050)
-#define SATA1_PHY_MODE_2       (SATA_VIRT_BASE | 0x4330)
-
-#define SDIO_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
-
-#define AUDIO_PHYS_BASE                (KIRKWOOD_REGS_PHYS_BASE | 0xA0000)
-#define AUDIO_VIRT_BASE                (KIRKWOOD_REGS_VIRT_BASE | 0xA0000)
+#define DDR_VIRT_BASE          (KIRKWOOD_REGS_VIRT_BASE + 0x00000)
+#define  DDR_WINDOW_CPU_BASE   (DDR_VIRT_BASE + 0x1500)
+#define DDR_OPERATION_BASE     (DDR_VIRT_BASE + 0x1418)
+
+#define DEV_BUS_PHYS_BASE      (KIRKWOOD_REGS_PHYS_BASE + 0x10000)
+#define DEV_BUS_VIRT_BASE      (KIRKWOOD_REGS_VIRT_BASE + 0x10000)
+#define  SAMPLE_AT_RESET       (DEV_BUS_VIRT_BASE + 0x0030)
+#define  DEVICE_ID             (DEV_BUS_VIRT_BASE + 0x0034)
+#define  GPIO_LOW_VIRT_BASE    (DEV_BUS_VIRT_BASE + 0x0100)
+#define  GPIO_HIGH_VIRT_BASE   (DEV_BUS_VIRT_BASE + 0x0140)
+#define  RTC_PHYS_BASE         (DEV_BUS_PHYS_BASE + 0x0300)
+#define  SPI_PHYS_BASE         (DEV_BUS_PHYS_BASE + 0x0600)
+#define  I2C_PHYS_BASE         (DEV_BUS_PHYS_BASE + 0x1000)
+#define  UART0_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2000)
+#define  UART0_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2000)
+#define  UART1_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2100)
+#define  UART1_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2100)
+
+#define BRIDGE_VIRT_BASE       (KIRKWOOD_REGS_VIRT_BASE + 0x20000)
+#define BRIDGE_PHYS_BASE       (KIRKWOOD_REGS_PHYS_BASE + 0x20000)
+
+#define CRYPTO_PHYS_BASE       (KIRKWOOD_REGS_PHYS_BASE + 0x30000)
+
+#define PCIE_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE + 0x40000)
+#define PCIE_LINK_CTRL         (PCIE_VIRT_BASE + 0x70)
+#define PCIE_STATUS            (PCIE_VIRT_BASE + 0x1a04)
+#define PCIE1_VIRT_BASE                (KIRKWOOD_REGS_VIRT_BASE + 0x44000)
+#define PCIE1_LINK_CTRL                (PCIE1_VIRT_BASE + 0x70)
+#define PCIE1_STATUS           (PCIE1_VIRT_BASE + 0x1a04)
+
+#define USB_PHYS_BASE          (KIRKWOOD_REGS_PHYS_BASE + 0x50000)
+
+#define XOR0_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x60800)
+#define XOR0_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE + 0x60800)
+#define XOR1_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x60900)
+#define XOR1_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE + 0x60900)
+#define XOR0_HIGH_PHYS_BASE    (KIRKWOOD_REGS_PHYS_BASE + 0x60A00)
+#define XOR0_HIGH_VIRT_BASE    (KIRKWOOD_REGS_VIRT_BASE + 0x60A00)
+#define XOR1_HIGH_PHYS_BASE    (KIRKWOOD_REGS_PHYS_BASE + 0x60B00)
+#define XOR1_HIGH_VIRT_BASE    (KIRKWOOD_REGS_VIRT_BASE + 0x60B00)
+
+#define GE00_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x70000)
+#define GE01_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x74000)
+
+#define SATA_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x80000)
+#define SATA_VIRT_BASE         (KIRKWOOD_REGS_VIRT_BASE + 0x80000)
+#define SATA0_IF_CTRL          (SATA_VIRT_BASE + 0x2050)
+#define SATA0_PHY_MODE_2       (SATA_VIRT_BASE + 0x2330)
+#define SATA1_IF_CTRL          (SATA_VIRT_BASE + 0x4050)
+#define SATA1_PHY_MODE_2       (SATA_VIRT_BASE + 0x4330)
+
+#define SDIO_PHYS_BASE         (KIRKWOOD_REGS_PHYS_BASE + 0x90000)
+
+#define AUDIO_PHYS_BASE                (KIRKWOOD_REGS_PHYS_BASE + 0xA0000)
+#define AUDIO_VIRT_BASE                (KIRKWOOD_REGS_VIRT_BASE + 0xA0000)
 
 /*
  * Supported devices and revisions.
index 20149a7fd2807d3c789af1d923f03a4f1f671338..884703535a0a1d8253dcdf43f53f317b13ae2d10 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
 #include <plat/orion-gpio.h>
 #include <plat/irq.h>
@@ -30,14 +31,14 @@ static int __initdata gpio1_irqs[4] = {
 
 void __init kirkwood_init_irq(void)
 {
-       orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-       orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
+       orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+       orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
 
        /*
         * Initialize gpiolib for GPIOs 0-49.
         */
-       orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_LOW_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 0, 32, GPIO_LOW_VIRT_BASE, 0,
                        IRQ_KIRKWOOD_GPIO_START, gpio0_irqs);
-       orion_gpio_init(NULL, 32, 18, (void __iomem *)GPIO_HIGH_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 32, 18, GPIO_HIGH_VIRT_BASE, 0,
                        IRQ_KIRKWOOD_GPIO_START + 32, gpio1_irqs);
 }
index 532d8acb38f910233e8f525a68ab928dc9961e85..ec544918b12c057b56109c1e688a217bf9ac5750 100644 (file)
@@ -47,8 +47,8 @@ void kirkwood_enable_pcie(void)
 void kirkwood_pcie_id(u32 *dev, u32 *rev)
 {
        kirkwood_enable_pcie();
-       *dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
-       *rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
+       *dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
+       *rev = orion_pcie_rev(PCIE_VIRT_BASE);
 }
 
 struct pcie_port {
@@ -133,7 +133,7 @@ static struct pci_ops pcie_ops = {
 
 static void __init pcie0_ioresources_init(struct pcie_port *pp)
 {
-       pp->base = (void __iomem *)PCIE_VIRT_BASE;
+       pp->base = PCIE_VIRT_BASE;
        pp->irq = IRQ_KIRKWOOD_PCIE;
 
        /*
@@ -147,7 +147,7 @@ static void __init pcie0_ioresources_init(struct pcie_port *pp)
 
 static void __init pcie1_ioresources_init(struct pcie_port *pp)
 {
-       pp->base = (void __iomem *)PCIE1_VIRT_BASE;
+       pp->base = PCIE1_VIRT_BASE;
        pp->irq = IRQ_KIRKWOOD_PCIE1;
 
        /*
@@ -255,11 +255,11 @@ static struct hw_pci kirkwood_pci __initdata = {
        .map_irq        = kirkwood_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int index, unsigned long base)
+static void __init add_pcie_port(int index, void __iomem *base)
 {
        printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
 
-       if (orion_pcie_link_up((void __iomem *)base)) {
+       if (orion_pcie_link_up(base)) {
                printk(KERN_INFO "link up\n");
                pcie_port_map[num_pcie_ports++] = index;
        } else
index 5bbca26804425b0f8858a3cfed59973619fab348..367a9400f53273347481a7713db7a01d1ff327fc 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <linux/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -161,7 +162,7 @@ static int __init ts41x_pci_init(void)
                 * (Marvell 88sx7042/sata_mv) is known to stop working
                 * after a few minutes.
                 */
-               orion_pcie_reset((void __iomem *)PCIE_VIRT_BASE);
+               orion_pcie_reset(PCIE_VIRT_BASE);
 
                kirkwood_pcie_id(&dev, &rev);
                if (dev == MV88F6282_DEV_ID)
index a344a373928b751551eba16881173514163e6d04..2448fcf09eb145dbbf19327cd7b12d56a42cad55 100644 (file)
@@ -37,8 +37,8 @@
 #include "devices.h"
 #include "common.h"
 
-static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
-static const unsigned        qsd8x50_surf_smc91x_gpio __initdata = 156;
+static const resource_size_t qsd8x50_surf_smc91x_base __initconst = 0x70000300;
+static const unsigned        qsd8x50_surf_smc91x_gpio __initconst = 156;
 
 /* Leave smc91x resources empty here, as we'll fill them in
  * at run-time: they vary from board to board, and the true
index 137e479d15a0a48d81410eb60d05e239c7226812..343c435b4176ac6cd323ac556fd5f1ae9f62c0b2 100644 (file)
@@ -48,7 +48,7 @@ static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, i
         * so we don't need to take that into account here.
         */
 
-       return (void __iomem *)((win < 8) ? WIN0_OFF(win) : WIN8_OFF(win));
+       return (win < 8) ? WIN0_OFF(win) : WIN8_OFF(win);
 }
 
 /*
@@ -72,10 +72,10 @@ void __init mv78xx0_setup_cpu_mbus(void)
         */
        if (mv78xx0_core_index() == 0)
                orion_setup_cpu_mbus_target(&addr_map_cfg,
-                                           DDR_WINDOW_CPU0_BASE);
+                                           (void __iomem *) DDR_WINDOW_CPU0_BASE);
        else
                orion_setup_cpu_mbus_target(&addr_map_cfg,
-                                           DDR_WINDOW_CPU1_BASE);
+                                           (void __iomem *) DDR_WINDOW_CPU1_BASE);
 }
 
 void __init mv78xx0_setup_pcie_io_win(int window, u32 base, u32 size,
index a6f3cd21e8c29f3f914604a0553eac0f5a8da195..131cd4883f3db21019c15dc8efc296d61d65a7e6 100644 (file)
@@ -130,12 +130,12 @@ static int get_tclk(void)
  ****************************************************************************/
 static struct map_desc mv78xx0_io_desc[] __initdata = {
        {
-               .virtual        = MV78XX0_CORE_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) MV78XX0_CORE_REGS_VIRT_BASE,
                .pfn            = 0,
                .length         = MV78XX0_CORE_REGS_SIZE,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = MV78XX0_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) MV78XX0_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(MV78XX0_REGS_PHYS_BASE),
                .length         = MV78XX0_REGS_SIZE,
                .type           = MT_DEVICE,
index eb187e0e059bdbb1459b2ae21d69b6050176cba2..5f03484584d4e1aed603b3df15cf23b7cbced792 100644 (file)
 
 #include <mach/mv78xx0.h>
 
-#define CPU_CONTROL            (BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL            (BRIDGE_VIRT_BASE + 0x0104)
 #define L2_WRITETHROUGH                0x00020000
 
-#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK           (BRIDGE_VIRT_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN      0x00000004
 
-#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET      (BRIDGE_VIRT_BASE + 0x010c)
 #define SOFT_RESET             0x00000001
 
 #define BRIDGE_INT_TIMER1_CLR  (~0x0004)
 
-#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE          (BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_ERR_OFF      0x0000
 #define IRQ_CAUSE_LOW_OFF      0x0004
 #define IRQ_CAUSE_HIGH_OFF     0x0008
@@ -30,7 +30,7 @@
 #define IRQ_MASK_LOW_OFF       0x0010
 #define IRQ_MASK_HIGH_OFF      0x0014
 
-#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE                (BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE                (BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE                (BRIDGE_PHYS_BASE + 0x0300)
 
 #endif
index bd03fed1128eeaa93863428062f24d1f1fa2d285..46200a183cf2cbf5f96bd6e62f8eb3a0cc4240f3 100644 (file)
@@ -41,7 +41,7 @@
  */
 #define MV78XX0_CORE0_REGS_PHYS_BASE   0xf1020000
 #define MV78XX0_CORE1_REGS_PHYS_BASE   0xf1024000
-#define MV78XX0_CORE_REGS_VIRT_BASE    0xfe400000
+#define MV78XX0_CORE_REGS_VIRT_BASE    IOMEM(0xfe400000)
 #define MV78XX0_CORE_REGS_PHYS_BASE    0xfe400000
 #define MV78XX0_CORE_REGS_SIZE         SZ_16K
 
@@ -49,7 +49,7 @@
 #define MV78XX0_PCIE_IO_SIZE           SZ_1M
 
 #define MV78XX0_REGS_PHYS_BASE         0xf1000000
-#define MV78XX0_REGS_VIRT_BASE         0xfd000000
+#define MV78XX0_REGS_VIRT_BASE         IOMEM(0xfd000000)
 #define MV78XX0_REGS_SIZE              SZ_1M
 
 #define MV78XX0_PCIE_MEM_PHYS_BASE     0xc0000000
 /*
  * Register Map
  */
-#define DDR_VIRT_BASE          (MV78XX0_REGS_VIRT_BASE | 0x00000)
-#define  DDR_WINDOW_CPU0_BASE  (DDR_VIRT_BASE | 0x1500)
-#define  DDR_WINDOW_CPU1_BASE  (DDR_VIRT_BASE | 0x1570)
-
-#define DEV_BUS_PHYS_BASE      (MV78XX0_REGS_PHYS_BASE | 0x10000)
-#define DEV_BUS_VIRT_BASE      (MV78XX0_REGS_VIRT_BASE | 0x10000)
-#define  SAMPLE_AT_RESET_LOW   (DEV_BUS_VIRT_BASE | 0x0030)
-#define  SAMPLE_AT_RESET_HIGH  (DEV_BUS_VIRT_BASE | 0x0034)
-#define  GPIO_VIRT_BASE                (DEV_BUS_VIRT_BASE | 0x0100)
-#define  I2C_0_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x1000)
-#define  I2C_1_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x1100)
-#define  UART0_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2000)
-#define  UART0_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2000)
-#define  UART1_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2100)
-#define  UART1_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2100)
-#define  UART2_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2200)
-#define  UART2_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2200)
-#define  UART3_PHYS_BASE       (DEV_BUS_PHYS_BASE | 0x2300)
-#define  UART3_VIRT_BASE       (DEV_BUS_VIRT_BASE | 0x2300)
-
-#define GE10_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x30000)
-#define GE11_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x34000)
-
-#define PCIE00_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x40000)
-#define PCIE01_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x44000)
-#define PCIE02_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x48000)
-#define PCIE03_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x4c000)
-
-#define USB0_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x50000)
-#define USB1_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x51000)
-#define USB2_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x52000)
-
-#define GE00_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x70000)
-#define GE01_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0x74000)
-
-#define PCIE10_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x80000)
-#define PCIE11_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x84000)
-#define PCIE12_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x88000)
-#define PCIE13_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE | 0x8c000)
-
-#define SATA_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE | 0xa0000)
+#define DDR_VIRT_BASE          (MV78XX0_REGS_VIRT_BASE + 0x00000)
+#define  DDR_WINDOW_CPU0_BASE  (DDR_VIRT_BASE + 0x1500)
+#define  DDR_WINDOW_CPU1_BASE  (DDR_VIRT_BASE + 0x1570)
+
+#define DEV_BUS_PHYS_BASE      (MV78XX0_REGS_PHYS_BASE + 0x10000)
+#define DEV_BUS_VIRT_BASE      (MV78XX0_REGS_VIRT_BASE + 0x10000)
+#define  SAMPLE_AT_RESET_LOW   (DEV_BUS_VIRT_BASE + 0x0030)
+#define  SAMPLE_AT_RESET_HIGH  (DEV_BUS_VIRT_BASE + 0x0034)
+#define  GPIO_VIRT_BASE                (DEV_BUS_VIRT_BASE + 0x0100)
+#define  I2C_0_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x1000)
+#define  I2C_1_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x1100)
+#define  UART0_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2000)
+#define  UART0_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2000)
+#define  UART1_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2100)
+#define  UART1_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2100)
+#define  UART2_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2200)
+#define  UART2_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2200)
+#define  UART3_PHYS_BASE       (DEV_BUS_PHYS_BASE + 0x2300)
+#define  UART3_VIRT_BASE       (DEV_BUS_VIRT_BASE + 0x2300)
+
+#define GE10_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x30000)
+#define GE11_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x34000)
+
+#define PCIE00_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x40000)
+#define PCIE01_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x44000)
+#define PCIE02_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x48000)
+#define PCIE03_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x4c000)
+
+#define USB0_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x50000)
+#define USB1_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x51000)
+#define USB2_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x52000)
+
+#define GE00_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x70000)
+#define GE01_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x74000)
+
+#define PCIE10_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x80000)
+#define PCIE11_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x84000)
+#define PCIE12_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x88000)
+#define PCIE13_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x8c000)
+
+#define SATA_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0xa0000)
 
 /*
  * Supported devices and revisions.
index 4d720f2aedba878d38e30af4cacbc239b062d7a0..32073444024b2dc19517534a521cae998a04da08 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
 #include <plat/orion-gpio.h>
 #include <plat/irq.h>
@@ -24,16 +25,16 @@ static int __initdata gpio0_irqs[4] = {
 
 void __init mv78xx0_init_irq(void)
 {
-       orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-       orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
-       orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
+       orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+       orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
+       orion_irq_init(64, IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF);
 
        /*
         * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
         * registers for core #1 are at an offset of 0x18 from those of
         * core #0.)
         */
-       orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE,
+       orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE,
                        mv78xx0_core_index() ? 0x18 : 0,
                        IRQ_MV78XX0_GPIO_START, gpio0_irqs);
 }
index 26a059b4f4720173b1f12430d2a62bb0e1173f35..a9a154a646dde94fb75b81f86cd6aa094250edfe 100644 (file)
@@ -34,8 +34,8 @@ static struct resource pcie_io_space;
 
 void __init mv78xx0_pcie_id(u32 *dev, u32 *rev)
 {
-       *dev = orion_pcie_dev_id((void __iomem *)PCIE00_VIRT_BASE);
-       *rev = orion_pcie_rev((void __iomem *)PCIE00_VIRT_BASE);
+       *dev = orion_pcie_dev_id(PCIE00_VIRT_BASE);
+       *rev = orion_pcie_rev(PCIE00_VIRT_BASE);
 }
 
 u32 pcie_port_size[8] = {
@@ -223,11 +223,11 @@ static struct hw_pci mv78xx0_pci __initdata = {
        .map_irq        = mv78xx0_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int maj, int min, unsigned long base)
+static void __init add_pcie_port(int maj, int min, void __iomem *base)
 {
        printk(KERN_INFO "MV78xx0 PCIe port %d.%d: ", maj, min);
 
-       if (orion_pcie_link_up((void __iomem *)base)) {
+       if (orion_pcie_link_up(base)) {
                struct pcie_port *pp = &pcie_port[num_pcie_ports++];
 
                printk("link up\n");
@@ -235,7 +235,7 @@ static void __init add_pcie_port(int maj, int min, unsigned long base)
                pp->maj = maj;
                pp->min = min;
                pp->root_bus_nr = -1;
-               pp->base = (void __iomem *)base;
+               pp->base = base;
                spin_lock_init(&pp->conf_lock);
                memset(&pp->res, 0, sizeof(pp->res));
        } else {
@@ -249,7 +249,7 @@ void __init mv78xx0_pcie_init(int init_port0, int init_port1)
 
        if (init_port0) {
                add_pcie_port(0, 0, PCIE00_VIRT_BASE);
-               if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
+               if (!orion_pcie_x4_mode(PCIE00_VIRT_BASE)) {
                        add_pcie_port(0, 1, PCIE01_VIRT_BASE);
                        add_pcie_port(0, 2, PCIE02_VIRT_BASE);
                        add_pcie_port(0, 3, PCIE03_VIRT_BASE);
index 7b270358536e15f737a78f3b75e59f19a298908f..416d46ef7ebd3f3a477225327a708e5dd339a126 100644 (file)
@@ -6,6 +6,8 @@ config ARCH_MVEBU
        select GENERIC_IRQ_CHIP
        select IRQ_DOMAIN
        select MULTI_IRQ_HANDLER
+       select PINCTRL
+       select PLAT_ORION
        select SPARSE_IRQ
 
 if ARCH_MVEBU
@@ -13,13 +15,25 @@ if ARCH_MVEBU
 menu "Marvell SOC with device tree"
 
 config MACH_ARMADA_370_XP
-       bool "Marvell Armada 370 and Aramada XP boards"
+       bool
        select ARMADA_370_XP_TIMER
        select CPU_V7
+
+config MACH_ARMADA_370
+       bool "Marvell Armada 370 boards"
+       select MACH_ARMADA_370_XP
+       select PINCTRL_ARMADA_370
        help
+         Say 'Y' here if you want your kernel to support boards based
+         on the Marvell Armada 370 SoC with device tree.
 
-         Say 'Y' here if you want your kernel to support boards based on
-         Marvell Armada 370 or Armada XP with device tree.
+config MACH_ARMADA_XP
+       bool "Marvell Armada XP boards"
+       select MACH_ARMADA_370_XP
+       select PINCTRL_ARMADA_XP
+       help
+         Say 'Y' here if you want your kernel to support boards based
+         on the Marvell Armada XP SoC with device tree.
 
 endmenu
 
index 6ea8998ab8f13ed5edc14c203d13f453f38b5a08..57f996b6aa0e36a3beb0481d39973e25d927aa54 100644 (file)
@@ -1,4 +1,5 @@
-ccflags-$(ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
+       -I$(srctree)/arch/arm/plat-orion/include
 
 obj-y += system-controller.o
-obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o
+obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o
diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c
new file mode 100644 (file)
index 0000000..fe454a4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Address map functions for Marvell 370 / XP SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <plat/addr-map.h>
+
+/*
+ * Generic Address Decode Windows bit settings
+ */
+#define ARMADA_XP_TARGET_DEV_BUS       1
+#define   ARMADA_XP_ATTR_DEV_BOOTROM    0x1D
+#define ARMADA_XP_TARGET_ETH1          3
+#define ARMADA_XP_TARGET_PCIE_0_2      4
+#define ARMADA_XP_TARGET_ETH0          7
+#define ARMADA_XP_TARGET_PCIE_1_3      8
+
+#define ARMADA_370_TARGET_DEV_BUS       1
+#define   ARMADA_370_ATTR_DEV_BOOTROM   0x1D
+#define ARMADA_370_TARGET_PCIE_0        4
+#define ARMADA_370_TARGET_PCIE_1        8
+
+#define ARMADA_WINDOW_8_PLUS_OFFSET       0x90
+#define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180
+
+static const struct __initdata orion_addr_map_info
+armada_xp_addr_map_info[] = {
+       /*
+        * Window for the BootROM, needed for SMP on Armada XP
+        */
+       { 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS,
+         ARMADA_XP_ATTR_DEV_BOOTROM, -1 },
+       /* End marker */
+       { -1, 0, 0, 0, 0, 0 },
+};
+
+static const struct __initdata orion_addr_map_info
+armada_370_addr_map_info[] = {
+       /* End marker */
+       { -1, 0, 0, 0, 0, 0 },
+};
+
+static struct of_device_id of_addr_decoding_controller_table[] = {
+       { .compatible = "marvell,armada-addr-decoding-controller" },
+       { /* end of list */ },
+};
+
+static void __iomem *
+armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
+{
+       unsigned int offset;
+
+       /* The register layout is a bit annoying and the below code
+        * tries to cope with it.
+        * - At offset 0x0, there are the registers for the first 8
+        *   windows, with 4 registers of 32 bits per window (ctrl,
+        *   base, remap low, remap high)
+        * - Then at offset 0x80, there is a hole of 0x10 bytes for
+        *   the internal registers base address and internal units
+        *   sync barrier register.
+        * - Then at offset 0x90, there the registers for 12
+        *   windows, with only 2 registers of 32 bits per window
+        *   (ctrl, base).
+        */
+       if (win < 8)
+               offset = (win << 4);
+       else
+               offset = ARMADA_WINDOW_8_PLUS_OFFSET + (win << 3);
+
+       return cfg->bridge_virt_base + offset;
+}
+
+static struct __initdata orion_addr_map_cfg addr_map_cfg = {
+       .num_wins = 20,
+       .remappable_wins = 8,
+       .win_cfg_base = armada_cfg_base,
+};
+
+static int __init armada_setup_cpu_mbus(void)
+{
+       struct device_node *np;
+       void __iomem *mbus_unit_addr_decoding_base;
+       void __iomem *sdram_addr_decoding_base;
+
+       np = of_find_matching_node(NULL, of_addr_decoding_controller_table);
+       if (!np)
+               return -ENODEV;
+
+       mbus_unit_addr_decoding_base = of_iomap(np, 0);
+       BUG_ON(!mbus_unit_addr_decoding_base);
+
+       sdram_addr_decoding_base =
+               mbus_unit_addr_decoding_base +
+               ARMADA_SDRAM_ADDR_DECODING_OFFSET;
+
+       addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;
+
+       /*
+        * Disable, clear and configure windows.
+        */
+       if (of_machine_is_compatible("marvell,armadaxp"))
+               orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info);
+       else if (of_machine_is_compatible("marvell,armada370"))
+               orion_config_wins(&addr_map_cfg, armada_370_addr_map_info);
+       else {
+               pr_err("Unsupported SoC\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Setup MBUS dram target info.
+        */
+       orion_setup_cpu_mbus_target(&addr_map_cfg,
+                                   sdram_addr_decoding_base);
+       return 0;
+}
+
+/* Using a early_initcall is needed so that this initialization gets
+ * done before the SMP initialization, which requires the BootROM to
+ * be remapped. */
+early_initcall(armada_setup_cpu_mbus);
index b46418a8b3522ca7f1295d2c81bdb8893771eefb..49d791548ad60c026c324cffc753a90b1f73844b 100644 (file)
@@ -25,7 +25,7 @@
 
 static struct map_desc armada_370_xp_io_desc[] __initdata = {
        {
-               .virtual        = ARMADA_370_XP_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) ARMADA_370_XP_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(ARMADA_370_XP_REGS_PHYS_BASE),
                .length         = ARMADA_370_XP_REGS_SIZE,
                .type           = MT_DEVICE,
index 25f0ca8d78205bfe44336c15ad06fa625d895c39..aac9bebc6b03da7f865381f1efa335a4c31532b2 100644 (file)
@@ -16,7 +16,7 @@
 #define __MACH_ARMADA_370_XP_H
 
 #define ARMADA_370_XP_REGS_PHYS_BASE   0xd0000000
-#define ARMADA_370_XP_REGS_VIRT_BASE   0xfeb00000
+#define ARMADA_370_XP_REGS_VIRT_BASE   IOMEM(0xfeb00000)
 #define ARMADA_370_XP_REGS_SIZE                SZ_1M
 
 #endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/include/mach/gpio.h b/arch/arm/mach-mvebu/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..40a8c17
--- /dev/null
@@ -0,0 +1 @@
+/* empty */
index 0cc54dd553e36fa7c56d9a56b46adba881fdc2f8..726c02c9c0cdcfd87ac88a4ec0584712ab58bc69 100644 (file)
@@ -357,6 +357,33 @@ static inline void omap_init_uwire(void) {}
 #endif
 
 
+#define OMAP1_RNG_BASE         0xfffe5000
+
+static struct resource omap1_rng_resources[] = {
+       {
+               .start          = OMAP1_RNG_BASE,
+               .end            = OMAP1_RNG_BASE + 0x4f,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap1_rng_device = {
+       .name           = "omap_rng",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(omap1_rng_resources),
+       .resource       = omap1_rng_resources,
+};
+
+static void omap1_init_rng(void)
+{
+       if (!cpu_is_omap16xx())
+               return;
+
+       (void) platform_device_register(&omap1_rng_device);
+}
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -395,6 +422,7 @@ static int __init omap1_init_devices(void)
        omap_init_spi100k();
        omap_init_sti();
        omap_init_uwire();
+       omap1_init_rng();
 
        return 0;
 }
index aa81593db1af9f054058f2c1ed87d295e15bbafd..cdeb9d3ef64096f7ca3a2082ccb6c72038dce995 100644 (file)
@@ -141,7 +141,7 @@ static int __init omap1_dm_timer_init(void)
 
                pdata->set_timer_src = omap1_dm_timer_set_src;
                pdata->timer_capability = OMAP_TIMER_ALWON |
-                               OMAP_TIMER_NEEDS_RESET;
+                               OMAP_TIMER_NEEDS_RESET | OMAP_TIMER_HAS_DSP_IRQ;
 
                ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
                if (ret) {
index 7d6abda3b74e7d2bd16abc4c5e49d71bbf5a4505..fe40d9e488c96cdf1c68ba1d6dd7acc9631b360b 100644 (file)
@@ -179,6 +179,7 @@ obj-$(CONFIG_ARCH_OMAP4)            += omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)                        += emu.o
+obj-$(CONFIG_HW_PERF_EVENTS)           += pmu.o
 
 obj-$(CONFIG_OMAP_MBOX_FWK)            += mailbox_mach.o
 mailbox_mach-objs                      := mailbox.o
index 3e2d76f05af4e4328ba9eb970ca8c118eff9e491..cea3abace815716b4fea93aa1e9aae1c61238740 100644 (file)
@@ -202,7 +202,7 @@ static inline void __init apollon_init_smc91x(void)
                return;
        }
 
-       clk_enable(gpmc_fck);
+       clk_prepare_enable(gpmc_fck);
        rate = clk_get_rate(gpmc_fck);
 
        eth_cs = APOLLON_ETH_CS;
@@ -246,7 +246,7 @@ static inline void __init apollon_init_smc91x(void)
                gpmc_cs_free(APOLLON_ETH_CS);
        }
 out:
-       clk_disable(gpmc_fck);
+       clk_disable_unprepare(gpmc_fck);
        clk_put(gpmc_fck);
 }
 
index f6c48dd764fe4ec60e26b60796b8383f74803a2a..8d04bf851af44e36568f4824a0d3cbb84760d566 100644 (file)
@@ -265,9 +265,9 @@ static inline void __init h4_init_debug(void)
                return;
        }
 
-       clk_enable(gpmc_fck);
+       clk_prepare_enable(gpmc_fck);
        rate = clk_get_rate(gpmc_fck);
-       clk_disable(gpmc_fck);
+       clk_disable_unprepare(gpmc_fck);
        clk_put(gpmc_fck);
 
        if (is_gpmc_muxed())
@@ -311,7 +311,7 @@ static inline void __init h4_init_debug(void)
                gpmc_cs_free(eth_cs);
 
 out:
-       clk_disable(gpmc_fck);
+       clk_disable_unprepare(gpmc_fck);
        clk_put(gpmc_fck);
 }
 
index e0dd70b9d9170030b819d57151753915a82af696..2b012f9d69255454b4639b48d533c5f33df3bec2 100644 (file)
@@ -171,7 +171,7 @@ static void __init omap4_ehci_init(void)
                return;
        }
        clk_set_rate(phy_ref_clk, 19200000);
-       clk_enable(phy_ref_clk);
+       clk_prepare_enable(phy_ref_clk);
 
        /* disable the power to the usb hub prior to init and reset phy+hub */
        ret = gpio_request_array(panda_ehci_gpios,
index 3945c5017085abdb72cfd61532fb33c864df23c4..ed85fb898c7fd62b8526d0bf1e0bea1d23ff26fd 100644 (file)
@@ -33,6 +33,7 @@
 #include "common.h"
 #include <plat/dma.h>
 #include <plat/gpmc.h>
+#include <plat/omap-pm.h>
 #include "gpmc-smc91x.h"
 
 #include "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"
@@ -1217,6 +1222,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();
@@ -1227,6 +1256,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 b19a1f7234ae9446786e3d370ceeeec7889428e9..c2d15212d64d768530e1b94b9d8cf4ad0ff8cec9 100644 (file)
@@ -59,7 +59,7 @@ static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
        omap2_cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
 
        omap2_cm_wait_idlest(cm_idlest_pll, status_mask,
-                            OMAP24XX_CM_IDLEST_VAL, clk->name);
+                            OMAP24XX_CM_IDLEST_VAL, __clk_get_name(clk));
 
        /*
         * REVISIT: Should we return an error code if omap2_wait_clock_ready()
index cabcfdba524659b470a7b674a6ca4bea9cc703d4..3524f0e7b6d5b0db13975d978850dc6fc42f4480 100644 (file)
@@ -68,14 +68,15 @@ unsigned long omap2_table_mpu_recalc(struct clk *clk)
 long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
 {
        const struct prcm_config *ptr;
-       long highest_rate;
+       long highest_rate, sys_clk_rate;
 
        highest_rate = -EINVAL;
+       sys_clk_rate = __clk_get_rate(sclk);
 
        for (ptr = rate_table; ptr->mpu_speed; ptr++) {
                if (!(ptr->flags & cpu_mask))
                        continue;
-               if (ptr->xtal_speed != sclk->rate)
+               if (ptr->xtal_speed != sys_clk_rate)
                        continue;
 
                highest_rate = ptr->mpu_speed;
@@ -94,12 +95,15 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
        const struct prcm_config *prcm;
        unsigned long found_speed = 0;
        unsigned long flags;
+       long sys_clk_rate;
+
+       sys_clk_rate = __clk_get_rate(sclk);
 
        for (prcm = rate_table; prcm->mpu_speed; prcm++) {
                if (!(prcm->flags & cpu_mask))
                        continue;
 
-               if (prcm->xtal_speed != sclk->rate)
+               if (prcm->xtal_speed != sys_clk_rate)
                        continue;
 
                if (prcm->mpu_speed <= rate) {
index 298887b5bf66c5168a248372b26d5410658f1ae4..7c6da2f731dc75683512af15df6510886f03c1e8 100644 (file)
@@ -56,6 +56,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        struct omap_sdrc_params *sdrc_cs0;
        struct omap_sdrc_params *sdrc_cs1;
        int ret;
+       unsigned long clkrate;
 
        if (!clk || !rate)
                return -EINVAL;
@@ -64,11 +65,12 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        if (validrate != rate)
                return -EINVAL;
 
-       sdrcrate = sdrc_ick_p->rate;
-       if (rate > clk->rate)
-               sdrcrate <<= ((rate / clk->rate) >> 1);
+       sdrcrate = __clk_get_rate(sdrc_ick_p);
+       clkrate = __clk_get_rate(clk);
+       if (rate > clkrate)
+               sdrcrate <<= ((rate / clkrate) >> 1);
        else
-               sdrcrate >>= ((clk->rate / rate) >> 1);
+               sdrcrate >>= ((clkrate / rate) >> 1);
 
        ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
        if (ret)
@@ -82,7 +84,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        /*
         * XXX This only needs to be done when the CPU frequency changes
         */
-       _mpurate = arm_fck_p->rate / CYCLES_PER_MHZ;
+       _mpurate = __clk_get_rate(arm_fck_p) / CYCLES_PER_MHZ;
        c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
        c += 1;  /* for safety */
        c *= SDRC_MPURATE_LOOPS;
@@ -90,8 +92,8 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        if (c == 0)
                c = 1;
 
-       pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
-                validrate);
+       pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n",
+                clkrate, validrate);
        pr_debug("clock: SDRC CS0 timing params used: RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
                 sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
                 sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
@@ -102,14 +104,14 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 
        if (sdrc_cs1)
                omap3_configure_core_dpll(
-                                 new_div, unlock_dll, c, rate > clk->rate,
+                                 new_div, unlock_dll, c, rate > clkrate,
                                  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
                                  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
                                  sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
                                  sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
        else
                omap3_configure_core_dpll(
-                                 new_div, unlock_dll, c, rate > clk->rate,
+                                 new_div, unlock_dll, c, rate > clkrate,
                                  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
                                  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
                                  0, 0, 0, 0);
index 19a980956d446d87ae281083d876e6b770084e5f..eaed3900a83c7519d029e1a11e439c797e75769b 100644 (file)
@@ -72,7 +72,7 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
        if (!clks->parent) {
                /* This indicates a data problem */
                WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
-                    clk->name, src_clk->name);
+                    __clk_get_name(clk), __clk_get_name(src_clk));
                return NULL;
        }
 
@@ -127,7 +127,8 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
        if (max_div == 0) {
                /* This indicates an error in the clksel data */
                WARN(1, "clock: %s: could not find divisor for parent %s\n",
-                    clk->name, src_clk->parent->name);
+                    __clk_get_name(clk),
+                    __clk_get_name(__clk_get_parent(src_clk)));
                return 0;
        }
 
@@ -176,8 +177,10 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
 {
        const struct clksel *clks;
        const struct clksel_rate *clkr;
+       struct clk *parent;
 
-       clks = _get_clksel_by_parent(clk, clk->parent);
+       parent = __clk_get_parent(clk);
+       clks = _get_clksel_by_parent(clk, parent);
        if (!clks)
                return 0;
 
@@ -191,8 +194,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
 
        if (!clkr->div) {
                /* This indicates a data error */
-               WARN(1, "clock: %s: could not find fieldval %d parent %s\n",
-                    clk->name, field_val, clk->parent->name);
+               WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
+                    __clk_get_name(clk), field_val, __clk_get_name(parent));
                return 0;
        }
 
@@ -213,11 +216,13 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 {
        const struct clksel *clks;
        const struct clksel_rate *clkr;
+       struct clk *parent;
 
        /* should never happen */
        WARN_ON(div == 0);
 
-       clks = _get_clksel_by_parent(clk, clk->parent);
+       parent = __clk_get_parent(clk);
+       clks = _get_clksel_by_parent(clk, parent);
        if (!clks)
                return ~0;
 
@@ -230,8 +235,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
        }
 
        if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor %d parent %s\n",
-                      clk->name, div, clk->parent->name);
+               pr_err("clock: %s: could not find divisor %d for parent %s\n",
+                      __clk_get_name(clk), div, __clk_get_name(parent));
                return ~0;
        }
 
@@ -281,16 +286,23 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
        const struct clksel *clks;
        const struct clksel_rate *clkr;
        u32 last_div = 0;
+       struct clk *parent;
+       unsigned long parent_rate;
+       const char *clk_name;
+
+       parent = __clk_get_parent(clk);
+       parent_rate = __clk_get_rate(parent);
+       clk_name = __clk_get_name(clk);
 
        if (!clk->clksel || !clk->clksel_mask)
                return ~0;
 
        pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
-                clk->name, target_rate);
+                clk_name, target_rate);
 
        *new_div = 1;
 
-       clks = _get_clksel_by_parent(clk, clk->parent);
+       clks = _get_clksel_by_parent(clk, parent);
        if (!clks)
                return ~0;
 
@@ -300,29 +312,29 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 
                /* Sanity check */
                if (clkr->div <= last_div)
-                       pr_err("clock: %s: clksel_rate table not sorted",
-                              clk->name);
+                       pr_err("clock: %s: clksel_rate table not sorted\n",
+                              clk_name);
 
                last_div = clkr->div;
 
-               test_rate = clk->parent->rate / clkr->div;
+               test_rate = parent_rate / clkr->div;
 
                if (test_rate <= target_rate)
                        break; /* found it */
        }
 
        if (!clkr->div) {
-               pr_err("clock: %s: could not find divisor for target rate %ld parent %s\n",
-                      clk->name, target_rate, clk->parent->name);
+               pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
+                      clk_name, target_rate, __clk_get_name(parent));
                return ~0;
        }
 
        *new_div = clkr->div;
 
        pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
-                (clk->parent->rate / clkr->div));
+                (parent_rate / clkr->div));
 
-       return clk->parent->rate / clkr->div;
+       return parent_rate / clkr->div;
 }
 
 /*
@@ -344,10 +356,15 @@ void omap2_init_clksel_parent(struct clk *clk)
        const struct clksel *clks;
        const struct clksel_rate *clkr;
        u32 r, found = 0;
+       struct clk *parent;
+       const char *clk_name;
 
        if (!clk->clksel || !clk->clksel_mask)
                return;
 
+       parent = __clk_get_parent(clk);
+       clk_name = __clk_get_name(clk);
+
        r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
        r >>= __ffs(clk->clksel_mask);
 
@@ -357,11 +374,13 @@ void omap2_init_clksel_parent(struct clk *clk)
                                continue;
 
                        if (clkr->val == r) {
-                               if (clk->parent != clks->parent) {
+                               if (parent != clks->parent) {
                                        pr_debug("clock: %s: inited parent to %s (was %s)\n",
-                                                clk->name, clks->parent->name,
-                                                ((clk->parent) ?
-                                                 clk->parent->name : "NULL"));
+                                                clk_name,
+                                                __clk_get_name(clks->parent),
+                                                ((parent) ?
+                                                 __clk_get_name(parent) :
+                                                "NULL"));
                                        clk_reparent(clk, clks->parent);
                                };
                                found = 1;
@@ -371,7 +390,7 @@ void omap2_init_clksel_parent(struct clk *clk)
 
        /* This indicates a data error */
        WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
-            clk->name, r);
+            clk_name, r);
 
        return;
 }
@@ -389,15 +408,17 @@ unsigned long omap2_clksel_recalc(struct clk *clk)
 {
        unsigned long rate;
        u32 div = 0;
+       struct clk *parent;
 
        div = _read_divisor(clk);
        if (div == 0)
-               return clk->rate;
+               return __clk_get_rate(clk);
 
-       rate = clk->parent->rate / div;
+       parent = __clk_get_parent(clk);
+       rate = __clk_get_rate(parent) / div;
 
-       pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n", clk->name,
-                rate, div);
+       pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
+                __clk_get_name(clk), rate, div);
 
        return rate;
 }
@@ -452,9 +473,10 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 
        _write_clksel_reg(clk, field_val);
 
-       clk->rate = clk->parent->rate / new_div;
+       clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
 
-       pr_debug("clock: %s: set rate to %ld\n", clk->name, clk->rate);
+       pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
+                __clk_get_rate(clk));
 
        return 0;
 }
@@ -496,13 +518,15 @@ int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
        clk_reparent(clk, new_parent);
 
        /* CLKSEL clocks follow their parents' rates, divided by a divisor */
-       clk->rate = new_parent->rate;
+       clk->rate = __clk_get_rate(new_parent);
 
        if (parent_div > 0)
-               clk->rate /= parent_div;
+               __clk_get_rate(clk) /= parent_div;
 
        pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
-                clk->name, clk->parent->name, clk->rate);
+                __clk_get_name(clk),
+                __clk_get_name(__clk_get_parent(clk)),
+                __clk_get_rate(clk));
 
        return 0;
 }
index 83b658bf385ae4b01c8ea279313016fa991f91d2..80411142f4823c9626115fb5847f87f35d7f1d8c 100644 (file)
@@ -87,7 +87,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
        dd = clk->dpll_data;
 
        /* DPLL divider must result in a valid jitter correction val */
-       fint = clk->parent->rate / n;
+       fint = __clk_get_rate(__clk_get_parent(clk)) / n;
 
        if (cpu_is_omap24xx()) {
                /* Should not be called for OMAP2, so warn if it is called */
@@ -252,16 +252,16 @@ u32 omap2_get_dpll_rate(struct clk *clk)
        if (cpu_is_omap24xx()) {
                if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
                    v == OMAP2XXX_EN_DPLL_FRBYPASS)
-                       return dd->clk_bypass->rate;
+                       return __clk_get_rate(dd->clk_bypass);
        } else if (cpu_is_omap34xx()) {
                if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
                    v == OMAP3XXX_EN_DPLL_FRBYPASS)
-                       return dd->clk_bypass->rate;
+                       return __clk_get_rate(dd->clk_bypass);
        } else if (soc_is_am33xx() || cpu_is_omap44xx()) {
                if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
                    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
                    v == OMAP4XXX_EN_DPLL_MNBYPASS)
-                       return dd->clk_bypass->rate;
+                       return __clk_get_rate(dd->clk_bypass);
        }
 
        v = __raw_readl(dd->mult_div1_reg);
@@ -270,7 +270,7 @@ u32 omap2_get_dpll_rate(struct clk *clk)
        dpll_div = v & dd->div1_mask;
        dpll_div >>= __ffs(dd->div1_mask);
 
-       dpll_clk = (long long)dd->clk_ref->rate * dpll_mult;
+       dpll_clk = (long long) __clk_get_rate(dd->clk_ref) * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
        return dpll_clk;
@@ -296,16 +296,20 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
        unsigned long scaled_rt_rp;
        unsigned long new_rate = 0;
        struct dpll_data *dd;
+       unsigned long ref_rate;
+       const char *clk_name;
 
        if (!clk || !clk->dpll_data)
                return ~0;
 
        dd = clk->dpll_data;
 
+       ref_rate = __clk_get_rate(dd->clk_ref);
+       clk_name = __clk_get_name(clk);
        pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
-                clk->name, target_rate);
+                clk_name, target_rate);
 
-       scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
+       scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR);
        scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
 
        dd->last_rounded_rate = 0;
@@ -332,14 +336,14 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
                        break;
 
                r = _dpll_test_mult(&m, n, &new_rate, target_rate,
-                                   dd->clk_ref->rate);
+                                   ref_rate);
 
                /* m can't be set low enough for this n - try with a larger n */
                if (r == DPLL_MULT_UNDERFLOW)
                        continue;
 
                pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
-                        clk->name, m, n, new_rate);
+                        clk_name, m, n, new_rate);
 
                if (target_rate == new_rate) {
                        dd->last_rounded_m = m;
@@ -350,8 +354,8 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
        }
 
        if (target_rate != new_rate) {
-               pr_debug("clock: %s: cannot round to rate %ld\n", clk->name,
-                        target_rate);
+               pr_debug("clock: %s: cannot round to rate %ld\n",
+                        clk_name, target_rate);
                return ~0;
        }
 
index e97f98ffe8b2a852356a06aee8f06d18aeac9993..961ac8f7e13d8c84a1cbb4587255ea685520bd18 100644 (file)
@@ -78,7 +78,7 @@ static void _omap2_module_wait_ready(struct clk *clk)
        clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
 
        omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), idlest_val,
-                            clk->name);
+                            __clk_get_name(clk));
 }
 
 /* Public functions */
@@ -94,18 +94,21 @@ static void _omap2_module_wait_ready(struct clk *clk)
 void omap2_init_clk_clkdm(struct clk *clk)
 {
        struct clockdomain *clkdm;
+       const char *clk_name;
 
        if (!clk->clkdm_name)
                return;
 
+       clk_name = __clk_get_name(clk);
+
        clkdm = clkdm_lookup(clk->clkdm_name);
        if (clkdm) {
                pr_debug("clock: associated clk %s to clkdm %s\n",
-                        clk->name, clk->clkdm_name);
+                        clk_name, clk->clkdm_name);
                clk->clkdm = clkdm;
        } else {
                pr_debug("clock: could not associate clk %s to clkdm %s\n",
-                        clk->name, clk->clkdm_name);
+                        clk_name, clk->clkdm_name);
        }
 }
 
index 12c178dbc9f579c5658d46e884ee160587fbd7df..c3cde1a2b6de6d71956043cbd72054b6f3052438 100644 (file)
@@ -1804,6 +1804,7 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gfx_ick",      &gfx_ick,       CK_242X),
        /* DSS domain clocks */
        CLK("omapdss_dss",      "ick",          &dss_ick,       CK_242X),
+       CLK(NULL,       "dss_ick",              &dss_ick,       CK_242X),
        CLK(NULL,       "dss1_fck",             &dss1_fck,      CK_242X),
        CLK(NULL,       "dss2_fck",     &dss2_fck,      CK_242X),
        CLK(NULL,       "dss_54m_fck",  &dss_54m_fck,   CK_242X),
@@ -1843,12 +1844,16 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_242X),
        CLK(NULL,       "gpt12_fck",    &gpt12_fck,     CK_242X),
        CLK("omap-mcbsp.1", "ick",      &mcbsp1_ick,    CK_242X),
+       CLK(NULL,       "mcbsp1_ick",   &mcbsp1_ick,    CK_242X),
        CLK(NULL,       "mcbsp1_fck",   &mcbsp1_fck,    CK_242X),
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_242X),
+       CLK(NULL,       "mcbsp2_ick",   &mcbsp2_ick,    CK_242X),
        CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_242X),
        CLK("omap2_mcspi.1", "ick",     &mcspi1_ick,    CK_242X),
+       CLK(NULL,       "mcspi1_ick",   &mcspi1_ick,    CK_242X),
        CLK(NULL,       "mcspi1_fck",   &mcspi1_fck,    CK_242X),
        CLK("omap2_mcspi.2", "ick",     &mcspi2_ick,    CK_242X),
+       CLK(NULL,       "mcspi2_ick",   &mcspi2_ick,    CK_242X),
        CLK(NULL,       "mcspi2_fck",   &mcspi2_fck,    CK_242X),
        CLK(NULL,       "uart1_ick",    &uart1_ick,     CK_242X),
        CLK(NULL,       "uart1_fck",    &uart1_fck,     CK_242X),
@@ -1859,12 +1864,15 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "gpios_ick",    &gpios_ick,     CK_242X),
        CLK(NULL,       "gpios_fck",    &gpios_fck,     CK_242X),
        CLK("omap_wdt", "ick",          &mpu_wdt_ick,   CK_242X),
+       CLK(NULL,       "mpu_wdt_ick",          &mpu_wdt_ick,   CK_242X),
        CLK(NULL,       "mpu_wdt_fck",  &mpu_wdt_fck,   CK_242X),
        CLK(NULL,       "sync_32k_ick", &sync_32k_ick,  CK_242X),
        CLK(NULL,       "wdt1_ick",     &wdt1_ick,      CK_242X),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_242X),
        CLK("omap24xxcam", "fck",       &cam_fck,       CK_242X),
+       CLK(NULL,       "cam_fck",      &cam_fck,       CK_242X),
        CLK("omap24xxcam", "ick",       &cam_ick,       CK_242X),
+       CLK(NULL,       "cam_ick",      &cam_ick,       CK_242X),
        CLK(NULL,       "mailboxes_ick", &mailboxes_ick,        CK_242X),
        CLK(NULL,       "wdt4_ick",     &wdt4_ick,      CK_242X),
        CLK(NULL,       "wdt4_fck",     &wdt4_fck,      CK_242X),
@@ -1873,16 +1881,22 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "mspro_ick",    &mspro_ick,     CK_242X),
        CLK(NULL,       "mspro_fck",    &mspro_fck,     CK_242X),
        CLK("mmci-omap.0", "ick",       &mmc_ick,       CK_242X),
+       CLK(NULL,       "mmc_ick",      &mmc_ick,       CK_242X),
        CLK("mmci-omap.0", "fck",       &mmc_fck,       CK_242X),
+       CLK(NULL,       "mmc_fck",      &mmc_fck,       CK_242X),
        CLK(NULL,       "fac_ick",      &fac_ick,       CK_242X),
        CLK(NULL,       "fac_fck",      &fac_fck,       CK_242X),
        CLK(NULL,       "eac_ick",      &eac_ick,       CK_242X),
        CLK(NULL,       "eac_fck",      &eac_fck,       CK_242X),
        CLK("omap_hdq.0", "ick",        &hdq_ick,       CK_242X),
+       CLK(NULL,       "hdq_ick",      &hdq_ick,       CK_242X),
        CLK("omap_hdq.0", "fck",        &hdq_fck,       CK_242X),
+       CLK(NULL,       "hdq_fck",      &hdq_fck,       CK_242X),
        CLK("omap_i2c.1", "ick",        &i2c1_ick,      CK_242X),
+       CLK(NULL,       "i2c1_ick",     &i2c1_ick,      CK_242X),
        CLK(NULL,       "i2c1_fck",     &i2c1_fck,      CK_242X),
        CLK("omap_i2c.2", "ick",        &i2c2_ick,      CK_242X),
+       CLK(NULL,       "i2c2_ick",     &i2c2_ick,      CK_242X),
        CLK(NULL,       "i2c2_fck",     &i2c2_fck,      CK_242X),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_242X),
        CLK(NULL,       "sdma_fck",     &sdma_fck,      CK_242X),
@@ -1892,14 +1906,18 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "vlynq_fck",    &vlynq_fck,     CK_242X),
        CLK(NULL,       "des_ick",      &des_ick,       CK_242X),
        CLK("omap-sham",        "ick",  &sha_ick,       CK_242X),
+       CLK(NULL,       "sha_ick",      &sha_ick,       CK_242X),
        CLK("omap_rng", "ick",          &rng_ick,       CK_242X),
+       CLK(NULL,       "rng_ick",              &rng_ick,       CK_242X),
        CLK("omap-aes", "ick",  &aes_ick,       CK_242X),
+       CLK(NULL,       "aes_ick",      &aes_ick,       CK_242X),
        CLK(NULL,       "pka_ick",      &pka_ick,       CK_242X),
        CLK(NULL,       "usb_fck",      &usb_fck,       CK_242X),
        CLK("musb-hdrc",        "fck",  &osc_ck,        CK_242X),
-       CLK(NULL,       "timer_32k_ck", &func_32k_ck,   CK_243X),
-       CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_243X),
-       CLK(NULL,       "timer_ext_ck", &alt_ck,        CK_243X),
+       CLK(NULL,       "timer_32k_ck", &func_32k_ck,   CK_242X),
+       CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_242X),
+       CLK(NULL,       "timer_ext_ck", &alt_ck,        CK_242X),
+       CLK(NULL,       "cpufreq_ck",   &virt_prcm_set, CK_242X),
 };
 
 /*
index 7ea91398217af0ac65b8137438061d63278399e9..22404fe435e75369e288937b4b4e5d2e1969fd45 100644 (file)
@@ -1888,6 +1888,7 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "mdm_osc_ck",   &mdm_osc_ck,    CK_243X),
        /* DSS domain clocks */
        CLK("omapdss_dss",      "ick",          &dss_ick,       CK_243X),
+       CLK(NULL,       "dss_ick",              &dss_ick,       CK_243X),
        CLK(NULL,       "dss1_fck",             &dss1_fck,      CK_243X),
        CLK(NULL,       "dss2_fck",     &dss2_fck,      CK_243X),
        CLK(NULL,       "dss_54m_fck",  &dss_54m_fck,   CK_243X),
@@ -1927,20 +1928,28 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_243X),
        CLK(NULL,       "gpt12_fck",    &gpt12_fck,     CK_243X),
        CLK("omap-mcbsp.1", "ick",      &mcbsp1_ick,    CK_243X),
+       CLK(NULL,       "mcbsp1_ick",   &mcbsp1_ick,    CK_243X),
        CLK(NULL,       "mcbsp1_fck",   &mcbsp1_fck,    CK_243X),
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_243X),
+       CLK(NULL,       "mcbsp2_ick",   &mcbsp2_ick,    CK_243X),
        CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_243X),
        CLK("omap-mcbsp.3", "ick",      &mcbsp3_ick,    CK_243X),
+       CLK(NULL,       "mcbsp3_ick",   &mcbsp3_ick,    CK_243X),
        CLK(NULL,       "mcbsp3_fck",   &mcbsp3_fck,    CK_243X),
        CLK("omap-mcbsp.4", "ick",      &mcbsp4_ick,    CK_243X),
+       CLK(NULL,       "mcbsp4_ick",   &mcbsp4_ick,    CK_243X),
        CLK(NULL,       "mcbsp4_fck",   &mcbsp4_fck,    CK_243X),
        CLK("omap-mcbsp.5", "ick",      &mcbsp5_ick,    CK_243X),
+       CLK(NULL,       "mcbsp5_ick",   &mcbsp5_ick,    CK_243X),
        CLK(NULL,       "mcbsp5_fck",   &mcbsp5_fck,    CK_243X),
        CLK("omap2_mcspi.1", "ick",     &mcspi1_ick,    CK_243X),
+       CLK(NULL,       "mcspi1_ick",   &mcspi1_ick,    CK_243X),
        CLK(NULL,       "mcspi1_fck",   &mcspi1_fck,    CK_243X),
        CLK("omap2_mcspi.2", "ick",     &mcspi2_ick,    CK_243X),
+       CLK(NULL,       "mcspi2_ick",   &mcspi2_ick,    CK_243X),
        CLK(NULL,       "mcspi2_fck",   &mcspi2_fck,    CK_243X),
        CLK("omap2_mcspi.3", "ick",     &mcspi3_ick,    CK_243X),
+       CLK(NULL,       "mcspi3_ick",   &mcspi3_ick,    CK_243X),
        CLK(NULL,       "mcspi3_fck",   &mcspi3_fck,    CK_243X),
        CLK(NULL,       "uart1_ick",    &uart1_ick,     CK_243X),
        CLK(NULL,       "uart1_fck",    &uart1_fck,     CK_243X),
@@ -1951,13 +1960,16 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "gpios_ick",    &gpios_ick,     CK_243X),
        CLK(NULL,       "gpios_fck",    &gpios_fck,     CK_243X),
        CLK("omap_wdt", "ick",          &mpu_wdt_ick,   CK_243X),
+       CLK(NULL,       "mpu_wdt_ick",  &mpu_wdt_ick,   CK_243X),
        CLK(NULL,       "mpu_wdt_fck",  &mpu_wdt_fck,   CK_243X),
        CLK(NULL,       "sync_32k_ick", &sync_32k_ick,  CK_243X),
        CLK(NULL,       "wdt1_ick",     &wdt1_ick,      CK_243X),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_243X),
        CLK(NULL,       "icr_ick",      &icr_ick,       CK_243X),
        CLK("omap24xxcam", "fck",       &cam_fck,       CK_243X),
+       CLK(NULL,       "cam_fck",      &cam_fck,       CK_243X),
        CLK("omap24xxcam", "ick",       &cam_ick,       CK_243X),
+       CLK(NULL,       "cam_ick",      &cam_ick,       CK_243X),
        CLK(NULL,       "mailboxes_ick", &mailboxes_ick,        CK_243X),
        CLK(NULL,       "wdt4_ick",     &wdt4_ick,      CK_243X),
        CLK(NULL,       "wdt4_fck",     &wdt4_fck,      CK_243X),
@@ -1966,10 +1978,14 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "fac_ick",      &fac_ick,       CK_243X),
        CLK(NULL,       "fac_fck",      &fac_fck,       CK_243X),
        CLK("omap_hdq.0", "ick",        &hdq_ick,       CK_243X),
+       CLK(NULL,       "hdq_ick",      &hdq_ick,       CK_243X),
        CLK("omap_hdq.1", "fck",        &hdq_fck,       CK_243X),
+       CLK(NULL,       "hdq_fck",      &hdq_fck,       CK_243X),
        CLK("omap_i2c.1", "ick",        &i2c1_ick,      CK_243X),
+       CLK(NULL,       "i2c1_ick",     &i2c1_ick,      CK_243X),
        CLK(NULL,       "i2chs1_fck",   &i2chs1_fck,    CK_243X),
        CLK("omap_i2c.2", "ick",        &i2c2_ick,      CK_243X),
+       CLK(NULL,       "i2c2_ick",     &i2c2_ick,      CK_243X),
        CLK(NULL,       "i2chs2_fck",   &i2chs2_fck,    CK_243X),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_243X),
        CLK(NULL,       "sdma_fck",     &sdma_fck,      CK_243X),
@@ -1978,22 +1994,29 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "des_ick",      &des_ick,       CK_243X),
        CLK("omap-sham",        "ick",  &sha_ick,       CK_243X),
        CLK("omap_rng", "ick",          &rng_ick,       CK_243X),
+       CLK(NULL,       "rng_ick",      &rng_ick,       CK_243X),
        CLK("omap-aes", "ick",  &aes_ick,       CK_243X),
        CLK(NULL,       "pka_ick",      &pka_ick,       CK_243X),
        CLK(NULL,       "usb_fck",      &usb_fck,       CK_243X),
        CLK("musb-omap2430",    "ick",  &usbhs_ick,     CK_243X),
+       CLK(NULL,       "usbhs_ick",    &usbhs_ick,     CK_243X),
        CLK("omap_hsmmc.0", "ick",      &mmchs1_ick,    CK_243X),
+       CLK(NULL,       "mmchs1_ick",   &mmchs1_ick,    CK_243X),
        CLK(NULL,       "mmchs1_fck",   &mmchs1_fck,    CK_243X),
        CLK("omap_hsmmc.1", "ick",      &mmchs2_ick,    CK_243X),
+       CLK(NULL,       "mmchs2_ick",   &mmchs2_ick,    CK_243X),
        CLK(NULL,       "mmchs2_fck",   &mmchs2_fck,    CK_243X),
        CLK(NULL,       "gpio5_ick",    &gpio5_ick,     CK_243X),
        CLK(NULL,       "gpio5_fck",    &gpio5_fck,     CK_243X),
        CLK(NULL,       "mdm_intc_ick", &mdm_intc_ick,  CK_243X),
        CLK("omap_hsmmc.0", "mmchsdb_fck",      &mmchsdb1_fck,  CK_243X),
+       CLK(NULL,       "mmchsdb1_fck",         &mmchsdb1_fck,  CK_243X),
        CLK("omap_hsmmc.1", "mmchsdb_fck",      &mmchsdb2_fck,  CK_243X),
+       CLK(NULL,       "mmchsdb2_fck",         &mmchsdb2_fck,  CK_243X),
        CLK(NULL,       "timer_32k_ck",  &func_32k_ck,   CK_243X),
        CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_243X),
        CLK(NULL,       "timer_ext_ck", &alt_ck,        CK_243X),
+       CLK(NULL,       "cpufreq_ck",   &virt_prcm_set, CK_243X),
 };
 
 /*
index 2026311a4ff69e6decffe4c25aa49a6fee07400b..b87b88c2638b968ae834f5d4df2dade5c388c52a 100644 (file)
@@ -1013,6 +1013,7 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "dpll_core_m5_ck",      &dpll_core_m5_ck,       CK_AM33XX),
        CLK(NULL,       "dpll_core_m6_ck",      &dpll_core_m6_ck,       CK_AM33XX),
        CLK(NULL,       "dpll_mpu_ck",          &dpll_mpu_ck,   CK_AM33XX),
+       CLK("cpu0",     NULL,                   &dpll_mpu_ck,           CK_AM33XX),
        CLK(NULL,       "dpll_mpu_m2_ck",       &dpll_mpu_m2_ck,        CK_AM33XX),
        CLK(NULL,       "dpll_ddr_ck",          &dpll_ddr_ck,   CK_AM33XX),
        CLK(NULL,       "dpll_ddr_m2_ck",       &dpll_ddr_m2_ck,        CK_AM33XX),
index 15cdc6471737741f8088bfaa11e3eee0fd7d868b..83bb01427d405b4aa506c84882a4c522e8d58a7e 100644 (file)
@@ -63,15 +63,15 @@ void __init omap3_clk_lock_dpll5(void)
 
        dpll5_clk = clk_get(NULL, "dpll5_ck");
        clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
-       clk_enable(dpll5_clk);
+       clk_prepare_enable(dpll5_clk);
 
        /* Program dpll5_m2_clk divider for no division */
        dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
-       clk_enable(dpll5_m2_clk);
+       clk_prepare_enable(dpll5_m2_clk);
        clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
 
-       clk_disable(dpll5_m2_clk);
-       clk_disable(dpll5_clk);
+       clk_disable_unprepare(dpll5_m2_clk);
+       clk_disable_unprepare(dpll5_clk);
        return;
 }
 
index 700317a1bd16f6ac803d544f26d0008f4352189b..1f42c9d5ecf3131b5f55fd6d2152912d44b2d9ff 100644 (file)
@@ -3215,7 +3215,6 @@ static struct clk dummy_apb_pclk = {
  * clkdev
  */
 
-/* XXX At some point we should rename this file to clock3xxx_data.c */
 static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "apb_pclk",     &dummy_apb_pclk,        CK_3XXX),
        CLK(NULL,       "omap_32k_fck", &omap_32k_fck,  CK_3XXX),
@@ -3243,11 +3242,13 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
        CLK(NULL,       "dpll3_m3_ck",  &dpll3_m3_ck,   CK_3XXX),
        CLK(NULL,       "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
+       CLK(NULL,       "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
        CLK("etb",      "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
        CLK(NULL,       "dpll4_ck",     &dpll4_ck,      CK_3XXX),
        CLK(NULL,       "dpll4_x2_ck",  &dpll4_x2_ck,   CK_3XXX),
        CLK(NULL,       "omap_192m_alwon_fck", &omap_192m_alwon_fck, CK_36XX),
        CLK(NULL,       "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
+       CLK(NULL,       "omap_96m_alwon_fck_3630", &omap_96m_alwon_fck_3630, CK_36XX),
        CLK(NULL,       "omap_96m_fck", &omap_96m_fck,  CK_3XXX),
        CLK(NULL,       "cm_96m_fck",   &cm_96m_fck,    CK_3XXX),
        CLK(NULL,       "omap_54m_fck", &omap_54m_fck,  CK_3XXX),
@@ -3263,6 +3264,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
        CLK(NULL,       "dpll4_m6_ck",  &dpll4_m6_ck,   CK_3XXX),
        CLK(NULL,       "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
+       CLK(NULL,       "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
        CLK("etb",      "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
        CLK(NULL,       "dpll5_ck",     &dpll5_ck,      CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "dpll5_m2_ck",  &dpll5_m2_ck,   CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
@@ -3272,6 +3274,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "dpll1_fck",    &dpll1_fck,     CK_3XXX),
        CLK(NULL,       "mpu_ck",       &mpu_ck,        CK_3XXX),
        CLK(NULL,       "arm_fck",      &arm_fck,       CK_3XXX),
+       CLK(NULL,       "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
        CLK("etb",      "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
        CLK(NULL,       "dpll2_fck",    &dpll2_fck,     CK_34XX | CK_36XX),
        CLK(NULL,       "iva2_ck",      &iva2_ck,       CK_34XX | CK_36XX),
@@ -3295,6 +3298,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ts_fck",       &ts_fck,        CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "usbtll_fck",   &usbtll_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK("usbhs_omap",       "usbtll_fck",   &usbtll_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK("usbhs_tll",        "usbtll_fck",   &usbtll_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "core_96m_fck", &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "mmchs3_fck",   &mmchs3_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "mmchs2_fck",   &mmchs2_fck,    CK_3XXX),
@@ -3315,6 +3319,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
        CLK(NULL,       "core_12m_fck", &core_12m_fck,  CK_3XXX),
        CLK("omap_hdq.0",       "fck",  &hdq_fck,       CK_3XXX),
+       CLK(NULL,       "hdq_fck",      &hdq_fck,       CK_3XXX),
        CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es1,   CK_3430ES1),
        CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es2,   CK_3430ES2PLUS | CK_36XX),
        CLK(NULL,       "ssi_sst_fck",  &ssi_sst_fck_3430es1,   CK_3430ES1),
@@ -3322,6 +3327,8 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "core_l3_ick",  &core_l3_ick,   CK_3XXX),
        CLK("musb-omap2430",    "ick",  &hsotgusb_ick_3430es1,  CK_3430ES1),
        CLK("musb-omap2430",    "ick",  &hsotgusb_ick_3430es2,  CK_3430ES2PLUS | CK_36XX),
+       CLK(NULL,       "hsotgusb_ick", &hsotgusb_ick_3430es1,  CK_3430ES1),
+       CLK(NULL,       "hsotgusb_ick", &hsotgusb_ick_3430es2,  CK_3430ES2PLUS | CK_36XX),
        CLK(NULL,       "sdrc_ick",     &sdrc_ick,      CK_3XXX),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_3XXX),
        CLK(NULL,       "security_l3_ick", &security_l3_ick, CK_34XX | CK_36XX),
@@ -3329,28 +3336,42 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "core_l4_ick",  &core_l4_ick,   CK_3XXX),
        CLK(NULL,       "usbtll_ick",   &usbtll_ick,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK("usbhs_omap",       "usbtll_ick",   &usbtll_ick,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK("usbhs_tll",        "usbtll_ick",   &usbtll_ick,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK("omap_hsmmc.2",     "ick",  &mmchs3_ick,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK(NULL,       "mmchs3_ick",   &mmchs3_ick,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "icr_ick",      &icr_ick,       CK_34XX | CK_36XX),
        CLK("omap-aes", "ick",  &aes2_ick,      CK_34XX | CK_36XX),
        CLK("omap-sham",        "ick",  &sha12_ick,     CK_34XX | CK_36XX),
        CLK(NULL,       "des2_ick",     &des2_ick,      CK_34XX | CK_36XX),
        CLK("omap_hsmmc.1",     "ick",  &mmchs2_ick,    CK_3XXX),
        CLK("omap_hsmmc.0",     "ick",  &mmchs1_ick,    CK_3XXX),
+       CLK(NULL,       "mmchs2_ick",   &mmchs2_ick,    CK_3XXX),
+       CLK(NULL,       "mmchs1_ick",   &mmchs1_ick,    CK_3XXX),
        CLK(NULL,       "mspro_ick",    &mspro_ick,     CK_34XX | CK_36XX),
        CLK("omap_hdq.0", "ick",        &hdq_ick,       CK_3XXX),
+       CLK(NULL,       "hdq_ick",      &hdq_ick,       CK_3XXX),
        CLK("omap2_mcspi.4", "ick",     &mcspi4_ick,    CK_3XXX),
        CLK("omap2_mcspi.3", "ick",     &mcspi3_ick,    CK_3XXX),
        CLK("omap2_mcspi.2", "ick",     &mcspi2_ick,    CK_3XXX),
        CLK("omap2_mcspi.1", "ick",     &mcspi1_ick,    CK_3XXX),
+       CLK(NULL,       "mcspi4_ick",   &mcspi4_ick,    CK_3XXX),
+       CLK(NULL,       "mcspi3_ick",   &mcspi3_ick,    CK_3XXX),
+       CLK(NULL,       "mcspi2_ick",   &mcspi2_ick,    CK_3XXX),
+       CLK(NULL,       "mcspi1_ick",   &mcspi1_ick,    CK_3XXX),
        CLK("omap_i2c.3", "ick",        &i2c3_ick,      CK_3XXX),
        CLK("omap_i2c.2", "ick",        &i2c2_ick,      CK_3XXX),
        CLK("omap_i2c.1", "ick",        &i2c1_ick,      CK_3XXX),
+       CLK(NULL,       "i2c3_ick",     &i2c3_ick,      CK_3XXX),
+       CLK(NULL,       "i2c2_ick",     &i2c2_ick,      CK_3XXX),
+       CLK(NULL,       "i2c1_ick",     &i2c1_ick,      CK_3XXX),
        CLK(NULL,       "uart2_ick",    &uart2_ick,     CK_3XXX),
        CLK(NULL,       "uart1_ick",    &uart1_ick,     CK_3XXX),
        CLK(NULL,       "gpt11_ick",    &gpt11_ick,     CK_3XXX),
        CLK(NULL,       "gpt10_ick",    &gpt10_ick,     CK_3XXX),
        CLK("omap-mcbsp.5", "ick",      &mcbsp5_ick,    CK_3XXX),
        CLK("omap-mcbsp.1", "ick",      &mcbsp1_ick,    CK_3XXX),
+       CLK(NULL,       "mcbsp5_ick",   &mcbsp5_ick,    CK_3XXX),
+       CLK(NULL,       "mcbsp1_ick",   &mcbsp1_ick,    CK_3XXX),
        CLK(NULL,       "fac_ick",      &fac_ick,       CK_3430ES1),
        CLK(NULL,       "mailboxes_ick", &mailboxes_ick, CK_34XX | CK_36XX),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_3XXX),
@@ -3369,7 +3390,9 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "dss_96m_fck",  &dss_96m_fck,   CK_3XXX),
        CLK(NULL,       "dss2_alwon_fck",       &dss2_alwon_fck, CK_3XXX),
        CLK("omapdss_dss",      "ick",          &dss_ick_3430es1,       CK_3430ES1),
+       CLK(NULL,       "dss_ick",              &dss_ick_3430es1,       CK_3430ES1),
        CLK("omapdss_dss",      "ick",          &dss_ick_3430es2,       CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+       CLK(NULL,       "dss_ick",              &dss_ick_3430es2,       CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "cam_mclk",     &cam_mclk,      CK_34XX | CK_36XX),
        CLK(NULL,       "cam_ick",      &cam_ick,       CK_34XX | CK_36XX),
        CLK(NULL,       "csi2_96m_fck", &csi2_96m_fck,  CK_34XX | CK_36XX),
@@ -3385,6 +3408,8 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "usb_host_hs_utmi_p2_clk",      &dummy_ck,      CK_3XXX),
        CLK("usbhs_omap",       "usb_tll_hs_usb_ch0_clk",       &dummy_ck,      CK_3XXX),
        CLK("usbhs_omap",       "usb_tll_hs_usb_ch1_clk",       &dummy_ck,      CK_3XXX),
+       CLK("usbhs_tll",        "usb_tll_hs_usb_ch0_clk",       &dummy_ck,      CK_3XXX),
+       CLK("usbhs_tll",        "usb_tll_hs_usb_ch1_clk",       &dummy_ck,      CK_3XXX),
        CLK(NULL,       "init_60m_fclk",        &dummy_ck,      CK_3XXX),
        CLK(NULL,       "usim_fck",     &usim_fck,      CK_3430ES2PLUS | CK_36XX),
        CLK(NULL,       "gpt1_fck",     &gpt1_fck,      CK_3XXX),
@@ -3394,6 +3419,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "wkup_l4_ick",  &wkup_l4_ick,   CK_34XX | CK_36XX),
        CLK(NULL,       "usim_ick",     &usim_ick,      CK_3430ES2PLUS | CK_36XX),
        CLK("omap_wdt", "ick",          &wdt2_ick,      CK_3XXX),
+       CLK(NULL,       "wdt2_ick",     &wdt2_ick,      CK_3XXX),
        CLK(NULL,       "wdt1_ick",     &wdt1_ick,      CK_3XXX),
        CLK(NULL,       "gpio1_ick",    &gpio1_ick,     CK_3XXX),
        CLK(NULL,       "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
@@ -3439,9 +3465,13 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK("omap-mcbsp.2", "ick",      &mcbsp2_ick,    CK_3XXX),
        CLK("omap-mcbsp.3", "ick",      &mcbsp3_ick,    CK_3XXX),
        CLK("omap-mcbsp.4", "ick",      &mcbsp4_ick,    CK_3XXX),
+       CLK(NULL,       "mcbsp4_ick",   &mcbsp2_ick,    CK_3XXX),
+       CLK(NULL,       "mcbsp3_ick",   &mcbsp3_ick,    CK_3XXX),
+       CLK(NULL,       "mcbsp2_ick",   &mcbsp4_ick,    CK_3XXX),
        CLK(NULL,       "mcbsp2_fck",   &mcbsp2_fck,    CK_3XXX),
        CLK(NULL,       "mcbsp3_fck",   &mcbsp3_fck,    CK_3XXX),
        CLK(NULL,       "mcbsp4_fck",   &mcbsp4_fck,    CK_3XXX),
+       CLK(NULL,       "emu_src_ck",   &emu_src_ck,    CK_3XXX),
        CLK("etb",      "emu_src_ck",   &emu_src_ck,    CK_3XXX),
        CLK(NULL,       "pclk_fck",     &pclk_fck,      CK_3XXX),
        CLK(NULL,       "pclkx2_fck",   &pclkx2_fck,    CK_3XXX),
@@ -3457,8 +3487,12 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ipss_ick",     &ipss_ick,      CK_AM35XX),
        CLK(NULL,       "rmii_ck",      &rmii_ck,       CK_AM35XX),
        CLK(NULL,       "pclk_ck",      &pclk_ck,       CK_AM35XX),
+       CLK(NULL,       "emac_ick",     &emac_ick,      CK_AM35XX),
+       CLK(NULL,       "emac_fck",     &emac_fck,      CK_AM35XX),
        CLK("davinci_emac.0",   NULL,   &emac_ick,      CK_AM35XX),
        CLK("davinci_mdio.0",   NULL,   &emac_fck,      CK_AM35XX),
+       CLK(NULL,       "vpfe_ick",     &emac_ick,      CK_AM35XX),
+       CLK(NULL,       "vpfe_fck",     &emac_fck,      CK_AM35XX),
        CLK("vpfe-capture",     "master",       &vpfe_ick,      CK_AM35XX),
        CLK("vpfe-capture",     "slave",        &vpfe_fck,      CK_AM35XX),
        CLK(NULL,       "hsotgusb_ick",         &hsotgusb_ick_am35xx,   CK_AM35XX),
@@ -3467,6 +3501,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "uart4_ick",    &uart4_ick_am35xx,      CK_AM35XX),
        CLK(NULL,       "timer_32k_ck", &omap_32k_fck,  CK_3XXX),
        CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_3XXX),
+       CLK(NULL,       "cpufreq_ck",   &dpll1_ck,      CK_3XXX),
 };
 
 
index 500682c051c1fee927af4329671a0df3f9e7ff3c..d661d138f27057d2dcc2130d741f6c0fa53bcb9d 100644 (file)
@@ -3156,6 +3156,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk,    CK_443X),
        CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk, CK_443X),
        CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk,   CK_443X),
+       CLK(NULL,       "dss_fck",                      &dss_fck,       CK_443X),
        CLK("omapdss_dss",      "ick",                          &dss_fck,       CK_443X),
        CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
        CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
@@ -3212,6 +3213,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
        CLK(NULL,       "ocp2scp_usb_phy_ick",          &ocp2scp_usb_phy_ick,   CK_443X),
        CLK(NULL,       "ocp_wp_noc_ick",               &ocp_wp_noc_ick,        CK_443X),
+       CLK(NULL,       "rng_ick",                      &rng_ick,       CK_443X),
        CLK("omap_rng", "ick",                          &rng_ick,       CK_443X),
        CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck,   CK_443X),
        CLK(NULL,       "sl2if_ick",                    &sl2if_ick,     CK_443X),
@@ -3243,6 +3245,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "uart3_fck",                    &uart3_fck,     CK_443X),
        CLK(NULL,       "uart4_fck",                    &uart4_fck,     CK_443X),
        CLK("usbhs_omap",       "fs_fck",               &usb_host_fs_fck,       CK_443X),
+       CLK(NULL,       "usb_host_fs_fck",              &usb_host_fs_fck,       CK_443X),
        CLK(NULL,       "utmi_p1_gfclk",                &utmi_p1_gfclk, CK_443X),
        CLK(NULL,       "usb_host_hs_utmi_p1_clk",      &usb_host_hs_utmi_p1_clk,       CK_443X),
        CLK(NULL,       "utmi_p2_gfclk",                &utmi_p2_gfclk, CK_443X),
@@ -3253,15 +3256,19 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "usb_host_hs_hsic60m_p2_clk",   &usb_host_hs_hsic60m_p2_clk,    CK_443X),
        CLK(NULL,       "usb_host_hs_hsic480m_p2_clk",  &usb_host_hs_hsic480m_p2_clk,   CK_443X),
        CLK(NULL,       "usb_host_hs_func48mclk",       &usb_host_hs_func48mclk,        CK_443X),
+       CLK(NULL,       "usb_host_hs_fck",              &usb_host_hs_fck,       CK_443X),
        CLK("usbhs_omap",       "hs_fck",               &usb_host_hs_fck,       CK_443X),
        CLK(NULL,       "otg_60m_gfclk",                &otg_60m_gfclk, CK_443X),
        CLK(NULL,       "usb_otg_hs_xclk",              &usb_otg_hs_xclk,       CK_443X),
+       CLK(NULL,       "usb_otg_hs_ick",               &usb_otg_hs_ick,        CK_443X),
        CLK("musb-omap2430",    "ick",                          &usb_otg_hs_ick,        CK_443X),
        CLK(NULL,       "usb_phy_cm_clk32k",            &usb_phy_cm_clk32k,     CK_443X),
        CLK(NULL,       "usb_tll_hs_usb_ch2_clk",       &usb_tll_hs_usb_ch2_clk,        CK_443X),
        CLK(NULL,       "usb_tll_hs_usb_ch0_clk",       &usb_tll_hs_usb_ch0_clk,        CK_443X),
        CLK(NULL,       "usb_tll_hs_usb_ch1_clk",       &usb_tll_hs_usb_ch1_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_ick",               &usb_tll_hs_ick,        CK_443X),
        CLK("usbhs_omap",       "usbtll_ick",           &usb_tll_hs_ick,        CK_443X),
+       CLK("usbhs_tll",        "usbtll_ick",           &usb_tll_hs_ick,        CK_443X),
        CLK(NULL,       "usim_ck",                      &usim_ck,       CK_443X),
        CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
        CLK(NULL,       "usim_fck",                     &usim_fck,      CK_443X),
@@ -3312,8 +3319,10 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "uart4_ick",                    &dummy_ck,      CK_443X),
        CLK("usbhs_omap",       "usbhost_ick",          &dummy_ck,              CK_443X),
        CLK("usbhs_omap",       "usbtll_fck",           &dummy_ck,      CK_443X),
+       CLK("usbhs_tll",        "usbtll_fck",           &dummy_ck,      CK_443X),
        CLK("omap_wdt", "ick",                          &dummy_ck,      CK_443X),
        CLK(NULL,       "timer_32k_ck", &sys_32k_ck,    CK_443X),
+       /* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
        CLK("omap_timer.1",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
        CLK("omap_timer.2",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
        CLK("omap_timer.3",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
@@ -3325,6 +3334,18 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("omap_timer.6",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
        CLK("omap_timer.7",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
        CLK("omap_timer.8",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("4a318000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("48032000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("48034000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("48036000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("4803e000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("48086000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("48088000.timer",   "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("49038000.timer",   "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("4903a000.timer",   "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("4903c000.timer",   "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("4903e000.timer",   "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK(NULL,       "cpufreq_ck",   &dpll_mpu_ck,   CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
index a1555627ad973048ea36f9dca72baa235dae52a3..cbb879139c51fd915c7ea50d00a6e91ad730d8b3 100644 (file)
@@ -899,6 +899,23 @@ bool clkdm_in_hwsup(struct clockdomain *clkdm)
        return ret;
 }
 
+/**
+ * clkdm_missing_idle_reporting - can @clkdm enter autoidle even if in use?
+ * @clkdm: struct clockdomain *
+ *
+ * Returns true if clockdomain @clkdm has the
+ * CLKDM_MISSING_IDLE_REPORTING flag set, or false if not or @clkdm is
+ * null.  More information is available in the documentation for the
+ * CLKDM_MISSING_IDLE_REPORTING macro.
+ */
+bool clkdm_missing_idle_reporting(struct clockdomain *clkdm)
+{
+       if (!clkdm)
+               return false;
+
+       return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false;
+}
+
 /* Clockdomain-to-clock/hwmod framework interface code */
 
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
index 5601dc13785ed606f0ce1bdf562472270489811a..629576be74445419fbc815fdfd8861cd2190943a 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * arch/arm/plat-omap/include/mach/clockdomain.h
- *
  * OMAP2/3 clockdomain framework functions
  *
- * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008, 2012 Texas Instruments, Inc.
  * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Paul Walmsley
  * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is
  *     active whenever the MPU is active.  True for interconnects and
  *     the WKUP clockdomains.
+ * CLKDM_MISSING_IDLE_REPORTING: The idle status of the IP blocks and
+ *     clocks inside this clockdomain are not taken into account by
+ *     the PRCM when determining whether the clockdomain is idle.
+ *     Without this flag, if the clockdomain is set to
+ *     hardware-supervised idle mode, the PRCM may transition the
+ *     enclosing powerdomain to a low power state, even when devices
+ *     inside the clockdomain and powerdomain are in use.  (An example
+ *     of such a clockdomain is the EMU clockdomain on OMAP3/4.)  If
+ *     this flag is set, and the clockdomain does not support the
+ *     force-sleep mode, then the HW_AUTO mode will be used to put the
+ *     clockdomain to sleep.  Similarly, if the clockdomain supports
+ *     the force-wakeup mode, then it will be used whenever a clock or
+ *     IP block inside the clockdomain is active, rather than the
+ *     HW_AUTO mode.
  */
 #define CLKDM_CAN_FORCE_SLEEP                  (1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP                 (1 << 1)
@@ -41,6 +53,7 @@
 #define CLKDM_CAN_DISABLE_AUTO                 (1 << 3)
 #define CLKDM_NO_AUTODEPS                      (1 << 4)
 #define CLKDM_ACTIVE_WITH_MPU                  (1 << 5)
+#define CLKDM_MISSING_IDLE_REPORTING           (1 << 6)
 
 #define CLKDM_CAN_HWSUP                (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP                (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
@@ -187,6 +200,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 void clkdm_allow_idle(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
 bool clkdm_in_hwsup(struct clockdomain *clkdm);
+bool clkdm_missing_idle_reporting(struct clockdomain *clkdm);
 
 int clkdm_wakeup(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
index f99e65cfb86223c77ed544d1a8fbe6a0c4ad4b51..9a7792aec6730f498a642810073888ad6b12df38 100644 (file)
@@ -162,6 +162,19 @@ static void _disable_hwsup(struct clockdomain *clkdm)
                                                clkdm->clktrctrl_mask);
 }
 
+static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+{
+       omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+       return 0;
+}
+
+static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+{
+       omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+       return 0;
+}
 
 static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
 {
@@ -170,6 +183,17 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
+       /*
+        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+        * more details on the unpleasant problem this is working
+        * around
+        */
+       if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+           !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+               _enable_hwsup(clkdm);
+               return 0;
+       }
+
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
@@ -193,6 +217,17 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
        if (!clkdm->clktrctrl_mask)
                return 0;
 
+       /*
+        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+        * more details on the unpleasant problem this is working
+        * around
+        */
+       if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
+           (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
+               omap3_clkdm_wakeup(clkdm);
+               return 0;
+       }
+
        hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
                                clkdm->clktrctrl_mask);
 
@@ -209,20 +244,6 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
        return 0;
 }
 
-static int omap3_clkdm_sleep(struct clockdomain *clkdm)
-{
-       omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
-                               clkdm->clktrctrl_mask);
-       return 0;
-}
-
-static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
-{
-       omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
-                               clkdm->clktrctrl_mask);
-       return 0;
-}
-
 static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
 {
        if (atomic_read(&clkdm->usecount) > 0)
index 762f2cc542cec0badf1316a5ae9144426892a54b..6fc6155625bc2473afbf1f31ad7b922a836019bb 100644 (file)
@@ -113,6 +113,17 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
        if (!clkdm->prcm_partition)
                return 0;
 
+       /*
+        * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
+        * more details on the unpleasant problem this is working
+        * around
+        */
+       if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
+           !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+               omap4_clkdm_allow_idle(clkdm);
+               return 0;
+       }
+
        hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
                                        clkdm->cm_inst, clkdm->clkdm_offs);
 
index 56089c49142a9e810a11ca0e60bbcf62f0fae7da..933a35cd124a33a1184639054afba1d582623fc0 100644 (file)
@@ -387,14 +387,11 @@ static struct clockdomain per_am35x_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 };
 
-/*
- * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
- * switched of even if sdti is in use
- */
 static struct clockdomain emu_clkdm = {
        .name           = "emu_clkdm",
        .pwrdm          = { .name = "emu_pwrdm" },
-       .flags          = /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
+       .flags          = (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP |
+                          CLKDM_MISSING_IDLE_REPORTING),
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
 };
 
index 63d60a773d3b2e51e7e65bd6131a207871daa0dc..b56d06b48782a8608f77c43f9902972c1cb24bd5 100644 (file)
@@ -390,7 +390,8 @@ static struct clockdomain emu_sys_44xx_clkdm = {
        .prcm_partition   = OMAP4430_PRM_PARTITION,
        .cm_inst          = OMAP4430_PRM_EMU_CM_INST,
        .clkdm_offs       = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
-       .flags            = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_FORCE_WAKEUP,
+       .flags            = (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_FORCE_WAKEUP |
+                            CLKDM_MISSING_IDLE_REPORTING),
 };
 
 static struct clockdomain l3_dma_44xx_clkdm = {
index 532027ee3d8db7d7f35d7f0ba5c3eb6882770002..adf7bb79b18fe6e78b3be9b5e4b2b68007a7ed4a 100644 (file)
  * CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER
  */
 #define AM33XX_AUTO_DPLL_MODE_SHIFT                    0
+#define AM33XX_AUTO_DPLL_MODE_WIDTH                    3
 #define AM33XX_AUTO_DPLL_MODE_MASK                     (0x7 << 0)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_ADC_FCLK_SHIFT              14
+#define AM33XX_CLKACTIVITY_ADC_FCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_ADC_FCLK_MASK               (1 << 16)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CAN_CLK_SHIFT               11
+#define AM33XX_CLKACTIVITY_CAN_CLK_WIDTH               1
 #define AM33XX_CLKACTIVITY_CAN_CLK_MASK                        (1 << 11)
 
 /* Used by CM_PER_CLK_24MHZ_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_SHIFT                4
+#define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_WIDTH                1
 #define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_MASK         (1 << 4)
 
 /* Used by CM_PER_CPSW_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_WIDTH      1
 #define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_MASK       (1 << 4)
 
 /* Used by CM_PER_L4HS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_WIDTH      1
 #define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_MASK       (1 << 4)
 
 /* Used by CM_PER_L4HS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_SHIFT       5
+#define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_WIDTH       1
 #define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_MASK                (1 << 5)
 
 /* Used by CM_PER_L4HS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_SHIFT                6
+#define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_WIDTH                1
 #define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_MASK         (1 << 6)
 
 /* Used by CM_PER_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_SHIFT         6
+#define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_MASK          (1 << 6)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT    9
+#define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_WIDTH    1
 #define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK     (1 << 9)
 
 /* Used by CM_L3_AON_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_DBGSYSCLK_SHIFT             2
+#define AM33XX_CLKACTIVITY_DBGSYSCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_DBGSYSCLK_MASK              (1 << 2)
 
 /* Used by CM_L3_AON_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_DEBUG_CLKA_SHIFT            4
+#define AM33XX_CLKACTIVITY_DEBUG_CLKA_WIDTH            1
 #define AM33XX_CLKACTIVITY_DEBUG_CLKA_MASK             (1 << 4)
 
 /* Used by CM_PER_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_EMIF_GCLK_SHIFT             2
+#define AM33XX_CLKACTIVITY_EMIF_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_EMIF_GCLK_MASK              (1 << 2)
 
 /* Used by CM_GFX_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GFX_FCLK_SHIFT              9
+#define AM33XX_CLKACTIVITY_GFX_FCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_GFX_FCLK_MASK               (1 << 9)
 
 /* Used by CM_GFX_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GFX_L3_GCLK_SHIFT           8
+#define AM33XX_CLKACTIVITY_GFX_L3_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_GFX_L3_GCLK_MASK            (1 << 8)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_SHIFT          8
+#define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_WIDTH          1
 #define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_MASK           (1 << 8)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_SHIFT         19
+#define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_MASK          (1 << 19)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_SHIFT         20
+#define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_MASK          (1 << 20)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_SHIFT         21
+#define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_MASK          (1 << 21)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_SHIFT         22
+#define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_MASK          (1 << 22)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_SHIFT         26
+#define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_MASK          (1 << 26)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_SHIFT         18
+#define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_MASK          (1 << 18)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_I2C0_GFCLK_SHIFT            11
+#define AM33XX_CLKACTIVITY_I2C0_GFCLK_WIDTH            1
 #define AM33XX_CLKACTIVITY_I2C0_GFCLK_MASK             (1 << 11)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_I2C_FCLK_SHIFT              24
+#define AM33XX_CLKACTIVITY_I2C_FCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_I2C_FCLK_MASK               (1 << 24)
 
 /* Used by CM_PER_PRUSS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_SHIFT                5
+#define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_WIDTH                1
 #define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_MASK         (1 << 5)
 
 /* Used by CM_PER_PRUSS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_SHIFT                4
+#define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_WIDTH                1
 #define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_MASK         (1 << 4)
 
 /* Used by CM_PER_PRUSS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_SHIFT       6
+#define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_WIDTH       1
 #define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_MASK                (1 << 6)
 
 /* Used by CM_PER_L3S_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L3S_GCLK_SHIFT              3
+#define AM33XX_CLKACTIVITY_L3S_GCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_L3S_GCLK_MASK               (1 << 3)
 
 /* Used by CM_L3_AON_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L3_AON_GCLK_SHIFT           3
+#define AM33XX_CLKACTIVITY_L3_AON_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_L3_AON_GCLK_MASK            (1 << 3)
 
 /* Used by CM_PER_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L3_GCLK_SHIFT               4
+#define AM33XX_CLKACTIVITY_L3_GCLK_WIDTH               1
 #define AM33XX_CLKACTIVITY_L3_GCLK_MASK                        (1 << 4)
 
 /* Used by CM_PER_L4FW_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4FW_GCLK_SHIFT             8
+#define AM33XX_CLKACTIVITY_L4FW_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_L4FW_GCLK_MASK              (1 << 8)
 
 /* Used by CM_PER_L4HS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4HS_GCLK_SHIFT             3
+#define AM33XX_CLKACTIVITY_L4HS_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_L4HS_GCLK_MASK              (1 << 3)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4LS_GCLK_SHIFT             8
+#define AM33XX_CLKACTIVITY_L4LS_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_L4LS_GCLK_MASK              (1 << 8)
 
 /* Used by CM_GFX_L4LS_GFX_CLKSTCTRL__1 */
 #define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_SHIFT         8
+#define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_MASK          (1 << 8)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT       8
+#define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_WIDTH       1
 #define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_MASK                (1 << 8)
 
 /* Used by CM_RTC_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4_RTC_GCLK_SHIFT           8
+#define AM33XX_CLKACTIVITY_L4_RTC_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_L4_RTC_GCLK_MASK            (1 << 8)
 
 /* Used by CM_L4_WKUP_AON_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_SHIFT      2
+#define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_WIDTH      1
 #define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_MASK       (1 << 2)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_SHIFT          2
+#define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_WIDTH          1
 #define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_MASK           (1 << 2)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_LCDC_GCLK_SHIFT             17
+#define AM33XX_CLKACTIVITY_LCDC_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_LCDC_GCLK_MASK              (1 << 17)
 
 /* Used by CM_PER_LCDC_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_WIDTH      1
 #define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_MASK       (1 << 4)
 
 /* Used by CM_PER_LCDC_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_SHIFT      5
+#define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_WIDTH      1
 #define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_MASK       (1 << 5)
 
 /* Used by CM_PER_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_MCASP_GCLK_SHIFT            7
+#define AM33XX_CLKACTIVITY_MCASP_GCLK_WIDTH            1
 #define AM33XX_CLKACTIVITY_MCASP_GCLK_MASK             (1 << 7)
 
 /* Used by CM_PER_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_MMC_FCLK_SHIFT              3
+#define AM33XX_CLKACTIVITY_MMC_FCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_MMC_FCLK_MASK               (1 << 3)
 
 /* Used by CM_MPU_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_MPU_CLK_SHIFT               2
+#define AM33XX_CLKACTIVITY_MPU_CLK_WIDTH               1
 #define AM33XX_CLKACTIVITY_MPU_CLK_MASK                        (1 << 2)
 
 /* Used by CM_PER_OCPWP_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_SHIFT         4
+#define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_MASK          (1 << 4)
 
 /* Used by CM_PER_OCPWP_L3_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_SHIFT         5
+#define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_WIDTH         1
 #define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_MASK          (1 << 5)
 
 /* Used by CM_RTC_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_RTC_32KCLK_SHIFT            9
+#define AM33XX_CLKACTIVITY_RTC_32KCLK_WIDTH            1
 #define AM33XX_CLKACTIVITY_RTC_32KCLK_MASK             (1 << 9)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_SPI_GCLK_SHIFT              25
+#define AM33XX_CLKACTIVITY_SPI_GCLK_WIDTH              1
 #define AM33XX_CLKACTIVITY_SPI_GCLK_MASK               (1 << 25)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_SR_SYSCLK_SHIFT             3
+#define AM33XX_CLKACTIVITY_SR_SYSCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_SR_SYSCLK_MASK              (1 << 3)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER0_GCLK_SHIFT           10
+#define AM33XX_CLKACTIVITY_TIMER0_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER0_GCLK_MASK            (1 << 10)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER1_GCLK_SHIFT           13
+#define AM33XX_CLKACTIVITY_TIMER1_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER1_GCLK_MASK            (1 << 13)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER2_GCLK_SHIFT           14
+#define AM33XX_CLKACTIVITY_TIMER2_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER2_GCLK_MASK            (1 << 14)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER3_GCLK_SHIFT           15
+#define AM33XX_CLKACTIVITY_TIMER3_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER3_GCLK_MASK            (1 << 15)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER4_GCLK_SHIFT           16
+#define AM33XX_CLKACTIVITY_TIMER4_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER4_GCLK_MASK            (1 << 16)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER5_GCLK_SHIFT           27
+#define AM33XX_CLKACTIVITY_TIMER5_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER5_GCLK_MASK            (1 << 27)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER6_GCLK_SHIFT           28
+#define AM33XX_CLKACTIVITY_TIMER6_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER6_GCLK_MASK            (1 << 28)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_TIMER7_GCLK_SHIFT           13
+#define AM33XX_CLKACTIVITY_TIMER7_GCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_TIMER7_GCLK_MASK            (1 << 13)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_UART0_GFCLK_SHIFT           12
+#define AM33XX_CLKACTIVITY_UART0_GFCLK_WIDTH           1
 #define AM33XX_CLKACTIVITY_UART0_GFCLK_MASK            (1 << 12)
 
 /* Used by CM_PER_L4LS_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_UART_GFCLK_SHIFT            10
+#define AM33XX_CLKACTIVITY_UART_GFCLK_WIDTH            1
 #define AM33XX_CLKACTIVITY_UART_GFCLK_MASK             (1 << 10)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_WDT0_GCLK_SHIFT             9
+#define AM33XX_CLKACTIVITY_WDT0_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_WDT0_GCLK_MASK              (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define AM33XX_CLKACTIVITY_WDT1_GCLK_SHIFT             4
+#define AM33XX_CLKACTIVITY_WDT1_GCLK_WIDTH             1
 #define AM33XX_CLKACTIVITY_WDT1_GCLK_MASK              (1 << 4)
 
 /* Used by CLKSEL_GFX_FCLK */
 #define AM33XX_CLKDIV_SEL_GFX_FCLK_SHIFT               0
+#define AM33XX_CLKDIV_SEL_GFX_FCLK_WIDTH               1
 #define AM33XX_CLKDIV_SEL_GFX_FCLK_MASK                        (1 << 0)
 
 /* Used by CM_CLKOUT_CTRL */
 #define AM33XX_CLKOUT2DIV_SHIFT                                3
-#define AM33XX_CLKOUT2DIV_MASK                         (0x05 << 3)
+#define AM33XX_CLKOUT2DIV_WIDTH                                3
+#define AM33XX_CLKOUT2DIV_MASK                         (0x7 << 3)
 
 /* Used by CM_CLKOUT_CTRL */
 #define AM33XX_CLKOUT2EN_SHIFT                         7
+#define AM33XX_CLKOUT2EN_WIDTH                         1
 #define AM33XX_CLKOUT2EN_MASK                          (1 << 7)
 
 /* Used by CM_CLKOUT_CTRL */
 #define AM33XX_CLKOUT2SOURCE_SHIFT                     0
-#define AM33XX_CLKOUT2SOURCE_MASK                      (0x02 << 0)
+#define AM33XX_CLKOUT2SOURCE_WIDTH                     3
+#define AM33XX_CLKOUT2SOURCE_MASK                      (0x7 << 0)
 
 /*
  * Used by CLKSEL_GPIO0_DBCLK, CLKSEL_LCDC_PIXEL_CLK, CLKSEL_TIMER2_CLK,
  * CLKSEL_TIMER7_CLK
  */
 #define AM33XX_CLKSEL_SHIFT                            0
+#define AM33XX_CLKSEL_WIDTH                            1
 #define AM33XX_CLKSEL_MASK                             (0x01 << 0)
 
 /*
  * CM_CPTS_RFT_CLKSEL
  */
 #define AM33XX_CLKSEL_0_0_SHIFT                                0
+#define AM33XX_CLKSEL_0_0_WIDTH                                1
 #define AM33XX_CLKSEL_0_0_MASK                         (1 << 0)
 
 #define AM33XX_CLKSEL_0_1_SHIFT                                0
+#define AM33XX_CLKSEL_0_1_WIDTH                                2
 #define AM33XX_CLKSEL_0_1_MASK                         (3 << 0)
 
 /* Renamed from CLKSEL Used by CLKSEL_TIMER1MS_CLK */
 #define AM33XX_CLKSEL_0_2_SHIFT                                0
+#define AM33XX_CLKSEL_0_2_WIDTH                                3
 #define AM33XX_CLKSEL_0_2_MASK                         (7 << 0)
 
 /* Used by CLKSEL_GFX_FCLK */
 #define AM33XX_CLKSEL_GFX_FCLK_SHIFT                   1
+#define AM33XX_CLKSEL_GFX_FCLK_WIDTH                   1
 #define AM33XX_CLKSEL_GFX_FCLK_MASK                    (1 << 1)
 
 /*
  * CM_GFX_L3_CLKSTCTRL, CM_GFX_L4LS_GFX_CLKSTCTRL__1, CM_CEFUSE_CLKSTCTRL
  */
 #define AM33XX_CLKTRCTRL_SHIFT                         0
+#define AM33XX_CLKTRCTRL_WIDTH                         2
 #define AM33XX_CLKTRCTRL_MASK                          (0x3 << 0)
 
 /*
  * CM_SSC_DELTAMSTEP_DPLL_PER
  */
 #define AM33XX_DELTAMSTEP_SHIFT                                0
-#define AM33XX_DELTAMSTEP_MASK                         (0x19 << 0)
+#define AM33XX_DELTAMSTEP_WIDTH                                20
+#define AM33XX_DELTAMSTEP_MASK                         (0xfffff << 0)
 
 /* Used by CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP, CM_CLKSEL_DPLL_MPU */
 #define AM33XX_DPLL_BYP_CLKSEL_SHIFT                   23
+#define AM33XX_DPLL_BYP_CLKSEL_WIDTH                   1
 #define AM33XX_DPLL_BYP_CLKSEL_MASK                    (1 << 23)
 
 /* Used by CM_CLKDCOLDO_DPLL_PER */
 #define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT          8
+#define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_WIDTH          1
 #define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_MASK           (1 << 8)
 
 /* Used by CM_CLKDCOLDO_DPLL_PER */
 #define AM33XX_DPLL_CLKDCOLDO_PWDN_SHIFT               12
+#define AM33XX_DPLL_CLKDCOLDO_PWDN_WIDTH               1
 #define AM33XX_DPLL_CLKDCOLDO_PWDN_MASK                        (1 << 12)
 
 /* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */
 #define AM33XX_DPLL_CLKOUT_DIV_SHIFT                   0
+#define AM33XX_DPLL_CLKOUT_DIV_WIDTH                   5
 #define AM33XX_DPLL_CLKOUT_DIV_MASK                    (0x1f << 0)
 
 /* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_PER */
 #define AM33XX_DPLL_CLKOUT_DIV_0_6_SHIFT               0
-#define AM33XX_DPLL_CLKOUT_DIV_0_6_MASK                        (0x06 << 0)
+#define AM33XX_DPLL_CLKOUT_DIV_0_6_WIDTH               7
+#define AM33XX_DPLL_CLKOUT_DIV_0_6_MASK                        (0x7f << 0)
 
 /* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */
 #define AM33XX_DPLL_CLKOUT_DIVCHACK_SHIFT              5
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_WIDTH              1
 #define AM33XX_DPLL_CLKOUT_DIVCHACK_MASK               (1 << 5)
 
 /* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_PER */
 #define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_SHIFT       7
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_WIDTH       1
 #define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_MASK                (1 << 7)
 
 /*
  * CM_DIV_M2_DPLL_PER
  */
 #define AM33XX_DPLL_CLKOUT_GATE_CTRL_SHIFT             8
+#define AM33XX_DPLL_CLKOUT_GATE_CTRL_WIDTH             1
 #define AM33XX_DPLL_CLKOUT_GATE_CTRL_MASK              (1 << 8)
 
 /*
  * CM_CLKSEL_DPLL_MPU
  */
 #define AM33XX_DPLL_DIV_SHIFT                          0
+#define AM33XX_DPLL_DIV_WIDTH                          7
 #define AM33XX_DPLL_DIV_MASK                           (0x7f << 0)
 
 #define AM33XX_DPLL_PER_DIV_MASK                       (0xff << 0)
 
 /* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_PERIPH */
 #define AM33XX_DPLL_DIV_0_7_SHIFT                      0
-#define AM33XX_DPLL_DIV_0_7_MASK                       (0x07 << 0)
+#define AM33XX_DPLL_DIV_0_7_WIDTH                      8
+#define AM33XX_DPLL_DIV_0_7_MASK                       (0xff << 0)
 
 /*
  * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
  * CM_CLKMODE_DPLL_MPU
  */
 #define AM33XX_DPLL_DRIFTGUARD_EN_SHIFT                        8
+#define AM33XX_DPLL_DRIFTGUARD_EN_WIDTH                        1
 #define AM33XX_DPLL_DRIFTGUARD_EN_MASK                 (1 << 8)
 
 /*
  * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define AM33XX_DPLL_EN_SHIFT                           0
+#define AM33XX_DPLL_EN_WIDTH                           3
 #define AM33XX_DPLL_EN_MASK                            (0x7 << 0)
 
 /*
  * CM_CLKMODE_DPLL_MPU
  */
 #define AM33XX_DPLL_LPMODE_EN_SHIFT                    10
+#define AM33XX_DPLL_LPMODE_EN_WIDTH                    1
 #define AM33XX_DPLL_LPMODE_EN_MASK                     (1 << 10)
 
 /*
  * CM_CLKSEL_DPLL_MPU
  */
 #define AM33XX_DPLL_MULT_SHIFT                         8
+#define AM33XX_DPLL_MULT_WIDTH                         11
 #define AM33XX_DPLL_MULT_MASK                          (0x7ff << 8)
 
 /* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_PERIPH */
 #define AM33XX_DPLL_MULT_PERIPH_SHIFT                  8
+#define AM33XX_DPLL_MULT_PERIPH_WIDTH                  12
 #define AM33XX_DPLL_MULT_PERIPH_MASK                   (0xfff << 8)
 
 /*
  * CM_CLKMODE_DPLL_MPU
  */
 #define AM33XX_DPLL_REGM4XEN_SHIFT                     11
+#define AM33XX_DPLL_REGM4XEN_WIDTH                     1
 #define AM33XX_DPLL_REGM4XEN_MASK                      (1 << 11)
 
 /* Used by CM_CLKSEL_DPLL_PERIPH */
 #define AM33XX_DPLL_SD_DIV_SHIFT                       24
-#define AM33XX_DPLL_SD_DIV_MASK                                (24, 31)
+#define AM33XX_DPLL_SD_DIV_WIDTH                       8
+#define AM33XX_DPLL_SD_DIV_MASK                                (0xff << 24)
 
 /*
  * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
  * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define AM33XX_DPLL_SSC_ACK_SHIFT                      13
+#define AM33XX_DPLL_SSC_ACK_WIDTH                      1
 #define AM33XX_DPLL_SSC_ACK_MASK                       (1 << 13)
 
 /*
  * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define AM33XX_DPLL_SSC_DOWNSPREAD_SHIFT               14
+#define AM33XX_DPLL_SSC_DOWNSPREAD_WIDTH               1
 #define AM33XX_DPLL_SSC_DOWNSPREAD_MASK                        (1 << 14)
 
 /*
  * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define AM33XX_DPLL_SSC_EN_SHIFT                       12
+#define AM33XX_DPLL_SSC_EN_WIDTH                       1
 #define AM33XX_DPLL_SSC_EN_MASK                                (1 << 12)
 
 /* Used by CM_DIV_M4_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT             0
+#define AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH             5
 #define AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK              (0x1f << 0)
 
 /* Used by CM_DIV_M4_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_WIDTH                1
 #define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_MASK         (1 << 5)
 
 /* Used by CM_DIV_M4_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_WIDTH       1
 #define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK                (1 << 8)
 
 /* Used by CM_DIV_M4_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT1_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT1_PWDN_WIDTH            1
 #define AM33XX_HSDIVIDER_CLKOUT1_PWDN_MASK             (1 << 12)
 
 /* Used by CM_DIV_M5_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT             0
+#define AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH             5
 #define AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK              (0x1f << 0)
 
 /* Used by CM_DIV_M5_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_WIDTH                1
 #define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_MASK         (1 << 5)
 
 /* Used by CM_DIV_M5_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_WIDTH       1
 #define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK                (1 << 8)
 
 /* Used by CM_DIV_M5_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT2_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT2_PWDN_WIDTH            1
 #define AM33XX_HSDIVIDER_CLKOUT2_PWDN_MASK             (1 << 12)
 
 /* Used by CM_DIV_M6_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT             0
-#define AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK              (0x04 << 0)
+#define AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH             5
+#define AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK              (0x1f << 0)
 
 /* Used by CM_DIV_M6_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_WIDTH                1
 #define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_MASK         (1 << 5)
 
 /* Used by CM_DIV_M6_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_WIDTH       1
 #define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK                (1 << 8)
 
 /* Used by CM_DIV_M6_DPLL_CORE */
 #define AM33XX_HSDIVIDER_CLKOUT3_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT3_PWDN_WIDTH            1
 #define AM33XX_HSDIVIDER_CLKOUT3_PWDN_MASK             (1 << 12)
 
 /*
  * CM_GFX_MMUCFG_CLKCTRL, CM_GFX_MMUDATA_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL
  */
 #define AM33XX_IDLEST_SHIFT                            16
+#define AM33XX_IDLEST_WIDTH                            2
 #define AM33XX_IDLEST_MASK                             (0x3 << 16)
-#define AM33XX_IDLEST_VAL                              0x3
 
 /* Used by CM_MAC_CLKSEL */
 #define AM33XX_MII_CLK_SEL_SHIFT                       2
+#define AM33XX_MII_CLK_SEL_WIDTH                       1
 #define AM33XX_MII_CLK_SEL_MASK                                (1 << 2)
 
 /*
  * CM_SSC_MODFREQDIV_DPLL_PER
  */
 #define AM33XX_MODFREQDIV_EXPONENT_SHIFT               8
-#define AM33XX_MODFREQDIV_EXPONENT_MASK                        (0x10 << 8)
+#define AM33XX_MODFREQDIV_EXPONENT_WIDTH               3
+#define AM33XX_MODFREQDIV_EXPONENT_MASK                        (0x7 << 8)
 
 /*
  * Used by CM_SSC_MODFREQDIV_DPLL_CORE, CM_SSC_MODFREQDIV_DPLL_DDR,
  * CM_SSC_MODFREQDIV_DPLL_PER
  */
 #define AM33XX_MODFREQDIV_MANTISSA_SHIFT               0
-#define AM33XX_MODFREQDIV_MANTISSA_MASK                        (0x06 << 0)
+#define AM33XX_MODFREQDIV_MANTISSA_WIDTH               7
+#define AM33XX_MODFREQDIV_MANTISSA_MASK                        (0x7f << 0)
 
 /*
  * Used by CM_MPU_MPU_CLKCTRL, CM_RTC_RTC_CLKCTRL, CM_PER_AES0_CLKCTRL,
  * CM_CEFUSE_CEFUSE_CLKCTRL
  */
 #define AM33XX_MODULEMODE_SHIFT                                0
+#define AM33XX_MODULEMODE_WIDTH                                2
 #define AM33XX_MODULEMODE_MASK                         (0x3 << 0)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_OPTCLK_DEBUG_CLKA_SHIFT                 30
+#define AM33XX_OPTCLK_DEBUG_CLKA_WIDTH                 1
 #define AM33XX_OPTCLK_DEBUG_CLKA_MASK                  (1 << 30)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_OPTFCLKEN_DBGSYSCLK_SHIFT               19
+#define AM33XX_OPTFCLKEN_DBGSYSCLK_WIDTH               1
 #define AM33XX_OPTFCLKEN_DBGSYSCLK_MASK                        (1 << 19)
 
 /* Used by CM_WKUP_GPIO0_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT            18
+#define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_WIDTH            1
 #define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_MASK             (1 << 18)
 
 /* Used by CM_PER_GPIO1_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_MASK            (1 << 18)
 
 /* Used by CM_PER_GPIO2_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_MASK            (1 << 18)
 
 /* Used by CM_PER_GPIO3_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_MASK            (1 << 18)
 
 /* Used by CM_PER_GPIO4_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_MASK            (1 << 18)
 
 /* Used by CM_PER_GPIO5_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_MASK            (1 << 18)
 
 /* Used by CM_PER_GPIO6_CLKCTRL */
 #define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_WIDTH           1
 #define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_MASK            (1 << 18)
 
 /*
  * CM_WKUP_WKUP_M3_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, CM_GFX_GFX_CLKCTRL
  */
 #define AM33XX_STBYST_SHIFT                            18
+#define AM33XX_STBYST_WIDTH                            1
 #define AM33XX_STBYST_MASK                             (1 << 18)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_STM_PMD_CLKDIVSEL_SHIFT                 27
-#define AM33XX_STM_PMD_CLKDIVSEL_MASK                  (0x29 << 27)
+#define AM33XX_STM_PMD_CLKDIVSEL_WIDTH                 3
+#define AM33XX_STM_PMD_CLKDIVSEL_MASK                  (0x7 << 27)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_STM_PMD_CLKSEL_SHIFT                    22
-#define AM33XX_STM_PMD_CLKSEL_MASK                     (0x23 << 22)
+#define AM33XX_STM_PMD_CLKSEL_WIDTH                    2
+#define AM33XX_STM_PMD_CLKSEL_MASK                     (0x3 << 22)
 
 /*
  * Used by CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDR, CM_IDLEST_DPLL_DISP,
  * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER
  */
 #define AM33XX_ST_DPLL_CLK_SHIFT                       0
+#define AM33XX_ST_DPLL_CLK_WIDTH                       1
 #define AM33XX_ST_DPLL_CLK_MASK                                (1 << 0)
 
 /* Used by CM_CLKDCOLDO_DPLL_PER */
 #define AM33XX_ST_DPLL_CLKDCOLDO_SHIFT                 8
+#define AM33XX_ST_DPLL_CLKDCOLDO_WIDTH                 1
 #define AM33XX_ST_DPLL_CLKDCOLDO_MASK                  (1 << 8)
 
 /*
  * CM_DIV_M2_DPLL_PER
  */
 #define AM33XX_ST_DPLL_CLKOUT_SHIFT                    9
+#define AM33XX_ST_DPLL_CLKOUT_WIDTH                    1
 #define AM33XX_ST_DPLL_CLKOUT_MASK                     (1 << 9)
 
 /* Used by CM_DIV_M4_DPLL_CORE */
 #define AM33XX_ST_HSDIVIDER_CLKOUT1_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT1_WIDTH              1
 #define AM33XX_ST_HSDIVIDER_CLKOUT1_MASK               (1 << 9)
 
 /* Used by CM_DIV_M5_DPLL_CORE */
 #define AM33XX_ST_HSDIVIDER_CLKOUT2_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT2_WIDTH              1
 #define AM33XX_ST_HSDIVIDER_CLKOUT2_MASK               (1 << 9)
 
 /* Used by CM_DIV_M6_DPLL_CORE */
 #define AM33XX_ST_HSDIVIDER_CLKOUT3_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT3_WIDTH              1
 #define AM33XX_ST_HSDIVIDER_CLKOUT3_MASK               (1 << 9)
 
 /*
  * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER
  */
 #define AM33XX_ST_MN_BYPASS_SHIFT                      8
+#define AM33XX_ST_MN_BYPASS_WIDTH                      1
 #define AM33XX_ST_MN_BYPASS_MASK                       (1 << 8)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_TRC_PMD_CLKDIVSEL_SHIFT                 24
-#define AM33XX_TRC_PMD_CLKDIVSEL_MASK                  (0x26 << 24)
+#define AM33XX_TRC_PMD_CLKDIVSEL_WIDTH                 3
+#define AM33XX_TRC_PMD_CLKDIVSEL_MASK                  (0x7 << 24)
 
 /* Used by CM_WKUP_DEBUGSS_CLKCTRL */
 #define AM33XX_TRC_PMD_CLKSEL_SHIFT                    20
-#define AM33XX_TRC_PMD_CLKSEL_MASK                     (0x21 << 20)
+#define AM33XX_TRC_PMD_CLKSEL_WIDTH                    2
+#define AM33XX_TRC_PMD_CLKSEL_MASK                     (0x3 << 20)
 
 /* Used by CONTROL_SEC_CLK_CTRL */
+#define AM33XX_TIMER0_CLKSEL_WIDTH                     2
 #define AM33XX_TIMER0_CLKSEL_MASK                      (0x3 << 4)
 #endif
index 975f6bda0e0b7a84855a2e6c90f8051df747f6a2..59598ffd878333978b1ca2ed52a26fee3b0e7f72 100644 (file)
 #define OMAP3430_ST_MAILBOXES_MASK                     (1 << 7)
 #define OMAP3430_ST_OMAPCTRL_SHIFT                     6
 #define OMAP3430_ST_OMAPCTRL_MASK                      (1 << 6)
+#define OMAP3430_ST_SAD2D_SHIFT                                3
+#define OMAP3430_ST_SAD2D_MASK                         (1 << 3)
 #define OMAP3430_ST_SDMA_SHIFT                         2
 #define OMAP3430_ST_SDMA_MASK                          (1 << 2)
 #define OMAP3430_ST_SDRC_SHIFT                         1
index 65597a7456381ce61c59e18af61dce641b05ed07..4c6c2f7de65bc6a66062079e1dd702f18ea06599 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP44xx Clock Management register bits
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2012 Texas Instruments, Inc.
  * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
@@ -24,6 +24,7 @@
 
 /* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_ABE_DYNDEP_SHIFT                              3
+#define OMAP4430_ABE_DYNDEP_WIDTH                              0x1
 #define OMAP4430_ABE_DYNDEP_MASK                               (1 << 3)
 
 /*
  * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ABE_STATDEP_SHIFT                             3
+#define OMAP4430_ABE_STATDEP_WIDTH                             0x1
 #define OMAP4430_ABE_STATDEP_MASK                              (1 << 3)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_ALWONCORE_DYNDEP_SHIFT                                16
+#define OMAP4430_ALWONCORE_DYNDEP_WIDTH                                0x1
 #define OMAP4430_ALWONCORE_DYNDEP_MASK                         (1 << 16)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_ALWONCORE_STATDEP_SHIFT                       16
+#define OMAP4430_ALWONCORE_STATDEP_WIDTH                       0x1
 #define OMAP4430_ALWONCORE_STATDEP_MASK                                (1 << 16)
 
 /*
  * CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
  */
 #define OMAP4430_AUTO_DPLL_MODE_SHIFT                          0
+#define OMAP4430_AUTO_DPLL_MODE_WIDTH                          0x3
 #define OMAP4430_AUTO_DPLL_MODE_MASK                           (0x7 << 0)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_CEFUSE_DYNDEP_SHIFT                           17
+#define OMAP4430_CEFUSE_DYNDEP_WIDTH                           0x1
 #define OMAP4430_CEFUSE_DYNDEP_MASK                            (1 << 17)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_CEFUSE_STATDEP_SHIFT                          17
+#define OMAP4430_CEFUSE_STATDEP_WIDTH                          0x1
 #define OMAP4430_CEFUSE_STATDEP_MASK                           (1 << 17)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_SHIFT               13
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK                        (1 << 13)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_SHIFT           12
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK            (1 << 12)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_LP_CLK_SHIFT                  9
+#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK                   (1 << 9)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_SYSCLK_SHIFT                  11
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK                   (1 << 11)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT                  8
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK                   (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT               11
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK                        (1 << 11)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT              12
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK               (1 << 12)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT              13
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK               (1 << 13)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_SHIFT           9
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK            (1 << 9)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_SHIFT                12
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_WIDTH                0x1
 #define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_MASK         (1 << 12)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT           9
+#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            (1 << 9)
 
 /* Used by CM_L4CFG_CLKSTCTRL */
 #define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT               9
+#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_WIDTH               0x1
 #define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK                        (1 << 9)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT          9
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_WIDTH          0x1
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           (1 << 9)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT                     9
+#define OMAP4430_CLKACTIVITY_DLL_CLK_WIDTH                     0x1
 #define OMAP4430_CLKACTIVITY_DLL_CLK_MASK                      (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT                 9
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_WIDTH                 0x1
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK                  (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT                 10
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_WIDTH                 0x1
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK                  (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT                  11
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK                   (1 << 11)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT                  12
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK                   (1 << 12)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT                  13
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK                   (1 << 13)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT                  14
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK                   (1 << 14)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_SHIFT           10
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK            (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_FCLK_SHIFT                    9
+#define OMAP4430_CLKACTIVITY_DSS_FCLK_WIDTH                    0x1
 #define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK                     (1 << 9)
 
 /* Used by CM_DUCATI_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DUCATI_GCLK_SHIFT                 8
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_WIDTH                 0x1
 #define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK                  (1 << 8)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_SHIFT                 8
+#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_WIDTH                 0x1
 #define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK                  (1 << 8)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT                  10
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT              15
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK               (1 << 15)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_SHIFT              10
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK               (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT                11
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_WIDTH                0x1
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK         (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT          20
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_WIDTH          0x1
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK           (1 << 20)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT               26
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK                        (1 << 26)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT          21
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_WIDTH          0x1
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK           (1 << 21)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT               27
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK                        (1 << 27)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT             13
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK              (1 << 13)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT              12
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK               (1 << 12)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT           28
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK            (1 << 28)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT           29
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK            (1 << 29)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT              11
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK               (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT              16
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT           17
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK            (1 << 17)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT           18
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK            (1 << 18)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT           19
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK            (1 << 19)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ISS_GCLK_SHIFT                    8
+#define OMAP4430_CLKACTIVITY_ISS_GCLK_WIDTH                    0x1
 #define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK                     (1 << 8)
 
 /* Used by CM_IVAHD_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_SHIFT              8
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK               (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT              10
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK               (1 << 10)
 
 /* Used by CM_L3_1_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT                  8
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_L3_2_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT                  8
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_SDMA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT               8
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT               8
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_L3INSTR_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_SHIFT              8
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK               (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_SHIFT             8
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_AO_ICLK_SHIFT                  8
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK                   (1 << 8)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT             8
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_L4CFG_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT                        9
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK                 (1 << 9)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT               9
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_SHIFT             9
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK              (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT               12
+#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK                        (1 << 12)
 
 /* Used by CM_MPU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT                        8
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK                 (1 << 8)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT               9
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT              16
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT               17
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK                        (1 << 17)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT               18
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK                        (1 << 18)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT               19
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK                        (1 << 19)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT           25
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_WIDTH           0x1
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK            (1 << 25)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT            20
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_WIDTH            0x1
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK             (1 << 20)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT            22
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_WIDTH            0x1
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK             (1 << 22)
 
 /* Used by CM_L4PER_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT               24
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK                        (1 << 24)
 
 /* Used by CM_MEMIF_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT                        10
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK                 (1 << 10)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SGX_GFCLK_SHIFT                   9
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK_WIDTH                   0x1
 #define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK                    (1 << 9)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_SHIFT              11
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK               (1 << 11)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_SHIFT               10
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK                        (1 << 10)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_SHIFT               9
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK                        (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SYS_CLK_SHIFT                     8
+#define OMAP4430_CLKACTIVITY_SYS_CLK_WIDTH                     0x1
 #define OMAP4430_CLKACTIVITY_SYS_CLK_MASK                      (1 << 8)
 
 /* Used by CM_TESLA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT              8
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK               (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT               22
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK                        (1 << 22)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT               23
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK                        (1 << 23)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT               24
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK                        (1 << 24)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT             10
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK              (1 << 10)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT                        14
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_WIDTH                        0x1
 #define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK                 (1 << 14)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT             15
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK              (1 << 15)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT                  10
+#define OMAP4430_CLKACTIVITY_USIM_GFCLK_WIDTH                  0x1
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT               30
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_WIDTH               0x1
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK                        (1 << 30)
 
 /* Used by CM_L3INIT_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT             25
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_WIDTH             0x1
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK              (1 << 25)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT              11
+#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_WIDTH              0x1
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               (1 << 11)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT               13
+#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_WIDTH               0x1
 #define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK                        (1 << 13)
 
 /*
  * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
  * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
- * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
  * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
  * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL
+ * CM_L4PER_DMTIMER9_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SHIFT                                  24
+#define OMAP4430_CLKSEL_WIDTH                                  0x1
 #define OMAP4430_CLKSEL_MASK                                   (1 << 24)
 
 /*
  * CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ, CM_L4_WKUP_CLKSEL
  */
 #define OMAP4430_CLKSEL_0_0_SHIFT                              0
+#define OMAP4430_CLKSEL_0_0_WIDTH                              0x1
 #define OMAP4430_CLKSEL_0_0_MASK                               (1 << 0)
 
 /* Renamed from CLKSEL Used by CM_BYPCLK_DPLL_IVA, CM_BYPCLK_DPLL_MPU */
 #define OMAP4430_CLKSEL_0_1_SHIFT                              0
+#define OMAP4430_CLKSEL_0_1_WIDTH                              0x2
 #define OMAP4430_CLKSEL_0_1_MASK                               (0x3 << 0)
 
 /* Renamed from CLKSEL Used by CM_L3INIT_HSI_CLKCTRL */
 #define OMAP4430_CLKSEL_24_25_SHIFT                            24
+#define OMAP4430_CLKSEL_24_25_WIDTH                            0x2
 #define OMAP4430_CLKSEL_24_25_MASK                             (0x3 << 24)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_CLKSEL_60M_SHIFT                              24
+#define OMAP4430_CLKSEL_60M_WIDTH                              0x1
 #define OMAP4430_CLKSEL_60M_MASK                               (1 << 24)
 
 /* Used by CM_MPU_MPU_CLKCTRL */
 #define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT                     25
+#define OMAP4460_CLKSEL_ABE_DIV_MODE_WIDTH                     0x1
 #define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK                      (1 << 25)
 
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT                                24
+#define OMAP4430_CLKSEL_AESS_FCLK_WIDTH                                0x1
 #define OMAP4430_CLKSEL_AESS_FCLK_MASK                         (1 << 24)
 
 /* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_CORE_SHIFT                             0
+#define OMAP4430_CLKSEL_CORE_WIDTH                             0x1
 #define OMAP4430_CLKSEL_CORE_MASK                              (1 << 0)
 
 /* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_CLKSEL_CORE_1_1_SHIFT                         1
+#define OMAP4430_CLKSEL_CORE_1_1_WIDTH                         0x1
 #define OMAP4430_CLKSEL_CORE_1_1_MASK                          (1 << 1)
 
 /* Used by CM_WKUP_USIM_CLKCTRL */
 #define OMAP4430_CLKSEL_DIV_SHIFT                              24
+#define OMAP4430_CLKSEL_DIV_WIDTH                              0x1
 #define OMAP4430_CLKSEL_DIV_MASK                               (1 << 24)
 
 /* Used by CM_MPU_MPU_CLKCTRL */
 #define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT                    24
+#define OMAP4460_CLKSEL_EMIF_DIV_MODE_WIDTH                    0x1
 #define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK                     (1 << 24)
 
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT                             24
+#define OMAP4430_CLKSEL_FCLK_WIDTH                             0x2
 #define OMAP4430_CLKSEL_FCLK_MASK                              (0x3 << 24)
 
 /* Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT                  25
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH                  0x1
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK                   (1 << 25)
 
 /*
  * CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT     26
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_WIDTH     0x2
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK      (0x3 << 26)
 
 /* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_L3_SHIFT                               4
+#define OMAP4430_CLKSEL_L3_WIDTH                               0x1
 #define OMAP4430_CLKSEL_L3_MASK                                        (1 << 4)
 
 /* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_CLKSEL_L3_SHADOW_SHIFT                                2
+#define OMAP4430_CLKSEL_L3_SHADOW_WIDTH                                0x1
 #define OMAP4430_CLKSEL_L3_SHADOW_MASK                         (1 << 2)
 
 /* Used by CM_CLKSEL_CORE */
 #define OMAP4430_CLKSEL_L4_SHIFT                               8
+#define OMAP4430_CLKSEL_L4_WIDTH                               0x1
 #define OMAP4430_CLKSEL_L4_MASK                                        (1 << 8)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_CLKSEL_OPP_SHIFT                              0
+#define OMAP4430_CLKSEL_OPP_WIDTH                              0x2
 #define OMAP4430_CLKSEL_OPP_MASK                               (0x3 << 0)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT                      27
+#define OMAP4430_CLKSEL_PMD_STM_CLK_WIDTH                      0x3
 #define OMAP4430_CLKSEL_PMD_STM_CLK_MASK                       (0x7 << 27)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_TRACE_CLK_SHIFT                    24
+#define OMAP4430_CLKSEL_PMD_TRACE_CLK_WIDTH                    0x3
 #define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK                     (0x7 << 24)
 
 /* Used by CM_GFX_GFX_CLKCTRL */
 #define OMAP4430_CLKSEL_SGX_FCLK_SHIFT                         24
+#define OMAP4430_CLKSEL_SGX_FCLK_WIDTH                         0x1
 #define OMAP4430_CLKSEL_SGX_FCLK_MASK                          (1 << 24)
 
 /*
  * CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SOURCE_SHIFT                           24
+#define OMAP4430_CLKSEL_SOURCE_WIDTH                           0x2
 #define OMAP4430_CLKSEL_SOURCE_MASK                            (0x3 << 24)
 
 /* Renamed from CLKSEL_SOURCE Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT                     24
+#define OMAP4430_CLKSEL_SOURCE_24_24_WIDTH                     0x1
 #define OMAP4430_CLKSEL_SOURCE_24_24_MASK                      (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_CLKSEL_UTMI_P1_SHIFT                          24
+#define OMAP4430_CLKSEL_UTMI_P1_WIDTH                          0x1
 #define OMAP4430_CLKSEL_UTMI_P1_MASK                           (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_CLKSEL_UTMI_P2_SHIFT                          25
+#define OMAP4430_CLKSEL_UTMI_P2_WIDTH                          0x1
 #define OMAP4430_CLKSEL_UTMI_P2_MASK                           (1 << 25)
 
 /*
  * CM_TESLA_CLKSTCTRL, CM_WKUP_CLKSTCTRL
  */
 #define OMAP4430_CLKTRCTRL_SHIFT                               0
+#define OMAP4430_CLKTRCTRL_WIDTH                               0x2
 #define OMAP4430_CLKTRCTRL_MASK                                        (0x3 << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_DIV_SHIFT                       0
+#define OMAP4430_CORE_DPLL_EMU_DIV_WIDTH                       0x7
 #define OMAP4430_CORE_DPLL_EMU_DIV_MASK                                (0x7f << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_MULT_SHIFT                      8
+#define OMAP4430_CORE_DPLL_EMU_MULT_WIDTH                      0xb
 #define OMAP4430_CORE_DPLL_EMU_MULT_MASK                       (0x7ff << 8)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_CUSTOM_SHIFT                                  6
+#define OMAP4430_CUSTOM_WIDTH                                  0x2
 #define OMAP4430_CUSTOM_MASK                                   (0x3 << 6)
 
 /* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_D2D_DYNDEP_SHIFT                              18
+#define OMAP4430_D2D_DYNDEP_WIDTH                              0x1
 #define OMAP4430_D2D_DYNDEP_MASK                               (1 << 18)
 
 /* Used by CM_MPU_STATICDEP */
 #define OMAP4430_D2D_STATDEP_SHIFT                             18
+#define OMAP4430_D2D_STATDEP_WIDTH                             0x1
 #define OMAP4430_D2D_STATDEP_MASK                              (1 << 18)
 
 /* Used by CM_CLKSEL_DPLL_MPU */
 #define OMAP4460_DCC_COUNT_MAX_SHIFT                           24
+#define OMAP4460_DCC_COUNT_MAX_WIDTH                           0x8
 #define OMAP4460_DCC_COUNT_MAX_MASK                            (0xff << 24)
 
 /* Used by CM_CLKSEL_DPLL_MPU */
  * CM_SSC_DELTAMSTEP_DPLL_UNIPRO, CM_SSC_DELTAMSTEP_DPLL_USB
  */
 #define OMAP4430_DELTAMSTEP_SHIFT                              0
+#define OMAP4430_DELTAMSTEP_WIDTH                              0x14
 #define OMAP4430_DELTAMSTEP_MASK                               (0xfffff << 0)
 
 /* Renamed from DELTAMSTEP Used by CM_SSC_DELTAMSTEP_DPLL_USB */
 #define OMAP4460_DELTAMSTEP_0_20_SHIFT                         0
+#define OMAP4460_DELTAMSTEP_0_20_WIDTH                         0x15
 #define OMAP4460_DELTAMSTEP_0_20_MASK                          (0x1fffff << 0)
 
 /* Used by CM_DLL_CTRL */
 #define OMAP4430_DLL_OVERRIDE_SHIFT                            0
+#define OMAP4430_DLL_OVERRIDE_WIDTH                            0x1
 #define OMAP4430_DLL_OVERRIDE_MASK                             (1 << 0)
 
 /* Renamed from DLL_OVERRIDE Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DLL_OVERRIDE_2_2_SHIFT                                2
+#define OMAP4430_DLL_OVERRIDE_2_2_WIDTH                                0x1
 #define OMAP4430_DLL_OVERRIDE_2_2_MASK                         (1 << 2)
 
 /* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DLL_RESET_SHIFT                               3
+#define OMAP4430_DLL_RESET_WIDTH                               0x1
 #define OMAP4430_DLL_RESET_MASK                                        (1 << 3)
 
 /*
  * CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB
  */
 #define OMAP4430_DPLL_BYP_CLKSEL_SHIFT                         23
+#define OMAP4430_DPLL_BYP_CLKSEL_WIDTH                         0x1
 #define OMAP4430_DPLL_BYP_CLKSEL_MASK                          (1 << 23)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT                        8
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_WIDTH                        0x1
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK                 (1 << 8)
 
 /* Used by CM_CLKSEL_DPLL_CORE */
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT                   20
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_WIDTH                   0x1
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK                    (1 << 20)
 
 /* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT                      0
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_WIDTH                      0x5
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK                       (0x1f << 0)
 
 /* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT                 5
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_WIDTH                 0x1
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK                  (1 << 5)
 
 /* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT                        8
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_WIDTH                        0x1
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK                 (1 << 8)
 
 /* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_SHIFT                 10
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_WIDTH                 0x1
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK                  (1 << 10)
 
 /*
  * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIV_SHIFT                         0
+#define OMAP4430_DPLL_CLKOUT_DIV_WIDTH                         0x5
 #define OMAP4430_DPLL_CLKOUT_DIV_MASK                          (0x1f << 0)
 
 /* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_SHIFT                     0
+#define OMAP4430_DPLL_CLKOUT_DIV_0_6_WIDTH                     0x7
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK                      (0x7f << 0)
 
 /*
  * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT                    5
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_WIDTH                    0x1
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK                     (1 << 5)
 
 /* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_SHIFT             7
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_WIDTH             0x1
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK              (1 << 7)
 
 /*
  * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT                   8
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_WIDTH                   0x1
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK                    (1 << 8)
 
 /* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT                       8
+#define OMAP4430_DPLL_CORE_DPLL_EN_WIDTH                       0x3
 #define OMAP4430_DPLL_CORE_DPLL_EN_MASK                                (0x7 << 8)
 
 /* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_DPLL_CORE_M2_DIV_SHIFT                                11
+#define OMAP4430_DPLL_CORE_M2_DIV_WIDTH                                0x5
 #define OMAP4430_DPLL_CORE_M2_DIV_MASK                         (0x1f << 11)
 
 /* Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_DPLL_CORE_M5_DIV_SHIFT                                3
+#define OMAP4430_DPLL_CORE_M5_DIV_WIDTH                                0x5
 #define OMAP4430_DPLL_CORE_M5_DIV_MASK                         (0x1f << 3)
 
 /*
  * CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_DIV_SHIFT                                        0
+#define OMAP4430_DPLL_DIV_WIDTH                                        0x7
 #define OMAP4430_DPLL_DIV_MASK                                 (0x7f << 0)
 
 /* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_DIV_0_7_SHIFT                            0
+#define OMAP4430_DPLL_DIV_0_7_WIDTH                            0x8
 #define OMAP4430_DPLL_DIV_0_7_MASK                             (0xff << 0)
 
 /*
  * CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT                      8
+#define OMAP4430_DPLL_DRIFTGUARD_EN_WIDTH                      0x1
 #define OMAP4430_DPLL_DRIFTGUARD_EN_MASK                       (1 << 8)
 
 /* Renamed from DPLL_DRIFTGUARD_EN Used by CM_CLKMODE_DPLL_UNIPRO */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_SHIFT                  3
+#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_WIDTH                  0x1
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK                   (1 << 3)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_EN_SHIFT                                 0
+#define OMAP4430_DPLL_EN_WIDTH                                 0x3
 #define OMAP4430_DPLL_EN_MASK                                  (0x7 << 0)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_LPMODE_EN_SHIFT                          10
+#define OMAP4430_DPLL_LPMODE_EN_WIDTH                          0x1
 #define OMAP4430_DPLL_LPMODE_EN_MASK                           (1 << 10)
 
 /*
  * CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_MULT_SHIFT                               8
+#define OMAP4430_DPLL_MULT_WIDTH                               0xb
 #define OMAP4430_DPLL_MULT_MASK                                        (0x7ff << 8)
 
 /* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_MULT_USB_SHIFT                           8
+#define OMAP4430_DPLL_MULT_USB_WIDTH                           0xc
 #define OMAP4430_DPLL_MULT_USB_MASK                            (0xfff << 8)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_REGM4XEN_SHIFT                           11
+#define OMAP4430_DPLL_REGM4XEN_WIDTH                           0x1
 #define OMAP4430_DPLL_REGM4XEN_MASK                            (1 << 11)
 
 /* Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_SD_DIV_SHIFT                             24
+#define OMAP4430_DPLL_SD_DIV_WIDTH                             0x8
 #define OMAP4430_DPLL_SD_DIV_MASK                              (0xff << 24)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_ACK_SHIFT                            13
+#define OMAP4430_DPLL_SSC_ACK_WIDTH                            0x1
 #define OMAP4430_DPLL_SSC_ACK_MASK                             (1 << 13)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT                     14
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_WIDTH                     0x1
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK                      (1 << 14)
 
 /*
  * CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_EN_SHIFT                             12
+#define OMAP4430_DPLL_SSC_EN_WIDTH                             0x1
 #define OMAP4430_DPLL_SSC_EN_MASK                              (1 << 12)
 
 /* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_DSS_DYNDEP_SHIFT                              8
+#define OMAP4430_DSS_DYNDEP_WIDTH                              0x1
 #define OMAP4430_DSS_DYNDEP_MASK                               (1 << 8)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
 #define OMAP4430_DSS_STATDEP_SHIFT                             8
+#define OMAP4430_DSS_STATDEP_WIDTH                             0x1
 #define OMAP4430_DSS_STATDEP_MASK                              (1 << 8)
 
 /* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_DUCATI_DYNDEP_SHIFT                           0
+#define OMAP4430_DUCATI_DYNDEP_WIDTH                           0x1
 #define OMAP4430_DUCATI_DYNDEP_MASK                            (1 << 0)
 
 /* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP */
 #define OMAP4430_DUCATI_STATDEP_SHIFT                          0
+#define OMAP4430_DUCATI_STATDEP_WIDTH                          0x1
 #define OMAP4430_DUCATI_STATDEP_MASK                           (1 << 0)
 
 /* Used by CM_SHADOW_FREQ_CONFIG1 */
 #define OMAP4430_FREQ_UPDATE_SHIFT                             0
+#define OMAP4430_FREQ_UPDATE_WIDTH                             0x1
 #define OMAP4430_FREQ_UPDATE_MASK                              (1 << 0)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_FUNC_SHIFT                                    16
+#define OMAP4430_FUNC_WIDTH                                    0xc
 #define OMAP4430_FUNC_MASK                                     (0xfff << 16)
 
 /* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_GFX_DYNDEP_SHIFT                              10
+#define OMAP4430_GFX_DYNDEP_WIDTH                              0x1
 #define OMAP4430_GFX_DYNDEP_MASK                               (1 << 10)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_GFX_STATDEP_SHIFT                             10
+#define OMAP4430_GFX_STATDEP_WIDTH                             0x1
 #define OMAP4430_GFX_STATDEP_MASK                              (1 << 10)
 
 /* Used by CM_SHADOW_FREQ_CONFIG2 */
 #define OMAP4430_GPMC_FREQ_UPDATE_SHIFT                                0
+#define OMAP4430_GPMC_FREQ_UPDATE_WIDTH                                0x1
 #define OMAP4430_GPMC_FREQ_UPDATE_MASK                         (1 << 0)
 
 /*
  * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT                   0
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_WIDTH                   0x5
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK                    (0x1f << 0)
 
 /*
  * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT              5
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_WIDTH              0x1
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK               (1 << 5)
 
 /*
  * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT             8
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_WIDTH             0x1
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK              (1 << 8)
 
 /*
  * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT                  12
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_WIDTH                  0x1
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK                   (1 << 12)
 
 /*
  * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT                   0
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_WIDTH                   0x5
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK                    (0x1f << 0)
 
 /*
  * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT              5
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_WIDTH              0x1
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK               (1 << 5)
 
 /*
  * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT             8
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_WIDTH             0x1
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK              (1 << 8)
 
 /*
  * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT                  12
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_WIDTH                  0x1
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK                   (1 << 12)
 
 /* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT                   0
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_WIDTH                   0x5
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK                    (0x1f << 0)
 
 /* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT              5
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_WIDTH              0x1
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK               (1 << 5)
 
 /* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT             8
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_WIDTH             0x1
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK              (1 << 8)
 
 /* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT                  12
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_WIDTH                  0x1
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK                   (1 << 12)
 
 /* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT                   0
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_WIDTH                   0x5
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK                    (0x1f << 0)
 
 /* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT              5
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_WIDTH              0x1
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK               (1 << 5)
 
 /* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT             8
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_WIDTH             0x1
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK              (1 << 8)
 
 /* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT                  12
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_WIDTH                  0x1
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK                   (1 << 12)
 
 /*
  * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
  * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
  * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
- * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
- * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
- * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL,
+ * CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
+ * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL, CM_CM1_PROFILING_CLKCTRL,
+ * CM_CM2_PROFILING_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL,
+ * CM_D2D_SAD2D_FW_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
  * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
- * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
- * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
- * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
- * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
- * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
- * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
- * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
+ * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
+ * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
  * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
  * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
  * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
  * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
  * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
- * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
- * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
- * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
- * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
- * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
- * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
- * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
- * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
- * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
- * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
+ * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL,
+ * CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL,
+ * CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL,
+ * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
  * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
  * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
  * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
- * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
- * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
- * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL,
+ * CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL,
+ * CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_IDLEST_SHIFT                                  16
+#define OMAP4430_IDLEST_WIDTH                                  0x2
 #define OMAP4430_IDLEST_MASK                                   (0x3 << 16)
 
 /* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_ISS_DYNDEP_SHIFT                              9
+#define OMAP4430_ISS_DYNDEP_WIDTH                              0x1
 #define OMAP4430_ISS_DYNDEP_MASK                               (1 << 9)
 
 /*
  * CM_TESLA_STATICDEP
  */
 #define OMAP4430_ISS_STATDEP_SHIFT                             9
+#define OMAP4430_ISS_STATDEP_WIDTH                             0x1
 #define OMAP4430_ISS_STATDEP_MASK                              (1 << 9)
 
 /* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_IVAHD_DYNDEP_SHIFT                            2
+#define OMAP4430_IVAHD_DYNDEP_WIDTH                            0x1
 #define OMAP4430_IVAHD_DYNDEP_MASK                             (1 << 2)
 
 /*
  * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_IVAHD_STATDEP_SHIFT                           2
+#define OMAP4430_IVAHD_STATDEP_WIDTH                           0x1
 #define OMAP4430_IVAHD_STATDEP_MASK                            (1 << 2)
 
 /* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_L3INIT_DYNDEP_SHIFT                           7
+#define OMAP4430_L3INIT_DYNDEP_WIDTH                           0x1
 #define OMAP4430_L3INIT_DYNDEP_MASK                            (1 << 7)
 
 /*
  * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3INIT_STATDEP_SHIFT                          7
+#define OMAP4430_L3INIT_STATDEP_WIDTH                          0x1
 #define OMAP4430_L3INIT_STATDEP_MASK                           (1 << 7)
 
 /*
  * CM_L4CFG_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_L3_1_DYNDEP_SHIFT                             5
+#define OMAP4430_L3_1_DYNDEP_WIDTH                             0x1
 #define OMAP4430_L3_1_DYNDEP_MASK                              (1 << 5)
 
 /*
  * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_1_STATDEP_SHIFT                            5
+#define OMAP4430_L3_1_STATDEP_WIDTH                            0x1
 #define OMAP4430_L3_1_STATDEP_MASK                             (1 << 5)
 
 /*
  * CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
  */
 #define OMAP4430_L3_2_DYNDEP_SHIFT                             6
+#define OMAP4430_L3_2_DYNDEP_WIDTH                             0x1
 #define OMAP4430_L3_2_DYNDEP_MASK                              (1 << 6)
 
 /*
  * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_2_STATDEP_SHIFT                            6
+#define OMAP4430_L3_2_STATDEP_WIDTH                            0x1
 #define OMAP4430_L3_2_STATDEP_MASK                             (1 << 6)
 
 /* Used by CM_L3_1_DYNAMICDEP */
 #define OMAP4430_L4CFG_DYNDEP_SHIFT                            12
+#define OMAP4430_L4CFG_DYNDEP_WIDTH                            0x1
 #define OMAP4430_L4CFG_DYNDEP_MASK                             (1 << 12)
 
 /*
  * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4CFG_STATDEP_SHIFT                           12
+#define OMAP4430_L4CFG_STATDEP_WIDTH                           0x1
 #define OMAP4430_L4CFG_STATDEP_MASK                            (1 << 12)
 
 /* Used by CM_L3_2_DYNAMICDEP */
 #define OMAP4430_L4PER_DYNDEP_SHIFT                            13
+#define OMAP4430_L4PER_DYNDEP_WIDTH                            0x1
 #define OMAP4430_L4PER_DYNDEP_MASK                             (1 << 13)
 
 /*
  * CM_L4SEC_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4PER_STATDEP_SHIFT                           13
+#define OMAP4430_L4PER_STATDEP_WIDTH                           0x1
 #define OMAP4430_L4PER_STATDEP_MASK                            (1 << 13)
 
 /* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
 #define OMAP4430_L4SEC_DYNDEP_SHIFT                            14
+#define OMAP4430_L4SEC_DYNDEP_WIDTH                            0x1
 #define OMAP4430_L4SEC_DYNDEP_MASK                             (1 << 14)
 
 /*
  * CM_SDMA_STATICDEP
  */
 #define OMAP4430_L4SEC_STATDEP_SHIFT                           14
+#define OMAP4430_L4SEC_STATDEP_WIDTH                           0x1
 #define OMAP4430_L4SEC_STATDEP_MASK                            (1 << 14)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_L4WKUP_DYNDEP_SHIFT                           15
+#define OMAP4430_L4WKUP_DYNDEP_WIDTH                           0x1
 #define OMAP4430_L4WKUP_DYNDEP_MASK                            (1 << 15)
 
 /*
  * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4WKUP_STATDEP_SHIFT                          15
+#define OMAP4430_L4WKUP_STATDEP_WIDTH                          0x1
 #define OMAP4430_L4WKUP_STATDEP_MASK                           (1 << 15)
 
 /*
  * CM_MPU_DYNAMICDEP
  */
 #define OMAP4430_MEMIF_DYNDEP_SHIFT                            4
+#define OMAP4430_MEMIF_DYNDEP_WIDTH                            0x1
 #define OMAP4430_MEMIF_DYNDEP_MASK                             (1 << 4)
 
 /*
  * CM_SDMA_STATICDEP, CM_TESLA_STATICDEP
  */
 #define OMAP4430_MEMIF_STATDEP_SHIFT                           4
+#define OMAP4430_MEMIF_STATDEP_WIDTH                           0x1
 #define OMAP4430_MEMIF_STATDEP_MASK                            (1 << 4)
 
 /*
  * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_EXPONENT_SHIFT                     8
+#define OMAP4430_MODFREQDIV_EXPONENT_WIDTH                     0x3
 #define OMAP4430_MODFREQDIV_EXPONENT_MASK                      (0x7 << 8)
 
 /*
  * CM_SSC_MODFREQDIV_DPLL_UNIPRO, CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_MANTISSA_SHIFT                     0
+#define OMAP4430_MODFREQDIV_MANTISSA_WIDTH                     0x7
 #define OMAP4430_MODFREQDIV_MANTISSA_MASK                      (0x7f << 0)
 
 /*
  * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
  * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
  * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
- * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
- * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
- * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_CM1_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL,
+ * CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
+ * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL, CM_CM1_PROFILING_CLKCTRL,
+ * CM_CM2_PROFILING_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL,
+ * CM_D2D_SAD2D_FW_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
  * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
- * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
- * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
- * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
- * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL,
- * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL,
- * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
- * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
- * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
+ * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
+ * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
  * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
  * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
  * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
  * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL,
  * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL,
- * CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL,
- * CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL,
- * CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL,
- * CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL,
- * CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL,
- * CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL,
- * CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
- * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
- * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
- * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
+ * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL,
+ * CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL,
+ * CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL,
+ * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
  * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
  * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
  * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
- * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
- * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
- * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL,
+ * CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL,
+ * CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_MODULEMODE_SHIFT                              0
+#define OMAP4430_MODULEMODE_WIDTH                              0x2
 #define OMAP4430_MODULEMODE_MASK                               (0x3 << 0)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4460_MPU_DYNDEP_SHIFT                              19
+#define OMAP4460_MPU_DYNDEP_WIDTH                              0x1
 #define OMAP4460_MPU_DYNDEP_MASK                               (1 << 19)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT                     9
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK_WIDTH                     0x1
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      (1 << 9)
 
 /* Used by CM_WKUP_BANDGAP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT                      8
+#define OMAP4430_OPTFCLKEN_BGAP_32K_WIDTH                      0x1
 #define OMAP4430_OPTFCLKEN_BGAP_32K_MASK                       (1 << 8)
 
 /* Used by CM_ALWON_USBPHY_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_CLK32K_SHIFT                                8
+#define OMAP4430_OPTFCLKEN_CLK32K_WIDTH                                0x1
 #define OMAP4430_OPTFCLKEN_CLK32K_MASK                         (1 << 8)
 
 /* Used by CM_CAM_ISS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT                       8
+#define OMAP4430_OPTFCLKEN_CTRLCLK_WIDTH                       0x1
 #define OMAP4430_OPTFCLKEN_CTRLCLK_MASK                                (1 << 8)
 
 /*
  * CM_WKUP_GPIO1_CLKCTRL
  */
 #define OMAP4430_OPTFCLKEN_DBCLK_SHIFT                         8
+#define OMAP4430_OPTFCLKEN_DBCLK_WIDTH                         0x1
 #define OMAP4430_OPTFCLKEN_DBCLK_MASK                          (1 << 8)
 
 /* Used by CM_MEMIF_DLL_CLKCTRL, CM_MEMIF_DLL_H_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DLL_CLK_SHIFT                       8
+#define OMAP4430_OPTFCLKEN_DLL_CLK_WIDTH                       0x1
 #define OMAP4430_OPTFCLKEN_DLL_CLK_MASK                                (1 << 8)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DSSCLK_SHIFT                                8
+#define OMAP4430_OPTFCLKEN_DSSCLK_WIDTH                                0x1
 #define OMAP4430_OPTFCLKEN_DSSCLK_MASK                         (1 << 8)
 
 /* Used by CM_WKUP_USIM_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK_SHIFT                          8
+#define OMAP4430_OPTFCLKEN_FCLK_WIDTH                          0x1
 #define OMAP4430_OPTFCLKEN_FCLK_MASK                           (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK0_SHIFT                         8
+#define OMAP4430_OPTFCLKEN_FCLK0_WIDTH                         0x1
 #define OMAP4430_OPTFCLKEN_FCLK0_MASK                          (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK1_SHIFT                         9
+#define OMAP4430_OPTFCLKEN_FCLK1_WIDTH                         0x1
 #define OMAP4430_OPTFCLKEN_FCLK1_MASK                          (1 << 9)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK2_SHIFT                         10
+#define OMAP4430_OPTFCLKEN_FCLK2_WIDTH                         0x1
 #define OMAP4430_OPTFCLKEN_FCLK2_MASK                          (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT                    15
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK_WIDTH                    0x1
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK                     (1 << 15)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT               13
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_WIDTH               0x1
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK                        (1 << 13)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT               14
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_WIDTH               0x1
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK                        (1 << 14)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT                        11
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_WIDTH                        0x1
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK                 (1 << 11)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT                        12
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_WIDTH                        0x1
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK                 (1 << 12)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT                 8
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_WIDTH                 0x1
 #define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK                  (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT               9
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_WIDTH               0x1
 #define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK                        (1 << 9)
 
 /* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PHY_48M_SHIFT                       8
+#define OMAP4430_OPTFCLKEN_PHY_48M_WIDTH                       0x1
 #define OMAP4430_OPTFCLKEN_PHY_48M_MASK                                (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT                   10
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK                    (1 << 10)
 
 /* Renamed from OPTFCLKEN_SLIMBUS_CLK Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT             11
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_WIDTH             0x1
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK              (1 << 11)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT                       10
+#define OMAP4430_OPTFCLKEN_SYS_CLK_WIDTH                       0x1
 #define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                (1 << 10)
 
 /* Used by CM_WKUP_BANDGAP_CLKCTRL */
 #define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT                       8
+#define OMAP4460_OPTFCLKEN_TS_FCLK_WIDTH                       0x1
 #define OMAP4460_OPTFCLKEN_TS_FCLK_MASK                                (1 << 8)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT                                11
+#define OMAP4430_OPTFCLKEN_TV_CLK_WIDTH                                0x1
 #define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         (1 << 11)
 
 /* Used by CM_L3INIT_UNIPRO1_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT                      8
+#define OMAP4430_OPTFCLKEN_TXPHYCLK_WIDTH                      0x1
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK                       (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT                   8
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT                   9
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT                   10
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT                   8
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT                   9
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT                   10
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_WIDTH                   0x1
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_XCLK_SHIFT                          8
+#define OMAP4430_OPTFCLKEN_XCLK_WIDTH                          0x1
 #define OMAP4430_OPTFCLKEN_XCLK_MASK                           (1 << 8)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_OVERRIDE_ENABLE_SHIFT                         19
+#define OMAP4430_OVERRIDE_ENABLE_WIDTH                         0x1
 #define OMAP4430_OVERRIDE_ENABLE_MASK                          (1 << 19)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_PAD_CLKS_GATE_SHIFT                           8
+#define OMAP4430_PAD_CLKS_GATE_WIDTH                           0x1
 #define OMAP4430_PAD_CLKS_GATE_MASK                            (1 << 8)
 
 /* Used by CM_CORE_DVFS_CURRENT, CM_IVA_DVFS_CURRENT */
 #define OMAP4430_PERF_CURRENT_SHIFT                            0
+#define OMAP4430_PERF_CURRENT_WIDTH                            0x8
 #define OMAP4430_PERF_CURRENT_MASK                             (0xff << 0)
 
 /*
  * CM_IVA_DVFS_PERF_TESLA
  */
 #define OMAP4430_PERF_REQ_SHIFT                                        0
+#define OMAP4430_PERF_REQ_WIDTH                                        0x8
 #define OMAP4430_PERF_REQ_MASK                                 (0xff << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE1_COMPLETED_SHIFT                                0
+#define OMAP4430_PHASE1_COMPLETED_WIDTH                                0x1
 #define OMAP4430_PHASE1_COMPLETED_MASK                         (1 << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2A_COMPLETED_SHIFT                       1
+#define OMAP4430_PHASE2A_COMPLETED_WIDTH                       0x1
 #define OMAP4430_PHASE2A_COMPLETED_MASK                                (1 << 1)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2B_COMPLETED_SHIFT                       2
+#define OMAP4430_PHASE2B_COMPLETED_WIDTH                       0x1
 #define OMAP4430_PHASE2B_COMPLETED_MASK                                (1 << 2)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_STM_MUX_CTRL_SHIFT                                20
+#define OMAP4430_PMD_STM_MUX_CTRL_WIDTH                                0x2
 #define OMAP4430_PMD_STM_MUX_CTRL_MASK                         (0x3 << 20)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT                      22
+#define OMAP4430_PMD_TRACE_MUX_CTRL_WIDTH                      0x2
 #define OMAP4430_PMD_TRACE_MUX_CTRL_MASK                       (0x3 << 22)
 
 /* Used by CM_DYN_DEP_PRESCAL */
 #define OMAP4430_PRESCAL_SHIFT                                 0
+#define OMAP4430_PRESCAL_WIDTH                                 0x6
 #define OMAP4430_PRESCAL_MASK                                  (0x3f << 0)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_R_RTL_SHIFT                                   11
+#define OMAP4430_R_RTL_WIDTH                                   0x5
 #define OMAP4430_R_RTL_MASK                                    (0x1f << 11)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL */
 #define OMAP4430_SAR_MODE_SHIFT                                        4
+#define OMAP4430_SAR_MODE_WIDTH                                        0x1
 #define OMAP4430_SAR_MODE_MASK                                 (1 << 4)
 
 /* Used by CM_SCALE_FCLK */
 #define OMAP4430_SCALE_FCLK_SHIFT                              0
+#define OMAP4430_SCALE_FCLK_WIDTH                              0x1
 #define OMAP4430_SCALE_FCLK_MASK                               (1 << 0)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_SCHEME_SHIFT                                  30
+#define OMAP4430_SCHEME_WIDTH                                  0x2
 #define OMAP4430_SCHEME_MASK                                   (0x3 << 30)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_SDMA_DYNDEP_SHIFT                             11
+#define OMAP4430_SDMA_DYNDEP_WIDTH                             0x1
 #define OMAP4430_SDMA_DYNDEP_MASK                              (1 << 11)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_SDMA_STATDEP_SHIFT                            11
+#define OMAP4430_SDMA_STATDEP_WIDTH                            0x1
 #define OMAP4430_SDMA_STATDEP_MASK                             (1 << 11)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_SLIMBUS_CLK_GATE_SHIFT                                10
+#define OMAP4430_SLIMBUS_CLK_GATE_WIDTH                                0x1
 #define OMAP4430_SLIMBUS_CLK_GATE_MASK                         (1 << 10)
 
 /*
  * Used by CM1_ABE_AESS_CLKCTRL, CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
- * CM_DUCATI_DUCATI_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_IVAHD_IVAHD_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * CM_D2D_SAD2D_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
- * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
- * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL,
- * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
- * CM_TESLA_TESLA_CLKCTRL
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
+ * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
  */
 #define OMAP4430_STBYST_SHIFT                                  18
+#define OMAP4430_STBYST_WIDTH                                  0x1
 #define OMAP4430_STBYST_MASK                                   (1 << 18)
 
 /*
  * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLK_SHIFT                             0
+#define OMAP4430_ST_DPLL_CLK_WIDTH                             0x1
 #define OMAP4430_ST_DPLL_CLK_MASK                              (1 << 0)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_ST_DPLL_CLKDCOLDO_SHIFT                       9
+#define OMAP4430_ST_DPLL_CLKDCOLDO_WIDTH                       0x1
 #define OMAP4430_ST_DPLL_CLKDCOLDO_MASK                                (1 << 9)
 
 /*
  * CM_DIV_M2_DPLL_MPU, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLKOUT_SHIFT                          9
+#define OMAP4430_ST_DPLL_CLKOUT_WIDTH                          0x1
 #define OMAP4430_ST_DPLL_CLKOUT_MASK                           (1 << 9)
 
 /* Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE, CM_DIV_M3_DPLL_PER */
 #define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT                       9
+#define OMAP4430_ST_DPLL_CLKOUTHIF_WIDTH                       0x1
 #define OMAP4430_ST_DPLL_CLKOUTHIF_MASK                                (1 << 9)
 
 /* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_ST_DPLL_CLKOUTX2_SHIFT                                11
+#define OMAP4430_ST_DPLL_CLKOUTX2_WIDTH                                0x1
 #define OMAP4430_ST_DPLL_CLKOUTX2_MASK                         (1 << 11)
 
 /*
  * CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT                    9
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_WIDTH                    0x1
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK                     (1 << 9)
 
 /*
  * CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT                    9
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_WIDTH                    0x1
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK                     (1 << 9)
 
 /* Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT                    9
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_WIDTH                    0x1
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK                     (1 << 9)
 
 /* Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_PER */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT                    9
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_WIDTH                    0x1
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK                     (1 << 9)
 
 /*
  * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
  */
 #define OMAP4430_ST_MN_BYPASS_SHIFT                            8
+#define OMAP4430_ST_MN_BYPASS_WIDTH                            0x1
 #define OMAP4430_ST_MN_BYPASS_MASK                             (1 << 8)
 
 /* Used by CM_SYS_CLKSEL */
 #define OMAP4430_SYS_CLKSEL_SHIFT                              0
+#define OMAP4430_SYS_CLKSEL_WIDTH                              0x3
 #define OMAP4430_SYS_CLKSEL_MASK                               (0x7 << 0)
 
 /* Used by CM_L4CFG_DYNAMICDEP */
 #define OMAP4430_TESLA_DYNDEP_SHIFT                            1
+#define OMAP4430_TESLA_DYNDEP_WIDTH                            0x1
 #define OMAP4430_TESLA_DYNDEP_MASK                             (1 << 1)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_TESLA_STATDEP_SHIFT                           1
+#define OMAP4430_TESLA_STATDEP_WIDTH                           0x1
 #define OMAP4430_TESLA_STATDEP_MASK                            (1 << 1)
 
 /*
  * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_WINDOWSIZE_SHIFT                              24
+#define OMAP4430_WINDOWSIZE_WIDTH                              0x4
 #define OMAP4430_WINDOWSIZE_MASK                               (0xf << 24)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_X_MAJOR_SHIFT                                 8
+#define OMAP4430_X_MAJOR_WIDTH                                 0x3
 #define OMAP4430_X_MAJOR_MASK                                  (0x7 << 8)
 
 /* Used by REVISION_CM1, REVISION_CM2 */
 #define OMAP4430_Y_MINOR_SHIFT                                 0
+#define OMAP4430_Y_MINOR_WIDTH                                 0x6
 #define OMAP4430_Y_MINOR_MASK                                  (0x3f << 0)
 #endif
index a911e76b4ecf6262641f3d8fc1f207fb564c24e7..7f07ab02a5b3f8d706daff3ff4f34e27fc7fb0ae 100644 (file)
@@ -35,7 +35,7 @@
 #define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP          0x3
 
 static const u8 cm_idlest_offs[] = {
-       CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
+       CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4
 };
 
 u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
index 088bbad73db541fcbceed4850e78369736bfc853..57b2f3c2fbf3469c6c99d9b72658c43d0207e819 100644 (file)
@@ -71,6 +71,7 @@
 #define OMAP24XX_CM_FCLKEN2                            0x0004
 #define OMAP24XX_CM_ICLKEN4                            0x001c
 #define OMAP24XX_CM_AUTOIDLE4                          0x003c
+#define OMAP24XX_CM_IDLEST4                            0x002c
 
 #define OMAP2430_CM_IDLEST3                            0x0028
 
index 123186ac7d2e018c274027c236fe8bf7831b6319..a89e8256fd0e2d022c62054edf2a00d8187c7157 100644 (file)
 
 /* AM33XX CONTROL_STATUS bitfields (partial) */
 #define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT           22
+#define AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH           0x2
 #define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK            (0x3 << 22)
 
 /* CONTROL OMAP STATUS register to identify OMAP3 features */
index d092d2a89ee0ff9879f77d4d5ac4c35559aaafa1..c8c211731d267a233b7b8ac56cd042f472d46985 100644 (file)
@@ -433,35 +433,24 @@ static void omap_init_mcspi(void)
 static inline void omap_init_mcspi(void) {}
 #endif
 
-static struct resource omap2_pmu_resource = {
-       .start  = 3 + OMAP_INTC_START,
-       .flags  = IORESOURCE_IRQ,
-};
-
-static struct resource omap3_pmu_resource = {
-       .start  = 3 + OMAP_INTC_START,
-       .flags  = IORESOURCE_IRQ,
-};
-
-static struct platform_device omap_pmu_device = {
-       .name           = "arm-pmu",
-       .id             = -1,
-       .num_resources  = 1,
-};
-
-static void omap_init_pmu(void)
+/**
+ * omap_init_rng - bind the RNG hwmod to the RNG omap_device
+ *
+ * Bind the RNG hwmod to the RNG omap_device.  No return value.
+ */
+static void omap_init_rng(void)
 {
-       if (cpu_is_omap24xx())
-               omap_pmu_device.resource = &omap2_pmu_resource;
-       else if (cpu_is_omap34xx())
-               omap_pmu_device.resource = &omap3_pmu_resource;
-       else
+       struct omap_hwmod *oh;
+       struct platform_device *pdev;
+
+       oh = omap_hwmod_lookup("rng");
+       if (!oh)
                return;
 
-       platform_device_register(&omap_pmu_device);
+       pdev = omap_device_build("omap_rng", -1, oh, NULL, 0, NULL, 0, 0);
+       WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n");
 }
 
-
 #if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
 
 #ifdef CONFIG_ARCH_OMAP2
@@ -646,8 +635,8 @@ static int __init omap2_init_devices(void)
                omap_init_mcpdm();
                omap_init_mcspi();
        }
-       omap_init_pmu();
        omap_init_sti();
+       omap_init_rng();
        omap_init_sham();
        omap_init_aes();
        omap_init_vout();
index af1ed7d24a1fbb20fd7e1fffba8ebb1f12bbcca5..7012068ccbf65542f3c184e41e72d427ee7840fa 100644 (file)
@@ -76,14 +76,14 @@ struct omap_dss_hwmod_data {
        const int id;
 };
 
-static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initconst = {
        { "dss_core", "omapdss_dss", -1 },
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
        { "dss_venc", "omapdss_venc", -1 },
 };
 
-static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initconst = {
        { "dss_core", "omapdss_dss", -1 },
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
@@ -91,7 +91,7 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
        { "dss_dsi1", "omapdss_dsi", 0 },
 };
 
-static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_core", "omapdss_dss", -1 },
        { "dss_dispc", "omapdss_dispc", -1 },
        { "dss_rfbi", "omapdss_rfbi", -1 },
@@ -488,7 +488,7 @@ int omap_dss_reset(struct omap_hwmod *oh)
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
                if (oc->_clk)
-                       clk_enable(oc->_clk);
+                       clk_prepare_enable(oc->_clk);
 
        dispc_disable_outputs();
 
@@ -515,7 +515,7 @@ int omap_dss_reset(struct omap_hwmod *oh)
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
                if (oc->_clk)
-                       clk_disable(oc->_clk);
+                       clk_disable_unprepare(oc->_clk);
 
        r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
 
index 27d79deb4ba2c5f36158c266a35f2774fb251977..814e1808e1586c64e51a8b5ec07be860c2043940 100644 (file)
@@ -63,8 +63,10 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
        const struct dpll_data *dd;
        int i = 0;
        int ret = -EINVAL;
+       const char *clk_name;
 
        dd = clk->dpll_data;
+       clk_name = __clk_get_name(clk);
 
        state <<= __ffs(dd->idlest_mask);
 
@@ -76,10 +78,10 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
 
        if (i == MAX_DPLL_WAIT_TRIES) {
                printk(KERN_ERR "clock: %s failed transition to '%s'\n",
-                      clk->name, (state) ? "locked" : "bypassed");
+                      clk_name, (state) ? "locked" : "bypassed");
        } else {
                pr_debug("clock: %s transition to '%s' in %d loops\n",
-                        clk->name, (state) ? "locked" : "bypassed", i);
+                        clk_name, (state) ? "locked" : "bypassed", i);
 
                ret = 0;
        }
@@ -93,7 +95,7 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
        unsigned long fint;
        u16 f = 0;
 
-       fint = clk->dpll_data->clk_ref->rate / n;
+       fint = __clk_get_rate(clk->dpll_data->clk_ref) / n;
 
        pr_debug("clock: fint is %lu\n", fint);
 
@@ -140,7 +142,7 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
        u8 state = 1;
        int r = 0;
 
-       pr_debug("clock: locking DPLL %s\n", clk->name);
+       pr_debug("clock: locking DPLL %s\n", __clk_get_name(clk));
 
        dd = clk->dpll_data;
        state <<= __ffs(dd->idlest_mask);
@@ -187,7 +189,7 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
                return -EINVAL;
 
        pr_debug("clock: configuring DPLL %s for low-power bypass\n",
-                clk->name);
+                __clk_get_name(clk));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -217,7 +219,7 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
        if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
                return -EINVAL;
 
-       pr_debug("clock: stopping DPLL %s\n", clk->name);
+       pr_debug("clock: stopping DPLL %s\n", __clk_get_name(clk));
 
        ai = omap3_dpll_autoidle_read(clk);
 
@@ -245,7 +247,7 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
 {
        unsigned long fint, clkinp; /* watch out for overflow */
 
-       clkinp = clk->parent->rate;
+       clkinp = __clk_get_rate(__clk_get_parent(clk));
        fint = (clkinp / n) * m;
 
        if (fint < 1000000000)
@@ -271,7 +273,7 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
        unsigned long clkinp, sd; /* watch out for overflow */
        int mod1, mod2;
 
-       clkinp = clk->parent->rate;
+       clkinp = __clk_get_rate(__clk_get_parent(clk));
 
        /*
         * target sigma-delta to near 250MHz
@@ -380,16 +382,19 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 {
        int r;
        struct dpll_data *dd;
+       struct clk *parent;
 
        dd = clk->dpll_data;
        if (!dd)
                return -EINVAL;
 
-       if (clk->rate == dd->clk_bypass->rate) {
-               WARN_ON(clk->parent != dd->clk_bypass);
+       parent = __clk_get_parent(clk);
+
+       if (__clk_get_rate(clk) == __clk_get_rate(dd->clk_bypass)) {
+               WARN_ON(parent != dd->clk_bypass);
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
-               WARN_ON(clk->parent != dd->clk_ref);
+               WARN_ON(parent != dd->clk_ref);
                r = _omap3_noncore_dpll_lock(clk);
        }
        /*
@@ -432,7 +437,7 @@ void omap3_noncore_dpll_disable(struct clk *clk)
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
        struct clk *new_parent = NULL;
-       unsigned long hw_rate;
+       unsigned long hw_rate, bypass_rate;
        u16 freqsel = 0;
        struct dpll_data *dd;
        int ret;
@@ -456,7 +461,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
        omap2_clk_enable(dd->clk_bypass);
        omap2_clk_enable(dd->clk_ref);
 
-       if (dd->clk_bypass->rate == rate &&
+       bypass_rate = __clk_get_rate(dd->clk_bypass);
+       if (bypass_rate == rate &&
            (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
                pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
 
@@ -479,7 +485,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
                }
 
                pr_debug("clock: %s: set rate: locking rate to %lu.\n",
-                        clk->name, rate);
+                        __clk_get_name(clk), rate);
 
                ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
                                                 dd->last_rounded_n, freqsel);
@@ -557,7 +563,7 @@ void omap3_dpll_allow_idle(struct clk *clk)
 
        if (!dd->autoidle_reg) {
                pr_debug("clock: DPLL %s: autoidle not supported\n",
-                       clk->name);
+                       __clk_get_name(clk));
                return;
        }
 
@@ -591,7 +597,7 @@ void omap3_dpll_deny_idle(struct clk *clk)
 
        if (!dd->autoidle_reg) {
                pr_debug("clock: DPLL %s: autoidle not supported\n",
-                       clk->name);
+                       __clk_get_name(clk));
                return;
        }
 
@@ -617,11 +623,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
        unsigned long rate;
        u32 v;
        struct clk *pclk;
+       unsigned long parent_rate;
 
        /* Walk up the parents of clk, looking for a DPLL */
-       pclk = clk->parent;
+       pclk = __clk_get_parent(clk);
        while (pclk && !pclk->dpll_data)
-               pclk = pclk->parent;
+               pclk = __clk_get_parent(pclk);
 
        /* clk does not have a DPLL as a parent?  error in the clock data */
        if (!pclk) {
@@ -633,12 +640,13 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 
        WARN_ON(!dd->enable_mask);
 
+       parent_rate = __clk_get_rate(__clk_get_parent(clk));
        v = __raw_readl(dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
-               rate = clk->parent->rate;
+               rate = parent_rate;
        else
-               rate = clk->parent->rate * 2;
+               rate = parent_rate * 2;
        return rate;
 }
 
index 72428bd45efc205c22e75059286172fc74ce0ba8..8ab1e1bde5e9e82b66968b48a73d16846af940fb 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
 #include <plat/cpu.h>
 #include <plat/gpmc.h>
 #include <plat/sdrc.h>
+#include <plat/omap_device.h>
 
 #include "soc.h"
 #include "common.h"
 
+#define        DEVICE_NAME             "omap-gpmc"
+
 /* GPMC register offsets */
 #define GPMC_REVISION          0x00
 #define GPMC_SYSCONFIG         0x10
 #define ENABLE_PREFETCH                (0x1 << 7)
 #define DMA_MPU_MODE           2
 
+#define        GPMC_REVISION_MAJOR(l)          ((l >> 4) & 0xf)
+#define        GPMC_REVISION_MINOR(l)          (l & 0xf)
+
+#define        GPMC_HAS_WR_ACCESS              0x1
+#define        GPMC_HAS_WR_DATA_MUX_BUS        0x2
+
 /* XXX: Only NAND irq has been considered,currently these are the only ones used
  */
 #define        GPMC_NR_IRQ             2
@@ -128,7 +138,10 @@ static struct resource     gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 static unsigned int gpmc_cs_map;       /* flag for cs which are initialized */
 static int gpmc_ecc_used = -EINVAL;    /* cs using ecc engine */
-
+static struct device *gpmc_dev;
+static int gpmc_irq;
+static resource_size_t phys_base, mem_size;
+static unsigned gpmc_capability;
 static void __iomem *gpmc_base;
 
 static struct clk *gpmc_l3_clk;
@@ -318,10 +331,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
        GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
-       if (cpu_is_omap34xx()) {
+       if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
                GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
+       if (gpmc_capability & GPMC_HAS_WR_ACCESS)
                GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
-       }
 
        /* caller is expected to have initialized CONFIG1 to cover
         * at least sync vs async
@@ -431,6 +444,20 @@ static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
        return r;
 }
 
+static int gpmc_cs_delete_mem(int cs)
+{
+       struct resource *res = &gpmc_cs_mem[cs];
+       int r;
+
+       spin_lock(&gpmc_mem_lock);
+       r = release_resource(&gpmc_cs_mem[cs]);
+       res->start = 0;
+       res->end = 0;
+       spin_unlock(&gpmc_mem_lock);
+
+       return r;
+}
+
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
        struct resource *res = &gpmc_cs_mem[cs];
@@ -767,7 +794,7 @@ static void gpmc_irq_noop(struct irq_data *data) { }
 
 static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
 
-static int gpmc_setup_irq(int gpmc_irq)
+static int gpmc_setup_irq(void)
 {
        int i;
        u32 regval;
@@ -811,7 +838,37 @@ static int gpmc_setup_irq(int gpmc_irq)
        return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
 }
 
-static void __init gpmc_mem_init(void)
+static __exit int gpmc_free_irq(void)
+{
+       int i;
+
+       if (gpmc_irq)
+               free_irq(gpmc_irq, NULL);
+
+       for (i = 0; i < GPMC_NR_IRQ; i++) {
+               irq_set_handler(gpmc_client_irq[i].irq, NULL);
+               irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
+               irq_modify_status(gpmc_client_irq[i].irq, 0, 0);
+       }
+
+       irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ);
+
+       return 0;
+}
+
+static void __devexit gpmc_mem_exit(void)
+{
+       int cs;
+
+       for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+               if (!gpmc_cs_mem_enabled(cs))
+                       continue;
+               gpmc_cs_delete_mem(cs);
+       }
+
+}
+
+static void __devinit gpmc_mem_init(void)
 {
        int cs;
        unsigned long boot_rom_space = 0;
@@ -838,65 +895,104 @@ static void __init gpmc_mem_init(void)
        }
 }
 
-static int __init gpmc_init(void)
+static __devinit int gpmc_probe(struct platform_device *pdev)
 {
        u32 l;
-       int ret = -EINVAL;
-       int gpmc_irq;
-       char *ck = NULL;
-
-       if (cpu_is_omap24xx()) {
-               ck = "core_l3_ck";
-               if (cpu_is_omap2420())
-                       l = OMAP2420_GPMC_BASE;
-               else
-                       l = OMAP34XX_GPMC_BASE;
-               gpmc_irq = 20 + OMAP_INTC_START;
-       } else if (cpu_is_omap34xx()) {
-               ck = "gpmc_fck";
-               l = OMAP34XX_GPMC_BASE;
-               gpmc_irq = 20 + OMAP_INTC_START;
-       } else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
-               /* Base address and irq number are same for OMAP4/5 */
-               ck = "gpmc_ck";
-               l = OMAP44XX_GPMC_BASE;
-               gpmc_irq = 20 + OMAP44XX_IRQ_GIC_START;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL)
+               return -ENOENT;
+
+       phys_base = res->start;
+       mem_size = resource_size(res);
+
+       gpmc_base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!gpmc_base) {
+               dev_err(&pdev->dev, "error: request memory / ioremap\n");
+               return -EADDRNOTAVAIL;
        }
 
-       if (WARN_ON(!ck))
-               return ret;
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL)
+               dev_warn(&pdev->dev, "Failed to get resource: irq\n");
+       else
+               gpmc_irq = res->start;
 
-       gpmc_l3_clk = clk_get(NULL, ck);
+       gpmc_l3_clk = clk_get(&pdev->dev, "fck");
        if (IS_ERR(gpmc_l3_clk)) {
-               printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-               BUG();
+               dev_err(&pdev->dev, "error: clk_get\n");
+               gpmc_irq = 0;
+               return PTR_ERR(gpmc_l3_clk);
        }
 
-       gpmc_base = ioremap(l, SZ_4K);
-       if (!gpmc_base) {
-               clk_put(gpmc_l3_clk);
-               printk(KERN_ERR "Could not get GPMC register memory\n");
-               BUG();
-       }
+       clk_prepare_enable(gpmc_l3_clk);
 
-       clk_enable(gpmc_l3_clk);
+       gpmc_dev = &pdev->dev;
 
        l = gpmc_read_reg(GPMC_REVISION);
-       printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-       /* Set smart idle mode and automatic L3 clock gating */
-       l = gpmc_read_reg(GPMC_SYSCONFIG);
-       l &= 0x03 << 3;
-       l |= (0x02 << 3) | (1 << 0);
-       gpmc_write_reg(GPMC_SYSCONFIG, l);
+       if (GPMC_REVISION_MAJOR(l) > 0x4)
+               gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
+       dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
+                GPMC_REVISION_MINOR(l));
+
        gpmc_mem_init();
 
-       ret = gpmc_setup_irq(gpmc_irq);
-       if (ret)
-               pr_err("gpmc: irq-%d could not claim: err %d\n",
-                                               gpmc_irq, ret);
-       return ret;
+       if (IS_ERR_VALUE(gpmc_setup_irq()))
+               dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
+
+       return 0;
 }
+
+static __exit int gpmc_remove(struct platform_device *pdev)
+{
+       gpmc_free_irq();
+       gpmc_mem_exit();
+       gpmc_dev = NULL;
+       return 0;
+}
+
+static struct platform_driver gpmc_driver = {
+       .probe          = gpmc_probe,
+       .remove         = __devexit_p(gpmc_remove),
+       .driver         = {
+               .name   = DEVICE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static __init int gpmc_init(void)
+{
+       return platform_driver_register(&gpmc_driver);
+}
+
+static __exit void gpmc_exit(void)
+{
+       platform_driver_unregister(&gpmc_driver);
+
+}
+
 postcore_initcall(gpmc_init);
+module_exit(gpmc_exit);
+
+static int __init omap_gpmc_init(void)
+{
+       struct omap_hwmod *oh;
+       struct platform_device *pdev;
+       char *oh_name = "gpmc";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up %s\n", oh_name);
+               return -ENODEV;
+       }
+
+       pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0);
+       WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
+
+       return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+}
+postcore_initcall(omap_gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
index 00c006686b0d08051cbaa8b9ceb6b64c6444f898..299ca2821ad1d6b0f6fed5a5a9712d5abeb2d5ce 100644 (file)
@@ -679,16 +679,25 @@ static int _init_main_clk(struct omap_hwmod *oh)
        if (!oh->main_clk)
                return 0;
 
-       oh->_clk = omap_clk_get_by_name(oh->main_clk);
-       if (!oh->_clk) {
+       oh->_clk = clk_get(NULL, oh->main_clk);
+       if (IS_ERR(oh->_clk)) {
                pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n",
                           oh->name, oh->main_clk);
                return -EINVAL;
        }
+       /*
+        * HACK: This needs a re-visit once clk_prepare() is implemented
+        * to do something meaningful. Today its just a no-op.
+        * If clk_prepare() is used at some point to do things like
+        * voltage scaling etc, then this would have to be moved to
+        * some point where subsystems like i2c and pmic become
+        * available.
+        */
+       clk_prepare(oh->_clk);
 
        if (!oh->_clk->clkdm)
-               pr_warning("omap_hwmod: %s: missing clockdomain for %s.\n",
-                          oh->main_clk, oh->_clk->name);
+               pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n",
+                          oh->name, oh->main_clk);
 
        return ret;
 }
@@ -715,13 +724,22 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                if (!os->clk)
                        continue;
 
-               c = omap_clk_get_by_name(os->clk);
-               if (!c) {
+               c = clk_get(NULL, os->clk);
+               if (IS_ERR(c)) {
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
                }
                os->_clk = c;
+               /*
+                * HACK: This needs a re-visit once clk_prepare() is implemented
+                * to do something meaningful. Today its just a no-op.
+                * If clk_prepare() is used at some point to do things like
+                * voltage scaling etc, then this would have to be moved to
+                * some point where subsystems like i2c and pmic become
+                * available.
+                */
+               clk_prepare(os->_clk);
        }
 
        return ret;
@@ -742,13 +760,22 @@ static int _init_opt_clks(struct omap_hwmod *oh)
        int ret = 0;
 
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) {
-               c = omap_clk_get_by_name(oc->clk);
-               if (!c) {
+               c = clk_get(NULL, oc->clk);
+               if (IS_ERR(c)) {
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
                }
                oc->_clk = c;
+               /*
+                * HACK: This needs a re-visit once clk_prepare() is implemented
+                * to do something meaningful. Today its just a no-op.
+                * If clk_prepare() is used at some point to do things like
+                * voltage scaling etc, then this would have to be moved to
+                * some point where subsystems like i2c and pmic become
+                * available.
+                */
+               clk_prepare(oc->_clk);
        }
 
        return ret;
@@ -827,7 +854,7 @@ static void _enable_optional_clocks(struct omap_hwmod *oh)
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
                if (oc->_clk) {
                        pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
-                                oc->_clk->name);
+                                __clk_get_name(oc->_clk));
                        clk_enable(oc->_clk);
                }
 }
@@ -842,7 +869,7 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
        for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
                if (oc->_clk) {
                        pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
-                                oc->_clk->name);
+                                __clk_get_name(oc->_clk));
                        clk_disable(oc->_clk);
                }
 }
@@ -900,10 +927,10 @@ static void _am33xx_enable_module(struct omap_hwmod *oh)
  */
 static int _omap4_wait_target_disable(struct omap_hwmod *oh)
 {
-       if (!oh || !oh->clkdm)
+       if (!oh)
                return -EINVAL;
 
-       if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+       if (oh->_int_flags & _HWMOD_NO_MPU_PORT || !oh->clkdm)
                return 0;
 
        if (oh->flags & HWMOD_NO_IDLEST)
@@ -1427,8 +1454,10 @@ static struct omap_hwmod *_lookup(const char *name)
  */
 static int _init_clkdm(struct omap_hwmod *oh)
 {
-       if (!oh->clkdm_name)
+       if (!oh->clkdm_name) {
+               pr_debug("omap_hwmod: %s: missing clockdomain\n", oh->name);
                return 0;
+       }
 
        oh->clkdm = clkdm_lookup(oh->clkdm_name);
        if (!oh->clkdm) {
@@ -1556,6 +1585,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 {
        struct omap_hwmod_rst_info ohri;
        int ret = -EINVAL;
+       int hwsup = 0;
 
        if (!oh)
                return -EINVAL;
@@ -1567,10 +1597,46 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
        if (IS_ERR_VALUE(ret))
                return ret;
 
+       if (oh->clkdm) {
+               /*
+                * A clockdomain must be in SW_SUP otherwise reset
+                * might not be completed. The clockdomain can be set
+                * in HW_AUTO only when the module become ready.
+                */
+               hwsup = clkdm_in_hwsup(oh->clkdm);
+               ret = clkdm_hwmod_enable(oh->clkdm, oh);
+               if (ret) {
+                       WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
+                            oh->name, oh->clkdm->name, ret);
+                       return ret;
+               }
+       }
+
+       _enable_clocks(oh);
+       if (soc_ops.enable_module)
+               soc_ops.enable_module(oh);
+
        ret = soc_ops.deassert_hardreset(oh, &ohri);
+
+       if (soc_ops.disable_module)
+               soc_ops.disable_module(oh);
+       _disable_clocks(oh);
+
        if (ret == -EBUSY)
                pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
 
+       if (!ret) {
+               /*
+                * Set the clockdomain to HW_AUTO, assuming that the
+                * previous state was HW_AUTO.
+                */
+               if (oh->clkdm && hwsup)
+                       clkdm_allow_idle(oh->clkdm);
+       } else {
+               if (oh->clkdm)
+                       clkdm_hwmod_disable(oh->clkdm, oh);
+       }
+
        return ret;
 }
 
@@ -1605,25 +1671,28 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 }
 
 /**
- * _are_any_hardreset_lines_asserted - return true if part of @oh is hard-reset
+ * _are_all_hardreset_lines_asserted - return true if the @oh is hard-reset
  * @oh: struct omap_hwmod *
  *
- * If any hardreset line associated with @oh is asserted, then return true.
- * Otherwise, if @oh has no hardreset lines associated with it, or if
- * no hardreset lines associated with @oh are asserted, then return false.
+ * If all hardreset lines associated with @oh are asserted, then return true.
+ * Otherwise, if part of @oh is out hardreset or if no hardreset lines
+ * associated with @oh are asserted, then return false.
  * This function is used to avoid executing some parts of the IP block
- * enable/disable sequence if a hardreset line is set.
+ * enable/disable sequence if its hardreset line is set.
  */
-static bool _are_any_hardreset_lines_asserted(struct omap_hwmod *oh)
+static bool _are_all_hardreset_lines_asserted(struct omap_hwmod *oh)
 {
-       int i;
+       int i, rst_cnt = 0;
 
        if (oh->rst_lines_cnt == 0)
                return false;
 
        for (i = 0; i < oh->rst_lines_cnt; i++)
                if (_read_hardreset(oh, oh->rst_lines[i].name) > 0)
-                       return true;
+                       rst_cnt++;
+
+       if (oh->rst_lines_cnt == rst_cnt)
+               return true;
 
        return false;
 }
@@ -1642,6 +1711,13 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
                return -EINVAL;
 
+       /*
+        * Since integration code might still be doing something, only
+        * disable if all lines are under hardreset.
+        */
+       if (!_are_all_hardreset_lines_asserted(oh))
+               return 0;
+
        pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
 
        omap4_cminst_module_disable(oh->clkdm->prcm_partition,
@@ -1649,9 +1725,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
                                    oh->clkdm->clkdm_offs,
                                    oh->prcm.omap4.clkctrl_offs);
 
-       if (_are_any_hardreset_lines_asserted(oh))
-               return 0;
-
        v = _omap4_wait_target_disable(oh);
        if (v)
                pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
@@ -1679,7 +1752,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
        am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
                                 oh->prcm.omap4.clkctrl_offs);
 
-       if (_are_any_hardreset_lines_asserted(oh))
+       if (_are_all_hardreset_lines_asserted(oh))
                return 0;
 
        v = _am33xx_wait_target_disable(oh);
@@ -1907,7 +1980,7 @@ static int _enable(struct omap_hwmod *oh)
        }
 
        /*
-        * If an IP block contains HW reset lines and any of them are
+        * If an IP block contains HW reset lines and all of them are
         * asserted, we let integration code associated with that
         * block handle the enable.  We've received very little
         * information on what those driver authors need, and until
@@ -1915,7 +1988,7 @@ static int _enable(struct omap_hwmod *oh)
         * posted to the public lists, this is probably the best we
         * can do.
         */
-       if (_are_any_hardreset_lines_asserted(oh))
+       if (_are_all_hardreset_lines_asserted(oh))
                return 0;
 
        /* Mux pins for device runtime if populated */
@@ -1934,7 +2007,8 @@ static int _enable(struct omap_hwmod *oh)
                 * completely the module. The clockdomain can be set
                 * in HW_AUTO only when the module become ready.
                 */
-               hwsup = clkdm_in_hwsup(oh->clkdm);
+               hwsup = clkdm_in_hwsup(oh->clkdm) &&
+                       !clkdm_missing_idle_reporting(oh->clkdm);
                r = clkdm_hwmod_enable(oh->clkdm, oh);
                if (r) {
                        WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
@@ -1996,7 +2070,7 @@ static int _idle(struct omap_hwmod *oh)
                return -EINVAL;
        }
 
-       if (_are_any_hardreset_lines_asserted(oh))
+       if (_are_all_hardreset_lines_asserted(oh))
                return 0;
 
        if (oh->class->sysc)
@@ -2084,7 +2158,7 @@ static int _shutdown(struct omap_hwmod *oh)
                return -EINVAL;
        }
 
-       if (_are_any_hardreset_lines_asserted(oh))
+       if (_are_all_hardreset_lines_asserted(oh))
                return 0;
 
        pr_debug("omap_hwmod: %s: disabling\n", oh->name);
@@ -2608,10 +2682,10 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)
  */
 static int _omap4_wait_target_ready(struct omap_hwmod *oh)
 {
-       if (!oh || !oh->clkdm)
+       if (!oh)
                return -EINVAL;
 
-       if (oh->flags & HWMOD_NO_IDLEST)
+       if (oh->flags & HWMOD_NO_IDLEST || !oh->clkdm)
                return 0;
 
        if (!_find_mpu_rt_port(oh))
index 10575a1bc1f1fa468c7b728702bf66dd4258c4f7..b5db6007c523413cfd0e2b4f1063b5451a231f00 100644 (file)
@@ -536,6 +536,15 @@ static struct omap_hwmod_addr_space omap2420_counter_32k_addrs[] = {
        { }
 };
 
+static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = {
+       {
+               .pa_start       = 0x6800a000,
+               .pa_end         = 0x6800afff,
+               .flags          = ADDR_TYPE_RT
+       },
+       { }
+};
+
 static struct omap_hwmod_ocp_if omap2420_l4_wkup__counter_32k = {
        .master         = &omap2xxx_l4_wkup_hwmod,
        .slave          = &omap2xxx_counter_32k_hwmod,
@@ -544,6 +553,14 @@ static struct omap_hwmod_ocp_if omap2420_l4_wkup__counter_32k = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if omap2420_l3__gpmc = {
+       .master         = &omap2xxx_l3_main_hwmod,
+       .slave          = &omap2xxx_gpmc_hwmod,
+       .clk            = "core_l3_ck",
+       .addr           = omap2420_gpmc_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
        &omap2xxx_l3_main__l4_core,
        &omap2xxx_mpu__l3_main,
@@ -585,8 +602,10 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
        &omap2420_l4_core__mcbsp1,
        &omap2420_l4_core__mcbsp2,
        &omap2420_l4_core__msdi1,
+       &omap2xxx_l4_core__rng,
        &omap2420_l4_core__hdq1w,
        &omap2420_l4_wkup__counter_32k,
+       &omap2420_l3__gpmc,
        NULL,
 };
 
index 60de70feeae50e3225ec9c7407e55f4983ce6323..c455e41b02374ce7028a2bb3b9c0f8c45a57f1eb 100644 (file)
@@ -888,6 +888,15 @@ static struct omap_hwmod_addr_space omap2430_counter_32k_addrs[] = {
        { }
 };
 
+static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = {
+       {
+               .pa_start       = 0x6e000000,
+               .pa_end         = 0x6e000fff,
+               .flags          = ADDR_TYPE_RT
+       },
+       { }
+};
+
 static struct omap_hwmod_ocp_if omap2430_l4_wkup__counter_32k = {
        .master         = &omap2xxx_l4_wkup_hwmod,
        .slave          = &omap2xxx_counter_32k_hwmod,
@@ -896,6 +905,14 @@ static struct omap_hwmod_ocp_if omap2430_l4_wkup__counter_32k = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if omap2430_l3__gpmc = {
+       .master         = &omap2xxx_l3_main_hwmod,
+       .slave          = &omap2xxx_gpmc_hwmod,
+       .clk            = "core_l3_ck",
+       .addr           = omap2430_gpmc_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
        &omap2xxx_l3_main__l4_core,
        &omap2xxx_mpu__l3_main,
@@ -945,7 +962,9 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
        &omap2430_l4_core__mcbsp4,
        &omap2430_l4_core__mcbsp5,
        &omap2430_l4_core__hdq1w,
+       &omap2xxx_l4_core__rng,
        &omap2430_l4_wkup__counter_32k,
+       &omap2430_l3__gpmc,
        NULL,
 };
 
index f853a0b1d5ca998790c9d34f0335e9b45c026d97..1a1287d62648df38ebe2f20474d91afa4c1ddf92 100644 (file)
@@ -129,6 +129,15 @@ struct omap_hwmod_addr_space omap2xxx_mcbsp2_addrs[] = {
        { }
 };
 
+static struct omap_hwmod_addr_space omap2_rng_addr_space[] = {
+       {
+               .pa_start       = 0x480a0000,
+               .pa_end         = 0x480a004f,
+               .flags          = ADDR_TYPE_RT
+       },
+       { }
+};
+
 /*
  * Common interconnect data
  */
@@ -372,3 +381,11 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_core -> rng */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__rng = {
+       .master         = &omap2xxx_l4_core_hwmod,
+       .slave          = &omap2xxx_rng_hwmod,
+       .clk            = "rng_ick",
+       .addr           = omap2_rng_addr_space,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
index feeb401cf87e882f5ac0e5eebc63259c29185e8a..35dcdb66a4e01c6ef63b77c81506953d6fc45b50 100644 (file)
@@ -172,6 +172,26 @@ struct omap_hwmod_class omap2xxx_mcspi_class = {
        .rev    = OMAP2_MCSPI_REV,
 };
 
+/*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2xxx_gpmc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_gpmc_hwmod_class = {
+       .name   = "gpmc",
+       .sysc   = &omap2xxx_gpmc_sysc,
+};
+
 /*
  * IP blocks
  */
@@ -198,8 +218,14 @@ struct omap_hwmod omap2xxx_l4_wkup_hwmod = {
 };
 
 /* MPU */
+static struct omap_hwmod_irq_info omap2xxx_mpu_irqs[] = {
+       { .name = "pmu", .irq = 3 },
+       { .irq = -1 }
+};
+
 struct omap_hwmod omap2xxx_mpu_hwmod = {
        .name           = "mpu",
+       .mpu_irqs       = omap2xxx_mpu_irqs,
        .class          = &mpu_hwmod_class,
        .main_clk       = "mpu_ck",
 };
@@ -220,6 +246,11 @@ static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
        .timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
+/* timers with DSP interrupt dev attribute */
+static struct omap_timer_capability_dev_attr capability_dsp_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_DSP_IRQ,
+};
+
 /* timer1 */
 
 struct omap_hwmod omap2xxx_timer1_hwmod = {
@@ -308,6 +339,7 @@ struct omap_hwmod omap2xxx_timer5_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -326,6 +358,7 @@ struct omap_hwmod omap2xxx_timer6_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -344,6 +377,7 @@ struct omap_hwmod omap2xxx_timer7_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -362,6 +396,7 @@ struct omap_hwmod omap2xxx_timer8_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -724,7 +759,6 @@ struct omap_hwmod omap2xxx_mcspi2_hwmod = {
        .dev_attr       = &omap_mcspi2_dev_attr,
 };
 
-
 static struct omap_hwmod_class omap2xxx_counter_hwmod_class = {
        .name   = "counter",
 };
@@ -743,3 +777,77 @@ struct omap_hwmod omap2xxx_counter_32k_hwmod = {
        },
        .class          = &omap2xxx_counter_hwmod_class,
 };
+
+/* gpmc */
+static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
+       { .irq = 20 },
+       { .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_gpmc_hwmod = {
+       .name           = "gpmc",
+       .class          = &omap2xxx_gpmc_hwmod_class,
+       .mpu_irqs       = omap2xxx_gpmc_irqs,
+       .main_clk       = "gpmc_fck",
+       /*
+        * XXX HWMOD_INIT_NO_RESET should not be needed for this IP
+        * block.  It is not being added due to any known bugs with
+        * resetting the GPMC IP block, but rather because any timings
+        * set by the bootloader are not being correctly programmed by
+        * the kernel from the board file or DT data.
+        * HWMOD_INIT_NO_RESET should be removed ASAP.
+        */
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
+                          HWMOD_NO_IDLEST),
+       .prcm           = {
+               .omap2  = {
+                       .prcm_reg_id = 3,
+                       .module_bit = OMAP24XX_EN_GPMC_MASK,
+                       .module_offs = CORE_MOD,
+               },
+       },
+};
+
+/* RNG */
+
+static struct omap_hwmod_class_sysconfig omap2_rng_sysc = {
+       .rev_offs       = 0x3c,
+       .sysc_offs      = 0x40,
+       .syss_offs      = 0x44,
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2_rng_hwmod_class = {
+       .name           = "rng",
+       .sysc           = &omap2_rng_sysc,
+};
+
+static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
+       { .irq = 52 },
+       { .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_rng_hwmod = {
+       .name           = "rng",
+       .mpu_irqs       = omap2_rng_mpu_irqs,
+       .main_clk       = "l4_ck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 4,
+                       .module_bit = OMAP24XX_EN_RNG_SHIFT,
+                       .idlest_reg_id = 4,
+                       .idlest_idle_bit = OMAP24XX_ST_RNG_SHIFT,
+               },
+       },
+       /*
+        * XXX The first read from the SYSSTATUS register of the RNG
+        * after the SYSCONFIG SOFTRESET bit is set triggers an
+        * imprecise external abort.  It's unclear why this happens.
+        * Until this is analyzed, skip the IP block reset.
+        */
+       .flags          = HWMOD_INIT_NO_RESET,
+       .class          = &omap2_rng_hwmod_class,
+};
index 94b38af17055aaa879df5a677f17bae83e550bbf..285777241d5a75d1202480781317556338fcd45b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <plat/dmtimer.h>
+#include <plat/iommu.h>
 
 #include "am35xx.h"
 
@@ -92,8 +93,14 @@ static struct omap_hwmod omap3xxx_l4_sec_hwmod = {
 };
 
 /* MPU */
+static struct omap_hwmod_irq_info omap3xxx_mpu_irqs[] = {
+       { .name = "pmu", .irq = 3 },
+       { .irq = -1 }
+};
+
 static struct omap_hwmod omap3xxx_mpu_hwmod = {
        .name           = "mpu",
+       .mpu_irqs       = omap3xxx_mpu_irqs,
        .class          = &mpu_hwmod_class,
        .main_clk       = "arm_fck",
 };
@@ -123,6 +130,24 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
        },
 };
 
+/*
+ * 'debugss' class
+ * debug and emulation sub system
+ */
+
+static struct omap_hwmod_class omap3xxx_debugss_hwmod_class = {
+       .name   = "debugss",
+};
+
+/* debugss */
+static struct omap_hwmod omap3xxx_debugss_hwmod = {
+       .name           = "debugss",
+       .class          = &omap3xxx_debugss_hwmod_class,
+       .clkdm_name     = "emu_clkdm",
+       .main_clk       = "emu_src_ck",
+       .flags          = HWMOD_NO_IDLEST,
+};
+
 /* timer class */
 static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
        .rev_offs       = 0x0000,
@@ -170,6 +195,16 @@ static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
        .timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
+/* timers with DSP interrupt dev attribute */
+static struct omap_timer_capability_dev_attr capability_dsp_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_DSP_IRQ,
+};
+
+/* pwm timers with DSP interrupt dev attribute */
+static struct omap_timer_capability_dev_attr capability_dsp_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_DSP_IRQ | OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod = {
        .name           = "timer1",
@@ -253,6 +288,7 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -270,6 +306,7 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -287,6 +324,7 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -304,7 +342,7 @@ static struct omap_hwmod omap3xxx_timer8_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
                },
        },
-       .dev_attr       = &capability_pwm_dev_attr,
+       .dev_attr       = &capability_dsp_pwm_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -2033,6 +2071,33 @@ static struct omap_hwmod omap3xxx_hdq1w_hwmod = {
        .class          = &omap2_hdq1w_class,
 };
 
+/* SAD2D */
+static struct omap_hwmod_rst_info omap3xxx_sad2d_resets[] = {
+       { .name = "rst_modem_pwron_sw", .rst_shift = 0 },
+       { .name = "rst_modem_sw", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_class omap3xxx_sad2d_class = {
+       .name                   = "sad2d",
+};
+
+static struct omap_hwmod omap3xxx_sad2d_hwmod = {
+       .name           = "sad2d",
+       .rst_lines      = omap3xxx_sad2d_resets,
+       .rst_lines_cnt  = ARRAY_SIZE(omap3xxx_sad2d_resets),
+       .main_clk       = "sad2d_ick",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_SAD2D_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_ST_SAD2D_SHIFT,
+               },
+       },
+       .class          = &omap3xxx_sad2d_class,
+};
+
 /*
  * '32K sync counter' class
  * 32-bit ordinary counter, clocked by the falling edge of the 32 khz clock
@@ -2067,6 +2132,49 @@ static struct omap_hwmod omap3xxx_counter_32k_hwmod = {
        },
 };
 
+/*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
+       .name   = "gpmc",
+       .sysc   = &omap3xxx_gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
+       { .irq = 20 },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod omap3xxx_gpmc_hwmod = {
+       .name           = "gpmc",
+       .class          = &omap3xxx_gpmc_hwmod_class,
+       .clkdm_name     = "core_l3_clkdm",
+       .mpu_irqs       = omap3xxx_gpmc_irqs,
+       .main_clk       = "gpmc_fck",
+       /*
+        * XXX HWMOD_INIT_NO_RESET should not be needed for this IP
+        * block.  It is not being added due to any known bugs with
+        * resetting the GPMC IP block, but rather because any timings
+        * set by the bootloader are not being correctly programmed by
+        * the kernel from the board file or DT data.
+        * HWMOD_INIT_NO_RESET should be removed ASAP.
+        */
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
+                          HWMOD_NO_IDLEST),
+};
+
 /*
  * interfaces
  */
@@ -2102,6 +2210,23 @@ static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
        .user   = OCP_USER_MPU,
 };
 
+static struct omap_hwmod_addr_space omap3xxx_l4_emu_addrs[] = {
+       {
+               .pa_start       = 0x54000000,
+               .pa_end         = 0x547fffff,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l3 -> debugss */
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_debugss = {
+       .master         = &omap3xxx_l3_main_hwmod,
+       .slave          = &omap3xxx_debugss_hwmod,
+       .addr           = omap3xxx_l4_emu_addrs,
+       .user           = OCP_USER_MPU,
+};
+
 /* DSS -> l3 */
 static struct omap_hwmod_ocp_if omap3430es1_dss__l3 = {
        .master         = &omap3430es1_dss_core_hwmod,
@@ -2137,6 +2262,14 @@ static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
        .user           = OCP_USER_MPU,
 };
 
+/* l3_core -> sad2d interface */
+static struct omap_hwmod_ocp_if omap3xxx_sad2d__l3 = {
+       .master         = &omap3xxx_sad2d_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "core_l3_ick",
+       .user           = OCP_USER_MPU,
+};
+
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
        .master = &omap3xxx_l4_core_hwmod,
@@ -2823,6 +2956,122 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/*
+ * 'mmu' class
+ * The memory management unit performs virtual to physical address translation
+ * for its requestors.
+ */
+
+static struct omap_hwmod_class_sysconfig mmu_sysc = {
+       .rev_offs       = 0x000,
+       .sysc_offs      = 0x010,
+       .syss_offs      = 0x014,
+       .sysc_flags     = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_mmu_hwmod_class = {
+       .name = "mmu",
+       .sysc = &mmu_sysc,
+};
+
+/* mmu isp */
+
+static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
+       .da_start       = 0x0,
+       .da_end         = 0xfffff000,
+       .nr_tlb_entries = 8,
+};
+
+static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
+       { .irq = 24 },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mmu_isp_addrs[] = {
+       {
+               .pa_start       = 0x480bd400,
+               .pa_end         = 0x480bd47f,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_core -> mmu isp */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmu_isp = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_mmu_isp_hwmod,
+       .addr           = omap3xxx_mmu_isp_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod omap3xxx_mmu_isp_hwmod = {
+       .name           = "mmu_isp",
+       .class          = &omap3xxx_mmu_hwmod_class,
+       .mpu_irqs       = omap3xxx_mmu_isp_irqs,
+       .main_clk       = "cam_ick",
+       .dev_attr       = &mmu_isp_dev_attr,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+#ifdef CONFIG_OMAP_IOMMU_IVA2
+
+/* mmu iva */
+
+static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
+       .da_start       = 0x11000000,
+       .da_end         = 0xfffff000,
+       .nr_tlb_entries = 32,
+};
+
+static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
+       { .irq = 28 },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_rst_info omap3xxx_mmu_iva_resets[] = {
+       { .name = "mmu", .rst_shift = 1, .st_shift = 9 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mmu_iva_addrs[] = {
+       {
+               .pa_start       = 0x5d000000,
+               .pa_end         = 0x5d00007f,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l3_main -> iva mmu */
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__mmu_iva = {
+       .master         = &omap3xxx_l3_main_hwmod,
+       .slave          = &omap3xxx_mmu_iva_hwmod,
+       .addr           = omap3xxx_mmu_iva_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod omap3xxx_mmu_iva_hwmod = {
+       .name           = "mmu_iva",
+       .class          = &omap3xxx_mmu_hwmod_class,
+       .mpu_irqs       = omap3xxx_mmu_iva_irqs,
+       .rst_lines      = omap3xxx_mmu_iva_resets,
+       .rst_lines_cnt  = ARRAY_SIZE(omap3xxx_mmu_iva_resets),
+       .main_clk       = "iva2_ck",
+       .prcm = {
+               .omap2 = {
+                       .module_offs = OMAP3430_IVA2_MOD,
+               },
+       },
+       .dev_attr       = &mmu_iva_dev_attr,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+#endif
+
 /* l4_per -> gpio4 */
 static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
        {
@@ -3168,6 +3417,15 @@ static struct omap_hwmod_addr_space omap3xxx_counter_32k_addrs[] = {
        { }
 };
 
+static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
+       {
+               .pa_start       = 0x6e000000,
+               .pa_end         = 0x6e000fff,
+               .flags          = ADDR_TYPE_RT
+       },
+       { }
+};
+
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
        .master         = &omap3xxx_l4_wkup_hwmod,
        .slave          = &omap3xxx_counter_32k_hwmod,
@@ -3277,10 +3535,19 @@ static struct omap_hwmod_ocp_if am35xx_l4_core__emac = {
        .user           = OCP_USER_MPU,
 };
 
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+       .master         = &omap3xxx_l3_main_hwmod,
+       .slave          = &omap3xxx_gpmc_hwmod,
+       .clk            = "core_l3_ick",
+       .addr           = omap3xxx_gpmc_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l3_main__l4_core,
        &omap3xxx_l3_main__l4_per,
        &omap3xxx_mpu__l3_main,
+       &omap3xxx_l3_main__l4_debugss,
        &omap3xxx_l4_core__l4_wkup,
        &omap3xxx_l4_core__mmc3,
        &omap3_l4_core__uart1,
@@ -3322,6 +3589,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
        &omap34xx_l4_core__mcspi3,
        &omap34xx_l4_core__mcspi4,
        &omap3xxx_l4_wkup__counter_32k,
+       &omap3xxx_l3_main__gpmc,
        NULL,
 };
 
@@ -3371,6 +3639,11 @@ static struct omap_hwmod_ocp_if *omap34xx_hwmod_ocp_ifs[] __initdata = {
        &omap34xx_l4_core__sr2,
        &omap3xxx_l4_core__mailbox,
        &omap3xxx_l4_core__hdq1w,
+       &omap3xxx_sad2d__l3,
+       &omap3xxx_l4_core__mmu_isp,
+#ifdef CONFIG_OMAP_IOMMU_IVA2
+       &omap3xxx_l3_main__mmu_iva,
+#endif
        NULL
 };
 
@@ -3391,6 +3664,11 @@ static struct omap_hwmod_ocp_if *omap36xx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l4_core__es3plus_mmc1,
        &omap3xxx_l4_core__es3plus_mmc2,
        &omap3xxx_l4_core__hdq1w,
+       &omap3xxx_sad2d__l3,
+       &omap3xxx_l4_core__mmu_isp,
+#ifdef CONFIG_OMAP_IOMMU_IVA2
+       &omap3xxx_l3_main__mmu_iva,
+#endif
        NULL
 };
 
index c7dcb606cd0c566b0ef710dd6fa2ce2df75f7946..8d7a93525bc6f8f13a10df61964596ca0aac18e1 100644 (file)
@@ -30,6 +30,7 @@
 #include <plat/mmc.h>
 #include <plat/dmtimer.h>
 #include <plat/common.h>
+#include <plat/iommu.h>
 
 #include "omap_hwmod_common_data.h"
 #include "cm1_44xx.h"
@@ -202,6 +203,9 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = {
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET,
+                       .lostcontext_mask = OMAP4430_LOSTMEM_AESSMEM_MASK,
+                       .flags        = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
                },
        },
 };
@@ -258,6 +262,11 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
        .name           = "mpu_private",
        .class          = &omap44xx_mpu_bus_hwmod_class,
        .clkdm_name     = "mpuss_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /*
@@ -342,6 +351,7 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET,
                        .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET,
+                       .lostcontext_mask = OMAP4430_LOSTCONTEXT_DFF_MASK,
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
@@ -446,6 +456,11 @@ static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = {
        .class          = &omap44xx_ctrl_module_hwmod_class,
        .clkdm_name     = "l4_cfg_clkdm",
        .mpu_irqs       = omap44xx_ctrl_module_core_irqs,
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* ctrl_module_pad_core */
@@ -453,6 +468,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_core_hwmod = {
        .name           = "ctrl_module_pad_core",
        .class          = &omap44xx_ctrl_module_hwmod_class,
        .clkdm_name     = "l4_cfg_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* ctrl_module_wkup */
@@ -460,6 +480,11 @@ static struct omap_hwmod omap44xx_ctrl_module_wkup_hwmod = {
        .name           = "ctrl_module_wkup",
        .class          = &omap44xx_ctrl_module_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* ctrl_module_pad_wkup */
@@ -467,6 +492,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_wkup_hwmod = {
        .name           = "ctrl_module_pad_wkup",
        .class          = &omap44xx_ctrl_module_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /*
@@ -611,7 +641,6 @@ static struct omap_hwmod_irq_info omap44xx_dsp_irqs[] = {
 
 static struct omap_hwmod_rst_info omap44xx_dsp_resets[] = {
        { .name = "dsp", .rst_shift = 0 },
-       { .name = "mmu_cache", .rst_shift = 1 },
 };
 
 static struct omap_hwmod omap44xx_dsp_hwmod = {
@@ -1323,6 +1352,14 @@ static struct omap_hwmod omap44xx_gpmc_hwmod = {
        .name           = "gpmc",
        .class          = &omap44xx_gpmc_hwmod_class,
        .clkdm_name     = "l3_2_clkdm",
+       /*
+        * XXX HWMOD_INIT_NO_RESET should not be needed for this IP
+        * block.  It is not being added due to any known bugs with
+        * resetting the GPMC IP block, but rather because any timings
+        * set by the bootloader are not being correctly programmed by
+        * the kernel from the board file or DT data.
+        * HWMOD_INIT_NO_RESET should be removed ASAP.
+        */
        .flags          = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
        .mpu_irqs       = omap44xx_gpmc_irqs,
        .sdma_reqs      = omap44xx_gpmc_sdma_reqs,
@@ -1631,7 +1668,6 @@ static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
 static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = {
        { .name = "cpu0", .rst_shift = 0 },
        { .name = "cpu1", .rst_shift = 1 },
-       { .name = "mmu_cache", .rst_shift = 2 },
 };
 
 static struct omap_hwmod omap44xx_ipu_hwmod = {
@@ -2437,6 +2473,137 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
        },
 };
 
+/*
+ * 'mmu' class
+ * The memory management unit performs virtual to physical address translation
+ * for its requestors.
+ */
+
+static struct omap_hwmod_class_sysconfig mmu_sysc = {
+       .rev_offs       = 0x000,
+       .sysc_offs      = 0x010,
+       .syss_offs      = 0x014,
+       .sysc_flags     = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_mmu_hwmod_class = {
+       .name = "mmu",
+       .sysc = &mmu_sysc,
+};
+
+/* mmu ipu */
+
+static struct omap_mmu_dev_attr mmu_ipu_dev_attr = {
+       .da_start       = 0x0,
+       .da_end         = 0xfffff000,
+       .nr_tlb_entries = 32,
+};
+
+static struct omap_hwmod omap44xx_mmu_ipu_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmu_ipu_irqs[] = {
+       { .irq = 100 + OMAP44XX_IRQ_GIC_START, },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_rst_info omap44xx_mmu_ipu_resets[] = {
+       { .name = "mmu_cache", .rst_shift = 2 },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmu_ipu_addrs[] = {
+       {
+               .pa_start       = 0x55082000,
+               .pa_end         = 0x550820ff,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l3_main_2 -> mmu_ipu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__mmu_ipu = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_mmu_ipu_hwmod,
+       .clk            = "l3_div_ck",
+       .addr           = omap44xx_mmu_ipu_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod omap44xx_mmu_ipu_hwmod = {
+       .name           = "mmu_ipu",
+       .class          = &omap44xx_mmu_hwmod_class,
+       .clkdm_name     = "ducati_clkdm",
+       .mpu_irqs       = omap44xx_mmu_ipu_irqs,
+       .rst_lines      = omap44xx_mmu_ipu_resets,
+       .rst_lines_cnt  = ARRAY_SIZE(omap44xx_mmu_ipu_resets),
+       .main_clk       = "ducati_clk_mux_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET,
+                       .rstctrl_offs = OMAP4_RM_DUCATI_RSTCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_DUCATI_DUCATI_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
+               },
+       },
+       .dev_attr       = &mmu_ipu_dev_attr,
+};
+
+/* mmu dsp */
+
+static struct omap_mmu_dev_attr mmu_dsp_dev_attr = {
+       .da_start       = 0x0,
+       .da_end         = 0xfffff000,
+       .nr_tlb_entries = 32,
+};
+
+static struct omap_hwmod omap44xx_mmu_dsp_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmu_dsp_irqs[] = {
+       { .irq = 28 + OMAP44XX_IRQ_GIC_START },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_rst_info omap44xx_mmu_dsp_resets[] = {
+       { .name = "mmu_cache", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmu_dsp_addrs[] = {
+       {
+               .pa_start       = 0x4a066000,
+               .pa_end         = 0x4a0660ff,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_cfg -> dsp */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mmu_dsp = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_mmu_dsp_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_mmu_dsp_addrs,
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod omap44xx_mmu_dsp_hwmod = {
+       .name           = "mmu_dsp",
+       .class          = &omap44xx_mmu_hwmod_class,
+       .clkdm_name     = "tesla_clkdm",
+       .mpu_irqs       = omap44xx_mmu_dsp_irqs,
+       .rst_lines      = omap44xx_mmu_dsp_resets,
+       .rst_lines_cnt  = ARRAY_SIZE(omap44xx_mmu_dsp_resets),
+       .main_clk       = "dpll_iva_m4x2_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET,
+                       .rstctrl_offs = OMAP4_RM_TESLA_RSTCTRL_OFFSET,
+                       .context_offs = OMAP4_RM_TESLA_TESLA_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
+               },
+       },
+       .dev_attr       = &mmu_dsp_dev_attr,
+};
+
 /*
  * 'mpu' class
  * mpu sub-system
@@ -2448,6 +2615,8 @@ static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
 
 /* mpu */
 static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+       { .name = "pmu0", .irq = 54 + OMAP44XX_IRQ_GIC_START },
+       { .name = "pmu1", .irq = 55 + OMAP44XX_IRQ_GIC_START },
        { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
        { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
        { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
@@ -2497,19 +2666,27 @@ static struct omap_hwmod omap44xx_ocmc_ram_hwmod = {
  * protocol
  */
 
+static struct omap_hwmod_class_sysconfig omap44xx_ocp2scp_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
 static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
        .name   = "ocp2scp",
+       .sysc   = &omap44xx_ocp2scp_sysc,
 };
 
 /* ocp2scp_usb_phy */
-static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = {
-       { .role = "phy_48m", .clk = "ocp2scp_usb_phy_phy_48m" },
-};
-
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
        .class          = &omap44xx_ocp2scp_hwmod_class,
        .clkdm_name     = "l3_init_clkdm",
+       .main_clk       = "ocp2scp_usb_phy_phy_48m",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET,
@@ -2517,8 +2694,6 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
-       .opt_clks       = ocp2scp_usb_phy_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks),
 };
 
 /*
@@ -2536,18 +2711,36 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = {
        .name           = "prcm_mpu",
        .class          = &omap44xx_prcm_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .flags          = HWMOD_NO_IDLEST,
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* cm_core_aon */
 static struct omap_hwmod omap44xx_cm_core_aon_hwmod = {
        .name           = "cm_core_aon",
        .class          = &omap44xx_prcm_hwmod_class,
+       .flags          = HWMOD_NO_IDLEST,
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* cm_core */
 static struct omap_hwmod omap44xx_cm_core_hwmod = {
        .name           = "cm_core",
        .class          = &omap44xx_prcm_hwmod_class,
+       .flags          = HWMOD_NO_IDLEST,
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /* prm */
@@ -2583,6 +2776,11 @@ static struct omap_hwmod omap44xx_scrm_hwmod = {
        .name           = "scrm",
        .class          = &omap44xx_scrm_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT,
+               },
+       },
 };
 
 /*
@@ -2901,6 +3099,16 @@ static struct omap_timer_capability_dev_attr capability_pwm_dev_attr = {
        .timer_capability       = OMAP_TIMER_HAS_PWM,
 };
 
+/* timers with DSP interrupt dev attribute */
+static struct omap_timer_capability_dev_attr capability_dsp_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_DSP_IRQ,
+};
+
+/* pwm timers with DSP interrupt dev attribute */
+static struct omap_timer_capability_dev_attr capability_dsp_pwm_dev_attr = {
+       .timer_capability       = OMAP_TIMER_HAS_DSP_IRQ | OMAP_TIMER_HAS_PWM,
+};
+
 /* timer1 */
 static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
        { .irq = 37 + OMAP44XX_IRQ_GIC_START },
@@ -3005,6 +3213,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
 };
 
 /* timer6 */
@@ -3027,6 +3236,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
 };
 
 /* timer7 */
@@ -3048,6 +3258,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
+       .dev_attr       = &capability_dsp_dev_attr,
 };
 
 /* timer8 */
@@ -3069,7 +3280,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_pwm_dev_attr,
+       .dev_attr       = &capability_dsp_pwm_dev_attr,
 };
 
 /* timer9 */
@@ -5262,11 +5473,21 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ocmc_ram = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap44xx_ocp2scp_usb_phy_addrs[] = {
+       {
+               .pa_start       = 0x4a0ad000,
+               .pa_end         = 0x4a0ad01f,
+               .flags          = ADDR_TYPE_RT
+       },
+       { }
+};
+
 /* l4_cfg -> ocp2scp_usb_phy */
 static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ocp2scp_usb_phy = {
        .master         = &omap44xx_l4_cfg_hwmod,
        .slave          = &omap44xx_ocp2scp_usb_phy_hwmod,
        .clk            = "l4_div_ck",
+       .addr           = omap44xx_ocp2scp_usb_phy_addrs,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -5886,7 +6107,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
 static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
        {
                .pa_start       = 0x4a0ab000,
-               .pa_end         = 0x4a0ab003,
+               .pa_end         = 0x4a0ab7ff,
                .flags          = ADDR_TYPE_RT
        },
        {
@@ -6097,6 +6318,8 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_per__mmc3,
        &omap44xx_l4_per__mmc4,
        &omap44xx_l4_per__mmc5,
+       &omap44xx_l3_main_2__mmu_ipu,
+       &omap44xx_l4_cfg__mmu_dsp,
        &omap44xx_l3_main_2__ocmc_ram,
        &omap44xx_l4_cfg__ocp2scp_usb_phy,
        &omap44xx_mpu_private__prcm_mpu,
index dddb677fed688c16b0198df03a646330da003968..2bc8f1705d4aa7ce18d779c27089116990979d14 100644 (file)
@@ -2,9 +2,8 @@
  * omap_hwmod_common_data.h - OMAP hwmod common macros and declarations
  *
  * Copyright (C) 2010-2011 Nokia Corporation
+ * Copyright (C) 2010-2012 Texas Instruments, Inc.
  * Paul Walmsley
- *
- * Copyright (C) 2010-2011 Texas Instruments, Inc.
  * Benoît Cousson
  *
  * This program is free software; you can redistribute it and/or modify
@@ -77,6 +76,8 @@ extern struct omap_hwmod omap2xxx_gpio4_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
 extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
+extern struct omap_hwmod omap2xxx_gpmc_hwmod;
+extern struct omap_hwmod omap2xxx_rng_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
@@ -103,6 +104,7 @@ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
 
 /* Common IP block data */
 extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
index 939bd6f70b51f1d4ad6df947d72196349d26b633..abefbc4d8e0b9bd452c54af22d3a09e7cd172af9 100644 (file)
@@ -80,7 +80,8 @@ static void __init omap2_init_processor_devices(void)
 
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-       if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
+       if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
+           !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
                clkdm_allow_idle(clkdm);
        else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
                 atomic_read(&clkdm->usecount) == 0)
@@ -188,7 +189,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
                goto exit;
        }
 
-       freq = clk->rate;
+       freq = clk_get_rate(clk);
        clk_put(clk);
 
        rcu_read_lock();
diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c
new file mode 100644 (file)
index 0000000..2a79176
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * OMAP2 ARM Performance Monitoring Unit (PMU) Support
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Contacts:
+ * Jon Hunter <jon-hunter@ti.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/pm_runtime.h>
+
+#include <asm/pmu.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+
+static char *omap2_pmu_oh_names[] = {"mpu"};
+static char *omap3_pmu_oh_names[] = {"mpu", "debugss"};
+static char *omap4430_pmu_oh_names[] = {"l3_main_3", "l3_instr", "debugss"};
+static struct platform_device *omap_pmu_dev;
+
+/**
+ * omap2_init_pmu - creates and registers PMU platform device
+ * @oh_num:    Number of OMAP HWMODs required to create PMU device
+ * @oh_names:  Array of OMAP HWMODS names required to create PMU device
+ *
+ * Uses OMAP HWMOD framework to create and register an ARM PMU device
+ * from a list of HWMOD names passed. Currently supports OMAP2, OMAP3
+ * and OMAP4 devices.
+ */
+static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[])
+{
+       int i;
+       struct omap_hwmod *oh[3];
+       char *dev_name = "arm-pmu";
+
+       if ((!oh_num) || (oh_num > 3))
+               return -EINVAL;
+
+       for (i = 0; i < oh_num; i++) {
+               oh[i] = omap_hwmod_lookup(oh_names[i]);
+               if (!oh[i]) {
+                       pr_err("Could not look up %s hwmod\n", oh_names[i]);
+                       return -ENODEV;
+               }
+       }
+
+       omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0,
+                                           NULL, 0, 0);
+       WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n",
+            dev_name);
+
+       if (IS_ERR(omap_pmu_dev))
+               return PTR_ERR(omap_pmu_dev);
+
+       pm_runtime_enable(&omap_pmu_dev->dev);
+
+       return 0;
+}
+
+static int __init omap_init_pmu(void)
+{
+       unsigned oh_num;
+       char **oh_names;
+
+       /*
+        * To create an ARM-PMU device the following HWMODs
+        * are required for the various OMAP2+ devices.
+        *
+        * OMAP24xx:    mpu
+        * OMAP3xxx:    mpu, debugss
+        * OMAP4430:    l3_main_3, l3_instr, debugss
+        * OMAP4460/70: mpu, debugss
+        */
+       if (cpu_is_omap443x()) {
+               oh_num = ARRAY_SIZE(omap4430_pmu_oh_names);
+               oh_names = omap4430_pmu_oh_names;
+               /* XXX Remove the next two lines when CTI driver available */
+               pr_info("ARM PMU: not yet supported on OMAP4430 due to missing CTI driver\n");
+               return 0;
+       } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+               oh_num = ARRAY_SIZE(omap3_pmu_oh_names);
+               oh_names = omap3_pmu_oh_names;
+       } else {
+               oh_num = ARRAY_SIZE(omap2_pmu_oh_names);
+               oh_names = omap2_pmu_oh_names;
+       }
+
+       return omap2_init_pmu(oh_num, oh_names);
+}
+subsys_initcall(omap_init_pmu);
index aeac6f35ca10cf4e4709bd79d69801d4475286ac..aceb4f464c9bdd13f843daef5e59abe65686fb88 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP4 powerdomain control
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010, 2012 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
@@ -151,6 +151,34 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
        return v;
 }
 
+/**
+ * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
+ * @pwrdm: struct powerdomain * to read the state for
+ *
+ * Reads the previous logic powerstate for a powerdomain. This
+ * function must determine the previous logic powerstate by first
+ * checking the previous powerstate for the domain. If that was OFF,
+ * then logic has been lost. If previous state was RETENTION, the
+ * function reads the setting for the next retention logic state to
+ * see the actual value.  In every other case, the logic is
+ * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
+ * depending whether the logic was retained or not.
+ */
+static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+       int state;
+
+       state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+       if (state == PWRDM_POWER_OFF)
+               return PWRDM_POWER_OFF;
+
+       if (state != PWRDM_POWER_RET)
+               return PWRDM_POWER_RET;
+
+       return omap4_pwrdm_read_logic_retst(pwrdm);
+}
+
 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
        u32 m, v;
@@ -179,6 +207,35 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
        return v;
 }
 
+/**
+ * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
+ * @pwrdm: struct powerdomain * to read mem powerstate for
+ * @bank: memory bank index
+ *
+ * Reads the previous memory powerstate for a powerdomain. This
+ * function must determine the previous memory powerstate by first
+ * checking the previous powerstate for the domain. If that was OFF,
+ * then logic has been lost. If previous state was RETENTION, the
+ * function reads the setting for the next memory retention state to
+ * see the actual value.  In every other case, the logic is
+ * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
+ * depending whether logic was retained or not.
+ */
+static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+       int state;
+
+       state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+       if (state == PWRDM_POWER_OFF)
+               return PWRDM_POWER_OFF;
+
+       if (state != PWRDM_POWER_RET)
+               return PWRDM_POWER_RET;
+
+       return omap4_pwrdm_read_mem_retst(pwrdm, bank);
+}
+
 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 {
        u32 c = 0;
@@ -217,9 +274,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
        .pwrdm_clear_all_prev_pwrst     = omap4_pwrdm_clear_all_prev_pwrst,
        .pwrdm_set_logic_retst  = omap4_pwrdm_set_logic_retst,
        .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
+       .pwrdm_read_prev_logic_pwrst    = omap4_pwrdm_read_prev_logic_pwrst,
        .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
        .pwrdm_read_mem_pwrst   = omap4_pwrdm_read_mem_pwrst,
        .pwrdm_read_mem_retst   = omap4_pwrdm_read_mem_retst,
+       .pwrdm_read_prev_mem_pwrst      = omap4_pwrdm_read_prev_mem_pwrst,
        .pwrdm_set_mem_onst     = omap4_pwrdm_set_mem_onst,
        .pwrdm_set_mem_retst    = omap4_pwrdm_set_mem_retst,
        .pwrdm_wait_transition  = omap4_pwrdm_wait_transition,
index e5f0503a68b09e5a2eff32e1a01350a33e32c91b..72df97482cc04f7eb95f8f5acfe87aa2372081e0 100644 (file)
 #define OMAP2430_EN_MDM_INTC_MASK                      (1 << 11)
 #define OMAP2430_EN_USBHS_SHIFT                                6
 #define OMAP2430_EN_USBHS_MASK                         (1 << 6)
+#define OMAP24XX_EN_GPMC_SHIFT                         1
+#define OMAP24XX_EN_GPMC_MASK                          (1 << 1)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
 #define OMAP2420_ST_MMC_SHIFT                          26
index ac95daaa4702dc6cd2f734e19e35c716d8c2e69c..3c434498e12e6faf034e1411d1b09b4b75a81c50 100644 (file)
 #ifdef CONFIG_MFD_OMAP_USB_HOST
 
 #define OMAP_USBHS_DEVICE      "usbhs_omap"
+#define OMAP_USBTLL_DEVICE     "usbhs_tll"
 #define        USBHS_UHH_HWMODNAME     "usb_host_hs"
 #define USBHS_TLL_HWMODNAME    "usb_tll_hs"
 
 static struct usbhs_omap_platform_data         usbhs_data;
+static struct usbtll_omap_platform_data                usbtll_data;
 static struct ehci_hcd_omap_platform_data      ehci_data;
 static struct ohci_hcd_omap_platform_data      ohci_data;
 
@@ -485,13 +487,14 @@ void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 
 void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 {
-       struct omap_hwmod       *oh[2];
+       struct omap_hwmod       *uhh_hwm, *tll_hwm;
        struct platform_device  *pdev;
        int                     bus_id = -1;
        int                     i;
 
        for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
                usbhs_data.port_mode[i] = pdata->port_mode[i];
+               usbtll_data.port_mode[i] = pdata->port_mode[i];
                ohci_data.port_mode[i] = pdata->port_mode[i];
                ehci_data.port_mode[i] = pdata->port_mode[i];
                ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
@@ -510,25 +513,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
                setup_4430ohci_io_mux(pdata->port_mode);
        }
 
-       oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
-       if (!oh[0]) {
+       uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
+       if (!uhh_hwm) {
                pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
                return;
        }
 
-       oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
-       if (!oh[1]) {
+       tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
+       if (!tll_hwm) {
                pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
                return;
        }
 
-       pdev = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2,
-                               (void *)&usbhs_data, sizeof(usbhs_data),
+       pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
+                               &usbtll_data, sizeof(usbtll_data),
                                omap_uhhtll_latency,
                                ARRAY_SIZE(omap_uhhtll_latency), false);
        if (IS_ERR(pdev)) {
-               pr_err("Could not build hwmod devices %s,%s\n",
-                       USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
+               pr_err("Could not build hwmod device %s\n",
+                      USBHS_TLL_HWMODNAME);
+               return;
+       }
+
+       pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
+                               &usbhs_data, sizeof(usbhs_data),
+                               omap_uhhtll_latency,
+                               ARRAY_SIZE(omap_uhhtll_latency), false);
+       if (IS_ERR(pdev)) {
+               pr_err("Could not build hwmod devices %s\n",
+                      USBHS_UHH_HWMODNAME);
                return;
        }
 }
index eaac83d1df6f2207a4106276ce8d95c75b686589..b5efc0fd31cb265ff1b9c53072301422fb31a450 100644 (file)
@@ -113,7 +113,8 @@ void __init orion5x_setup_cpu_mbus_bridge(void)
        /*
         * Setup MBUS dram target info.
         */
-       orion_setup_cpu_mbus_target(&addr_map_cfg, ORION5X_DDR_WINDOW_CPU_BASE);
+       orion_setup_cpu_mbus_target(&addr_map_cfg,
+                                   (void __iomem *) ORION5X_DDR_WINDOW_CPU_BASE);
 }
 
 void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
index 073c7d799068f6f8227da410613ea900f9c019d6..b3eb3da011601bdc6774f237d2db48d630a6f8d2 100644 (file)
  ****************************************************************************/
 static struct map_desc orion5x_io_desc[] __initdata = {
        {
-               .virtual        = ORION5X_REGS_VIRT_BASE,
+               .virtual        = (unsigned long) ORION5X_REGS_VIRT_BASE,
                .pfn            = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
                .length         = ORION5X_REGS_SIZE,
                .type           = MT_DEVICE,
        }, {
-               .virtual        = ORION5X_PCIE_WA_VIRT_BASE,
+               .virtual        = (unsigned long) ORION5X_PCIE_WA_VIRT_BASE,
                .pfn            = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
                .length         = ORION5X_PCIE_WA_SIZE,
                .type           = MT_DEVICE,
index 0e19db69f5c40850bec8d54c737eb7e6f576d9b5..e533588880ff5636fdaf2982988b33d0342a1c97 100644 (file)
@@ -701,7 +701,7 @@ static void __init dns323_init(void)
                 * Note: AFAIK, rev B1 needs the same treatement but I'll let
                 * somebody else test it.
                 */
-               writel(0x5, ORION5X_SATA_VIRT_BASE | 0x2c);
+               writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c);
                break;
        }
 }
index 11a3c1e9801f4bea759d6deb3ec9179b019c3650..461fd69a10ae58f7d7acd0672c95d9837b451d1a 100644 (file)
 
 #include <mach/orion5x.h>
 
-#define CPU_CONF               (ORION5X_BRIDGE_VIRT_BASE | 0x100)
+#define CPU_CONF               (ORION5X_BRIDGE_VIRT_BASE + 0x100)
 
-#define CPU_CTRL               (ORION5X_BRIDGE_VIRT_BASE | 0x104)
+#define CPU_CTRL               (ORION5X_BRIDGE_VIRT_BASE + 0x104)
 
-#define RSTOUTn_MASK           (ORION5X_BRIDGE_VIRT_BASE | 0x108)
+#define RSTOUTn_MASK           (ORION5X_BRIDGE_VIRT_BASE + 0x108)
 #define WDT_RESET_OUT_EN       0x0002
 
-#define CPU_SOFT_RESET         (ORION5X_BRIDGE_VIRT_BASE | 0x10c)
+#define CPU_SOFT_RESET         (ORION5X_BRIDGE_VIRT_BASE + 0x10c)
 
-#define BRIDGE_CAUSE           (ORION5X_BRIDGE_VIRT_BASE | 0x110)
+#define BRIDGE_CAUSE           (ORION5X_BRIDGE_VIRT_BASE + 0x110)
 
-#define POWER_MNG_CTRL_REG     (ORION5X_BRIDGE_VIRT_BASE | 0x11C)
+#define POWER_MNG_CTRL_REG     (ORION5X_BRIDGE_VIRT_BASE + 0x11C)
 
 #define WDT_INT_REQ            0x0008
 
 #define BRIDGE_INT_TIMER1_CLR  (~0x0004)
 
-#define MAIN_IRQ_CAUSE         (ORION5X_BRIDGE_VIRT_BASE | 0x200)
+#define MAIN_IRQ_CAUSE         (ORION5X_BRIDGE_VIRT_BASE + 0x200)
 
-#define MAIN_IRQ_MASK          (ORION5X_BRIDGE_VIRT_BASE | 0x204)
+#define MAIN_IRQ_MASK          (ORION5X_BRIDGE_VIRT_BASE + 0x204)
 
-#define TIMER_VIRT_BASE                (ORION5X_BRIDGE_VIRT_BASE | 0x300)
-#define TIMER_PHYS_BASE                (ORION5X_BRIDGE_PHYS_BASE | 0x300)
+#define TIMER_VIRT_BASE                (ORION5X_BRIDGE_VIRT_BASE + 0x300)
+#define TIMER_PHYS_BASE                (ORION5X_BRIDGE_PHYS_BASE + 0x300)
 #endif
index 1b60131b7f60828088b45e55de057d5ce6d13e2b..d265f5484a8e6934a7a1105c196539d27e6d3b15 100644 (file)
@@ -37,7 +37,7 @@
  * fd000000    f0000000        16M     PCIe WA space (Orion-1/Orion-NAS only)
  ****************************************************************************/
 #define ORION5X_REGS_PHYS_BASE         0xf1000000
-#define ORION5X_REGS_VIRT_BASE         0xfe000000
+#define ORION5X_REGS_VIRT_BASE         IOMEM(0xfe000000)
 #define ORION5X_REGS_SIZE              SZ_1M
 
 #define ORION5X_PCIE_IO_PHYS_BASE      0xf2000000
@@ -53,7 +53,7 @@
 
 /* Relevant only for Orion-1/Orion-NAS */
 #define ORION5X_PCIE_WA_PHYS_BASE      0xf0000000
-#define ORION5X_PCIE_WA_VIRT_BASE      0xfd000000
+#define ORION5X_PCIE_WA_VIRT_BASE      IOMEM(0xfd000000)
 #define ORION5X_PCIE_WA_SIZE           SZ_16M
 
 #define ORION5X_PCIE_MEM_PHYS_BASE     0xe0000000
  * Orion Registers Map
  ******************************************************************************/
 
-#define ORION5X_DDR_VIRT_BASE          (ORION5X_REGS_VIRT_BASE | 0x00000)
-#define  ORION5X_DDR_WINDOW_CPU_BASE    (ORION5X_DDR_VIRT_BASE | 0x1500)
-#define ORION5X_DEV_BUS_PHYS_BASE      (ORION5X_REGS_PHYS_BASE | 0x10000)
-#define ORION5X_DEV_BUS_VIRT_BASE      (ORION5X_REGS_VIRT_BASE | 0x10000)
-#define ORION5X_DEV_BUS_REG(x)         (ORION5X_DEV_BUS_VIRT_BASE | (x))
+#define ORION5X_DDR_VIRT_BASE          (ORION5X_REGS_VIRT_BASE + 0x00000)
+#define  ORION5X_DDR_WINDOW_CPU_BASE    (ORION5X_DDR_VIRT_BASE + 0x1500)
+#define ORION5X_DEV_BUS_PHYS_BASE      (ORION5X_REGS_PHYS_BASE + 0x10000)
+#define ORION5X_DEV_BUS_VIRT_BASE      (ORION5X_REGS_VIRT_BASE + 0x10000)
+#define ORION5X_DEV_BUS_REG(x)         (ORION5X_DEV_BUS_VIRT_BASE + (x))
 #define  GPIO_VIRT_BASE                        ORION5X_DEV_BUS_REG(0x0100)
-#define  SPI_PHYS_BASE                 (ORION5X_DEV_BUS_PHYS_BASE | 0x0600)
-#define  I2C_PHYS_BASE                 (ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
-#define  UART0_PHYS_BASE               (ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
-#define  UART0_VIRT_BASE               (ORION5X_DEV_BUS_VIRT_BASE | 0x2000)
-#define  UART1_PHYS_BASE               (ORION5X_DEV_BUS_PHYS_BASE | 0x2100)
-#define  UART1_VIRT_BASE               (ORION5X_DEV_BUS_VIRT_BASE | 0x2100)
+#define  SPI_PHYS_BASE                 (ORION5X_DEV_BUS_PHYS_BASE + 0x0600)
+#define  I2C_PHYS_BASE                 (ORION5X_DEV_BUS_PHYS_BASE + 0x1000)
+#define  UART0_PHYS_BASE               (ORION5X_DEV_BUS_PHYS_BASE + 0x2000)
+#define  UART0_VIRT_BASE               (ORION5X_DEV_BUS_VIRT_BASE + 0x2000)
+#define  UART1_PHYS_BASE               (ORION5X_DEV_BUS_PHYS_BASE + 0x2100)
+#define  UART1_VIRT_BASE               (ORION5X_DEV_BUS_VIRT_BASE + 0x2100)
 
-#define ORION5X_BRIDGE_VIRT_BASE       (ORION5X_REGS_VIRT_BASE | 0x20000)
-#define ORION5X_BRIDGE_PHYS_BASE       (ORION5X_REGS_PHYS_BASE | 0x20000)
+#define ORION5X_BRIDGE_VIRT_BASE       (ORION5X_REGS_VIRT_BASE + 0x20000)
+#define ORION5X_BRIDGE_PHYS_BASE       (ORION5X_REGS_PHYS_BASE + 0x20000)
 
-#define ORION5X_PCI_VIRT_BASE          (ORION5X_REGS_VIRT_BASE | 0x30000)
+#define ORION5X_PCI_VIRT_BASE          (ORION5X_REGS_VIRT_BASE + 0x30000)
 
-#define ORION5X_PCIE_VIRT_BASE         (ORION5X_REGS_VIRT_BASE | 0x40000)
+#define ORION5X_PCIE_VIRT_BASE         (ORION5X_REGS_VIRT_BASE + 0x40000)
 
-#define ORION5X_USB0_PHYS_BASE         (ORION5X_REGS_PHYS_BASE | 0x50000)
-#define ORION5X_USB0_VIRT_BASE         (ORION5X_REGS_VIRT_BASE | 0x50000)
+#define ORION5X_USB0_PHYS_BASE         (ORION5X_REGS_PHYS_BASE + 0x50000)
+#define ORION5X_USB0_VIRT_BASE         (ORION5X_REGS_VIRT_BASE + 0x50000)
 
-#define ORION5X_XOR_PHYS_BASE          (ORION5X_REGS_PHYS_BASE | 0x60900)
-#define ORION5X_XOR_VIRT_BASE          (ORION5X_REGS_VIRT_BASE | 0x60900)
+#define ORION5X_XOR_PHYS_BASE          (ORION5X_REGS_PHYS_BASE + 0x60900)
+#define ORION5X_XOR_VIRT_BASE          (ORION5X_REGS_VIRT_BASE + 0x60900)
 
-#define ORION5X_ETH_PHYS_BASE          (ORION5X_REGS_PHYS_BASE | 0x70000)
-#define ORION5X_ETH_VIRT_BASE          (ORION5X_REGS_VIRT_BASE | 0x70000)
+#define ORION5X_ETH_PHYS_BASE          (ORION5X_REGS_PHYS_BASE + 0x70000)
+#define ORION5X_ETH_VIRT_BASE          (ORION5X_REGS_VIRT_BASE + 0x70000)
 
-#define ORION5X_SATA_PHYS_BASE         (ORION5X_REGS_PHYS_BASE | 0x80000)
-#define ORION5X_SATA_VIRT_BASE         (ORION5X_REGS_VIRT_BASE | 0x80000)
+#define ORION5X_SATA_PHYS_BASE         (ORION5X_REGS_PHYS_BASE + 0x80000)
+#define ORION5X_SATA_VIRT_BASE         (ORION5X_REGS_VIRT_BASE + 0x80000)
 
-#define ORION5X_CRYPTO_PHYS_BASE       (ORION5X_REGS_PHYS_BASE | 0x90000)
+#define ORION5X_CRYPTO_PHYS_BASE       (ORION5X_REGS_PHYS_BASE + 0x90000)
 
-#define ORION5X_USB1_PHYS_BASE         (ORION5X_REGS_PHYS_BASE | 0xa0000)
-#define ORION5X_USB1_VIRT_BASE         (ORION5X_REGS_VIRT_BASE | 0xa0000)
+#define ORION5X_USB1_PHYS_BASE         (ORION5X_REGS_PHYS_BASE + 0xa0000)
+#define ORION5X_USB1_VIRT_BASE         (ORION5X_REGS_VIRT_BASE + 0xa0000)
 
 /*******************************************************************************
  * Device Bus Registers
index e152641cdb0e3e57b0059e87e9f8d97588f48f3b..30a192b9c51730da9dfb94ccdf93128ceb8143de 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
 #include <plat/orion-gpio.h>
 #include <plat/irq.h>
@@ -25,11 +26,11 @@ static int __initdata gpio0_irqs[4] = {
 
 void __init orion5x_init_irq(void)
 {
-       orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
+       orion_irq_init(0, MAIN_IRQ_MASK);
 
        /*
         * Initialize gpiolib for GPIOs 0-31.
         */
-       orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE, 0,
+       orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE, 0,
                        IRQ_ORION5X_GPIO_START, gpio0_irqs);
 }
index 6921d49b988d3152f36295815611ab711cdc57a3..cd50e328db2a46e4470e57bb8bbe5af0d30f595c 100644 (file)
@@ -38,7 +38,7 @@
 /*****************************************************************************
  * PCIe controller
  ****************************************************************************/
-#define PCIE_BASE      ((void __iomem *)ORION5X_PCIE_VIRT_BASE)
+#define PCIE_BASE      (ORION5X_PCIE_VIRT_BASE)
 
 void __init orion5x_pcie_id(u32 *dev, u32 *rev)
 {
@@ -111,7 +111,7 @@ static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
                return PCIBIOS_DEVICE_NOT_FOUND;
        }
 
-       ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
+       ret = orion_pcie_rd_conf_wa(ORION5X_PCIE_WA_VIRT_BASE,
                                    bus, devfn, where, size, val);
 
        return ret;
@@ -188,7 +188,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
 /*****************************************************************************
  * PCI controller
  ****************************************************************************/
-#define ORION5X_PCI_REG(x)     (ORION5X_PCI_VIRT_BASE | (x))
+#define ORION5X_PCI_REG(x)     (ORION5X_PCI_VIRT_BASE + (x))
 #define PCI_MODE               ORION5X_PCI_REG(0xd00)
 #define PCI_CMD                        ORION5X_PCI_REG(0xc00)
 #define PCI_P2P_CONF           ORION5X_PCI_REG(0x1d14)
index 0d4620ed853c7c3a3c7cc9a3995c50ceecc40e2e..96800aa1316d980d9e41f94c11360918aedb9ee1 100644 (file)
@@ -9,7 +9,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/regulator/machine.h>
 #include <linux/amba/bus.h>
 #include <mach/irqs.h>
index 5f6b7d543e55ffb5f519043a85466683b9557dd1..560e0df728f89931826f080cfe87dda6abcec128 100644 (file)
@@ -659,6 +659,7 @@ static void __init v2m_dt_init(void)
 
 const static char *v2m_dt_match[] __initconst = {
        "arm,vexpress",
+       "xen,xenvm",
        NULL,
 };
 
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 706b7e29397f5ebfc87a5de092eb4fd330a635ba..9d7ac20ef8f9dc59d426053d0facddbb7c4b6bfa 100644 (file)
@@ -312,33 +312,6 @@ void clk_enable_init_clocks(void)
        }
 }
 
-/**
- * omap_clk_get_by_name - locate OMAP struct clk by its name
- * @name: name of the struct clk to locate
- *
- * Locate an OMAP struct clk by its name.  Assumes that struct clk
- * names are unique.  Returns NULL if not found or a pointer to the
- * struct clk if found.
- */
-struct clk *omap_clk_get_by_name(const char *name)
-{
-       struct clk *c;
-       struct clk *ret = NULL;
-
-       mutex_lock(&clocks_mutex);
-
-       list_for_each_entry(c, &clocks, node) {
-               if (!strcmp(c->name, name)) {
-                       ret = c;
-                       break;
-               }
-       }
-
-       mutex_unlock(&clocks_mutex);
-
-       return ret;
-}
-
 int omap_clk_enable_autoidle_all(void)
 {
        struct clk *c;
index 656b9862279e7f757e9e1328a81279f20ef3b7e7..e2e2d045e428b710922d2c0da1a57f1b21549874 100644 (file)
@@ -19,6 +19,11 @@ struct module;
 struct clk;
 struct clockdomain;
 
+/* Temporary, needed during the common clock framework conversion */
+#define __clk_get_name(clk)    (clk->name)
+#define __clk_get_parent(clk)  (clk->parent)
+#define __clk_get_rate(clk)    (clk->rate)
+
 /**
  * struct clkops - some clock function pointers
  * @enable: fn ptr that enables the current clock in hardware
index 19e7fa577bd0ad04eadcc4276d0de4f40039dadd..85868e98c11cd4ce4466da49669ee4cafc41c29f 100644 (file)
@@ -60,6 +60,7 @@
 #define OMAP_TIMER_ALWON                               0x40000000
 #define OMAP_TIMER_HAS_PWM                             0x20000000
 #define OMAP_TIMER_NEEDS_RESET                         0x10000000
+#define OMAP_TIMER_HAS_DSP_IRQ                         0x08000000
 
 struct omap_timer_capability_dev_attr {
        u32 timer_capability;
index 88be3e628b339f49e6943f6fb6ad792546730aa6..68b5f0362f356a0adb402706fec5378828d716ae 100644 (file)
@@ -103,6 +103,19 @@ struct iommu_functions {
        ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
 };
 
+/**
+ * struct omap_mmu_dev_attr - OMAP mmu device attributes for omap_hwmod
+ * @da_start:          device address where the va space starts.
+ * @da_end:            device address where the va space ends.
+ * @nr_tlb_entries:    number of entries supported by the translation
+ *                     look-aside buffer (TLB).
+ */
+struct omap_mmu_dev_attr {
+       u32 da_start;
+       u32 da_end;
+       int nr_tlb_entries;
+};
+
 struct iommu_platform_data {
        const char *name;
        const char *clk_name;
@@ -126,6 +139,7 @@ struct omap_iommu_arch_data {
        struct omap_iommu *iommu_dev;
 };
 
+#ifdef CONFIG_IOMMU_API
 /**
  * dev_to_omap_iommu() - retrieves an omap iommu object from a user device
  * @dev: iommu client device
@@ -136,6 +150,7 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
 
        return arch_data->iommu_dev;
 }
+#endif
 
 /* IOMMU errors */
 #define OMAP_IOMMU_ERR_TLB_MISS                (1 << 0)
index e7259c0d33ec13f57fad7739beedaeba488e0983..106f50665804952edaf78b3f21167a78b9d5e1ec 100644 (file)
@@ -120,6 +120,10 @@ int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
 
+int omap_device_assert_hardreset(struct platform_device *pdev,
+                                const char *name);
+int omap_device_deassert_hardreset(struct platform_device *pdev,
+                                const char *name);
 int omap_device_idle_hwmods(struct omap_device *od);
 int omap_device_enable_hwmods(struct omap_device *od);
 
index 05330735f23fc63aa1186016ef31cebadcbdb62a..b3349f7b1a2cda6458ed75b541a07298c84e7234 100644 (file)
@@ -2,7 +2,7 @@
  * omap_hwmod macros, structures
  *
  * Copyright (C) 2009-2011 Nokia Corporation
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2012 Texas Instruments, Inc.
  * Paul Walmsley
  *
  * Created in collaboration with (alphabetical order): Benoît Cousson,
@@ -384,21 +384,38 @@ struct omap_hwmod_omap2_prcm {
        u8 idlest_stdby_bit;
 };
 
+/*
+ * Possible values for struct omap_hwmod_omap4_prcm.flags
+ *
+ * HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT: Some IP blocks don't have a PRCM
+ *     module-level context loss register associated with them; this
+ *     flag bit should be set in those cases
+ */
+#define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT                (1 << 0)
 
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
  * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register
  * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
+ * @flags: PRCM register capabilities for this IP block
+ *
+ * If @lostcontext_mask is not defined, context loss check code uses
+ * whole register without masking. @lostcontext_mask should only be
+ * defined in cases where @context_offs register is shared by two or
+ * more hwmods.
  */
 struct omap_hwmod_omap4_prcm {
        u16             clkctrl_offs;
        u16             rstctrl_offs;
        u16             rstst_offs;
        u16             context_offs;
+       u32             lostcontext_mask;
        u8              submodule_wkdep_bit;
        u8              modulemode;
+       u8              flags;
 };
 
 
@@ -591,9 +608,7 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
 int __init omap_hwmod_setup_one(const char *name);
 
 int omap_hwmod_enable(struct omap_hwmod *oh);
-int _omap_hwmod_enable(struct omap_hwmod *oh);
 int omap_hwmod_idle(struct omap_hwmod *oh);
-int _omap_hwmod_idle(struct omap_hwmod *oh);
 int omap_hwmod_shutdown(struct omap_hwmod *oh);
 
 int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
@@ -627,11 +642,6 @@ int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh,
 int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
                                 struct omap_hwmod *init_oh);
 
-int omap_hwmod_set_clockact_both(struct omap_hwmod *oh);
-int omap_hwmod_set_clockact_main(struct omap_hwmod *oh);
-int omap_hwmod_set_clockact_iclk(struct omap_hwmod *oh);
-int omap_hwmod_set_clockact_none(struct omap_hwmod *oh);
-
 int omap_hwmod_enable_wakeup(struct omap_hwmod *oh);
 int omap_hwmod_disable_wakeup(struct omap_hwmod *oh);
 
index bd20588c356b47703cc18aa0a78f29094126813b..87ee140fefaa94b5b14f8ff94dcc5fdaaaf4e07a 100644 (file)
@@ -4,6 +4,7 @@
 #define        __ASM_ARCH_OMAP_USB_H
 
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <linux/usb/musb.h>
 
 #define OMAP3_HS_USB_PORTS     3
@@ -63,6 +64,10 @@ struct usbhs_omap_platform_data {
        struct ehci_hcd_omap_platform_data      *ehci_data;
        struct ohci_hcd_omap_platform_data      *ohci_data;
 };
+
+struct usbtll_omap_platform_data {
+       enum usbhs_omap_port_mode               port_mode[OMAP3_HS_USB_PORTS];
+};
 /*-------------------------------------------------------------------------*/
 
 struct omap_musb_board_data {
@@ -81,6 +86,8 @@ enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
 extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
 
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
index d5f617c542d30f302b959aeb3a82906d42a712ba..cee85a55bd82d3ae3e5ef0874500320e4b359bf7 100644 (file)
@@ -261,10 +261,10 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
                return;
        }
 
-       r = omap_clk_get_by_name(clk_name);
+       r = clk_get(NULL, clk_name);
        if (IS_ERR(r)) {
                dev_err(&od->pdev->dev,
-                       "omap_clk_get_by_name for %s failed\n", clk_name);
+                       "clk_get for %s failed\n", clk_name);
                return;
        }
 
@@ -982,6 +982,61 @@ int omap_device_shutdown(struct platform_device *pdev)
        return ret;
 }
 
+/**
+ * omap_device_assert_hardreset - set a device's hardreset line
+ * @pdev: struct platform_device * to reset
+ * @name: const char * name of the reset line
+ *
+ * Set the hardreset line identified by @name on the IP blocks
+ * associated with the hwmods backing the platform_device @pdev.  All
+ * of the hwmods associated with @pdev must have the same hardreset
+ * line linked to them for this to work.  Passes along the return value
+ * of omap_hwmod_assert_hardreset() in the event of any failure, or
+ * returns 0 upon success.
+ */
+int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
+{
+       struct omap_device *od = to_omap_device(pdev);
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < od->hwmods_cnt; i++) {
+               ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+/**
+ * omap_device_deassert_hardreset - release a device's hardreset line
+ * @pdev: struct platform_device * to reset
+ * @name: const char * name of the reset line
+ *
+ * Release the hardreset line identified by @name on the IP blocks
+ * associated with the hwmods backing the platform_device @pdev.  All
+ * of the hwmods associated with @pdev must have the same hardreset
+ * line linked to them for this to work.  Passes along the return
+ * value of omap_hwmod_deassert_hardreset() in the event of any
+ * failure, or returns 0 upon success.
+ */
+int omap_device_deassert_hardreset(struct platform_device *pdev,
+                                  const char *name)
+{
+       struct omap_device *od = to_omap_device(pdev);
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < od->hwmods_cnt; i++) {
+               ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
 /**
  * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
  * @od: struct omap_device *
index c20ce0f5ce33a916b6c463648e5c4f5d0454ad6f..a82cecb849485002c57123abaf89f1d33290fea5 100644 (file)
@@ -1,10 +1,10 @@
 #
 # Makefile for the linux kernel.
 #
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
 
-obj-y  := irq.o pcie.o time.o common.o mpp.o addr-map.o
-obj-m  :=
-obj-n  :=
-obj-   :=
+obj-y                             += addr-map.o
 
-obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o pcie.o time.o common.o mpp.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y)
index 367ca89ac40303eb8340b6cede2588e25364bf1a..a7b8060c293a47d2394515c4751e9ea5f0311d6e 100644 (file)
@@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
 static void __init __iomem *
 orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
 {
-       return (void __iomem *)(cfg->bridge_virt_base + (win << 4));
+       return cfg->bridge_virt_base + (win << 4);
 }
 
 /*
@@ -143,19 +143,16 @@ void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
  * Setup MBUS dram target info.
  */
 void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
-                                       const u32 ddr_window_cpu_base)
+                                       const void __iomem *ddr_window_cpu_base)
 {
-       void __iomem *addr;
        int i;
        int cs;
 
        orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
 
-       addr = (void __iomem *)ddr_window_cpu_base;
-
        for (i = 0, cs = 0; i < 4; i++) {
-               u32 base = readl(addr + DDR_BASE_CS_OFF(i));
-               u32 size = readl(addr + DDR_SIZE_CS_OFF(i));
+               u32 base = readl(ddr_window_cpu_base + DDR_BASE_CS_OFF(i));
+               u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i));
 
                /*
                 * Chip select enabled?
index 87f53caef65555fff70accff483c5815d5c02a00..b8a688cad4c277119281b44b629a9bcfc8eb0717 100644 (file)
@@ -86,13 +86,13 @@ static void __init uart_complete(
        struct platform_device *orion_uart,
        struct plat_serial8250_port *data,
        struct resource *resources,
-       unsigned int membase,
+       void __iomem *membase,
        resource_size_t mapbase,
        unsigned int irq,
        struct clk *clk)
 {
        data->mapbase = mapbase;
-       data->membase = (void __iomem *)membase;
+       data->membase = membase;
        data->irq = irq;
        data->uartclk = uart_get_clk_rate(clk);
        orion_uart->dev.platform_data = data;
@@ -120,7 +120,7 @@ static struct platform_device orion_uart0 = {
        .id                     = PLAT8250_DEV_PLATFORM,
 };
 
-void __init orion_uart0_init(unsigned int membase,
+void __init orion_uart0_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk)
@@ -148,7 +148,7 @@ static struct platform_device orion_uart1 = {
        .id                     = PLAT8250_DEV_PLATFORM1,
 };
 
-void __init orion_uart1_init(unsigned int membase,
+void __init orion_uart1_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk)
@@ -176,7 +176,7 @@ static struct platform_device orion_uart2 = {
        .id                     = PLAT8250_DEV_PLATFORM2,
 };
 
-void __init orion_uart2_init(unsigned int membase,
+void __init orion_uart2_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk)
@@ -204,7 +204,7 @@ static struct platform_device orion_uart3 = {
        .id                     = 3,
 };
 
-void __init orion_uart3_init(unsigned int membase,
+void __init orion_uart3_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk)
index fd556f77562cd8508f53f66d751ec99c00a1ffb3..ec63e4a627d07c3f007bdc897a4c5daa55c2860e 100644 (file)
@@ -16,7 +16,7 @@ extern struct mbus_dram_target_info orion_mbus_dram_info;
 struct orion_addr_map_cfg {
        const int num_wins;     /* Total number of windows */
        const int remappable_wins;
-       const u32 bridge_virt_base;
+       void __iomem *bridge_virt_base;
 
        /* If NULL, the default cpu_win_can_remap will be used, using
           the value in remappable_wins */
@@ -49,5 +49,5 @@ void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
                                const u8 attr, const int remap);
 
 void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
-                                       const u32 ddr_window_cpu_base);
+                                       const void __iomem *ddr_window_cpu_base);
 #endif
index ae2377ef63e5d9c455e07a4c8db7590f8935d4dc..6bbc3fe5f58eec878490bc31c8173e336a644d1b 100644 (file)
 
 struct dsa_platform_data;
 
-void __init orion_uart0_init(unsigned int membase,
+void __init orion_uart0_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk);
 
-void __init orion_uart1_init(unsigned int membase,
+void __init orion_uart1_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk);
 
-void __init orion_uart2_init(unsigned int membase,
+void __init orion_uart2_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk);
 
-void __init orion_uart3_init(unsigned int membase,
+void __init orion_uart3_init(void __iomem *membase,
                             resource_size_t mapbase,
                             unsigned int irq,
                             struct clk *clk);
index 723adce99f4184ba9826cf73fa49cd4708d597f1..254552fee8895c7523abafba85e0d13784ccc098 100644 (file)
@@ -29,6 +29,6 @@
 #define MPP_OUTPUT_MASK                GENERIC_MPP(0, 0x0, 0, 1)
 
 void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
-                          unsigned int mpp_max, unsigned int dev_bus);
+                          unsigned int mpp_max, void __iomem *dev_bus);
 
 #endif
index 4d5f1f6e18dfb3b1c8b564b3a45cc083a26fc477..07527e417c62e1b1bddb16a7d9e4aa5bed93a6fb 100644 (file)
@@ -11,9 +11,9 @@
 #ifndef __PLAT_TIME_H
 #define __PLAT_TIME_H
 
-void orion_time_set_base(u32 timer_base);
+void orion_time_set_base(void __iomem *timer_base);
 
-void orion_time_init(u32 bridge_base, u32 bridge_timer1_clr_mask,
+void orion_time_init(void __iomem *bridge_base, u32 bridge_timer1_clr_mask,
                     unsigned int irq, unsigned int tclk);
 
 
index 7740bb31d662814a393e92989da4aac274ca2217..e686fe76a96b169c705322fcf2419844cabb76d2 100644 (file)
 #include <plat/mpp.h>
 
 /* Address of the ith MPP control register */
-static __init unsigned long mpp_ctrl_addr(unsigned int i,
-                                         unsigned long dev_bus)
+static __init void __iomem *mpp_ctrl_addr(unsigned int i,
+                                         void __iomem *dev_bus)
 {
        return dev_bus + (i) * 4;
 }
 
 
 void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
-                          unsigned int mpp_max, unsigned int dev_bus)
+                          unsigned int mpp_max, void __iomem *dev_bus)
 {
        unsigned int mpp_nr_regs = (1 + mpp_max/8);
        u32 mpp_ctrl[mpp_nr_regs];
index 1ed8d1397fcf76bc60c86e5cb89f79cd5b900e9b..0f4fa863dd552403fa8107efe5df56def7108a26 100644 (file)
@@ -180,13 +180,13 @@ static struct irqaction orion_timer_irq = {
 };
 
 void __init
-orion_time_set_base(u32 _timer_base)
+orion_time_set_base(void __iomem *_timer_base)
 {
-       timer_base = (void __iomem *)_timer_base;
+       timer_base = _timer_base;
 }
 
 void __init
-orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
+orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
                unsigned int irq, unsigned int tclk)
 {
        u32 u;
@@ -194,7 +194,7 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
        /*
         * Set SoC-specific data.
         */
-       bridge_base = (void __iomem *)_bridge_base;
+       bridge_base = _bridge_base;
        bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
 
        ticks_per_jiffy = (tclk + HZ/2) / HZ;
diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
new file mode 100644 (file)
index 0000000..4384103
--- /dev/null
@@ -0,0 +1 @@
+obj-y          := enlighten.o hypercall.o grant-table.o
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
new file mode 100644 (file)
index 0000000..59bcb96
--- /dev/null
@@ -0,0 +1,168 @@
+#include <xen/xen.h>
+#include <xen/events.h>
+#include <xen/grant_table.h>
+#include <xen/hvm.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/hvm/params.h>
+#include <xen/features.h>
+#include <xen/platform_pci.h>
+#include <xen/xenbus.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+struct start_info _xen_start_info;
+struct start_info *xen_start_info = &_xen_start_info;
+EXPORT_SYMBOL_GPL(xen_start_info);
+
+enum xen_domain_type xen_domain_type = XEN_NATIVE;
+EXPORT_SYMBOL_GPL(xen_domain_type);
+
+struct shared_info xen_dummy_shared_info;
+struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
+
+DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
+
+/* TODO: to be removed */
+__read_mostly int xen_have_vector_callback;
+EXPORT_SYMBOL_GPL(xen_have_vector_callback);
+
+int xen_platform_pci_unplug = XEN_UNPLUG_ALL;
+EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
+
+static __read_mostly int xen_events_irq = -1;
+
+int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
+                              unsigned long addr,
+                              unsigned long mfn, int nr,
+                              pgprot_t prot, unsigned domid)
+{
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
+
+/*
+ * see Documentation/devicetree/bindings/arm/xen.txt for the
+ * documentation of the Xen Device Tree format.
+ */
+#define GRANT_TABLE_PHYSADDR 0
+static int __init xen_guest_init(void)
+{
+       struct xen_add_to_physmap xatp;
+       static struct shared_info *shared_info_page = 0;
+       struct device_node *node;
+       int len;
+       const char *s = NULL;
+       const char *version = NULL;
+       const char *xen_prefix = "xen,xen-";
+       struct resource res;
+
+       node = of_find_compatible_node(NULL, NULL, "xen,xen");
+       if (!node) {
+               pr_debug("No Xen support\n");
+               return 0;
+       }
+       s = of_get_property(node, "compatible", &len);
+       if (strlen(xen_prefix) + 3  < len &&
+                       !strncmp(xen_prefix, s, strlen(xen_prefix)))
+               version = s + strlen(xen_prefix);
+       if (version == NULL) {
+               pr_debug("Xen version not found\n");
+               return 0;
+       }
+       if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
+               return 0;
+       xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+       xen_events_irq = irq_of_parse_and_map(node, 0);
+       pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
+                       version, xen_events_irq, xen_hvm_resume_frames);
+       xen_domain_type = XEN_HVM_DOMAIN;
+
+       xen_setup_features();
+       if (xen_feature(XENFEAT_dom0))
+               xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
+       else
+               xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED);
+
+       if (!shared_info_page)
+               shared_info_page = (struct shared_info *)
+                       get_zeroed_page(GFP_KERNEL);
+       if (!shared_info_page) {
+               pr_err("not enough memory\n");
+               return -ENOMEM;
+       }
+       xatp.domid = DOMID_SELF;
+       xatp.idx = 0;
+       xatp.space = XENMAPSPACE_shared_info;
+       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+       if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+               BUG();
+
+       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.
+        * The shared info contains exactly 1 CPU (the boot CPU). The guest
+        * is required to use VCPUOP_register_vcpu_info to place vcpu info
+        * for secondary CPUs as they are brought up. */
+       per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
+
+       gnttab_init();
+       if (!xen_initial_domain())
+               xenbus_probe(NULL);
+
+       return 0;
+}
+core_initcall(xen_guest_init);
+
+static irqreturn_t xen_arm_callback(int irq, void *arg)
+{
+       xen_hvm_evtchn_do_upcall();
+       return IRQ_HANDLED;
+}
+
+static int __init xen_init_events(void)
+{
+       if (!xen_domain() || xen_events_irq < 0)
+               return -ENODEV;
+
+       xen_init_IRQ();
+
+       if (request_percpu_irq(xen_events_irq, xen_arm_callback,
+                       "events", xen_vcpu)) {
+               pr_err("Error requesting IRQ %d\n", xen_events_irq);
+               return -EINVAL;
+       }
+
+       enable_percpu_irq(xen_events_irq, 0);
+
+       return 0;
+}
+postcore_initcall(xen_init_events);
+
+/* XXX: only until balloon is properly working */
+int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
+{
+       *pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL,
+                       get_order(nr_pages));
+       if (*pages == NULL)
+               return -ENOMEM;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);
+
+void free_xenballooned_pages(int nr_pages, struct page **pages)
+{
+       kfree(*pages);
+       *pages = NULL;
+}
+EXPORT_SYMBOL_GPL(free_xenballooned_pages);
diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c
new file mode 100644 (file)
index 0000000..dbd1330
--- /dev/null
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * grant_table.c
+ * ARM specific part
+ *
+ * Granting foreign access to our memory reservation.
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+#include <xen/interface/xen.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+
+int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+                          unsigned long max_nr_gframes,
+                          void **__shared)
+{
+       return -ENOSYS;
+}
+
+void arch_gnttab_unmap(void *shared, unsigned long nr_gframes)
+{
+       return;
+}
+
+int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
+                          unsigned long max_nr_gframes,
+                          grant_status_t **__shared)
+{
+       return -ENOSYS;
+}
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
new file mode 100644 (file)
index 0000000..074f5ed
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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.
+ */
+
+/*
+ * The Xen hypercall calling convention is very similar to the ARM
+ * procedure calling convention: the first paramter is passed in r0, the
+ * second in r1, the third in r2 and the fourth in r3. Considering that
+ * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
+ * in r4, differently from the procedure calling convention of using the
+ * stack for that case.
+ *
+ * The hypercall number is passed in r12.
+ *
+ * The return value is in r0.
+ *
+ * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
+ * hypercall tag.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <xen/interface/xen.h>
+
+
+/* HVC 0xEA1 */
+#ifdef CONFIG_THUMB2_KERNEL
+#define xen_hvc .word 0xf7e08ea1
+#else
+#define xen_hvc .word 0xe140ea71
+#endif
+
+#define HYPERCALL_SIMPLE(hypercall)            \
+ENTRY(HYPERVISOR_##hypercall)                  \
+       mov r12, #__HYPERVISOR_##hypercall;     \
+       xen_hvc;                                                        \
+       mov pc, lr;                                                     \
+ENDPROC(HYPERVISOR_##hypercall)
+
+#define HYPERCALL0 HYPERCALL_SIMPLE
+#define HYPERCALL1 HYPERCALL_SIMPLE
+#define HYPERCALL2 HYPERCALL_SIMPLE
+#define HYPERCALL3 HYPERCALL_SIMPLE
+#define HYPERCALL4 HYPERCALL_SIMPLE
+
+#define HYPERCALL5(hypercall)                  \
+ENTRY(HYPERVISOR_##hypercall)                  \
+       stmdb sp!, {r4}                                         \
+       ldr r4, [sp, #4]                                        \
+       mov r12, #__HYPERVISOR_##hypercall;     \
+       xen_hvc                                                         \
+       ldm sp!, {r4}                                           \
+       mov pc, lr                                                      \
+ENDPROC(HYPERVISOR_##hypercall)
+
+                .text
+
+HYPERCALL2(xen_version);
+HYPERCALL3(console_io);
+HYPERCALL3(grant_table_op);
+HYPERCALL2(sched_op);
+HYPERCALL2(event_channel_op);
+HYPERCALL2(hvm_op);
+HYPERCALL2(memory_op);
+HYPERCALL2(physdev_op);
+
+ENTRY(privcmd_call)
+       stmdb sp!, {r4}
+       mov r12, r0
+       mov r0, r1
+       mov r1, r2
+       mov r2, r3
+       ldr r3, [sp, #8]
+       ldr r4, [sp, #4]
+       xen_hvc
+       ldm sp!, {r4}
+       mov pc, lr
+ENDPROC(privcmd_call);
index a670a33ad7366b0262a14dc938060e6a9bb66225..37e610dc084ed76b532f0647f07d6c2085b69798 100644 (file)
@@ -55,6 +55,7 @@ typedef s64           compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64            compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -130,6 +131,64 @@ typedef u32                compat_old_sigset_t;
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               /* The padding is the same size as AArch64. */
+               int _pad[128/sizeof(int) - 3];
+
+               /* kill() */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid32_t _uid;  /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;    /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid32_t _uid;  /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       compat_pid_t _pid;      /* which child */
+                       __compat_uid32_t _uid;  /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       compat_uptr_t _addr; /* faulting insn/memory ref. */
+                       short _addr_lsb; /* LSB of the reported address */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       compat_long_t _band;    /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -139,7 +198,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index f8190ba45a3e3eaf85861863603ccc5e48e01f0d..db05f97661127ef5c16a0ab9c7c42794a1cee8f1 100644 (file)
@@ -35,7 +35,8 @@
 #define COMPAT_HWCAP_IDIVT     (1 << 18)
 #define COMPAT_HWCAP_IDIV      (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
 
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
 /*
  * This yields a mask that user programs can use to figure out what
  * instruction set this cpu supports.
@@ -49,5 +50,6 @@
 
 extern unsigned int elf_hwcap;
 #endif
+#endif
 
 #endif
index d87225cbead81d0110fbcba80bdd866e0a9690fc..a9f580c28f7ba1920d782931344b19a51b9a7ce8 100644 (file)
@@ -18,7 +18,8 @@
 
 #include <asm-generic/stat.h>
 
-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
 
 #include <asm/compat.h>
 
@@ -57,6 +58,7 @@ struct stat64 {
        compat_u64      st_ino;
 };
 
+#endif
 #endif
 
 #endif
index fe18a683274f41f079a3009becbfc28befacfda9..8f03dee066ed0a16e56b94bbe361b49372bf07d2 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#if !defined(__ASM_UNISTD_H) || defined(__SYSCALL)
-#define __ASM_UNISTD_H
 
 #ifndef __SYSCALL_COMPAT
 #include <asm-generic/unistd.h>
 #endif
 
-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
 #include <asm/unistd32.h>
 #endif
-
-#endif /* __ASM_UNISTD_H */
+#endif
index a50405f5ee42c20c65d8c113644aa25371faa841..3ba1f1a906296cf4e355ba73e9464da37b53d69c 100644 (file)
@@ -16,8 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#if !defined(__ASM_UNISTD32_H) || defined(__SYSCALL)
-#define __ASM_UNISTD32_H
 
 #ifndef __SYSCALL
 #define __SYSCALL(x, y)
@@ -754,5 +752,3 @@ __SYSCALL(__NR_syncfs, sys_syncfs)
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-
-#endif /* __ASM_UNISTD32_H */
index ac74c2f261e3a0b953d79baf6681f90cc3c5e23b..0790a87a4346eb3b0d1825dcdfb599d828243b78 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
-typedef struct compat_siginfo {
-       int si_signo;
-       int si_errno;
-       int si_code;
-
-       union {
-               /* The padding is the same size as AArch64. */
-               int _pad[SI_PAD_SIZE];
-
-               /* kill() */
-               struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid32_t _uid;  /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;    /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;        /* same as below */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid32_t _uid;  /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       compat_pid_t _pid;      /* which child */
-                       __compat_uid32_t _uid;  /* sender's uid */
-                       int _status;            /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       compat_uptr_t _addr; /* faulting insn/memory ref. */
-                       short _addr_lsb; /* LSB of the reported address */
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       compat_long_t _band;    /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-       } _sifields;
-} compat_siginfo_t;
-
 struct compat_sigaction {
        compat_uptr_t                   sa_handler;
        compat_ulong_t                  sa_flags;
index 3b3159b710d42de528b487bc9758cf04dfb9a7fa..e2c328739808f6d47651e09c226c6a709e929d96 100644 (file)
@@ -102,6 +102,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 #endif /* __ASM_AVR32_ELF_H */
index e6c6812a9abd7a48311dd87122a90be43b709ce1..14bc98ff668fb37b48b6ef80855f5a6f057e35f7 100644 (file)
@@ -132,6 +132,7 @@ do {                                                                                        \
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
index 1d08dd0702776678cc5d90b791e03767e402b64b..a9eb9597e03ccc3b08fb5ba86d4f3fb75dd09635 100644 (file)
@@ -6,6 +6,8 @@
 # for more details.
 #
 
+KBUILD_DEFCONFIG := dsk6455_defconfig
+
 cflags-y += -mno-dsbt -msdata=none
 
 cflags-$(CONFIG_C6X_BIG_KERNEL) += -mlong-calls
index f08e89183cda452844fda74bc27a4db8823647d1..277f1a4ecb0954ca63c5c64e1314973d0a9dddd3 100644 (file)
@@ -40,6 +40,7 @@ generic-y += sembuf.h
 generic-y += shmbuf.h
 generic-y += shmparam.h
 generic-y += siginfo.h
+generic-y += signal.h
 generic-y += socket.h
 generic-y += sockios.h
 generic-y += stat.h
index f4552db20b4a64f23733985c8bc98338270e5e54..32b997126adf76f00d5ab0fe9e08106d0856e6be 100644 (file)
@@ -77,7 +77,8 @@ do {                                                          \
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 /* C6X specific section types */
 #define SHT_C6000_UNWIND       0x70000001
diff --git a/arch/c6x/include/asm/signal.h b/arch/c6x/include/asm/signal.h
deleted file mode 100644 (file)
index f1cd870..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ASM_C6X_SIGNAL_H
-#define _ASM_C6X_SIGNAL_H
-
-#include <asm-generic/signal.h>
-
-#ifndef __ASSEMBLY__
-#include <linux/linkage.h>
-
-struct pt_regs;
-
-extern asmlinkage int do_rt_sigreturn(struct pt_regs *regs);
-extern asmlinkage void do_notify_resume(struct pt_regs *regs,
-                                       u32 thread_info_flags,
-                                       int syscall);
-#endif
-
-#endif /* _ASM_C6X_SIGNAL_H */
index 6d54ea4262eb6e538c0c9a55dd513d23578c7360..ed2259043eec278b5a792b0660a326e66e292142 100644 (file)
@@ -13,8 +13,6 @@
  *   NON INFRINGEMENT. See the GNU General Public License for
  *   more details.
  */
-#if !defined(_ASM_C6X_UNISTD_H) || defined(__SYSCALL)
-#define _ASM_C6X_UNISTD_H
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
@@ -22,5 +20,3 @@
 /* C6X-specific syscalls. */
 #define __NR_cache_sync        (__NR_arch_specific_syscall + 0)
 __SYSCALL(__NR_cache_sync, sys_cache_sync)
-
-#endif /* _ASM_C6X_UNISTD_H */
index 8a3d8e2b33c1e41c384255ecb764cee17af4a3c4..8182f2dc89d04077c4a05fd302cf7fe46bf80996 100644 (file)
@@ -86,6 +86,7 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
index c3819804a74b104765c60a16051ffeea4063cbb1..9ccbc80f0b11fbcefcc0f2cdbfeb61eb88fbe81f 100644 (file)
@@ -137,6 +137,7 @@ do {                                                                                        \
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
index 5fa3889d858bcbb5bc69b97fb6bd85ef3ca0471e..0b579927439d30e1fffc22cc37443df5da474736 100644 (file)
@@ -153,23 +153,22 @@ static int user_atoi(char __user *ubuf, size_t len)
 static int sysctl_pm_do_suspend(ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp, loff_t *fpos)
 {
-       int retval, mode;
+       int mode;
 
        if (*lenp <= 0)
                return -EIO;
 
        mode = user_atoi(buffer, *lenp);
-       if ((mode != 1) && (mode != 5))
-               return -EINVAL;
+       switch (mode) {
+       case 1:
+           return pm_do_suspend();
 
-       if (retval == 0) {
-               if (mode == 5)
-                   retval = pm_do_bus_sleep();
-               else
-                   retval = pm_do_suspend();
-       }
+       case 5:
+           return pm_do_bus_sleep();
 
-       return retval;
+       default:
+           return -EINVAL;
+       }
 }
 
 static int try_set_cmode(int new_cmode)
index 75cf7f4b2fa81d8e0bd18cf6d0ff3ae4d64f8004..1f1e5efb338514c17171b31c037427d1d5c5d5a4 100644 (file)
@@ -184,7 +184,7 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = {
        [6]     = {     _x1,    _x1_5,  _x1_5,  _x4_5,  _x0_375 },
 };
 
-static const struct clock_cmode __pminitdata *clock_cmodes;
+static const struct clock_cmode __pminitconst *clock_cmodes;
 static int __pminitdata clock_doubled;
 
 static struct uart_port __pminitdata __frv_uart0 = {
index 20f6497b2cd5d57cc25e167d3ef31487f7b8c943..c677b9d81d30a00f858bf268c29717a260231b07 100644 (file)
@@ -28,7 +28,7 @@
  *
  */
 
-static const uint8_t __initdata pci_bus0_irq_routing[32][4] = {
+static const uint8_t __initconst pci_bus0_irq_routing[32][4] = {
        [0 ] = { IRQ_FPGA_MB86943_PCI_INTA },
        [16] = { IRQ_FPGA_RTL8029_INTA },
        [17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
index c24fa250d6533cdb3a5429c102323ca19d356e0d..41193c396bffecd20b353ff558e40f4e9dff03ac 100644 (file)
@@ -54,7 +54,8 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #define R_H8_NONE       0
 #define R_H8_DIR32      1
index aaf5e5a48f93167c2513a00e56155b166ee631b8..4bdc7311784e7297ac6f0bbb67073bd2e41d1ae5 100644 (file)
@@ -51,6 +51,7 @@ asmlinkage void syscall_print(void *dummy,...)
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
  */
+asmlinkage
 int kernel_execve(const char *filename,
                  const char *const argv[],
                  const char *const envp[])
index a2ae5e9521378d6adbee4e01d39e7843819c305a..0a8b5cd5bf382ea4d789bd5853fa11adb1dd4dbc 100644 (file)
@@ -62,7 +62,7 @@ static struct irqaction itu_irq = {
        .flags          = IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {1, 2, 4, 8};
+static const int __initconst divide_rate[] = {1, 2, 4, 8};
 
 void __init h8300_timer_setup(void)
 {
index ae0d3816113944c9af2be73c8957aa4e52f220b1..462d9f581719dac4e771dbafa13dcd93f292843c 100644 (file)
@@ -57,7 +57,7 @@ static struct irqaction timer16_irq = {
        .flags          = IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {1, 2, 4, 8};
+static const int __initconst divide_rate[] = {1, 2, 4, 8};
 
 void __init h8300_timer_setup(void)
 {
index 7a1533fad47d93773dc191981f19f76233f30c98..505f3415b40fc3825a2730dd06bafe70c6d947a8 100644 (file)
@@ -77,7 +77,7 @@ static struct irqaction timer8_irq = {
        .flags          = IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {8, 64, 8192};
+static const int __initconst divide_rate[] = {8, 64, 8192};
 
 void __init h8300_timer_setup(void)
 {
index 2193a2e2859af4fac6a33a9ba3e509416c64227d..0350f6204ecf4aa50e19f20cc897968c9f70f09e 100644 (file)
@@ -66,7 +66,7 @@ static struct irqaction tpu_irq = {
        .flags          = IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {
+static const int __initconst divide_rate[] = {
 #if CONFIG_H8300_TPU_CH == 0
        1,4,16,64,0,0,0,0,
 #elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
index bc4f51bceef5e3927682feba994c78dc16e98dc5..0a50353e09d5e3b5ed62995bfdcf0f0dcbe632fa 100644 (file)
 #include <asm/gpio-internal.h>
 #include <asm/regs306x.h>
 
-const int __initdata h8300_saved_vectors[] = {
+const int __initconst h8300_saved_vectors[] = {
 #if defined(CONFIG_GDB_DEBUG)
        TRAP3_VEC,      /* TRAPA #3 is GDB breakpoint */
 #endif
        -1,
 };
 
-const h8300_vector __initdata h8300_trap_table[] = {
+const h8300_vector __initconst h8300_trap_table[] = {
        0, 0, 0, 0, 0, 0, 0, 0,
        system_call,
        0,
index 7b5f29febc0740a53d11ec410e892b813dee792a..f3a5511c16b140b75808749d5977a2f35846ef85 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/regs267x.h>
 
 /* saved vector list */
-const int __initdata h8300_saved_vectors[]={
+const int __initconst h8300_saved_vectors[] = {
 #if defined(CONFIG_GDB_DEBUG)
        TRACE_VEC,
        TRAP3_VEC,
@@ -27,7 +27,7 @@ const int __initdata h8300_saved_vectors[]={
 };
 
 /* trap entry table */
-const H8300_VECTOR __initdata h8300_trap_table[] = {
+const H8300_VECTOR __initconst h8300_trap_table[] = {
        0,0,0,0,0,
        trace_break,  /* TRACE */
        0,0,
index 37976a0d3650c60b6106b1ce8f0b8017ee93a3bd..82b499621e052f2a272cd137c81f23c84fe2ccf3 100644 (file)
@@ -217,7 +217,8 @@ do {                                        \
 #define ELF_PLATFORM  (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 #endif
 
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
index 4d0ecde3665f207bcf85c5cca7793dec4813640e..c0d5565030ae34680f944446ad9840bbd918da2b 100644 (file)
@@ -18,9 +18,6 @@
  * 02110-1301, USA.
  */
 
-#if !defined(_ASM_HEXAGON_UNISTD_H) || defined(__SYSCALL)
-#define _ASM_HEXAGON_UNISTD_H
-
 /*
  *  The kernel pulls this unistd.h in three different ways:
  *  1.  the "normal" way which gets all the __NR defines
@@ -32,5 +29,3 @@
 #define sys_mmap2 sys_mmap_pgoff
 
 #include <asm-generic/unistd.h>
-
-#endif
index 3d52a5bbd857702c62baece0a658714a8b3c1632..e88c5de27410bde450885459467ef50db4c0d21c 100644 (file)
@@ -71,6 +71,7 @@
  * with Xen so that we could have one ABI that works for 32 and 64 bit
  * guests. */
 typedef unsigned long xen_pfn_t;
+typedef unsigned long xen_ulong_t;
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint, unsigned int);
index 3bb12230721fed28140164dfcb707fb679ae6fdb..01f479ee1c4333d89f0ac57b322c544edc8c4378 100644 (file)
@@ -433,7 +433,7 @@ xen_resend_irq(unsigned int vector)
        (void)resend_irq_on_evtchn(vector);
 }
 
-const struct pv_irq_ops xen_irq_ops __initdata = {
+const struct pv_irq_ops xen_irq_ops __initconst = {
        .register_ipi = xen_register_ipi,
 
        .assign_irq_vector = xen_assign_irq_vector,
index 26110f330c8733b39df5fea32ef6cc8e5b9f0d90..1778517b90feb6810872be03a2deb1adca8467bc 100644 (file)
@@ -27,7 +27,7 @@ extern void (*late_time_init)(void);
 extern char xen_event_callback;
 void __init xen_init_IRQ(void);
 
-extern const struct pv_irq_ops xen_irq_ops __initdata;
+extern const struct pv_irq_ops xen_irq_ops __initconst;
 extern void xen_smp_intr_init(void);
 extern void xen_send_ipi(int cpu, int vec);
 
index b8da7d0574d20635f489315ea8caf957d063be08..70896161c636e50fbe299504f9a41be3fc8ae47d 100644 (file)
@@ -128,6 +128,7 @@ typedef elf_fpreg_t elf_fpregset_t;
    intent than poking at uname or /proc/cpuinfo.  */
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif  /* _ASM_M32R__ELF_H */
index 7cafb537d03ca0e207ed653ad13acd5fa6351874..d2b3935ae147ae68b4747c3e56e9185e98c6e527 100644 (file)
@@ -34,10 +34,9 @@ static inline void __clear_cache_all(void)
 {
 #ifdef CACHE_INVALIDATE
        __asm__ __volatile__ (
-               "movel  %0, %%d0\n\t"
-               "movec  %%d0, %%CACR\n\t"
+               "movec  %0, %%CACR\n\t"
                "nop\n\t"
-               : : "i" (CACHE_INVALIDATE) : "d0" );
+               : : "r" (CACHE_INVALIDATE) );
 #endif
 }
 
@@ -58,10 +57,9 @@ static inline void __flush_icache_all(void)
 {
 #ifdef CACHE_INVALIDATEI
        __asm__ __volatile__ (
-               "movel  %0, %%d0\n\t"
-               "movec  %%d0, %%CACR\n\t"
+               "movec  %0, %%CACR\n\t"
                "nop\n\t"
-               : : "i" (CACHE_INVALIDATEI) : "d0" );
+               : : "r" (CACHE_INVALIDATEI) );
 #endif
 }
 
@@ -72,19 +70,18 @@ static inline void __flush_dcache_all(void)
 #endif
 #ifdef CACHE_INVALIDATED
        __asm__ __volatile__ (
-               "movel  %0, %%d0\n\t"
-               "movec  %%d0, %%CACR\n\t"
+               "movec  %0, %%CACR\n\t"
                "nop\n\t"
-               : : "i" (CACHE_INVALIDATED) : "d0" );
+               : : "r" (CACHE_INVALIDATED) );
 #else
-       /* Flush the wrtite buffer */
+       /* Flush the write buffer */
        __asm__ __volatile__ ( "nop" );
 #endif
 }
 
 /*
  * Push cache entries at supplied address. We want to write back any dirty
- * data and the invalidate the cache lines associated with this address.
+ * data and then invalidate the cache lines associated with this address.
  */
 static inline void cache_push(unsigned long paddr, int len)
 {
index e9b7cda597440b5696360307cf0124ab569645c5..f83c1d0a87cf046c42e546bdc86827f8747d421e 100644 (file)
@@ -113,6 +113,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
index 69722366b084bc10e34c2d1ef9a01b78fdd146a2..4cf864f5ea7a5bf9347e52ed233bfc03e9029b16 100644 (file)
 /*
  *     Define the 5206 SIM register set addresses.
  */
-#define        MCFSIM_SIMR             0x03            /* SIM Config reg (r/w) */
-#define        MCFSIM_ICR1             0x14            /* Intr Ctrl reg 1 (r/w) */
-#define        MCFSIM_ICR2             0x15            /* Intr Ctrl reg 2 (r/w) */
-#define        MCFSIM_ICR3             0x16            /* Intr Ctrl reg 3 (r/w) */
-#define        MCFSIM_ICR4             0x17            /* Intr Ctrl reg 4 (r/w) */
-#define        MCFSIM_ICR5             0x18            /* Intr Ctrl reg 5 (r/w) */
-#define        MCFSIM_ICR6             0x19            /* Intr Ctrl reg 6 (r/w) */
-#define        MCFSIM_ICR7             0x1a            /* Intr Ctrl reg 7 (r/w) */
-#define        MCFSIM_ICR8             0x1b            /* Intr Ctrl reg 8 (r/w) */
-#define        MCFSIM_ICR9             0x1c            /* Intr Ctrl reg 9 (r/w) */
-#define        MCFSIM_ICR10            0x1d            /* Intr Ctrl reg 10 (r/w) */
-#define        MCFSIM_ICR11            0x1e            /* Intr Ctrl reg 11 (r/w) */
-#define        MCFSIM_ICR12            0x1f            /* Intr Ctrl reg 12 (r/w) */
-#define        MCFSIM_ICR13            0x20            /* Intr Ctrl reg 13 (r/w) */
+#define        MCFSIM_SIMR             (MCF_MBAR + 0x03)       /* SIM Config reg */
+#define        MCFSIM_ICR1             (MCF_MBAR + 0x14)       /* Intr Ctrl reg 1 */
+#define        MCFSIM_ICR2             (MCF_MBAR + 0x15)       /* Intr Ctrl reg 2 */
+#define        MCFSIM_ICR3             (MCF_MBAR + 0x16)       /* Intr Ctrl reg 3 */
+#define        MCFSIM_ICR4             (MCF_MBAR + 0x17)       /* Intr Ctrl reg 4 */
+#define        MCFSIM_ICR5             (MCF_MBAR + 0x18)       /* Intr Ctrl reg 5 */
+#define        MCFSIM_ICR6             (MCF_MBAR + 0x19)       /* Intr Ctrl reg 6 */
+#define        MCFSIM_ICR7             (MCF_MBAR + 0x1a)       /* Intr Ctrl reg 7 */
+#define        MCFSIM_ICR8             (MCF_MBAR + 0x1b)       /* Intr Ctrl reg 8 */
+#define        MCFSIM_ICR9             (MCF_MBAR + 0x1c)       /* Intr Ctrl reg 9 */
+#define        MCFSIM_ICR10            (MCF_MBAR + 0x1d)       /* Intr Ctrl reg 10 */
+#define        MCFSIM_ICR11            (MCF_MBAR + 0x1e)       /* Intr Ctrl reg 11 */
+#define        MCFSIM_ICR12            (MCF_MBAR + 0x1f)       /* Intr Ctrl reg 12 */
+#define        MCFSIM_ICR13            (MCF_MBAR + 0x20)       /* Intr Ctrl reg 13 */
 #ifdef CONFIG_M5206e
-#define        MCFSIM_ICR14            0x21            /* Intr Ctrl reg 14 (r/w) */
-#define        MCFSIM_ICR15            0x22            /* Intr Ctrl reg 15 (r/w) */
+#define        MCFSIM_ICR14            (MCF_MBAR + 0x21)       /* Intr Ctrl reg 14 */
+#define        MCFSIM_ICR15            (MCF_MBAR + 0x22)       /* Intr Ctrl reg 15 */
 #endif
 
-#define MCFSIM_IMR             0x36            /* Interrupt Mask reg (r/w) */
-#define MCFSIM_IPR             0x3a            /* Interrupt Pend reg (r/w) */
+#define        MCFSIM_IMR              (MCF_MBAR + 0x36)       /* Interrupt Mask */
+#define        MCFSIM_IPR              (MCF_MBAR + 0x3a)       /* Interrupt Pending */
 
-#define        MCFSIM_RSR              0x40            /* Reset Status reg (r/w) */
-#define        MCFSIM_SYPCR            0x41            /* System Protection reg (r/w)*/
+#define        MCFSIM_RSR              (MCF_MBAR + 0x40)       /* Reset Status */
+#define        MCFSIM_SYPCR            (MCF_MBAR + 0x41)       /* System Protection */
 
-#define        MCFSIM_SWIVR            0x42            /* SW Watchdog intr reg (r/w) */
-#define        MCFSIM_SWSR             0x43            /* SW Watchdog service (r/w) */
+#define        MCFSIM_SWIVR            (MCF_MBAR + 0x42)       /* SW Watchdog intr */
+#define        MCFSIM_SWSR             (MCF_MBAR + 0x43)       /* SW Watchdog srv */
 
 #define        MCFSIM_DCRR             (MCF_MBAR + 0x46) /* DRAM Refresh reg (r/w) */
 #define        MCFSIM_DCTR             (MCF_MBAR + 0x4a) /* DRAM Timing reg (r/w) */
 #define        MCFSIM_DMR1             (MCF_MBAR + 0x5c) /* DRAM 1 Mask reg (r/w) */
 #define        MCFSIM_DCR1             (MCF_MBAR + 0x63) /* DRAM 1 Control reg (r/w) */
 
-#define        MCFSIM_CSAR0            0x64            /* CS 0 Address 0 reg (r/w) */
-#define        MCFSIM_CSMR0            0x68            /* CS 0 Mask 0 reg (r/w) */
-#define        MCFSIM_CSCR0            0x6e            /* CS 0 Control reg (r/w) */
-#define        MCFSIM_CSAR1            0x70            /* CS 1 Address reg (r/w) */
-#define        MCFSIM_CSMR1            0x74            /* CS 1 Mask reg (r/w) */
-#define        MCFSIM_CSCR1            0x7a            /* CS 1 Control reg (r/w) */
-#define        MCFSIM_CSAR2            0x7c            /* CS 2 Address reg (r/w) */
-#define        MCFSIM_CSMR2            0x80            /* CS 2 Mask reg (r/w) */
-#define        MCFSIM_CSCR2            0x86            /* CS 2 Control reg (r/w) */
-#define        MCFSIM_CSAR3            0x88            /* CS 3 Address reg (r/w) */
-#define        MCFSIM_CSMR3            0x8c            /* CS 3 Mask reg (r/w) */
-#define        MCFSIM_CSCR3            0x92            /* CS 3 Control reg (r/w) */
-#define        MCFSIM_CSAR4            0x94            /* CS 4 Address reg (r/w) */
-#define        MCFSIM_CSMR4            0x98            /* CS 4 Mask reg (r/w) */
-#define        MCFSIM_CSCR4            0x9e            /* CS 4 Control reg (r/w) */
-#define        MCFSIM_CSAR5            0xa0            /* CS 5 Address reg (r/w) */
-#define        MCFSIM_CSMR5            0xa4            /* CS 5 Mask reg (r/w) */
-#define        MCFSIM_CSCR5            0xaa            /* CS 5 Control reg (r/w) */
-#define        MCFSIM_CSAR6            0xac            /* CS 6 Address reg (r/w) */
-#define        MCFSIM_CSMR6            0xb0            /* CS 6 Mask reg (r/w) */
-#define        MCFSIM_CSCR6            0xb6            /* CS 6 Control reg (r/w) */
-#define        MCFSIM_CSAR7            0xb8            /* CS 7 Address reg (r/w) */
-#define        MCFSIM_CSMR7            0xbc            /* CS 7 Mask reg (r/w) */
-#define        MCFSIM_CSCR7            0xc2            /* CS 7 Control reg (r/w) */
-#define        MCFSIM_DMCR             0xc6            /* Default control */
+#define        MCFSIM_CSAR0            (MCF_MBAR + 0x64)       /* CS 0 Address reg */
+#define        MCFSIM_CSMR0            (MCF_MBAR + 0x68)       /* CS 0 Mask reg */
+#define        MCFSIM_CSCR0            (MCF_MBAR + 0x6e)       /* CS 0 Control reg */
+#define        MCFSIM_CSAR1            (MCF_MBAR + 0x70)       /* CS 1 Address reg */
+#define        MCFSIM_CSMR1            (MCF_MBAR + 0x74)       /* CS 1 Mask reg */
+#define        MCFSIM_CSCR1            (MCF_MBAR + 0x7a)       /* CS 1 Control reg */
+#define        MCFSIM_CSAR2            (MCF_MBAR + 0x7c)       /* CS 2 Address reg */
+#define        MCFSIM_CSMR2            (MCF_MBAR + 0x80)       /* CS 2 Mask reg */
+#define        MCFSIM_CSCR2            (MCF_MBAR + 0x86)       /* CS 2 Control reg */
+#define        MCFSIM_CSAR3            (MCF_MBAR + 0x88)       /* CS 3 Address reg */
+#define        MCFSIM_CSMR3            (MCF_MBAR + 0x8c)       /* CS 3 Mask reg */
+#define        MCFSIM_CSCR3            (MCF_MBAR + 0x92)       /* CS 3 Control reg */
+#define        MCFSIM_CSAR4            (MCF_MBAR + 0x94)       /* CS 4 Address reg */
+#define        MCFSIM_CSMR4            (MCF_MBAR + 0x98)       /* CS 4 Mask reg */
+#define        MCFSIM_CSCR4            (MCF_MBAR + 0x9e)       /* CS 4 Control reg */
+#define        MCFSIM_CSAR5            (MCF_MBAR + 0xa0)       /* CS 5 Address reg */
+#define        MCFSIM_CSMR5            (MCF_MBAR + 0xa4)       /* CS 5 Mask reg */
+#define        MCFSIM_CSCR5            (MCF_MBAR + 0xaa)       /* CS 5 Control reg */
+#define        MCFSIM_CSAR6            (MCF_MBAR + 0xac)       /* CS 6 Address reg */
+#define        MCFSIM_CSMR6            (MCF_MBAR + 0xb0)       /* CS 6 Mask reg */
+#define        MCFSIM_CSCR6            (MCF_MBAR + 0xb6)       /* CS 6 Control reg */
+#define        MCFSIM_CSAR7            (MCF_MBAR + 0xb8)       /* CS 7 Address reg */
+#define        MCFSIM_CSMR7            (MCF_MBAR + 0xbc)       /* CS 7 Mask reg */
+#define        MCFSIM_CSCR7            (MCF_MBAR + 0xc2)       /* CS 7 Control reg */
+#define        MCFSIM_DMCR             (MCF_MBAR + 0xc6)       /* Default control */
 
 #ifdef CONFIG_M5206e
-#define        MCFSIM_PAR              0xca            /* Pin Assignment reg (r/w) */
+#define        MCFSIM_PAR              (MCF_MBAR + 0xca)       /* Pin Assignment */
 #else
-#define        MCFSIM_PAR              0xcb            /* Pin Assignment reg (r/w) */
+#define        MCFSIM_PAR              (MCF_MBAR + 0xcb)       /* Pin Assignment */
 #endif
 
 #define        MCFTIMER_BASE1          (MCF_MBAR + 0x100)      /* Base of TIMER1 */
index 91d3abc3f2a53492a7e8a10316c9cae398d59bdb..5e06b4eb57f330b6315777032d4602beae022334 100644 (file)
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PODR                   MCFGPIO_PODR_ADDR
-#define MCFGPIO_PDDR                   MCFGPIO_PDDR_ADDR
-#define MCFGPIO_PPDR                   MCFGPIO_PPDSDR_ADDR
-#define MCFGPIO_SETR                   MCFGPIO_PPDSDR_ADDR
-#define MCFGPIO_CLRR                   MCFGPIO_PCLRR_ADDR
+#define MCFGPIO_PODR           MCFGPIO_PODR_ADDR
+#define MCFGPIO_PDDR           MCFGPIO_PDDR_ADDR
+#define MCFGPIO_PPDR           MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_SETR           MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_CLRR           MCFGPIO_PCLRR_ADDR
 
-#define MCFGPIO_PIN_MAX                        107
-#define MCFGPIO_IRQ_MAX                        8
-#define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
+#define MCFGPIO_PIN_MAX                107
+#define MCFGPIO_IRQ_MAX                8
+#define MCFGPIO_IRQ_VECBASE    MCFINT_VECBASE
 
 /*
  * Pin Assignment
 */
+#define        MCFGPIO_PAR_AD          (MCF_IPSBAR + 0x100040)
+#define        MCFGPIO_PAR_BUSCTL      (MCF_IPSBAR + 0x100042)
+#define        MCFGPIO_PAR_BS          (MCF_IPSBAR + 0x100044)
+#define        MCFGPIO_PAR_CS          (MCF_IPSBAR + 0x100045)
+#define        MCFGPIO_PAR_SDRAM       (MCF_IPSBAR + 0x100046)
+#define        MCFGPIO_PAR_FECI2C      (MCF_IPSBAR + 0x100047)
+#define        MCFGPIO_PAR_UART        (MCF_IPSBAR + 0x100048)
 #define        MCFGPIO_PAR_QSPI        (MCF_IPSBAR + 0x10004A)
 #define        MCFGPIO_PAR_TIMER       (MCF_IPSBAR + 0x10004C)
+#define        MCFGPIO_PAR_ETPU        (MCF_IPSBAR + 0x10004E)
 
 /*
  * DMA unit base addresses.
index 7f0c2c3660fd15b986db84e59a2f067b003a1835..fdf45e6807c9eacce5e16bd552023e7d751eece7 100644 (file)
 /*
  *     Define the 5249 SIM register set addresses.
  */
-#define        MCFSIM_RSR              0x00            /* Reset Status reg (r/w) */
-#define        MCFSIM_SYPCR            0x01            /* System Protection reg (r/w)*/
-#define        MCFSIM_SWIVR            0x02            /* SW Watchdog intr reg (r/w) */
-#define        MCFSIM_SWSR             0x03            /* SW Watchdog service (r/w) */
-#define        MCFSIM_PAR              0x04            /* Pin Assignment reg (r/w) */
-#define        MCFSIM_IRQPAR           0x06            /* Interrupt Assignment reg (r/w) */
-#define        MCFSIM_MPARK            0x0C            /* BUS Master Control Reg*/
-#define        MCFSIM_IPR              0x40            /* Interrupt Pend reg (r/w) */
-#define        MCFSIM_IMR              0x44            /* Interrupt Mask reg (r/w) */
-#define        MCFSIM_AVR              0x4b            /* Autovector Ctrl reg (r/w) */
-#define        MCFSIM_ICR0             0x4c            /* Intr Ctrl reg 0 (r/w) */
-#define        MCFSIM_ICR1             0x4d            /* Intr Ctrl reg 1 (r/w) */
-#define        MCFSIM_ICR2             0x4e            /* Intr Ctrl reg 2 (r/w) */
-#define        MCFSIM_ICR3             0x4f            /* Intr Ctrl reg 3 (r/w) */
-#define        MCFSIM_ICR4             0x50            /* Intr Ctrl reg 4 (r/w) */
-#define        MCFSIM_ICR5             0x51            /* Intr Ctrl reg 5 (r/w) */
-#define        MCFSIM_ICR6             0x52            /* Intr Ctrl reg 6 (r/w) */
-#define        MCFSIM_ICR7             0x53            /* Intr Ctrl reg 7 (r/w) */
-#define        MCFSIM_ICR8             0x54            /* Intr Ctrl reg 8 (r/w) */
-#define        MCFSIM_ICR9             0x55            /* Intr Ctrl reg 9 (r/w) */
-#define        MCFSIM_ICR10            0x56            /* Intr Ctrl reg 10 (r/w) */
-#define        MCFSIM_ICR11            0x57            /* Intr Ctrl reg 11 (r/w) */
-
-#define MCFSIM_CSAR0           0x80            /* CS 0 Address 0 reg (r/w) */
-#define MCFSIM_CSMR0           0x84            /* CS 0 Mask 0 reg (r/w) */
-#define MCFSIM_CSCR0           0x8a            /* CS 0 Control reg (r/w) */
-#define MCFSIM_CSAR1           0x8c            /* CS 1 Address reg (r/w) */
-#define MCFSIM_CSMR1           0x90            /* CS 1 Mask reg (r/w) */
-#define MCFSIM_CSCR1           0x96            /* CS 1 Control reg (r/w) */
-#define MCFSIM_CSAR2           0x98            /* CS 2 Address reg (r/w) */
-#define MCFSIM_CSMR2           0x9c            /* CS 2 Mask reg (r/w) */
-#define MCFSIM_CSCR2           0xa2            /* CS 2 Control reg (r/w) */
-#define MCFSIM_CSAR3           0xa4            /* CS 3 Address reg (r/w) */
-#define MCFSIM_CSMR3           0xa8            /* CS 3 Mask reg (r/w) */
-#define MCFSIM_CSCR3           0xae            /* CS 3 Control reg (r/w) */
+#define        MCFSIM_RSR              (MCF_MBAR + 0x00)       /* Reset Status */
+#define        MCFSIM_SYPCR            (MCF_MBAR + 0x01)       /* System Protection */
+#define        MCFSIM_SWIVR            (MCF_MBAR + 0x02)       /* SW Watchdog intr */
+#define        MCFSIM_SWSR             (MCF_MBAR + 0x03)       /* SW Watchdog srv */
+#define        MCFSIM_PAR              (MCF_MBAR + 0x04)       /* Pin Assignment */
+#define        MCFSIM_IRQPAR           (MCF_MBAR + 0x06)       /* Intr Assignment */
+#define        MCFSIM_MPARK            (MCF_MBAR + 0x0C)       /* BUS Master Ctrl */
+#define        MCFSIM_IPR              (MCF_MBAR + 0x40)       /* Interrupt Pending */
+#define        MCFSIM_IMR              (MCF_MBAR + 0x44)       /* Interrupt Mask */
+#define        MCFSIM_AVR              (MCF_MBAR + 0x4b)       /* Autovector Ctrl */
+#define        MCFSIM_ICR0             (MCF_MBAR + 0x4c)       /* Intr Ctrl reg 0 */
+#define        MCFSIM_ICR1             (MCF_MBAR + 0x4d)       /* Intr Ctrl reg 1 */
+#define        MCFSIM_ICR2             (MCF_MBAR + 0x4e)       /* Intr Ctrl reg 2 */
+#define        MCFSIM_ICR3             (MCF_MBAR + 0x4f)       /* Intr Ctrl reg 3 */
+#define        MCFSIM_ICR4             (MCF_MBAR + 0x50)       /* Intr Ctrl reg 4 */
+#define        MCFSIM_ICR5             (MCF_MBAR + 0x51)       /* Intr Ctrl reg 5 */
+#define        MCFSIM_ICR6             (MCF_MBAR + 0x52)       /* Intr Ctrl reg 6 */
+#define        MCFSIM_ICR7             (MCF_MBAR + 0x53)       /* Intr Ctrl reg 7 */
+#define        MCFSIM_ICR8             (MCF_MBAR + 0x54)       /* Intr Ctrl reg 8 */
+#define        MCFSIM_ICR9             (MCF_MBAR + 0x55)       /* Intr Ctrl reg 9 */
+#define        MCFSIM_ICR10            (MCF_MBAR + 0x56)       /* Intr Ctrl reg 10 */
+#define        MCFSIM_ICR11            (MCF_MBAR + 0x57)       /* Intr Ctrl reg 11 */
+
+#define        MCFSIM_CSAR0            (MCF_MBAR + 0x80)       /* CS 0 Address reg */
+#define        MCFSIM_CSMR0            (MCF_MBAR + 0x84)       /* CS 0 Mask reg */
+#define        MCFSIM_CSCR0            (MCF_MBAR + 0x8a)       /* CS 0 Control reg */
+#define        MCFSIM_CSAR1            (MCF_MBAR + 0x8c)       /* CS 1 Address reg */
+#define        MCFSIM_CSMR1            (MCF_MBAR + 0x90)       /* CS 1 Mask reg */
+#define        MCFSIM_CSCR1            (MCF_MBAR + 0x96)       /* CS 1 Control reg */
+#define        MCFSIM_CSAR2            (MCF_MBAR + 0x98)       /* CS 2 Address reg */
+#define        MCFSIM_CSMR2            (MCF_MBAR + 0x9c)       /* CS 2 Mask reg */
+#define        MCFSIM_CSCR2            (MCF_MBAR + 0xa2)       /* CS 2 Control reg */
+#define        MCFSIM_CSAR3            (MCF_MBAR + 0xa4)       /* CS 3 Address reg */
+#define        MCFSIM_CSMR3            (MCF_MBAR + 0xa8)       /* CS 3 Mask reg */
+#define        MCFSIM_CSCR3            (MCF_MBAR + 0xae)       /* CS 3 Control reg */
 
 #define MCFSIM_DCR             (MCF_MBAR + 0x100)      /* DRAM Control */
 #define MCFSIM_DACR0           (MCF_MBAR + 0x108)      /* DRAM 0 Addr/Ctrl */
 #define        MCFSIM2_GPIO1ENABLE     (MCF_MBAR2 + 0x0B8)     /* GPIO1 enabled */
 #define        MCFSIM2_GPIO1FUNC       (MCF_MBAR2 + 0x0BC)     /* GPIO1 function */
 
-#define        MCFSIM2_GPIOINTSTAT     0xc0            /* GPIO interrupt status */
-#define        MCFSIM2_GPIOINTCLEAR    0xc0            /* GPIO interrupt clear */
-#define        MCFSIM2_GPIOINTENABLE   0xc4            /* GPIO interrupt enable */
+#define        MCFSIM2_GPIOINTSTAT     (MCF_MBAR2 + 0xc0)      /* GPIO intr status */
+#define        MCFSIM2_GPIOINTCLEAR    (MCF_MBAR2 + 0xc0)      /* GPIO intr clear */
+#define        MCFSIM2_GPIOINTENABLE   (MCF_MBAR2 + 0xc4)      /* GPIO intr enable */
 
-#define        MCFSIM2_INTLEVEL1       0x140           /* Interrupt level reg 1 */
-#define        MCFSIM2_INTLEVEL2       0x144           /* Interrupt level reg 2 */
-#define        MCFSIM2_INTLEVEL3       0x148           /* Interrupt level reg 3 */
-#define        MCFSIM2_INTLEVEL4       0x14c           /* Interrupt level reg 4 */
-#define        MCFSIM2_INTLEVEL5       0x150           /* Interrupt level reg 5 */
-#define        MCFSIM2_INTLEVEL6       0x154           /* Interrupt level reg 6 */
-#define        MCFSIM2_INTLEVEL7       0x158           /* Interrupt level reg 7 */
-#define        MCFSIM2_INTLEVEL8       0x15c           /* Interrupt level reg 8 */
+#define        MCFSIM2_INTLEVEL1       (MCF_MBAR2 + 0x140)     /* Intr level reg 1 */
+#define        MCFSIM2_INTLEVEL2       (MCF_MBAR2 + 0x144)     /* Intr level reg 2 */
+#define        MCFSIM2_INTLEVEL3       (MCF_MBAR2 + 0x148)     /* Intr level reg 3 */
+#define        MCFSIM2_INTLEVEL4       (MCF_MBAR2 + 0x14c)     /* Intr level reg 4 */
+#define        MCFSIM2_INTLEVEL5       (MCF_MBAR2 + 0x150)     /* Intr level reg 5 */
+#define        MCFSIM2_INTLEVEL6       (MCF_MBAR2 + 0x154)     /* Intr level reg 6 */
+#define        MCFSIM2_INTLEVEL7       (MCF_MBAR2 + 0x158)     /* Intr level reg 7 */
+#define        MCFSIM2_INTLEVEL8       (MCF_MBAR2 + 0x15c)     /* Intr level reg 8 */
 
-#define        MCFSIM2_DMAROUTE        0x188           /* DMA routing */
+#define        MCFSIM2_DMAROUTE        (MCF_MBAR2 + 0x188)     /* DMA routing */
 
-#define        MCFSIM2_IDECONFIG1      0x18c           /* IDEconfig1 */
-#define        MCFSIM2_IDECONFIG2      0x190           /* IDEconfig2 */
+#define        MCFSIM2_IDECONFIG1      (MCF_MBAR2 + 0x18c)     /* IDEconfig1 */
+#define        MCFSIM2_IDECONFIG2      (MCF_MBAR2 + 0x190)     /* IDEconfig2 */
 
 /*
  * Define the base interrupt for the second interrupt controller.
index 6da24f6539027066aea0b96f27fe19f6f659bc21..acab61cb91ed9589922724c11501123230ea51c4 100644 (file)
 /*
  *     Define the 525x SIM register set addresses.
  */
-#define MCFSIM_RSR             0x00            /* Reset Status reg (r/w) */
-#define MCFSIM_SYPCR           0x01            /* System Protection reg (r/w)*/
-#define MCFSIM_SWIVR           0x02            /* SW Watchdog intr reg (r/w) */
-#define MCFSIM_SWSR            0x03            /* SW Watchdog service (r/w) */
-#define MCFSIM_MPARK           0x0C            /* BUS Master Control Reg*/
-#define MCFSIM_IPR             0x40            /* Interrupt Pend reg (r/w) */
-#define MCFSIM_IMR             0x44            /* Interrupt Mask reg (r/w) */
-#define MCFSIM_ICR0            0x4c            /* Intr Ctrl reg 0 (r/w) */
-#define MCFSIM_ICR1            0x4d            /* Intr Ctrl reg 1 (r/w) */
-#define MCFSIM_ICR2            0x4e            /* Intr Ctrl reg 2 (r/w) */
-#define MCFSIM_ICR3            0x4f            /* Intr Ctrl reg 3 (r/w) */
-#define MCFSIM_ICR4            0x50            /* Intr Ctrl reg 4 (r/w) */
-#define MCFSIM_ICR5            0x51            /* Intr Ctrl reg 5 (r/w) */
-#define MCFSIM_ICR6            0x52            /* Intr Ctrl reg 6 (r/w) */
-#define MCFSIM_ICR7            0x53            /* Intr Ctrl reg 7 (r/w) */
-#define MCFSIM_ICR8            0x54            /* Intr Ctrl reg 8 (r/w) */
-#define MCFSIM_ICR9            0x55            /* Intr Ctrl reg 9 (r/w) */
-#define MCFSIM_ICR10           0x56            /* Intr Ctrl reg 10 (r/w) */
-#define MCFSIM_ICR11           0x57            /* Intr Ctrl reg 11 (r/w) */
-
-#define MCFSIM_CSAR0           0x80            /* CS 0 Address 0 reg (r/w) */
-#define MCFSIM_CSMR0           0x84            /* CS 0 Mask 0 reg (r/w) */
-#define MCFSIM_CSCR0           0x8a            /* CS 0 Control reg (r/w) */
-#define MCFSIM_CSAR1           0x8c            /* CS 1 Address reg (r/w) */
-#define MCFSIM_CSMR1           0x90            /* CS 1 Mask reg (r/w) */
-#define MCFSIM_CSCR1           0x96            /* CS 1 Control reg (r/w) */
-#define MCFSIM_CSAR2           0x98            /* CS 2 Address reg (r/w) */
-#define MCFSIM_CSMR2           0x9c            /* CS 2 Mask reg (r/w) */
-#define MCFSIM_CSCR2           0xa2            /* CS 2 Control reg (r/w) */
-#define MCFSIM_CSAR3           0xa4            /* CS 3 Address reg (r/w) */
-#define MCFSIM_CSMR3           0xa8            /* CS 3 Mask reg (r/w) */
-#define MCFSIM_CSCR3           0xae            /* CS 3 Control reg (r/w) */
-#define MCFSIM_CSAR4           0xb0            /* CS 4 Address reg (r/w) */
-#define MCFSIM_CSMR4           0xb4            /* CS 4 Mask reg (r/w) */
-#define MCFSIM_CSCR4           0xba            /* CS 4 Control reg (r/w) */
+#define MCFSIM_RSR             (MCF_MBAR + 0x00)       /* Reset Status */
+#define MCFSIM_SYPCR           (MCF_MBAR + 0x01)       /* System Protection */
+#define MCFSIM_SWIVR           (MCF_MBAR + 0x02)       /* SW Watchdog intr */
+#define MCFSIM_SWSR            (MCF_MBAR + 0x03)       /* SW Watchdog srv */
+#define MCFSIM_MPARK           (MCF_MBAR + 0x0C)       /* BUS Master Ctrl */
+#define MCFSIM_IPR             (MCF_MBAR + 0x40)       /* Interrupt Pending */
+#define MCFSIM_IMR             (MCF_MBAR + 0x44)       /* Interrupt Mask */
+#define MCFSIM_ICR0            (MCF_MBAR + 0x4c)       /* Intr Ctrl reg 0 */
+#define MCFSIM_ICR1            (MCF_MBAR + 0x4d)       /* Intr Ctrl reg 1 */
+#define MCFSIM_ICR2            (MCF_MBAR + 0x4e)       /* Intr Ctrl reg 2 */
+#define MCFSIM_ICR3            (MCF_MBAR + 0x4f)       /* Intr Ctrl reg 3 */
+#define MCFSIM_ICR4            (MCF_MBAR + 0x50)       /* Intr Ctrl reg 4 */
+#define MCFSIM_ICR5            (MCF_MBAR + 0x51)       /* Intr Ctrl reg 5 */
+#define MCFSIM_ICR6            (MCF_MBAR + 0x52)       /* Intr Ctrl reg 6 */
+#define MCFSIM_ICR7            (MCF_MBAR + 0x53)       /* Intr Ctrl reg 7 */
+#define MCFSIM_ICR8            (MCF_MBAR + 0x54)       /* Intr Ctrl reg 8 */
+#define MCFSIM_ICR9            (MCF_MBAR + 0x55)       /* Intr Ctrl reg 9 */
+#define MCFSIM_ICR10           (MCF_MBAR + 0x56)       /* Intr Ctrl reg 10 */
+#define MCFSIM_ICR11           (MCF_MBAR + 0x57)       /* Intr Ctrl reg 11 */
+
+#define MCFSIM_CSAR0           (MCF_MBAR + 0x80)       /* CS 0 Address reg */
+#define MCFSIM_CSMR0           (MCF_MBAR + 0x84)       /* CS 0 Mask reg */
+#define MCFSIM_CSCR0           (MCF_MBAR + 0x8a)       /* CS 0 Control reg */
+#define MCFSIM_CSAR1           (MCF_MBAR + 0x8c)       /* CS 1 Address reg */
+#define MCFSIM_CSMR1           (MCF_MBAR + 0x90)       /* CS 1 Mask reg */
+#define MCFSIM_CSCR1           (MCF_MBAR + 0x96)       /* CS 1 Control reg */
+#define MCFSIM_CSAR2           (MCF_MBAR + 0x98)       /* CS 2 Address reg */
+#define MCFSIM_CSMR2           (MCF_MBAR + 0x9c)       /* CS 2 Mask reg */
+#define MCFSIM_CSCR2           (MCF_MBAR + 0xa2)       /* CS 2 Control reg */
+#define MCFSIM_CSAR3           (MCF_MBAR + 0xa4)       /* CS 3 Address reg */
+#define MCFSIM_CSMR3           (MCF_MBAR + 0xa8)       /* CS 3 Mask reg */
+#define MCFSIM_CSCR3           (MCF_MBAR + 0xae)       /* CS 3 Control reg */
+#define MCFSIM_CSAR4           (MCF_MBAR + 0xb0)       /* CS 4 Address reg */
+#define MCFSIM_CSMR4           (MCF_MBAR + 0xb4)       /* CS 4 Mask reg */
+#define MCFSIM_CSCR4           (MCF_MBAR + 0xba)       /* CS 4 Control reg */
 
 #define MCFSIM_DCR             (MCF_MBAR + 0x100)      /* DRAM Control */
 #define MCFSIM_DACR0           (MCF_MBAR + 0x108)      /* DRAM 0 Addr/Ctrl */
index a58f1760d858f6f1e9499bede581d07849bd4df6..1fb01bb05d6ca263e73b4756623ed310584d1f67 100644 (file)
 /*
  *     Define the 5272 SIM register set addresses.
  */
-#define        MCFSIM_SCR              0x04            /* SIM Config reg (r/w) */
-#define        MCFSIM_SPR              0x06            /* System Protection reg (r/w)*/
-#define        MCFSIM_PMR              0x08            /* Power Management reg (r/w) */
-#define        MCFSIM_APMR             0x0e            /* Active Low Power reg (r/w) */
-#define        MCFSIM_DIR              0x10            /* Device Identity reg (r/w) */
-
-#define        MCFSIM_ICR1             0x20            /* Intr Ctrl reg 1 (r/w) */
-#define        MCFSIM_ICR2             0x24            /* Intr Ctrl reg 2 (r/w) */
-#define        MCFSIM_ICR3             0x28            /* Intr Ctrl reg 3 (r/w) */
-#define        MCFSIM_ICR4             0x2c            /* Intr Ctrl reg 4 (r/w) */
-
-#define MCFSIM_ISR             0x30            /* Interrupt Source reg (r/w) */
-#define MCFSIM_PITR            0x34            /* Interrupt Transition (r/w) */
-#define        MCFSIM_PIWR             0x38            /* Interrupt Wakeup reg (r/w) */
-#define        MCFSIM_PIVR             0x3f            /* Interrupt Vector reg (r/w( */
-
-#define        MCFSIM_WRRR             0x280           /* Watchdog reference (r/w) */
-#define        MCFSIM_WIRR             0x284           /* Watchdog interrupt (r/w) */
-#define        MCFSIM_WCR              0x288           /* Watchdog counter (r/w) */
-#define        MCFSIM_WER              0x28c           /* Watchdog event (r/w) */
-
-#define        MCFSIM_CSBR0            0x40            /* CS0 Base Address (r/w) */
-#define        MCFSIM_CSOR0            0x44            /* CS0 Option (r/w) */
-#define        MCFSIM_CSBR1            0x48            /* CS1 Base Address (r/w) */
-#define        MCFSIM_CSOR1            0x4c            /* CS1 Option (r/w) */
-#define        MCFSIM_CSBR2            0x50            /* CS2 Base Address (r/w) */
-#define        MCFSIM_CSOR2            0x54            /* CS2 Option (r/w) */
-#define        MCFSIM_CSBR3            0x58            /* CS3 Base Address (r/w) */
-#define        MCFSIM_CSOR3            0x5c            /* CS3 Option (r/w) */
-#define        MCFSIM_CSBR4            0x60            /* CS4 Base Address (r/w) */
-#define        MCFSIM_CSOR4            0x64            /* CS4 Option (r/w) */
-#define        MCFSIM_CSBR5            0x68            /* CS5 Base Address (r/w) */
-#define        MCFSIM_CSOR5            0x6c            /* CS5 Option (r/w) */
-#define        MCFSIM_CSBR6            0x70            /* CS6 Base Address (r/w) */
-#define        MCFSIM_CSOR6            0x74            /* CS6 Option (r/w) */
-#define        MCFSIM_CSBR7            0x78            /* CS7 Base Address (r/w) */
-#define        MCFSIM_CSOR7            0x7c            /* CS7 Option (r/w) */
-
-#define        MCFSIM_SDCR             0x180           /* SDRAM Configuration (r/w) */
-#define        MCFSIM_SDTR             0x184           /* SDRAM Timing (r/w) */
-#define        MCFSIM_DCAR0            0x4c            /* DRAM 0 Address reg(r/w) */
-#define        MCFSIM_DCMR0            0x50            /* DRAM 0 Mask reg (r/w) */
-#define        MCFSIM_DCCR0            0x57            /* DRAM 0 Control reg (r/w) */
-#define        MCFSIM_DCAR1            0x58            /* DRAM 1 Address reg (r/w) */
-#define        MCFSIM_DCMR1            0x5c            /* DRAM 1 Mask reg (r/w) */
-#define        MCFSIM_DCCR1            0x63            /* DRAM 1 Control reg (r/w) */
+#define        MCFSIM_SCR              (MCF_MBAR + 0x04)       /* SIM Config reg */
+#define        MCFSIM_SPR              (MCF_MBAR + 0x06)       /* System Protection */
+#define        MCFSIM_PMR              (MCF_MBAR + 0x08)       /* Power Management */
+#define        MCFSIM_APMR             (MCF_MBAR + 0x0e)       /* Active Low Power */
+#define        MCFSIM_DIR              (MCF_MBAR + 0x10)       /* Device Identity */
+
+#define        MCFSIM_ICR1             (MCF_MBAR + 0x20)       /* Intr Ctrl reg 1 */
+#define        MCFSIM_ICR2             (MCF_MBAR + 0x24)       /* Intr Ctrl reg 2 */
+#define        MCFSIM_ICR3             (MCF_MBAR + 0x28)       /* Intr Ctrl reg 3 */
+#define        MCFSIM_ICR4             (MCF_MBAR + 0x2c)       /* Intr Ctrl reg 4 */
+
+#define        MCFSIM_ISR              (MCF_MBAR + 0x30)       /* Intr Source */
+#define        MCFSIM_PITR             (MCF_MBAR + 0x34)       /* Intr Transition */
+#define        MCFSIM_PIWR             (MCF_MBAR + 0x38)       /* Intr Wakeup */
+#define        MCFSIM_PIVR             (MCF_MBAR + 0x3f)       /* Intr Vector */
+
+#define        MCFSIM_WRRR             (MCF_MBAR + 0x280)      /* Watchdog reference */
+#define        MCFSIM_WIRR             (MCF_MBAR + 0x284)      /* Watchdog interrupt */
+#define        MCFSIM_WCR              (MCF_MBAR + 0x288)      /* Watchdog counter */
+#define        MCFSIM_WER              (MCF_MBAR + 0x28c)      /* Watchdog event */
+
+#define        MCFSIM_CSBR0            (MCF_MBAR + 0x40)       /* CS0 Base Address */
+#define        MCFSIM_CSOR0            (MCF_MBAR + 0x44)       /* CS0 Option */
+#define        MCFSIM_CSBR1            (MCF_MBAR + 0x48)       /* CS1 Base Address */
+#define        MCFSIM_CSOR1            (MCF_MBAR + 0x4c)       /* CS1 Option */
+#define        MCFSIM_CSBR2            (MCF_MBAR + 0x50)       /* CS2 Base Address */
+#define        MCFSIM_CSOR2            (MCF_MBAR + 0x54)       /* CS2 Option */
+#define        MCFSIM_CSBR3            (MCF_MBAR + 0x58)       /* CS3 Base Address */
+#define        MCFSIM_CSOR3            (MCF_MBAR + 0x5c)       /* CS3 Option */
+#define        MCFSIM_CSBR4            (MCF_MBAR + 0x60)       /* CS4 Base Address */
+#define        MCFSIM_CSOR4            (MCF_MBAR + 0x64)       /* CS4 Option */
+#define        MCFSIM_CSBR5            (MCF_MBAR + 0x68)       /* CS5 Base Address */
+#define        MCFSIM_CSOR5            (MCF_MBAR + 0x6c)       /* CS5 Option */
+#define        MCFSIM_CSBR6            (MCF_MBAR + 0x70)       /* CS6 Base Address */
+#define        MCFSIM_CSOR6            (MCF_MBAR + 0x74)       /* CS6 Option */
+#define        MCFSIM_CSBR7            (MCF_MBAR + 0x78)       /* CS7 Base Address */
+#define        MCFSIM_CSOR7            (MCF_MBAR + 0x7c)       /* CS7 Option */
+
+#define        MCFSIM_SDCR             (MCF_MBAR + 0x180)      /* SDRAM Config */
+#define        MCFSIM_SDTR             (MCF_MBAR + 0x184)      /* SDRAM Timing */
+#define        MCFSIM_DCAR0            (MCF_MBAR + 0x4c)       /* DRAM 0 Address */
+#define        MCFSIM_DCMR0            (MCF_MBAR + 0x50)       /* DRAM 0 Mask */
+#define        MCFSIM_DCCR0            (MCF_MBAR + 0x57)       /* DRAM 0 Control */
+#define        MCFSIM_DCAR1            (MCF_MBAR + 0x58)       /* DRAM 1 Address */
+#define        MCFSIM_DCMR1            (MCF_MBAR + 0x5c)       /* DRAM 1 Mask reg */
+#define        MCFSIM_DCCR1            (MCF_MBAR + 0x63)       /* DRAM 1 Control */
 
 #define        MCFUART_BASE0           (MCF_MBAR + 0x100) /* Base address UART0 */
 #define        MCFUART_BASE1           (MCF_MBAR + 0x140) /* Base address UART1 */
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PIN_MAX                        48
-#define MCFGPIO_IRQ_MAX                        -1
-#define MCFGPIO_IRQ_VECBASE            -1
+#define MCFGPIO_PIN_MAX                48
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
+
 /****************************************************************************/
 #endif /* m5272sim_h */
index 71aa5104d3d61fd459c26216bb6a3b835b1a3774..1bebbe78055a6e879277baee77064b7b025ef429 100644 (file)
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PODR                   MCFGPIO_PODR_ADDR
-#define MCFGPIO_PDDR                   MCFGPIO_PDDR_ADDR
-#define MCFGPIO_PPDR                   MCFGPIO_PPDSDR_ADDR
-#define MCFGPIO_SETR                   MCFGPIO_PPDSDR_ADDR
-#define MCFGPIO_CLRR                   MCFGPIO_PCLRR_ADDR
+#define MCFGPIO_PODR           MCFGPIO_PODR_ADDR
+#define MCFGPIO_PDDR           MCFGPIO_PDDR_ADDR
+#define MCFGPIO_PPDR           MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_SETR           MCFGPIO_PPDSDR_ADDR
+#define MCFGPIO_CLRR           MCFGPIO_PCLRR_ADDR
 
-#define MCFGPIO_PIN_MAX                        100
-#define MCFGPIO_IRQ_MAX                        8
-#define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
+#define MCFGPIO_PIN_MAX                100
+#define MCFGPIO_IRQ_MAX                8
+#define MCFGPIO_IRQ_VECBASE    MCFINT_VECBASE
 
+/*
+ * Port Pin Assignment registers.
+ */
+#define MCFGPIO_PAR_AD         (MCF_IPSBAR + 0x100040)
+#define MCFGPIO_PAR_BUSCTL     (MCF_IPSBAR + 0x100042)
+#define MCFGPIO_PAR_BS         (MCF_IPSBAR + 0x100044)
+#define MCFGPIO_PAR_CS         (MCF_IPSBAR + 0x100045)
+#define MCFGPIO_PAR_SDRAM      (MCF_IPSBAR + 0x100046)
+#define MCFGPIO_PAR_FECI2C     (MCF_IPSBAR + 0x100047)
+#define MCFGPIO_PAR_UART       (MCF_IPSBAR + 0x100048)
 #define MCFGPIO_PAR_QSPI       (MCF_IPSBAR + 0x10004A)
 #define MCFGPIO_PAR_TIMER      (MCF_IPSBAR + 0x10004C)
-#endif
+
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x0ff0
+#define UART2_ENABLE_MASK      0x3000
+#endif /* CONFIG_M5271 */
 
 #ifdef CONFIG_M5275
 #define MCFGPIO_PODR_BUSCTL    (MCF_IPSBAR + 0x100004)
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PODR                   MCFGPIO_PODR_BUSCTL
-#define MCFGPIO_PDDR                   MCFGPIO_PDDR_BUSCTL
-#define MCFGPIO_PPDR                   MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_SETR                   MCFGPIO_PPDSDR_BUSCTL
-#define MCFGPIO_CLRR                   MCFGPIO_PCLRR_BUSCTL
+#define MCFGPIO_PODR           MCFGPIO_PODR_BUSCTL
+#define MCFGPIO_PDDR           MCFGPIO_PDDR_BUSCTL
+#define MCFGPIO_PPDR           MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_SETR           MCFGPIO_PPDSDR_BUSCTL
+#define MCFGPIO_CLRR           MCFGPIO_PCLRR_BUSCTL
 
-#define MCFGPIO_PIN_MAX                        148
-#define MCFGPIO_IRQ_MAX                        8
-#define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
+#define MCFGPIO_PIN_MAX                148
+#define MCFGPIO_IRQ_MAX                8
+#define MCFGPIO_IRQ_VECBASE    MCFINT_VECBASE
 
+/*
+ * Port Pin Assignment registers.
+ */
+#define MCFGPIO_PAR_AD         (MCF_IPSBAR + 0x100070)
+#define MCFGPIO_PAR_CS         (MCF_IPSBAR + 0x100071)
+#define MCFGPIO_PAR_BUSCTL     (MCF_IPSBAR + 0x100072)
+#define MCFGPIO_PAR_USB                (MCF_IPSBAR + 0x100076)
+#define MCFGPIO_PAR_FEC0HL     (MCF_IPSBAR + 0x100078)
+#define MCFGPIO_PAR_FEC1HL     (MCF_IPSBAR + 0x100079)
+#define MCFGPIO_PAR_TIMER      (MCF_IPSBAR + 0x10007A)
+#define MCFGPIO_PAR_UART       (MCF_IPSBAR + 0x10007C)
 #define MCFGPIO_PAR_QSPI       (MCF_IPSBAR + 0x10007E)
-#endif
+#define MCFGPIO_PAR_SDRAM      (MCF_IPSBAR + 0x100080)
+#define MCFGPIO_PAR_FECI2C     (MCF_IPSBAR + 0x100082)
+#define MCFGPIO_PAR_BS         (MCF_IPSBAR + 0x100084)
+
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x00f0
+#define UART2_ENABLE_MASK      0x3f00
+#endif /* CONFIG_M5275 */
 
 /*
  * PIT timer base addresses.
 #define MCFEPORT_EPPDR         (MCF_IPSBAR + 0x130005)
 #define MCFEPORT_EPFR          (MCF_IPSBAR + 0x130006)
 
-/*
- *     GPIO pins setups to enable the UARTs.
- */
-#ifdef CONFIG_M5271
-#define MCF_GPIO_PAR_UART      0x100048        /* PAR UART address */
-#define UART0_ENABLE_MASK      0x000f
-#define UART1_ENABLE_MASK      0x0ff0
-#define UART2_ENABLE_MASK      0x3000
-#endif
-#ifdef CONFIG_M5275
-#define MCF_GPIO_PAR_UART      0x10007c        /* PAR UART address */
-#define UART0_ENABLE_MASK      0x000f
-#define UART1_ENABLE_MASK      0x00f0
-#define UART2_ENABLE_MASK      0x3f00 
-#endif
-
 /*
  *  Reset Control Unit (relative to IPSBAR).
  */
index 4acb3c0a642e7b4a4d0aba83414c12e99ca5a419..cf68ca0ac3a50ab99c3b09477319ddfc8e4688bd 100644 (file)
 #define MCFGPIO_IRQ_VECBASE    MCFINT_VECBASE
 #define MCFGPIO_PIN_MAX                180
 
-
-/*
- *     Derek Cheung - 6 Feb 2005
- *             add I2C and QSPI register definition using Freescale's MCF5282
- */
-/* set Port AS pin for I2C or UART */
-#define MCF5282_GPIO_PASPAR     (volatile u16 *) (MCF_IPSBAR + 0x00100056)
-
-/* Port UA Pin Assignment Register (8 Bit) */
-#define MCF5282_GPIO_PUAPAR    0x10005C
-
-/* Interrupt Mask Register Register Low */ 
-#define MCF5282_INTC0_IMRL      (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
-/* Interrupt Control Register 7 */
-#define MCF5282_INTC0_ICR17     (volatile u8 *) (MCF_IPSBAR + 0x0C51)
-
-
 /*
  *  Reset Control Unit (relative to IPSBAR).
  */
 #define        MCF_RCR_SWRESET         0x80            /* Software reset bit */
 #define        MCF_RCR_FRCSTOUT        0x40            /* Force external reset */
 
-/*********************************************************************
-*
-* Inter-IC (I2C) Module
-*
-*********************************************************************/
-/* Read/Write access macros for general use */
-#define MCF5282_I2C_I2ADR       (volatile u8 *) (MCF_IPSBAR + 0x0300) // Address 
-#define MCF5282_I2C_I2FDR       (volatile u8 *) (MCF_IPSBAR + 0x0304) // Freq Divider
-#define MCF5282_I2C_I2CR        (volatile u8 *) (MCF_IPSBAR + 0x0308) // Control
-#define MCF5282_I2C_I2SR        (volatile u8 *) (MCF_IPSBAR + 0x030C) // Status
-#define MCF5282_I2C_I2DR        (volatile u8 *) (MCF_IPSBAR + 0x0310) // Data I/O
-
-/* Bit level definitions and macros */
-#define MCF5282_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
-
-#define MCF5282_I2C_I2FDR_IC(x)                         (((x)&0x3F))
-
-#define MCF5282_I2C_I2CR_IEN    (0x80) // I2C enable
-#define MCF5282_I2C_I2CR_IIEN   (0x40)  // interrupt enable
-#define MCF5282_I2C_I2CR_MSTA   (0x20)  // master/slave mode
-#define MCF5282_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
-#define MCF5282_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
-#define MCF5282_I2C_I2CR_RSTA   (0x04)  // repeat start
-
-#define MCF5282_I2C_I2SR_ICF    (0x80)  // data transfer bit
-#define MCF5282_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
-#define MCF5282_I2C_I2SR_IBB    (0x20)  // I2C bus busy
-#define MCF5282_I2C_I2SR_IAL    (0x10)  // aribitration lost
-#define MCF5282_I2C_I2SR_SRW    (0x04)  // slave read/write
-#define MCF5282_I2C_I2SR_IIF    (0x02)  // I2C interrupt
-#define MCF5282_I2C_I2SR_RXAK   (0x01)  // received acknowledge
-
-
+/****************************************************************************/
 #endif /* m528xsim_h */
index 3bc3adaa7ee0138f7438090dae100c1b85ed8b87..5d0bb7ec31f89186a2268926366f02ed82bbbd83 100644 (file)
 /*
  *     Define the 5307 SIM register set addresses.
  */
-#define        MCFSIM_RSR              0x00            /* Reset Status reg (r/w) */
-#define        MCFSIM_SYPCR            0x01            /* System Protection reg (r/w)*/
-#define        MCFSIM_SWIVR            0x02            /* SW Watchdog intr reg (r/w) */
-#define        MCFSIM_SWSR             0x03            /* SW Watchdog service (r/w) */
-#define        MCFSIM_PAR              0x04            /* Pin Assignment reg (r/w) */
-#define        MCFSIM_IRQPAR           0x06            /* Interrupt Assignment reg (r/w) */
-#define        MCFSIM_PLLCR            0x08            /* PLL Control Reg*/
-#define        MCFSIM_MPARK            0x0C            /* BUS Master Control Reg*/
-#define        MCFSIM_IPR              0x40            /* Interrupt Pend reg (r/w) */
-#define        MCFSIM_IMR              0x44            /* Interrupt Mask reg (r/w) */
-#define        MCFSIM_AVR              0x4b            /* Autovector Ctrl reg (r/w) */
-#define        MCFSIM_ICR0             0x4c            /* Intr Ctrl reg 0 (r/w) */
-#define        MCFSIM_ICR1             0x4d            /* Intr Ctrl reg 1 (r/w) */
-#define        MCFSIM_ICR2             0x4e            /* Intr Ctrl reg 2 (r/w) */
-#define        MCFSIM_ICR3             0x4f            /* Intr Ctrl reg 3 (r/w) */
-#define        MCFSIM_ICR4             0x50            /* Intr Ctrl reg 4 (r/w) */
-#define        MCFSIM_ICR5             0x51            /* Intr Ctrl reg 5 (r/w) */
-#define        MCFSIM_ICR6             0x52            /* Intr Ctrl reg 6 (r/w) */
-#define        MCFSIM_ICR7             0x53            /* Intr Ctrl reg 7 (r/w) */
-#define        MCFSIM_ICR8             0x54            /* Intr Ctrl reg 8 (r/w) */
-#define        MCFSIM_ICR9             0x55            /* Intr Ctrl reg 9 (r/w) */
-#define        MCFSIM_ICR10            0x56            /* Intr Ctrl reg 10 (r/w) */
-#define        MCFSIM_ICR11            0x57            /* Intr Ctrl reg 11 (r/w) */
-
-#define MCFSIM_CSAR0           0x80            /* CS 0 Address 0 reg (r/w) */
-#define MCFSIM_CSMR0           0x84            /* CS 0 Mask 0 reg (r/w) */
-#define MCFSIM_CSCR0           0x8a            /* CS 0 Control reg (r/w) */
-#define MCFSIM_CSAR1           0x8c            /* CS 1 Address reg (r/w) */
-#define MCFSIM_CSMR1           0x90            /* CS 1 Mask reg (r/w) */
-#define MCFSIM_CSCR1           0x96            /* CS 1 Control reg (r/w) */
+#define        MCFSIM_RSR              (MCF_MBAR + 0x00)       /* Reset Status reg */
+#define        MCFSIM_SYPCR            (MCF_MBAR + 0x01)       /* System Protection */
+#define        MCFSIM_SWIVR            (MCF_MBAR + 0x02)       /* SW Watchdog intr */
+#define        MCFSIM_SWSR             (MCF_MBAR + 0x03)       /* SW Watchdog service*/
+#define        MCFSIM_PAR              (MCF_MBAR + 0x04)       /* Pin Assignment */
+#define        MCFSIM_IRQPAR           (MCF_MBAR + 0x06)       /* Itr Assignment */
+#define        MCFSIM_PLLCR            (MCF_MBAR + 0x08)       /* PLL Ctrl Reg */
+#define        MCFSIM_MPARK            (MCF_MBAR + 0x0C)       /* BUS Master Ctrl */
+#define        MCFSIM_IPR              (MCF_MBAR + 0x40)       /* Interrupt Pend */
+#define        MCFSIM_IMR              (MCF_MBAR + 0x44)       /* Interrupt Mask */
+#define        MCFSIM_AVR              (MCF_MBAR + 0x4b)       /* Autovector Ctrl */
+#define        MCFSIM_ICR0             (MCF_MBAR + 0x4c)       /* Intr Ctrl reg 0 */
+#define        MCFSIM_ICR1             (MCF_MBAR + 0x4d)       /* Intr Ctrl reg 1 */
+#define        MCFSIM_ICR2             (MCF_MBAR + 0x4e)       /* Intr Ctrl reg 2 */
+#define        MCFSIM_ICR3             (MCF_MBAR + 0x4f)       /* Intr Ctrl reg 3 */
+#define        MCFSIM_ICR4             (MCF_MBAR + 0x50)       /* Intr Ctrl reg 4 */
+#define        MCFSIM_ICR5             (MCF_MBAR + 0x51)       /* Intr Ctrl reg 5 */
+#define        MCFSIM_ICR6             (MCF_MBAR + 0x52)       /* Intr Ctrl reg 6 */
+#define        MCFSIM_ICR7             (MCF_MBAR + 0x53)       /* Intr Ctrl reg 7 */
+#define        MCFSIM_ICR8             (MCF_MBAR + 0x54)       /* Intr Ctrl reg 8 */
+#define        MCFSIM_ICR9             (MCF_MBAR + 0x55)       /* Intr Ctrl reg 9 */
+#define        MCFSIM_ICR10            (MCF_MBAR + 0x56)       /* Intr Ctrl reg 10 */
+#define        MCFSIM_ICR11            (MCF_MBAR + 0x57)       /* Intr Ctrl reg 11 */
+
+#define MCFSIM_CSAR0           (MCF_MBAR + 0x80)       /* CS 0 Address reg */
+#define MCFSIM_CSMR0           (MCF_MBAR + 0x84)       /* CS 0 Mask reg */
+#define MCFSIM_CSCR0           (MCF_MBAR + 0x8a)       /* CS 0 Control reg */
+#define MCFSIM_CSAR1           (MCF_MBAR + 0x8c)       /* CS 1 Address reg */
+#define MCFSIM_CSMR1           (MCF_MBAR + 0x90)       /* CS 1 Mask reg */
+#define MCFSIM_CSCR1           (MCF_MBAR + 0x96)       /* CS 1 Control reg */
 
 #ifdef CONFIG_OLDMASK
-#define MCFSIM_CSBAR           0x98            /* CS Base Address reg (r/w) */
-#define MCFSIM_CSBAMR          0x9c            /* CS Base Mask reg (r/w) */
-#define MCFSIM_CSMR2           0x9e            /* CS 2 Mask reg (r/w) */
-#define MCFSIM_CSCR2           0xa2            /* CS 2 Control reg (r/w) */
-#define MCFSIM_CSMR3           0xaa            /* CS 3 Mask reg (r/w) */
-#define MCFSIM_CSCR3           0xae            /* CS 3 Control reg (r/w) */
-#define MCFSIM_CSMR4           0xb6            /* CS 4 Mask reg (r/w) */
-#define MCFSIM_CSCR4           0xba            /* CS 4 Control reg (r/w) */
-#define MCFSIM_CSMR5           0xc2            /* CS 5 Mask reg (r/w) */
-#define MCFSIM_CSCR5           0xc6            /* CS 5 Control reg (r/w) */
-#define MCFSIM_CSMR6           0xce            /* CS 6 Mask reg (r/w) */
-#define MCFSIM_CSCR6           0xd2            /* CS 6 Control reg (r/w) */
-#define MCFSIM_CSMR7           0xda            /* CS 7 Mask reg (r/w) */
-#define MCFSIM_CSCR7           0xde            /* CS 7 Control reg (r/w) */
+#define MCFSIM_CSBAR           (MCF_MBAR + 0x98)       /* CS Base Address */
+#define MCFSIM_CSBAMR          (MCF_MBAR + 0x9c)       /* CS Base Mask */
+#define MCFSIM_CSMR2           (MCF_MBAR + 0x9e)       /* CS 2 Mask reg */
+#define MCFSIM_CSCR2           (MCF_MBAR + 0xa2)       /* CS 2 Control reg */
+#define MCFSIM_CSMR3           (MCF_MBAR + 0xaa)       /* CS 3 Mask reg */
+#define MCFSIM_CSCR3           (MCF_MBAR + 0xae)       /* CS 3 Control reg */
+#define MCFSIM_CSMR4           (MCF_MBAR + 0xb6)       /* CS 4 Mask reg */
+#define MCFSIM_CSCR4           (MCF_MBAR + 0xba)       /* CS 4 Control reg */
+#define MCFSIM_CSMR5           (MCF_MBAR + 0xc2)       /* CS 5 Mask reg */
+#define MCFSIM_CSCR5           (MCF_MBAR + 0xc6)       /* CS 5 Control reg */
+#define MCFSIM_CSMR6           (MCF_MBAR + 0xce)       /* CS 6 Mask reg */
+#define MCFSIM_CSCR6           (MCF_MBAR + 0xd2)       /* CS 6 Control reg */
+#define MCFSIM_CSMR7           (MCF_MBAR + 0xda)       /* CS 7 Mask reg */
+#define MCFSIM_CSCR7           (MCF_MBAR + 0xde)       /* CS 7 Control reg */
 #else
-#define MCFSIM_CSAR2           0x98            /* CS 2 Address reg (r/w) */
-#define MCFSIM_CSMR2           0x9c            /* CS 2 Mask reg (r/w) */
-#define MCFSIM_CSCR2           0xa2            /* CS 2 Control reg (r/w) */
-#define MCFSIM_CSAR3           0xa4            /* CS 3 Address reg (r/w) */
-#define MCFSIM_CSMR3           0xa8            /* CS 3 Mask reg (r/w) */
-#define MCFSIM_CSCR3           0xae            /* CS 3 Control reg (r/w) */
-#define MCFSIM_CSAR4           0xb0            /* CS 4 Address reg (r/w) */
-#define MCFSIM_CSMR4           0xb4            /* CS 4 Mask reg (r/w) */
-#define MCFSIM_CSCR4           0xba            /* CS 4 Control reg (r/w) */
-#define MCFSIM_CSAR5           0xbc            /* CS 5 Address reg (r/w) */
-#define MCFSIM_CSMR5           0xc0            /* CS 5 Mask reg (r/w) */
-#define MCFSIM_CSCR5           0xc6            /* CS 5 Control reg (r/w) */
-#define MCFSIM_CSAR6           0xc8            /* CS 6 Address reg (r/w) */
-#define MCFSIM_CSMR6           0xcc            /* CS 6 Mask reg (r/w) */
-#define MCFSIM_CSCR6           0xd2            /* CS 6 Control reg (r/w) */
-#define MCFSIM_CSAR7           0xd4            /* CS 7 Address reg (r/w) */
-#define MCFSIM_CSMR7           0xd8            /* CS 7 Mask reg (r/w) */
-#define MCFSIM_CSCR7           0xde            /* CS 7 Control reg (r/w) */
+#define MCFSIM_CSAR2           (MCF_MBAR + 0x98)       /* CS 2 Address reg */
+#define MCFSIM_CSMR2           (MCF_MBAR + 0x9c)       /* CS 2 Mask reg */
+#define MCFSIM_CSCR2           (MCF_MBAR + 0xa2)       /* CS 2 Control reg */
+#define MCFSIM_CSAR3           (MCF_MBAR + 0xa4)       /* CS 3 Address reg */
+#define MCFSIM_CSMR3           (MCF_MBAR + 0xa8)       /* CS 3 Mask reg */
+#define MCFSIM_CSCR3           (MCF_MBAR + 0xae)       /* CS 3 Control reg */
+#define MCFSIM_CSAR4           (MCF_MBAR + 0xb0)       /* CS 4 Address reg */
+#define MCFSIM_CSMR4           (MCF_MBAR + 0xb4)       /* CS 4 Mask reg */
+#define MCFSIM_CSCR4           (MCF_MBAR + 0xba)       /* CS 4 Control reg */
+#define MCFSIM_CSAR5           (MCF_MBAR + 0xbc)       /* CS 5 Address reg */
+#define MCFSIM_CSMR5           (MCF_MBAR + 0xc0)       /* CS 5 Mask reg */
+#define MCFSIM_CSCR5           (MCF_MBAR + 0xc6)       /* CS 5 Control reg */
+#define MCFSIM_CSAR6           (MCF_MBAR + 0xc8)       /* CS 6 Address reg */
+#define MCFSIM_CSMR6           (MCF_MBAR + 0xcc)       /* CS 6 Mask reg */
+#define MCFSIM_CSCR6           (MCF_MBAR + 0xd2)       /* CS 6 Control reg */
+#define MCFSIM_CSAR7           (MCF_MBAR + 0xd4)       /* CS 7 Address reg */
+#define MCFSIM_CSMR7           (MCF_MBAR + 0xd8)       /* CS 7 Mask reg */
+#define MCFSIM_CSCR7           (MCF_MBAR + 0xde)       /* CS 7 Control reg */
 #endif /* CONFIG_OLDMASK */
 
 #define MCFSIM_DCR             (MCF_MBAR + 0x100)      /* DRAM Control */
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PIN_MAX                        16
-#define MCFGPIO_IRQ_MAX                        -1
-#define MCFGPIO_IRQ_VECBASE            -1
+#define MCFGPIO_PIN_MAX                16
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
 
 
 /* Definition offset address for CS2-7  -- old mask 5307 */
 /*
  *       Defines for the IRQPAR Register
  */
-#define IRQ5_LEVEL4    0x80
-#define IRQ3_LEVEL6    0x40
-#define IRQ1_LEVEL2    0x20
+#define IRQ5_LEVEL4            0x80
+#define IRQ3_LEVEL6            0x40
+#define IRQ1_LEVEL2            0x20
 
 /*
  *     Define system peripheral IRQ usage.
index 5ca7b298c6eb1686bb044c987a73b1f7196b2a04..8668e47ced0e6ebbd019b183f2f6dde0c6197cc7 100644 (file)
 
 #include <asm/m53xxacr.h>
 
-#define MCF_REG32(x) (*(volatile unsigned long  *)(x))
-#define MCF_REG16(x) (*(volatile unsigned short *)(x))
-#define MCF_REG08(x) (*(volatile unsigned char  *)(x))
-
 #define MCFINT_VECBASE      64
 #define MCFINT_UART0        26          /* Interrupt number for UART0 */
 #define MCFINT_UART1        27          /* Interrupt number for UART1 */
@@ -38,7 +34,7 @@
 
 #define        MCF_IRQ_QSPI        (MCFINT_VECBASE + MCFINT_QSPI)
 
-#define MCF_WTM_WCR    MCF_REG16(0xFC098000)
+#define MCF_WTM_WCR            0xFC098000
 
 /*
  *     Define the 532x SIM register set addresses.
 #define MCFPM_PPMHR1           0xfc040038
 #define MCFPM_LPCR             0xec090007
 
-/*********************************************************************
- *
- * Inter-IC (I2C) Module
- *
- *********************************************************************/
-
-/* Read/Write access macros for general use */
-#define MCF532x_I2C_I2ADR       (volatile u8 *) (0xFC058000) // Address 
-#define MCF532x_I2C_I2FDR       (volatile u8 *) (0xFC058004) // Freq Divider
-#define MCF532x_I2C_I2CR        (volatile u8 *) (0xFC058008) // Control
-#define MCF532x_I2C_I2SR        (volatile u8 *) (0xFC05800C) // Status
-#define MCF532x_I2C_I2DR        (volatile u8 *) (0xFC058010) // Data I/O
-
-/* Bit level definitions and macros */
-#define MCF532x_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
-
-#define MCF532x_I2C_I2FDR_IC(x)                         (((x)&0x3F))
-
-#define MCF532x_I2C_I2CR_IEN    (0x80) // I2C enable
-#define MCF532x_I2C_I2CR_IIEN   (0x40)  // interrupt enable
-#define MCF532x_I2C_I2CR_MSTA   (0x20)  // master/slave mode
-#define MCF532x_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
-#define MCF532x_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
-#define MCF532x_I2C_I2CR_RSTA   (0x04)  // repeat start
-
-#define MCF532x_I2C_I2SR_ICF    (0x80)  // data transfer bit
-#define MCF532x_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
-#define MCF532x_I2C_I2SR_IBB    (0x20)  // I2C bus busy
-#define MCF532x_I2C_I2SR_IAL    (0x10)  // aribitration lost
-#define MCF532x_I2C_I2SR_SRW    (0x04)  // slave read/write
-#define MCF532x_I2C_I2SR_IIF    (0x02)  // I2C interrupt
-#define MCF532x_I2C_I2SR_RXAK   (0x01)  // received acknowledge
-
-#define MCF532x_PAR_FECI2C     (volatile u8 *) (0xFC0A4053)
-
-
 /*
  *     The M5329EVB board needs a help getting its devices initialized 
  *     at kernel start time if dBUG doesn't set it up (for example 
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_CCM_CCR               MCF_REG16(0xFC0A0004)
-#define MCF_CCM_RCON              MCF_REG16(0xFC0A0008)
-#define MCF_CCM_CIR               MCF_REG16(0xFC0A000A)
-#define MCF_CCM_MISCCR            MCF_REG16(0xFC0A0010)
-#define MCF_CCM_CDR               MCF_REG16(0xFC0A0012)
-#define MCF_CCM_UHCSR             MCF_REG16(0xFC0A0014)
-#define MCF_CCM_UOCSR             MCF_REG16(0xFC0A0016)
+#define MCF_CCM_CCR               0xFC0A0004
+#define MCF_CCM_RCON              0xFC0A0008
+#define MCF_CCM_CIR               0xFC0A000A
+#define MCF_CCM_MISCCR            0xFC0A0010
+#define MCF_CCM_CDR               0xFC0A0012
+#define MCF_CCM_UHCSR             0xFC0A0014
+#define MCF_CCM_UOCSR             0xFC0A0016
 
 /* Bit definitions and macros for MCF_CCM_CCR */
 #define MCF_CCM_CCR_RESERVED      (0x0001)
 #define MCF_CCM_UOCSR_DPPD        (0x2000)
 #define MCF_CCM_UOCSR_PORTIND(x)  (((x)&0x0003)<<14)
 
-/*********************************************************************
- *
- * DMA Timers (DTIM)
- *
- *********************************************************************/
-
-/* Register read/write macros */
-#define MCF_DTIM0_DTMR           MCF_REG16(0xFC070000)
-#define MCF_DTIM0_DTXMR          MCF_REG08(0xFC070002)
-#define MCF_DTIM0_DTER           MCF_REG08(0xFC070003)
-#define MCF_DTIM0_DTRR           MCF_REG32(0xFC070004)
-#define MCF_DTIM0_DTCR           MCF_REG32(0xFC070008)
-#define MCF_DTIM0_DTCN           MCF_REG32(0xFC07000C)
-#define MCF_DTIM1_DTMR           MCF_REG16(0xFC074000)
-#define MCF_DTIM1_DTXMR          MCF_REG08(0xFC074002)
-#define MCF_DTIM1_DTER           MCF_REG08(0xFC074003)
-#define MCF_DTIM1_DTRR           MCF_REG32(0xFC074004)
-#define MCF_DTIM1_DTCR           MCF_REG32(0xFC074008)
-#define MCF_DTIM1_DTCN           MCF_REG32(0xFC07400C)
-#define MCF_DTIM2_DTMR           MCF_REG16(0xFC078000)
-#define MCF_DTIM2_DTXMR          MCF_REG08(0xFC078002)
-#define MCF_DTIM2_DTER           MCF_REG08(0xFC078003)
-#define MCF_DTIM2_DTRR           MCF_REG32(0xFC078004)
-#define MCF_DTIM2_DTCR           MCF_REG32(0xFC078008)
-#define MCF_DTIM2_DTCN           MCF_REG32(0xFC07800C)
-#define MCF_DTIM3_DTMR           MCF_REG16(0xFC07C000)
-#define MCF_DTIM3_DTXMR          MCF_REG08(0xFC07C002)
-#define MCF_DTIM3_DTER           MCF_REG08(0xFC07C003)
-#define MCF_DTIM3_DTRR           MCF_REG32(0xFC07C004)
-#define MCF_DTIM3_DTCR           MCF_REG32(0xFC07C008)
-#define MCF_DTIM3_DTCN           MCF_REG32(0xFC07C00C)
-#define MCF_DTIM_DTMR(x)         MCF_REG16(0xFC070000+((x)*0x4000))
-#define MCF_DTIM_DTXMR(x)        MCF_REG08(0xFC070002+((x)*0x4000))
-#define MCF_DTIM_DTER(x)         MCF_REG08(0xFC070003+((x)*0x4000))
-#define MCF_DTIM_DTRR(x)         MCF_REG32(0xFC070004+((x)*0x4000))
-#define MCF_DTIM_DTCR(x)         MCF_REG32(0xFC070008+((x)*0x4000))
-#define MCF_DTIM_DTCN(x)         MCF_REG32(0xFC07000C+((x)*0x4000))
-
-/* Bit definitions and macros for MCF_DTIM_DTMR */
-#define MCF_DTIM_DTMR_RST        (0x0001)
-#define MCF_DTIM_DTMR_CLK(x)     (((x)&0x0003)<<1)
-#define MCF_DTIM_DTMR_FRR        (0x0008)
-#define MCF_DTIM_DTMR_ORRI       (0x0010)
-#define MCF_DTIM_DTMR_OM         (0x0020)
-#define MCF_DTIM_DTMR_CE(x)      (((x)&0x0003)<<6)
-#define MCF_DTIM_DTMR_PS(x)      (((x)&0x00FF)<<8)
-#define MCF_DTIM_DTMR_CE_ANY     (0x00C0)
-#define MCF_DTIM_DTMR_CE_FALL    (0x0080)
-#define MCF_DTIM_DTMR_CE_RISE    (0x0040)
-#define MCF_DTIM_DTMR_CE_NONE    (0x0000)
-#define MCF_DTIM_DTMR_CLK_DTIN   (0x0006)
-#define MCF_DTIM_DTMR_CLK_DIV16  (0x0004)
-#define MCF_DTIM_DTMR_CLK_DIV1   (0x0002)
-#define MCF_DTIM_DTMR_CLK_STOP   (0x0000)
-
-/* Bit definitions and macros for MCF_DTIM_DTXMR */
-#define MCF_DTIM_DTXMR_MODE16    (0x01)
-#define MCF_DTIM_DTXMR_DMAEN     (0x80)
-
-/* Bit definitions and macros for MCF_DTIM_DTER */
-#define MCF_DTIM_DTER_CAP        (0x01)
-#define MCF_DTIM_DTER_REF        (0x02)
-
-/* Bit definitions and macros for MCF_DTIM_DTRR */
-#define MCF_DTIM_DTRR_REF(x)     (((x)&0xFFFFFFFF)<<0)
-
-/* Bit definitions and macros for MCF_DTIM_DTCR */
-#define MCF_DTIM_DTCR_CAP(x)     (((x)&0xFFFFFFFF)<<0)
-
-/* Bit definitions and macros for MCF_DTIM_DTCN */
-#define MCF_DTIM_DTCN_CNT(x)     (((x)&0xFFFFFFFF)<<0)
-
 /*********************************************************************
  *
  * FlexBus Chip Selects (FBCS)
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_FBCS0_CSAR         MCF_REG32(0xFC008000)
-#define MCF_FBCS0_CSMR         MCF_REG32(0xFC008004)
-#define MCF_FBCS0_CSCR         MCF_REG32(0xFC008008)
-#define MCF_FBCS1_CSAR         MCF_REG32(0xFC00800C)
-#define MCF_FBCS1_CSMR         MCF_REG32(0xFC008010)
-#define MCF_FBCS1_CSCR         MCF_REG32(0xFC008014)
-#define MCF_FBCS2_CSAR         MCF_REG32(0xFC008018)
-#define MCF_FBCS2_CSMR         MCF_REG32(0xFC00801C)
-#define MCF_FBCS2_CSCR         MCF_REG32(0xFC008020)
-#define MCF_FBCS3_CSAR         MCF_REG32(0xFC008024)
-#define MCF_FBCS3_CSMR         MCF_REG32(0xFC008028)
-#define MCF_FBCS3_CSCR         MCF_REG32(0xFC00802C)
-#define MCF_FBCS4_CSAR         MCF_REG32(0xFC008030)
-#define MCF_FBCS4_CSMR         MCF_REG32(0xFC008034)
-#define MCF_FBCS4_CSCR         MCF_REG32(0xFC008038)
-#define MCF_FBCS5_CSAR         MCF_REG32(0xFC00803C)
-#define MCF_FBCS5_CSMR         MCF_REG32(0xFC008040)
-#define MCF_FBCS5_CSCR         MCF_REG32(0xFC008044)
-#define MCF_FBCS_CSAR(x)       MCF_REG32(0xFC008000+((x)*0x00C))
-#define MCF_FBCS_CSMR(x)       MCF_REG32(0xFC008004+((x)*0x00C))
-#define MCF_FBCS_CSCR(x)       MCF_REG32(0xFC008008+((x)*0x00C))
+#define MCF_FBCS0_CSAR         0xFC008000
+#define MCF_FBCS0_CSMR         0xFC008004
+#define MCF_FBCS0_CSCR         0xFC008008
+#define MCF_FBCS1_CSAR         0xFC00800C
+#define MCF_FBCS1_CSMR         0xFC008010
+#define MCF_FBCS1_CSCR         0xFC008014
+#define MCF_FBCS2_CSAR         0xFC008018
+#define MCF_FBCS2_CSMR         0xFC00801C
+#define MCF_FBCS2_CSCR         0xFC008020
+#define MCF_FBCS3_CSAR         0xFC008024
+#define MCF_FBCS3_CSMR         0xFC008028
+#define MCF_FBCS3_CSCR         0xFC00802C
+#define MCF_FBCS4_CSAR         0xFC008030
+#define MCF_FBCS4_CSMR         0xFC008034
+#define MCF_FBCS4_CSCR         0xFC008038
+#define MCF_FBCS5_CSAR         0xFC00803C
+#define MCF_FBCS5_CSMR         0xFC008040
+#define MCF_FBCS5_CSCR         0xFC008044
 
 /* Bit definitions and macros for MCF_FBCS_CSAR */
 #define MCF_FBCS_CSAR_BA(x)    ((x)&0xFFFF0000)
 #define MCFGPIO_PCLRR_LCDDATAL         (0xFC0A404B)
 #define MCFGPIO_PCLRR_LCDCTLH          (0xFC0A404C)
 #define MCFGPIO_PCLRR_LCDCTLL          (0xFC0A404D)
-#define MCF_GPIO_PAR_FEC               MCF_REG08(0xFC0A4050)
-#define MCF_GPIO_PAR_PWM               MCF_REG08(0xFC0A4051)
-#define MCF_GPIO_PAR_BUSCTL            MCF_REG08(0xFC0A4052)
-#define MCF_GPIO_PAR_FECI2C            MCF_REG08(0xFC0A4053)
-#define MCF_GPIO_PAR_BE                        MCF_REG08(0xFC0A4054)
-#define MCF_GPIO_PAR_CS                        MCF_REG08(0xFC0A4055)
-#define MCF_GPIO_PAR_SSI               MCF_REG16(0xFC0A4056)
-#define MCF_GPIO_PAR_UART              MCF_REG16(0xFC0A4058)
-#define MCF_GPIO_PAR_QSPI              MCF_REG16(0xFC0A405A)
-#define MCF_GPIO_PAR_TIMER             MCF_REG08(0xFC0A405C)
-#define MCF_GPIO_PAR_LCDDATA           MCF_REG08(0xFC0A405D)
-#define MCF_GPIO_PAR_LCDCTL            MCF_REG16(0xFC0A405E)
-#define MCF_GPIO_PAR_IRQ               MCF_REG16(0xFC0A4060)
-#define MCF_GPIO_MSCR_FLEXBUS          MCF_REG08(0xFC0A4064)
-#define MCF_GPIO_MSCR_SDRAM            MCF_REG08(0xFC0A4065)
-#define MCF_GPIO_DSCR_I2C              MCF_REG08(0xFC0A4068)
-#define MCF_GPIO_DSCR_PWM              MCF_REG08(0xFC0A4069)
-#define MCF_GPIO_DSCR_FEC              MCF_REG08(0xFC0A406A)
-#define MCF_GPIO_DSCR_UART             MCF_REG08(0xFC0A406B)
-#define MCF_GPIO_DSCR_QSPI             MCF_REG08(0xFC0A406C)
-#define MCF_GPIO_DSCR_TIMER            MCF_REG08(0xFC0A406D)
-#define MCF_GPIO_DSCR_SSI              MCF_REG08(0xFC0A406E)
-#define MCF_GPIO_DSCR_LCD              MCF_REG08(0xFC0A406F)
-#define MCF_GPIO_DSCR_DEBUG            MCF_REG08(0xFC0A4070)
-#define MCF_GPIO_DSCR_CLKRST           MCF_REG08(0xFC0A4071)
-#define MCF_GPIO_DSCR_IRQ              MCF_REG08(0xFC0A4072)
+#define MCFGPIO_PAR_FEC                        (0xFC0A4050)
+#define MCFGPIO_PAR_PWM                        (0xFC0A4051)
+#define MCFGPIO_PAR_BUSCTL             (0xFC0A4052)
+#define MCFGPIO_PAR_FECI2C             (0xFC0A4053)
+#define MCFGPIO_PAR_BE                 (0xFC0A4054)
+#define MCFGPIO_PAR_CS                 (0xFC0A4055)
+#define MCFGPIO_PAR_SSI                        (0xFC0A4056)
+#define MCFGPIO_PAR_UART               (0xFC0A4058)
+#define MCFGPIO_PAR_QSPI               (0xFC0A405A)
+#define MCFGPIO_PAR_TIMER              (0xFC0A405C)
+#define MCFGPIO_PAR_LCDDATA            (0xFC0A405D)
+#define MCFGPIO_PAR_LCDCTL             (0xFC0A405E)
+#define MCFGPIO_PAR_IRQ                        (0xFC0A4060)
+#define MCFGPIO_MSCR_FLEXBUS           (0xFC0A4064)
+#define MCFGPIO_MSCR_SDRAM             (0xFC0A4065)
+#define MCFGPIO_DSCR_I2C               (0xFC0A4068)
+#define MCFGPIO_DSCR_PWM               (0xFC0A4069)
+#define MCFGPIO_DSCR_FEC               (0xFC0A406A)
+#define MCFGPIO_DSCR_UART              (0xFC0A406B)
+#define MCFGPIO_DSCR_QSPI              (0xFC0A406C)
+#define MCFGPIO_DSCR_TIMER             (0xFC0A406D)
+#define MCFGPIO_DSCR_SSI               (0xFC0A406E)
+#define MCFGPIO_DSCR_LCD               (0xFC0A406F)
+#define MCFGPIO_DSCR_DEBUG             (0xFC0A4070)
+#define MCFGPIO_DSCR_CLKRST            (0xFC0A4071)
+#define MCFGPIO_DSCR_IRQ               (0xFC0A4072)
 
 /* Bit definitions and macros for MCF_GPIO_PODR_FECH */
 #define MCF_GPIO_PODR_FECH_PODR_FECH0              (0x01)
 #define MCFGPIO_IRQ_MAX                        8
 #define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
 
-
-/*********************************************************************
- *
- * Interrupt Controller (INTC)
- *
- *********************************************************************/
-
-/* Register read/write macros */
-#define MCF_INTC0_IPRH             MCF_REG32(0xFC048000)
-#define MCF_INTC0_IPRL             MCF_REG32(0xFC048004)
-#define MCF_INTC0_IMRH             MCF_REG32(0xFC048008)
-#define MCF_INTC0_IMRL             MCF_REG32(0xFC04800C)
-#define MCF_INTC0_INTFRCH          MCF_REG32(0xFC048010)
-#define MCF_INTC0_INTFRCL          MCF_REG32(0xFC048014)
-#define MCF_INTC0_ICONFIG          MCF_REG16(0xFC04801A)
-#define MCF_INTC0_SIMR             MCF_REG08(0xFC04801C)
-#define MCF_INTC0_CIMR             MCF_REG08(0xFC04801D)
-#define MCF_INTC0_CLMASK           MCF_REG08(0xFC04801E)
-#define MCF_INTC0_SLMASK           MCF_REG08(0xFC04801F)
-#define MCF_INTC0_ICR0             MCF_REG08(0xFC048040)
-#define MCF_INTC0_ICR1             MCF_REG08(0xFC048041)
-#define MCF_INTC0_ICR2             MCF_REG08(0xFC048042)
-#define MCF_INTC0_ICR3             MCF_REG08(0xFC048043)
-#define MCF_INTC0_ICR4             MCF_REG08(0xFC048044)
-#define MCF_INTC0_ICR5             MCF_REG08(0xFC048045)
-#define MCF_INTC0_ICR6             MCF_REG08(0xFC048046)
-#define MCF_INTC0_ICR7             MCF_REG08(0xFC048047)
-#define MCF_INTC0_ICR8             MCF_REG08(0xFC048048)
-#define MCF_INTC0_ICR9             MCF_REG08(0xFC048049)
-#define MCF_INTC0_ICR10            MCF_REG08(0xFC04804A)
-#define MCF_INTC0_ICR11            MCF_REG08(0xFC04804B)
-#define MCF_INTC0_ICR12            MCF_REG08(0xFC04804C)
-#define MCF_INTC0_ICR13            MCF_REG08(0xFC04804D)
-#define MCF_INTC0_ICR14            MCF_REG08(0xFC04804E)
-#define MCF_INTC0_ICR15            MCF_REG08(0xFC04804F)
-#define MCF_INTC0_ICR16            MCF_REG08(0xFC048050)
-#define MCF_INTC0_ICR17            MCF_REG08(0xFC048051)
-#define MCF_INTC0_ICR18            MCF_REG08(0xFC048052)
-#define MCF_INTC0_ICR19            MCF_REG08(0xFC048053)
-#define MCF_INTC0_ICR20            MCF_REG08(0xFC048054)
-#define MCF_INTC0_ICR21            MCF_REG08(0xFC048055)
-#define MCF_INTC0_ICR22            MCF_REG08(0xFC048056)
-#define MCF_INTC0_ICR23            MCF_REG08(0xFC048057)
-#define MCF_INTC0_ICR24            MCF_REG08(0xFC048058)
-#define MCF_INTC0_ICR25            MCF_REG08(0xFC048059)
-#define MCF_INTC0_ICR26            MCF_REG08(0xFC04805A)
-#define MCF_INTC0_ICR27            MCF_REG08(0xFC04805B)
-#define MCF_INTC0_ICR28            MCF_REG08(0xFC04805C)
-#define MCF_INTC0_ICR29            MCF_REG08(0xFC04805D)
-#define MCF_INTC0_ICR30            MCF_REG08(0xFC04805E)
-#define MCF_INTC0_ICR31            MCF_REG08(0xFC04805F)
-#define MCF_INTC0_ICR32            MCF_REG08(0xFC048060)
-#define MCF_INTC0_ICR33            MCF_REG08(0xFC048061)
-#define MCF_INTC0_ICR34            MCF_REG08(0xFC048062)
-#define MCF_INTC0_ICR35            MCF_REG08(0xFC048063)
-#define MCF_INTC0_ICR36            MCF_REG08(0xFC048064)
-#define MCF_INTC0_ICR37            MCF_REG08(0xFC048065)
-#define MCF_INTC0_ICR38            MCF_REG08(0xFC048066)
-#define MCF_INTC0_ICR39            MCF_REG08(0xFC048067)
-#define MCF_INTC0_ICR40            MCF_REG08(0xFC048068)
-#define MCF_INTC0_ICR41            MCF_REG08(0xFC048069)
-#define MCF_INTC0_ICR42            MCF_REG08(0xFC04806A)
-#define MCF_INTC0_ICR43            MCF_REG08(0xFC04806B)
-#define MCF_INTC0_ICR44            MCF_REG08(0xFC04806C)
-#define MCF_INTC0_ICR45            MCF_REG08(0xFC04806D)
-#define MCF_INTC0_ICR46            MCF_REG08(0xFC04806E)
-#define MCF_INTC0_ICR47            MCF_REG08(0xFC04806F)
-#define MCF_INTC0_ICR48            MCF_REG08(0xFC048070)
-#define MCF_INTC0_ICR49            MCF_REG08(0xFC048071)
-#define MCF_INTC0_ICR50            MCF_REG08(0xFC048072)
-#define MCF_INTC0_ICR51            MCF_REG08(0xFC048073)
-#define MCF_INTC0_ICR52            MCF_REG08(0xFC048074)
-#define MCF_INTC0_ICR53            MCF_REG08(0xFC048075)
-#define MCF_INTC0_ICR54            MCF_REG08(0xFC048076)
-#define MCF_INTC0_ICR55            MCF_REG08(0xFC048077)
-#define MCF_INTC0_ICR56            MCF_REG08(0xFC048078)
-#define MCF_INTC0_ICR57            MCF_REG08(0xFC048079)
-#define MCF_INTC0_ICR58            MCF_REG08(0xFC04807A)
-#define MCF_INTC0_ICR59            MCF_REG08(0xFC04807B)
-#define MCF_INTC0_ICR60            MCF_REG08(0xFC04807C)
-#define MCF_INTC0_ICR61            MCF_REG08(0xFC04807D)
-#define MCF_INTC0_ICR62            MCF_REG08(0xFC04807E)
-#define MCF_INTC0_ICR63            MCF_REG08(0xFC04807F)
-#define MCF_INTC0_ICR(x)           MCF_REG08(0xFC048040+((x)*0x001))
-#define MCF_INTC0_SWIACK           MCF_REG08(0xFC0480E0)
-#define MCF_INTC0_L1IACK           MCF_REG08(0xFC0480E4)
-#define MCF_INTC0_L2IACK           MCF_REG08(0xFC0480E8)
-#define MCF_INTC0_L3IACK           MCF_REG08(0xFC0480EC)
-#define MCF_INTC0_L4IACK           MCF_REG08(0xFC0480F0)
-#define MCF_INTC0_L5IACK           MCF_REG08(0xFC0480F4)
-#define MCF_INTC0_L6IACK           MCF_REG08(0xFC0480F8)
-#define MCF_INTC0_L7IACK           MCF_REG08(0xFC0480FC)
-#define MCF_INTC0_LIACK(x)         MCF_REG08(0xFC0480E4+((x)*0x004))
-#define MCF_INTC1_IPRH             MCF_REG32(0xFC04C000)
-#define MCF_INTC1_IPRL             MCF_REG32(0xFC04C004)
-#define MCF_INTC1_IMRH             MCF_REG32(0xFC04C008)
-#define MCF_INTC1_IMRL             MCF_REG32(0xFC04C00C)
-#define MCF_INTC1_INTFRCH          MCF_REG32(0xFC04C010)
-#define MCF_INTC1_INTFRCL          MCF_REG32(0xFC04C014)
-#define MCF_INTC1_ICONFIG          MCF_REG16(0xFC04C01A)
-#define MCF_INTC1_SIMR             MCF_REG08(0xFC04C01C)
-#define MCF_INTC1_CIMR             MCF_REG08(0xFC04C01D)
-#define MCF_INTC1_CLMASK           MCF_REG08(0xFC04C01E)
-#define MCF_INTC1_SLMASK           MCF_REG08(0xFC04C01F)
-#define MCF_INTC1_ICR0             MCF_REG08(0xFC04C040)
-#define MCF_INTC1_ICR1             MCF_REG08(0xFC04C041)
-#define MCF_INTC1_ICR2             MCF_REG08(0xFC04C042)
-#define MCF_INTC1_ICR3             MCF_REG08(0xFC04C043)
-#define MCF_INTC1_ICR4             MCF_REG08(0xFC04C044)
-#define MCF_INTC1_ICR5             MCF_REG08(0xFC04C045)
-#define MCF_INTC1_ICR6             MCF_REG08(0xFC04C046)
-#define MCF_INTC1_ICR7             MCF_REG08(0xFC04C047)
-#define MCF_INTC1_ICR8             MCF_REG08(0xFC04C048)
-#define MCF_INTC1_ICR9             MCF_REG08(0xFC04C049)
-#define MCF_INTC1_ICR10            MCF_REG08(0xFC04C04A)
-#define MCF_INTC1_ICR11            MCF_REG08(0xFC04C04B)
-#define MCF_INTC1_ICR12            MCF_REG08(0xFC04C04C)
-#define MCF_INTC1_ICR13            MCF_REG08(0xFC04C04D)
-#define MCF_INTC1_ICR14            MCF_REG08(0xFC04C04E)
-#define MCF_INTC1_ICR15            MCF_REG08(0xFC04C04F)
-#define MCF_INTC1_ICR16            MCF_REG08(0xFC04C050)
-#define MCF_INTC1_ICR17            MCF_REG08(0xFC04C051)
-#define MCF_INTC1_ICR18            MCF_REG08(0xFC04C052)
-#define MCF_INTC1_ICR19            MCF_REG08(0xFC04C053)
-#define MCF_INTC1_ICR20            MCF_REG08(0xFC04C054)
-#define MCF_INTC1_ICR21            MCF_REG08(0xFC04C055)
-#define MCF_INTC1_ICR22            MCF_REG08(0xFC04C056)
-#define MCF_INTC1_ICR23            MCF_REG08(0xFC04C057)
-#define MCF_INTC1_ICR24            MCF_REG08(0xFC04C058)
-#define MCF_INTC1_ICR25            MCF_REG08(0xFC04C059)
-#define MCF_INTC1_ICR26            MCF_REG08(0xFC04C05A)
-#define MCF_INTC1_ICR27            MCF_REG08(0xFC04C05B)
-#define MCF_INTC1_ICR28            MCF_REG08(0xFC04C05C)
-#define MCF_INTC1_ICR29            MCF_REG08(0xFC04C05D)
-#define MCF_INTC1_ICR30            MCF_REG08(0xFC04C05E)
-#define MCF_INTC1_ICR31            MCF_REG08(0xFC04C05F)
-#define MCF_INTC1_ICR32            MCF_REG08(0xFC04C060)
-#define MCF_INTC1_ICR33            MCF_REG08(0xFC04C061)
-#define MCF_INTC1_ICR34            MCF_REG08(0xFC04C062)
-#define MCF_INTC1_ICR35            MCF_REG08(0xFC04C063)
-#define MCF_INTC1_ICR36            MCF_REG08(0xFC04C064)
-#define MCF_INTC1_ICR37            MCF_REG08(0xFC04C065)
-#define MCF_INTC1_ICR38            MCF_REG08(0xFC04C066)
-#define MCF_INTC1_ICR39            MCF_REG08(0xFC04C067)
-#define MCF_INTC1_ICR40            MCF_REG08(0xFC04C068)
-#define MCF_INTC1_ICR41            MCF_REG08(0xFC04C069)
-#define MCF_INTC1_ICR42            MCF_REG08(0xFC04C06A)
-#define MCF_INTC1_ICR43            MCF_REG08(0xFC04C06B)
-#define MCF_INTC1_ICR44            MCF_REG08(0xFC04C06C)
-#define MCF_INTC1_ICR45            MCF_REG08(0xFC04C06D)
-#define MCF_INTC1_ICR46            MCF_REG08(0xFC04C06E)
-#define MCF_INTC1_ICR47            MCF_REG08(0xFC04C06F)
-#define MCF_INTC1_ICR48            MCF_REG08(0xFC04C070)
-#define MCF_INTC1_ICR49            MCF_REG08(0xFC04C071)
-#define MCF_INTC1_ICR50            MCF_REG08(0xFC04C072)
-#define MCF_INTC1_ICR51            MCF_REG08(0xFC04C073)
-#define MCF_INTC1_ICR52            MCF_REG08(0xFC04C074)
-#define MCF_INTC1_ICR53            MCF_REG08(0xFC04C075)
-#define MCF_INTC1_ICR54            MCF_REG08(0xFC04C076)
-#define MCF_INTC1_ICR55            MCF_REG08(0xFC04C077)
-#define MCF_INTC1_ICR56            MCF_REG08(0xFC04C078)
-#define MCF_INTC1_ICR57            MCF_REG08(0xFC04C079)
-#define MCF_INTC1_ICR58            MCF_REG08(0xFC04C07A)
-#define MCF_INTC1_ICR59            MCF_REG08(0xFC04C07B)
-#define MCF_INTC1_ICR60            MCF_REG08(0xFC04C07C)
-#define MCF_INTC1_ICR61            MCF_REG08(0xFC04C07D)
-#define MCF_INTC1_ICR62            MCF_REG08(0xFC04C07E)
-#define MCF_INTC1_ICR63            MCF_REG08(0xFC04C07F)
-#define MCF_INTC1_ICR(x)           MCF_REG08(0xFC04C040+((x)*0x001))
-#define MCF_INTC1_SWIACK           MCF_REG08(0xFC04C0E0)
-#define MCF_INTC1_L1IACK           MCF_REG08(0xFC04C0E4)
-#define MCF_INTC1_L2IACK           MCF_REG08(0xFC04C0E8)
-#define MCF_INTC1_L3IACK           MCF_REG08(0xFC04C0EC)
-#define MCF_INTC1_L4IACK           MCF_REG08(0xFC04C0F0)
-#define MCF_INTC1_L5IACK           MCF_REG08(0xFC04C0F4)
-#define MCF_INTC1_L6IACK           MCF_REG08(0xFC04C0F8)
-#define MCF_INTC1_L7IACK           MCF_REG08(0xFC04C0FC)
-#define MCF_INTC1_LIACK(x)         MCF_REG08(0xFC04C0E4+((x)*0x004))
-#define MCF_INTC_IPRH(x)           MCF_REG32(0xFC048000+((x)*0x4000))
-#define MCF_INTC_IPRL(x)           MCF_REG32(0xFC048004+((x)*0x4000))
-#define MCF_INTC_IMRH(x)           MCF_REG32(0xFC048008+((x)*0x4000))
-#define MCF_INTC_IMRL(x)           MCF_REG32(0xFC04800C+((x)*0x4000))
-#define MCF_INTC_INTFRCH(x)        MCF_REG32(0xFC048010+((x)*0x4000))
-#define MCF_INTC_INTFRCL(x)        MCF_REG32(0xFC048014+((x)*0x4000))
-#define MCF_INTC_ICONFIG(x)        MCF_REG16(0xFC04801A+((x)*0x4000))
-#define MCF_INTC_SIMR(x)           MCF_REG08(0xFC04801C+((x)*0x4000))
-#define MCF_INTC_CIMR(x)           MCF_REG08(0xFC04801D+((x)*0x4000))
-#define MCF_INTC_CLMASK(x)         MCF_REG08(0xFC04801E+((x)*0x4000))
-#define MCF_INTC_SLMASK(x)         MCF_REG08(0xFC04801F+((x)*0x4000))
-#define MCF_INTC_ICR0(x)           MCF_REG08(0xFC048040+((x)*0x4000))
-#define MCF_INTC_ICR1(x)           MCF_REG08(0xFC048041+((x)*0x4000))
-#define MCF_INTC_ICR2(x)           MCF_REG08(0xFC048042+((x)*0x4000))
-#define MCF_INTC_ICR3(x)           MCF_REG08(0xFC048043+((x)*0x4000))
-#define MCF_INTC_ICR4(x)           MCF_REG08(0xFC048044+((x)*0x4000))
-#define MCF_INTC_ICR5(x)           MCF_REG08(0xFC048045+((x)*0x4000))
-#define MCF_INTC_ICR6(x)           MCF_REG08(0xFC048046+((x)*0x4000))
-#define MCF_INTC_ICR7(x)           MCF_REG08(0xFC048047+((x)*0x4000))
-#define MCF_INTC_ICR8(x)           MCF_REG08(0xFC048048+((x)*0x4000))
-#define MCF_INTC_ICR9(x)           MCF_REG08(0xFC048049+((x)*0x4000))
-#define MCF_INTC_ICR10(x)          MCF_REG08(0xFC04804A+((x)*0x4000))
-#define MCF_INTC_ICR11(x)          MCF_REG08(0xFC04804B+((x)*0x4000))
-#define MCF_INTC_ICR12(x)          MCF_REG08(0xFC04804C+((x)*0x4000))
-#define MCF_INTC_ICR13(x)          MCF_REG08(0xFC04804D+((x)*0x4000))
-#define MCF_INTC_ICR14(x)          MCF_REG08(0xFC04804E+((x)*0x4000))
-#define MCF_INTC_ICR15(x)          MCF_REG08(0xFC04804F+((x)*0x4000))
-#define MCF_INTC_ICR16(x)          MCF_REG08(0xFC048050+((x)*0x4000))
-#define MCF_INTC_ICR17(x)          MCF_REG08(0xFC048051+((x)*0x4000))
-#define MCF_INTC_ICR18(x)          MCF_REG08(0xFC048052+((x)*0x4000))
-#define MCF_INTC_ICR19(x)          MCF_REG08(0xFC048053+((x)*0x4000))
-#define MCF_INTC_ICR20(x)          MCF_REG08(0xFC048054+((x)*0x4000))
-#define MCF_INTC_ICR21(x)          MCF_REG08(0xFC048055+((x)*0x4000))
-#define MCF_INTC_ICR22(x)          MCF_REG08(0xFC048056+((x)*0x4000))
-#define MCF_INTC_ICR23(x)          MCF_REG08(0xFC048057+((x)*0x4000))
-#define MCF_INTC_ICR24(x)          MCF_REG08(0xFC048058+((x)*0x4000))
-#define MCF_INTC_ICR25(x)          MCF_REG08(0xFC048059+((x)*0x4000))
-#define MCF_INTC_ICR26(x)          MCF_REG08(0xFC04805A+((x)*0x4000))
-#define MCF_INTC_ICR27(x)          MCF_REG08(0xFC04805B+((x)*0x4000))
-#define MCF_INTC_ICR28(x)          MCF_REG08(0xFC04805C+((x)*0x4000))
-#define MCF_INTC_ICR29(x)          MCF_REG08(0xFC04805D+((x)*0x4000))
-#define MCF_INTC_ICR30(x)          MCF_REG08(0xFC04805E+((x)*0x4000))
-#define MCF_INTC_ICR31(x)          MCF_REG08(0xFC04805F+((x)*0x4000))
-#define MCF_INTC_ICR32(x)          MCF_REG08(0xFC048060+((x)*0x4000))
-#define MCF_INTC_ICR33(x)          MCF_REG08(0xFC048061+((x)*0x4000))
-#define MCF_INTC_ICR34(x)          MCF_REG08(0xFC048062+((x)*0x4000))
-#define MCF_INTC_ICR35(x)          MCF_REG08(0xFC048063+((x)*0x4000))
-#define MCF_INTC_ICR36(x)          MCF_REG08(0xFC048064+((x)*0x4000))
-#define MCF_INTC_ICR37(x)          MCF_REG08(0xFC048065+((x)*0x4000))
-#define MCF_INTC_ICR38(x)          MCF_REG08(0xFC048066+((x)*0x4000))
-#define MCF_INTC_ICR39(x)          MCF_REG08(0xFC048067+((x)*0x4000))
-#define MCF_INTC_ICR40(x)          MCF_REG08(0xFC048068+((x)*0x4000))
-#define MCF_INTC_ICR41(x)          MCF_REG08(0xFC048069+((x)*0x4000))
-#define MCF_INTC_ICR42(x)          MCF_REG08(0xFC04806A+((x)*0x4000))
-#define MCF_INTC_ICR43(x)          MCF_REG08(0xFC04806B+((x)*0x4000))
-#define MCF_INTC_ICR44(x)          MCF_REG08(0xFC04806C+((x)*0x4000))
-#define MCF_INTC_ICR45(x)          MCF_REG08(0xFC04806D+((x)*0x4000))
-#define MCF_INTC_ICR46(x)          MCF_REG08(0xFC04806E+((x)*0x4000))
-#define MCF_INTC_ICR47(x)          MCF_REG08(0xFC04806F+((x)*0x4000))
-#define MCF_INTC_ICR48(x)          MCF_REG08(0xFC048070+((x)*0x4000))
-#define MCF_INTC_ICR49(x)          MCF_REG08(0xFC048071+((x)*0x4000))
-#define MCF_INTC_ICR50(x)          MCF_REG08(0xFC048072+((x)*0x4000))
-#define MCF_INTC_ICR51(x)          MCF_REG08(0xFC048073+((x)*0x4000))
-#define MCF_INTC_ICR52(x)          MCF_REG08(0xFC048074+((x)*0x4000))
-#define MCF_INTC_ICR53(x)          MCF_REG08(0xFC048075+((x)*0x4000))
-#define MCF_INTC_ICR54(x)          MCF_REG08(0xFC048076+((x)*0x4000))
-#define MCF_INTC_ICR55(x)          MCF_REG08(0xFC048077+((x)*0x4000))
-#define MCF_INTC_ICR56(x)          MCF_REG08(0xFC048078+((x)*0x4000))
-#define MCF_INTC_ICR57(x)          MCF_REG08(0xFC048079+((x)*0x4000))
-#define MCF_INTC_ICR58(x)          MCF_REG08(0xFC04807A+((x)*0x4000))
-#define MCF_INTC_ICR59(x)          MCF_REG08(0xFC04807B+((x)*0x4000))
-#define MCF_INTC_ICR60(x)          MCF_REG08(0xFC04807C+((x)*0x4000))
-#define MCF_INTC_ICR61(x)          MCF_REG08(0xFC04807D+((x)*0x4000))
-#define MCF_INTC_ICR62(x)          MCF_REG08(0xFC04807E+((x)*0x4000))
-#define MCF_INTC_ICR63(x)          MCF_REG08(0xFC04807F+((x)*0x4000))
-#define MCF_INTC_SWIACK(x)         MCF_REG08(0xFC0480E0+((x)*0x4000))
-#define MCF_INTC_L1IACK(x)         MCF_REG08(0xFC0480E4+((x)*0x4000))
-#define MCF_INTC_L2IACK(x)         MCF_REG08(0xFC0480E8+((x)*0x4000))
-#define MCF_INTC_L3IACK(x)         MCF_REG08(0xFC0480EC+((x)*0x4000))
-#define MCF_INTC_L4IACK(x)         MCF_REG08(0xFC0480F0+((x)*0x4000))
-#define MCF_INTC_L5IACK(x)         MCF_REG08(0xFC0480F4+((x)*0x4000))
-#define MCF_INTC_L6IACK(x)         MCF_REG08(0xFC0480F8+((x)*0x4000))
-#define MCF_INTC_L7IACK(x)         MCF_REG08(0xFC0480FC+((x)*0x4000))
-
-/* Bit definitions and macros for MCF_INTC_IPRH */
-#define MCF_INTC_IPRH_INT32        (0x00000001)
-#define MCF_INTC_IPRH_INT33        (0x00000002)
-#define MCF_INTC_IPRH_INT34        (0x00000004)
-#define MCF_INTC_IPRH_INT35        (0x00000008)
-#define MCF_INTC_IPRH_INT36        (0x00000010)
-#define MCF_INTC_IPRH_INT37        (0x00000020)
-#define MCF_INTC_IPRH_INT38        (0x00000040)
-#define MCF_INTC_IPRH_INT39        (0x00000080)
-#define MCF_INTC_IPRH_INT40        (0x00000100)
-#define MCF_INTC_IPRH_INT41        (0x00000200)
-#define MCF_INTC_IPRH_INT42        (0x00000400)
-#define MCF_INTC_IPRH_INT43        (0x00000800)
-#define MCF_INTC_IPRH_INT44        (0x00001000)
-#define MCF_INTC_IPRH_INT45        (0x00002000)
-#define MCF_INTC_IPRH_INT46        (0x00004000)
-#define MCF_INTC_IPRH_INT47        (0x00008000)
-#define MCF_INTC_IPRH_INT48        (0x00010000)
-#define MCF_INTC_IPRH_INT49        (0x00020000)
-#define MCF_INTC_IPRH_INT50        (0x00040000)
-#define MCF_INTC_IPRH_INT51        (0x00080000)
-#define MCF_INTC_IPRH_INT52        (0x00100000)
-#define MCF_INTC_IPRH_INT53        (0x00200000)
-#define MCF_INTC_IPRH_INT54        (0x00400000)
-#define MCF_INTC_IPRH_INT55        (0x00800000)
-#define MCF_INTC_IPRH_INT56        (0x01000000)
-#define MCF_INTC_IPRH_INT57        (0x02000000)
-#define MCF_INTC_IPRH_INT58        (0x04000000)
-#define MCF_INTC_IPRH_INT59        (0x08000000)
-#define MCF_INTC_IPRH_INT60        (0x10000000)
-#define MCF_INTC_IPRH_INT61        (0x20000000)
-#define MCF_INTC_IPRH_INT62        (0x40000000)
-#define MCF_INTC_IPRH_INT63        (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_IPRL */
-#define MCF_INTC_IPRL_INT0         (0x00000001)
-#define MCF_INTC_IPRL_INT1         (0x00000002)
-#define MCF_INTC_IPRL_INT2         (0x00000004)
-#define MCF_INTC_IPRL_INT3         (0x00000008)
-#define MCF_INTC_IPRL_INT4         (0x00000010)
-#define MCF_INTC_IPRL_INT5         (0x00000020)
-#define MCF_INTC_IPRL_INT6         (0x00000040)
-#define MCF_INTC_IPRL_INT7         (0x00000080)
-#define MCF_INTC_IPRL_INT8         (0x00000100)
-#define MCF_INTC_IPRL_INT9         (0x00000200)
-#define MCF_INTC_IPRL_INT10        (0x00000400)
-#define MCF_INTC_IPRL_INT11        (0x00000800)
-#define MCF_INTC_IPRL_INT12        (0x00001000)
-#define MCF_INTC_IPRL_INT13        (0x00002000)
-#define MCF_INTC_IPRL_INT14        (0x00004000)
-#define MCF_INTC_IPRL_INT15        (0x00008000)
-#define MCF_INTC_IPRL_INT16        (0x00010000)
-#define MCF_INTC_IPRL_INT17        (0x00020000)
-#define MCF_INTC_IPRL_INT18        (0x00040000)
-#define MCF_INTC_IPRL_INT19        (0x00080000)
-#define MCF_INTC_IPRL_INT20        (0x00100000)
-#define MCF_INTC_IPRL_INT21        (0x00200000)
-#define MCF_INTC_IPRL_INT22        (0x00400000)
-#define MCF_INTC_IPRL_INT23        (0x00800000)
-#define MCF_INTC_IPRL_INT24        (0x01000000)
-#define MCF_INTC_IPRL_INT25        (0x02000000)
-#define MCF_INTC_IPRL_INT26        (0x04000000)
-#define MCF_INTC_IPRL_INT27        (0x08000000)
-#define MCF_INTC_IPRL_INT28        (0x10000000)
-#define MCF_INTC_IPRL_INT29        (0x20000000)
-#define MCF_INTC_IPRL_INT30        (0x40000000)
-#define MCF_INTC_IPRL_INT31        (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_IMRH */
-#define MCF_INTC_IMRH_INT_MASK32   (0x00000001)
-#define MCF_INTC_IMRH_INT_MASK33   (0x00000002)
-#define MCF_INTC_IMRH_INT_MASK34   (0x00000004)
-#define MCF_INTC_IMRH_INT_MASK35   (0x00000008)
-#define MCF_INTC_IMRH_INT_MASK36   (0x00000010)
-#define MCF_INTC_IMRH_INT_MASK37   (0x00000020)
-#define MCF_INTC_IMRH_INT_MASK38   (0x00000040)
-#define MCF_INTC_IMRH_INT_MASK39   (0x00000080)
-#define MCF_INTC_IMRH_INT_MASK40   (0x00000100)
-#define MCF_INTC_IMRH_INT_MASK41   (0x00000200)
-#define MCF_INTC_IMRH_INT_MASK42   (0x00000400)
-#define MCF_INTC_IMRH_INT_MASK43   (0x00000800)
-#define MCF_INTC_IMRH_INT_MASK44   (0x00001000)
-#define MCF_INTC_IMRH_INT_MASK45   (0x00002000)
-#define MCF_INTC_IMRH_INT_MASK46   (0x00004000)
-#define MCF_INTC_IMRH_INT_MASK47   (0x00008000)
-#define MCF_INTC_IMRH_INT_MASK48   (0x00010000)
-#define MCF_INTC_IMRH_INT_MASK49   (0x00020000)
-#define MCF_INTC_IMRH_INT_MASK50   (0x00040000)
-#define MCF_INTC_IMRH_INT_MASK51   (0x00080000)
-#define MCF_INTC_IMRH_INT_MASK52   (0x00100000)
-#define MCF_INTC_IMRH_INT_MASK53   (0x00200000)
-#define MCF_INTC_IMRH_INT_MASK54   (0x00400000)
-#define MCF_INTC_IMRH_INT_MASK55   (0x00800000)
-#define MCF_INTC_IMRH_INT_MASK56   (0x01000000)
-#define MCF_INTC_IMRH_INT_MASK57   (0x02000000)
-#define MCF_INTC_IMRH_INT_MASK58   (0x04000000)
-#define MCF_INTC_IMRH_INT_MASK59   (0x08000000)
-#define MCF_INTC_IMRH_INT_MASK60   (0x10000000)
-#define MCF_INTC_IMRH_INT_MASK61   (0x20000000)
-#define MCF_INTC_IMRH_INT_MASK62   (0x40000000)
-#define MCF_INTC_IMRH_INT_MASK63   (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_IMRL */
-#define MCF_INTC_IMRL_INT_MASK0    (0x00000001)
-#define MCF_INTC_IMRL_INT_MASK1    (0x00000002)
-#define MCF_INTC_IMRL_INT_MASK2    (0x00000004)
-#define MCF_INTC_IMRL_INT_MASK3    (0x00000008)
-#define MCF_INTC_IMRL_INT_MASK4    (0x00000010)
-#define MCF_INTC_IMRL_INT_MASK5    (0x00000020)
-#define MCF_INTC_IMRL_INT_MASK6    (0x00000040)
-#define MCF_INTC_IMRL_INT_MASK7    (0x00000080)
-#define MCF_INTC_IMRL_INT_MASK8    (0x00000100)
-#define MCF_INTC_IMRL_INT_MASK9    (0x00000200)
-#define MCF_INTC_IMRL_INT_MASK10   (0x00000400)
-#define MCF_INTC_IMRL_INT_MASK11   (0x00000800)
-#define MCF_INTC_IMRL_INT_MASK12   (0x00001000)
-#define MCF_INTC_IMRL_INT_MASK13   (0x00002000)
-#define MCF_INTC_IMRL_INT_MASK14   (0x00004000)
-#define MCF_INTC_IMRL_INT_MASK15   (0x00008000)
-#define MCF_INTC_IMRL_INT_MASK16   (0x00010000)
-#define MCF_INTC_IMRL_INT_MASK17   (0x00020000)
-#define MCF_INTC_IMRL_INT_MASK18   (0x00040000)
-#define MCF_INTC_IMRL_INT_MASK19   (0x00080000)
-#define MCF_INTC_IMRL_INT_MASK20   (0x00100000)
-#define MCF_INTC_IMRL_INT_MASK21   (0x00200000)
-#define MCF_INTC_IMRL_INT_MASK22   (0x00400000)
-#define MCF_INTC_IMRL_INT_MASK23   (0x00800000)
-#define MCF_INTC_IMRL_INT_MASK24   (0x01000000)
-#define MCF_INTC_IMRL_INT_MASK25   (0x02000000)
-#define MCF_INTC_IMRL_INT_MASK26   (0x04000000)
-#define MCF_INTC_IMRL_INT_MASK27   (0x08000000)
-#define MCF_INTC_IMRL_INT_MASK28   (0x10000000)
-#define MCF_INTC_IMRL_INT_MASK29   (0x20000000)
-#define MCF_INTC_IMRL_INT_MASK30   (0x40000000)
-#define MCF_INTC_IMRL_INT_MASK31   (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_INTFRCH */
-#define MCF_INTC_INTFRCH_INTFRC32  (0x00000001)
-#define MCF_INTC_INTFRCH_INTFRC33  (0x00000002)
-#define MCF_INTC_INTFRCH_INTFRC34  (0x00000004)
-#define MCF_INTC_INTFRCH_INTFRC35  (0x00000008)
-#define MCF_INTC_INTFRCH_INTFRC36  (0x00000010)
-#define MCF_INTC_INTFRCH_INTFRC37  (0x00000020)
-#define MCF_INTC_INTFRCH_INTFRC38  (0x00000040)
-#define MCF_INTC_INTFRCH_INTFRC39  (0x00000080)
-#define MCF_INTC_INTFRCH_INTFRC40  (0x00000100)
-#define MCF_INTC_INTFRCH_INTFRC41  (0x00000200)
-#define MCF_INTC_INTFRCH_INTFRC42  (0x00000400)
-#define MCF_INTC_INTFRCH_INTFRC43  (0x00000800)
-#define MCF_INTC_INTFRCH_INTFRC44  (0x00001000)
-#define MCF_INTC_INTFRCH_INTFRC45  (0x00002000)
-#define MCF_INTC_INTFRCH_INTFRC46  (0x00004000)
-#define MCF_INTC_INTFRCH_INTFRC47  (0x00008000)
-#define MCF_INTC_INTFRCH_INTFRC48  (0x00010000)
-#define MCF_INTC_INTFRCH_INTFRC49  (0x00020000)
-#define MCF_INTC_INTFRCH_INTFRC50  (0x00040000)
-#define MCF_INTC_INTFRCH_INTFRC51  (0x00080000)
-#define MCF_INTC_INTFRCH_INTFRC52  (0x00100000)
-#define MCF_INTC_INTFRCH_INTFRC53  (0x00200000)
-#define MCF_INTC_INTFRCH_INTFRC54  (0x00400000)
-#define MCF_INTC_INTFRCH_INTFRC55  (0x00800000)
-#define MCF_INTC_INTFRCH_INTFRC56  (0x01000000)
-#define MCF_INTC_INTFRCH_INTFRC57  (0x02000000)
-#define MCF_INTC_INTFRCH_INTFRC58  (0x04000000)
-#define MCF_INTC_INTFRCH_INTFRC59  (0x08000000)
-#define MCF_INTC_INTFRCH_INTFRC60  (0x10000000)
-#define MCF_INTC_INTFRCH_INTFRC61  (0x20000000)
-#define MCF_INTC_INTFRCH_INTFRC62  (0x40000000)
-#define MCF_INTC_INTFRCH_INTFRC63  (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_INTFRCL */
-#define MCF_INTC_INTFRCL_INTFRC0   (0x00000001)
-#define MCF_INTC_INTFRCL_INTFRC1   (0x00000002)
-#define MCF_INTC_INTFRCL_INTFRC2   (0x00000004)
-#define MCF_INTC_INTFRCL_INTFRC3   (0x00000008)
-#define MCF_INTC_INTFRCL_INTFRC4   (0x00000010)
-#define MCF_INTC_INTFRCL_INTFRC5   (0x00000020)
-#define MCF_INTC_INTFRCL_INTFRC6   (0x00000040)
-#define MCF_INTC_INTFRCL_INTFRC7   (0x00000080)
-#define MCF_INTC_INTFRCL_INTFRC8   (0x00000100)
-#define MCF_INTC_INTFRCL_INTFRC9   (0x00000200)
-#define MCF_INTC_INTFRCL_INTFRC10  (0x00000400)
-#define MCF_INTC_INTFRCL_INTFRC11  (0x00000800)
-#define MCF_INTC_INTFRCL_INTFRC12  (0x00001000)
-#define MCF_INTC_INTFRCL_INTFRC13  (0x00002000)
-#define MCF_INTC_INTFRCL_INTFRC14  (0x00004000)
-#define MCF_INTC_INTFRCL_INTFRC15  (0x00008000)
-#define MCF_INTC_INTFRCL_INTFRC16  (0x00010000)
-#define MCF_INTC_INTFRCL_INTFRC17  (0x00020000)
-#define MCF_INTC_INTFRCL_INTFRC18  (0x00040000)
-#define MCF_INTC_INTFRCL_INTFRC19  (0x00080000)
-#define MCF_INTC_INTFRCL_INTFRC20  (0x00100000)
-#define MCF_INTC_INTFRCL_INTFRC21  (0x00200000)
-#define MCF_INTC_INTFRCL_INTFRC22  (0x00400000)
-#define MCF_INTC_INTFRCL_INTFRC23  (0x00800000)
-#define MCF_INTC_INTFRCL_INTFRC24  (0x01000000)
-#define MCF_INTC_INTFRCL_INTFRC25  (0x02000000)
-#define MCF_INTC_INTFRCL_INTFRC26  (0x04000000)
-#define MCF_INTC_INTFRCL_INTFRC27  (0x08000000)
-#define MCF_INTC_INTFRCL_INTFRC28  (0x10000000)
-#define MCF_INTC_INTFRCL_INTFRC29  (0x20000000)
-#define MCF_INTC_INTFRCL_INTFRC30  (0x40000000)
-#define MCF_INTC_INTFRCL_INTFRC31  (0x80000000)
-
-/* Bit definitions and macros for MCF_INTC_ICONFIG */
-#define MCF_INTC_ICONFIG_EMASK     (0x0020)
-#define MCF_INTC_ICONFIG_ELVLPRI1  (0x0200)
-#define MCF_INTC_ICONFIG_ELVLPRI2  (0x0400)
-#define MCF_INTC_ICONFIG_ELVLPRI3  (0x0800)
-#define MCF_INTC_ICONFIG_ELVLPRI4  (0x1000)
-#define MCF_INTC_ICONFIG_ELVLPRI5  (0x2000)
-#define MCF_INTC_ICONFIG_ELVLPRI6  (0x4000)
-#define MCF_INTC_ICONFIG_ELVLPRI7  (0x8000)
-
-/* Bit definitions and macros for MCF_INTC_SIMR */
-#define MCF_INTC_SIMR_SIMR(x)      (((x)&0x7F)<<0)
-
-/* Bit definitions and macros for MCF_INTC_CIMR */
-#define MCF_INTC_CIMR_CIMR(x)      (((x)&0x7F)<<0)
-
-/* Bit definitions and macros for MCF_INTC_CLMASK */
-#define MCF_INTC_CLMASK_CLMASK(x)  (((x)&0x0F)<<0)
-
-/* Bit definitions and macros for MCF_INTC_SLMASK */
-#define MCF_INTC_SLMASK_SLMASK(x)  (((x)&0x0F)<<0)
-
-/* Bit definitions and macros for MCF_INTC_ICR */
-#define MCF_INTC_ICR_IL(x)         (((x)&0x07)<<0)
-
-/* Bit definitions and macros for MCF_INTC_SWIACK */
-#define MCF_INTC_SWIACK_VECTOR(x)  (((x)&0xFF)<<0)
-
-/* Bit definitions and macros for MCF_INTC_LIACK */
-#define MCF_INTC_LIACK_VECTOR(x)   (((x)&0xFF)<<0)
-
-/********************************************************************/
-/*********************************************************************
-*
-* LCD Controller (LCDC)
-*
-*********************************************************************/
-
-/* Register read/write macros */
-#define MCF_LCDC_LSSAR                  MCF_REG32(0xFC0AC000)
-#define MCF_LCDC_LSR                    MCF_REG32(0xFC0AC004)
-#define MCF_LCDC_LVPWR                  MCF_REG32(0xFC0AC008)
-#define MCF_LCDC_LCPR                   MCF_REG32(0xFC0AC00C)
-#define MCF_LCDC_LCWHBR                 MCF_REG32(0xFC0AC010)
-#define MCF_LCDC_LCCMR                  MCF_REG32(0xFC0AC014)
-#define MCF_LCDC_LPCR                   MCF_REG32(0xFC0AC018)
-#define MCF_LCDC_LHCR                   MCF_REG32(0xFC0AC01C)
-#define MCF_LCDC_LVCR                   MCF_REG32(0xFC0AC020)
-#define MCF_LCDC_LPOR                   MCF_REG32(0xFC0AC024)
-#define MCF_LCDC_LSCR                   MCF_REG32(0xFC0AC028)
-#define MCF_LCDC_LPCCR                  MCF_REG32(0xFC0AC02C)
-#define MCF_LCDC_LDCR                   MCF_REG32(0xFC0AC030)
-#define MCF_LCDC_LRMCR                  MCF_REG32(0xFC0AC034)
-#define MCF_LCDC_LICR                   MCF_REG32(0xFC0AC038)
-#define MCF_LCDC_LIER                   MCF_REG32(0xFC0AC03C)
-#define MCF_LCDC_LISR                   MCF_REG32(0xFC0AC040)
-#define MCF_LCDC_LGWSAR                 MCF_REG32(0xFC0AC050)
-#define MCF_LCDC_LGWSR                  MCF_REG32(0xFC0AC054)
-#define MCF_LCDC_LGWVPWR                MCF_REG32(0xFC0AC058)
-#define MCF_LCDC_LGWPOR                 MCF_REG32(0xFC0AC05C)
-#define MCF_LCDC_LGWPR                  MCF_REG32(0xFC0AC060)
-#define MCF_LCDC_LGWCR                  MCF_REG32(0xFC0AC064)
-#define MCF_LCDC_LGWDCR                 MCF_REG32(0xFC0AC068)
-#define MCF_LCDC_BPLUT_BASE             MCF_REG32(0xFC0AC800)
-#define MCF_LCDC_GWLUT_BASE             MCF_REG32(0xFC0ACC00)
-
-/* Bit definitions and macros for MCF_LCDC_LSSAR */
-#define MCF_LCDC_LSSAR_SSA(x)           (((x)&0x3FFFFFFF)<<2)
-
-/* Bit definitions and macros for MCF_LCDC_LSR */
-#define MCF_LCDC_LSR_YMAX(x)            (((x)&0x000003FF)<<0)
-#define MCF_LCDC_LSR_XMAX(x)            (((x)&0x0000003F)<<20)
-
-/* Bit definitions and macros for MCF_LCDC_LVPWR */
-#define MCF_LCDC_LVPWR_VPW(x)           (((x)&0x000003FF)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_LCPR */
-#define MCF_LCDC_LCPR_CYP(x)            (((x)&0x000003FF)<<0)
-#define MCF_LCDC_LCPR_CXP(x)            (((x)&0x000003FF)<<16)
-#define MCF_LCDC_LCPR_OP                (0x10000000)
-#define MCF_LCDC_LCPR_CC(x)             (((x)&0x00000003)<<30)
-#define MCF_LCDC_LCPR_CC_TRANSPARENT    (0x00000000)
-#define MCF_LCDC_LCPR_CC_OR             (0x40000000)
-#define MCF_LCDC_LCPR_CC_XOR            (0x80000000)
-#define MCF_LCDC_LCPR_CC_AND            (0xC0000000)
-#define MCF_LCDC_LCPR_OP_ON             (0x10000000)
-#define MCF_LCDC_LCPR_OP_OFF            (0x00000000)
-
-/* Bit definitions and macros for MCF_LCDC_LCWHBR */
-#define MCF_LCDC_LCWHBR_BD(x)           (((x)&0x000000FF)<<0)
-#define MCF_LCDC_LCWHBR_CH(x)           (((x)&0x0000001F)<<16)
-#define MCF_LCDC_LCWHBR_CW(x)           (((x)&0x0000001F)<<24)
-#define MCF_LCDC_LCWHBR_BK_EN           (0x80000000)
-#define MCF_LCDC_LCWHBR_BK_EN_ON        (0x80000000)
-#define MCF_LCDC_LCWHBR_BK_EN_OFF       (0x00000000)
-
-/* Bit definitions and macros for MCF_LCDC_LCCMR */
-#define MCF_LCDC_LCCMR_CUR_COL_B(x)     (((x)&0x0000003F)<<0)
-#define MCF_LCDC_LCCMR_CUR_COL_G(x)     (((x)&0x0000003F)<<6)
-#define MCF_LCDC_LCCMR_CUR_COL_R(x)     (((x)&0x0000003F)<<12)
-
-/* Bit definitions and macros for MCF_LCDC_LPCR */
-#define MCF_LCDC_LPCR_PCD(x)            (((x)&0x0000003F)<<0)
-#define MCF_LCDC_LPCR_SHARP             (0x00000040)
-#define MCF_LCDC_LPCR_SCLKSEL           (0x00000080)
-#define MCF_LCDC_LPCR_ACD(x)            (((x)&0x0000007F)<<8)
-#define MCF_LCDC_LPCR_ACDSEL            (0x00008000)
-#define MCF_LCDC_LPCR_REV_VS            (0x00010000)
-#define MCF_LCDC_LPCR_SWAP_SEL          (0x00020000)
-#define MCF_LCDC_LPCR_ENDSEL            (0x00040000)
-#define MCF_LCDC_LPCR_SCLKIDLE          (0x00080000)
-#define MCF_LCDC_LPCR_OEPOL             (0x00100000)
-#define MCF_LCDC_LPCR_CLKPOL            (0x00200000)
-#define MCF_LCDC_LPCR_LPPOL             (0x00400000)
-#define MCF_LCDC_LPCR_FLM               (0x00800000)
-#define MCF_LCDC_LPCR_PIXPOL            (0x01000000)
-#define MCF_LCDC_LPCR_BPIX(x)           (((x)&0x00000007)<<25)
-#define MCF_LCDC_LPCR_PBSIZ(x)          (((x)&0x00000003)<<28)
-#define MCF_LCDC_LPCR_COLOR             (0x40000000)
-#define MCF_LCDC_LPCR_TFT               (0x80000000)
-#define MCF_LCDC_LPCR_MODE_MONOCGROME   (0x00000000)
-#define MCF_LCDC_LPCR_MODE_CSTN         (0x40000000)
-#define MCF_LCDC_LPCR_MODE_TFT          (0xC0000000)
-#define MCF_LCDC_LPCR_PBSIZ_1           (0x00000000)
-#define MCF_LCDC_LPCR_PBSIZ_2           (0x10000000)
-#define MCF_LCDC_LPCR_PBSIZ_4           (0x20000000)
-#define MCF_LCDC_LPCR_PBSIZ_8           (0x30000000)
-#define MCF_LCDC_LPCR_BPIX_1bpp         (0x00000000)
-#define MCF_LCDC_LPCR_BPIX_2bpp         (0x02000000)
-#define MCF_LCDC_LPCR_BPIX_4bpp         (0x04000000)
-#define MCF_LCDC_LPCR_BPIX_8bpp         (0x06000000)
-#define MCF_LCDC_LPCR_BPIX_12bpp        (0x08000000)
-#define MCF_LCDC_LPCR_BPIX_16bpp        (0x0A000000)
-#define MCF_LCDC_LPCR_BPIX_18bpp        (0x0C000000)
-
-#define MCF_LCDC_LPCR_PANEL_TYPE(x)     (((x)&0x00000003)<<30) 
-
-/* Bit definitions and macros for MCF_LCDC_LHCR */
-#define MCF_LCDC_LHCR_H_WAIT_2(x)       (((x)&0x000000FF)<<0)
-#define MCF_LCDC_LHCR_H_WAIT_1(x)       (((x)&0x000000FF)<<8)
-#define MCF_LCDC_LHCR_H_WIDTH(x)        (((x)&0x0000003F)<<26)
-
-/* Bit definitions and macros for MCF_LCDC_LVCR */
-#define MCF_LCDC_LVCR_V_WAIT_2(x)       (((x)&0x000000FF)<<0)
-#define MCF_LCDC_LVCR_V_WAIT_1(x)       (((x)&0x000000FF)<<8)
-#define MCF_LCDC_LVCR_V_WIDTH(x)      (((x)&0x0000003F)<<26)
-
-/* Bit definitions and macros for MCF_LCDC_LPOR */
-#define MCF_LCDC_LPOR_POS(x)            (((x)&0x0000001F)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_LPCCR */
-#define MCF_LCDC_LPCCR_PW(x)            (((x)&0x000000FF)<<0)
-#define MCF_LCDC_LPCCR_CC_EN            (0x00000100)
-#define MCF_LCDC_LPCCR_SCR(x)           (((x)&0x00000003)<<9)
-#define MCF_LCDC_LPCCR_LDMSK            (0x00008000)
-#define MCF_LCDC_LPCCR_CLS_HI_WIDTH(x)  (((x)&0x000001FF)<<16)
-#define MCF_LCDC_LPCCR_SCR_LINEPULSE    (0x00000000)
-#define MCF_LCDC_LPCCR_SCR_PIXELCLK     (0x00002000)
-#define MCF_LCDC_LPCCR_SCR_LCDCLOCK     (0x00004000)
-
-/* Bit definitions and macros for MCF_LCDC_LDCR */
-#define MCF_LCDC_LDCR_TM(x)             (((x)&0x0000001F)<<0)
-#define MCF_LCDC_LDCR_HM(x)             (((x)&0x0000001F)<<16)
-#define MCF_LCDC_LDCR_BURST             (0x80000000)
-
-/* Bit definitions and macros for MCF_LCDC_LRMCR */
-#define MCF_LCDC_LRMCR_SEL_REF          (0x00000001)
-
-/* Bit definitions and macros for MCF_LCDC_LICR */
-#define MCF_LCDC_LICR_INTCON            (0x00000001)
-#define MCF_LCDC_LICR_INTSYN            (0x00000004)
-#define MCF_LCDC_LICR_GW_INT_CON        (0x00000010)
-
-/* Bit definitions and macros for MCF_LCDC_LIER */
-#define MCF_LCDC_LIER_BOF_EN            (0x00000001)
-#define MCF_LCDC_LIER_EOF_EN            (0x00000002)
-#define MCF_LCDC_LIER_ERR_RES_EN        (0x00000004)
-#define MCF_LCDC_LIER_UDR_ERR_EN        (0x00000008)
-#define MCF_LCDC_LIER_GW_BOF_EN         (0x00000010)
-#define MCF_LCDC_LIER_GW_EOF_EN         (0x00000020)
-#define MCF_LCDC_LIER_GW_ERR_RES_EN     (0x00000040)
-#define MCF_LCDC_LIER_GW_UDR_ERR_EN     (0x00000080)
-
-/* Bit definitions and macros for MCF_LCDC_LISR */
-#define MCF_LCDC_LISR_BOF               (0x00000001)
-#define MCF_LCDC_LISR_EOF               (0x00000002)
-#define MCF_LCDC_LISR_ERR_RES           (0x00000004)
-#define MCF_LCDC_LISR_UDR_ERR           (0x00000008)
-#define MCF_LCDC_LISR_GW_BOF            (0x00000010)
-#define MCF_LCDC_LISR_GW_EOF            (0x00000020)
-#define MCF_LCDC_LISR_GW_ERR_RES        (0x00000040)
-#define MCF_LCDC_LISR_GW_UDR_ERR        (0x00000080)
-
-/* Bit definitions and macros for MCF_LCDC_LGWSAR */
-#define MCF_LCDC_LGWSAR_GWSA(x)         (((x)&0x3FFFFFFF)<<2)
-
-/* Bit definitions and macros for MCF_LCDC_LGWSR */
-#define MCF_LCDC_LGWSR_GWH(x)           (((x)&0x000003FF)<<0)
-#define MCF_LCDC_LGWSR_GWW(x)           (((x)&0x0000003F)<<20)
-
-/* Bit definitions and macros for MCF_LCDC_LGWVPWR */
-#define MCF_LCDC_LGWVPWR_GWVPW(x)       (((x)&0x000003FF)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_LGWPOR */
-#define MCF_LCDC_LGWPOR_GWPO(x)         (((x)&0x0000001F)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_LGWPR */
-#define MCF_LCDC_LGWPR_GWYP(x)          (((x)&0x000003FF)<<0)
-#define MCF_LCDC_LGWPR_GWXP(x)          (((x)&0x000003FF)<<16)
-
-/* Bit definitions and macros for MCF_LCDC_LGWCR */
-#define MCF_LCDC_LGWCR_GWCKB(x)         (((x)&0x0000003F)<<0)
-#define MCF_LCDC_LGWCR_GWCKG(x)         (((x)&0x0000003F)<<6)
-#define MCF_LCDC_LGWCR_GWCKR(x)         (((x)&0x0000003F)<<12)
-#define MCF_LCDC_LGWCR_GW_RVS           (0x00200000)
-#define MCF_LCDC_LGWCR_GWE              (0x00400000)
-#define MCF_LCDC_LGWCR_GWCKE            (0x00800000)
-#define MCF_LCDC_LGWCR_GWAV(x)          (((x)&0x000000FF)<<24)
-
-/* Bit definitions and macros for MCF_LCDC_LGWDCR */
-#define MCF_LCDC_LGWDCR_GWTM(x)         (((x)&0x0000001F)<<0)
-#define MCF_LCDC_LGWDCR_GWHM(x)         (((x)&0x0000001F)<<16)
-#define MCF_LCDC_LGWDCR_GWBT            (0x80000000)
-
-/* Bit definitions and macros for MCF_LCDC_LSCR */
-#define MCF_LCDC_LSCR_PS_RISE_DELAY(x)    (((x)&0x0000003F)<<26)
-#define MCF_LCDC_LSCR_CLS_RISE_DELAY(x)   (((x)&0x000000FF)<<16)
-#define MCF_LCDC_LSCR_REV_TOGGLE_DELAY(x) (((x)&0x0000000F)<<8)
-#define MCF_LCDC_LSCR_GRAY_2(x)                  (((x)&0x0000000F)<<4)
-#define MCF_LCDC_LSCR_GRAY_1(x)                  (((x)&0x0000000F)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_BPLUT_BASE */
-#define MCF_LCDC_BPLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
-
-/* Bit definitions and macros for MCF_LCDC_GWLUT_BASE */
-#define MCF_LCDC_GWLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
-
 /*********************************************************************
  *
  * Phase Locked Loop (PLL)
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_PLL_PODR              MCF_REG08(0xFC0C0000)
-#define MCF_PLL_PLLCR             MCF_REG08(0xFC0C0004)
-#define MCF_PLL_PMDR              MCF_REG08(0xFC0C0008)
-#define MCF_PLL_PFDR              MCF_REG08(0xFC0C000C)
+#define MCF_PLL_PODR              0xFC0C0000
+#define MCF_PLL_PLLCR             0xFC0C0004
+#define MCF_PLL_PMDR              0xFC0C0008
+#define MCF_PLL_PFDR              0xFC0C000C
 
 /* Bit definitions and macros for MCF_PLL_PODR */
 #define MCF_PLL_PODR_BUSDIV(x)    (((x)&0x0F)<<0)
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_SCM_MPR                    MCF_REG32(0xFC000000)
-#define MCF_SCM_PACRA                  MCF_REG32(0xFC000020)
-#define MCF_SCM_PACRB                  MCF_REG32(0xFC000024)
-#define MCF_SCM_PACRC                  MCF_REG32(0xFC000028)
-#define MCF_SCM_PACRD                  MCF_REG32(0xFC00002C)
-#define MCF_SCM_PACRE                  MCF_REG32(0xFC000040)
-#define MCF_SCM_PACRF                  MCF_REG32(0xFC000044)
+#define MCF_SCM_MPR                    0xFC000000
+#define MCF_SCM_PACRA                  0xFC000020
+#define MCF_SCM_PACRB                  0xFC000024
+#define MCF_SCM_PACRC                  0xFC000028
+#define MCF_SCM_PACRD                  0xFC00002C
+#define MCF_SCM_PACRE                  0xFC000040
+#define MCF_SCM_PACRF                  0xFC000044
 
-#define MCF_SCM_BCR                    MCF_REG32(0xFC040024)
+#define MCF_SCM_BCR                    0xFC040024
 
 /*********************************************************************
  *
  *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_SDRAMC_SDMR                        MCF_REG32(0xFC0B8000)
-#define MCF_SDRAMC_SDCR                        MCF_REG32(0xFC0B8004)
-#define MCF_SDRAMC_SDCFG1              MCF_REG32(0xFC0B8008)
-#define MCF_SDRAMC_SDCFG2              MCF_REG32(0xFC0B800C)
-#define MCF_SDRAMC_LIMP_FIX            MCF_REG32(0xFC0B8080)
-#define MCF_SDRAMC_SDDS                        MCF_REG32(0xFC0B8100)
-#define MCF_SDRAMC_SDCS0               MCF_REG32(0xFC0B8110)
-#define MCF_SDRAMC_SDCS1               MCF_REG32(0xFC0B8114)
-#define MCF_SDRAMC_SDCS2               MCF_REG32(0xFC0B8118)
-#define MCF_SDRAMC_SDCS3               MCF_REG32(0xFC0B811C)
-#define MCF_SDRAMC_SDCS(x)             MCF_REG32(0xFC0B8110+((x)*0x004))
+#define MCF_SDRAMC_SDMR                        0xFC0B8000
+#define MCF_SDRAMC_SDCR                        0xFC0B8004
+#define MCF_SDRAMC_SDCFG1              0xFC0B8008
+#define MCF_SDRAMC_SDCFG2              0xFC0B800C
+#define MCF_SDRAMC_LIMP_FIX            0xFC0B8080
+#define MCF_SDRAMC_SDDS                        0xFC0B8100
+#define MCF_SDRAMC_SDCS0               0xFC0B8110
+#define MCF_SDRAMC_SDCS1               0xFC0B8114
+#define MCF_SDRAMC_SDCS2               0xFC0B8118
+#define MCF_SDRAMC_SDCS3               0xFC0B811C
 
 /* Bit definitions and macros for MCF_SDRAMC_SDMR */
 #define MCF_SDRAMC_SDMR_CMD            (0x00010000)
 #define MCF_SDRAMC_SDCS_CSSZ_2GBYTE    (0x0000001E)
 #define MCF_SDRAMC_SDCS_CSSZ_4GBYTE    (0x0000001F)
 
-/*********************************************************************
- *
- *      FlexCAN module registers
- *
- *********************************************************************/
-#define MCF_FLEXCAN_BASEADDR(x)                (0xFC020000+(x)*0x0800)
-#define MCF_FLEXCAN_CANMCR(x)          MCF_REG32(0xFC020000+(x)*0x0800+0x00)
-#define MCF_FLEXCAN_CANCTRL(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x04)
-#define MCF_FLEXCAN_TIMER(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x08)
-#define MCF_FLEXCAN_RXGMASK(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x10)
-#define MCF_FLEXCAN_RX14MASK(x)                MCF_REG32(0xFC020000+(x)*0x0800+0x14)
-#define MCF_FLEXCAN_RX15MASK(x)                MCF_REG32(0xFC020000+(x)*0x0800+0x18)
-#define MCF_FLEXCAN_ERRCNT(x)          MCF_REG32(0xFC020000+(x)*0x0800+0x1C)
-#define MCF_FLEXCAN_ERRSTAT(x)         MCF_REG32(0xFC020000+(x)*0x0800+0x20)
-#define MCF_FLEXCAN_IMASK(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x28)
-#define MCF_FLEXCAN_IFLAG(x)           MCF_REG32(0xFC020000+(x)*0x0800+0x30)
-
-#define MCF_FLEXCAN_MB_CNT(x,y)                MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x0)
-#define MCF_FLEXCAN_MB_ID(x,y)         MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x4)
-#define MCF_FLEXCAN_MB_DB(x,y,z)       MCF_REG08(0xFC020080+(x)*0x0800+(y)*0x10+0x8+(z)*0x1)
-
-/*
- *      FlexCAN Module Configuration Register
- */
-#define CANMCR_MDIS            (0x80000000)
-#define CANMCR_FRZ             (0x40000000)
-#define CANMCR_HALT            (0x10000000)
-#define CANMCR_SOFTRST         (0x02000000)
-#define CANMCR_FRZACK          (0x01000000)
-#define CANMCR_SUPV            (0x00800000)
-#define CANMCR_MAXMB(x)         ((x)&0x0F)
-
-/*
- *      FlexCAN Control Register
- */
-#define CANCTRL_PRESDIV(x)      (((x)&0xFF)<<24)
-#define CANCTRL_RJW(x)          (((x)&0x03)<<22)
-#define CANCTRL_PSEG1(x)        (((x)&0x07)<<19)
-#define CANCTRL_PSEG2(x)        (((x)&0x07)<<16)
-#define CANCTRL_BOFFMSK         (0x00008000)
-#define CANCTRL_ERRMSK         (0x00004000)
-#define CANCTRL_CLKSRC         (0x00002000)
-#define CANCTRL_LPB            (0x00001000)
-#define CANCTRL_SAMP           (0x00000080)
-#define CANCTRL_BOFFREC         (0x00000040)
-#define CANCTRL_TSYNC           (0x00000020)
-#define CANCTRL_LBUF            (0x00000010)
-#define CANCTRL_LOM             (0x00000008)
-#define CANCTRL_PROPSEG(x)      ((x)&0x07)
-
-/*
- *      FlexCAN Error Counter Register
- */
-#define ERRCNT_RXECTR(x)        (((x)&0xFF)<<8)
-#define ERRCNT_TXECTR(x)        ((x)&0xFF)
-
-/*
- *      FlexCAN Error and Status Register
- */
-#define ERRSTAT_BITERR(x)       (((x)&0x03)<<14)
-#define ERRSTAT_ACKERR           (0x00002000)
-#define ERRSTAT_CRCERR           (0x00001000)
-#define ERRSTAT_FRMERR           (0x00000800)
-#define ERRSTAT_STFERR           (0x00000400)
-#define ERRSTAT_TXWRN            (0x00000200)
-#define ERRSTAT_RXWRN            (0x00000100)
-#define ERRSTAT_IDLE             (0x00000080)
-#define ERRSTAT_TXRX             (0x00000040)
-#define ERRSTAT_FLTCONF(x)       (((x)&0x03)<<4)
-#define ERRSTAT_BOFFINT          (0x00000004)
-#define ERRSTAT_ERRINT           (0x00000002)
-
 /*
- *      Interrupt Mask Register
- */
-#define IMASK_BUF15M           (0x8000)
-#define IMASK_BUF14M           (0x4000)
-#define IMASK_BUF13M           (0x2000)
-#define IMASK_BUF12M           (0x1000)
-#define IMASK_BUF11M           (0x0800)
-#define IMASK_BUF10M           (0x0400)
-#define IMASK_BUF9M            (0x0200)
-#define IMASK_BUF8M            (0x0100)
-#define IMASK_BUF7M            (0x0080)
-#define IMASK_BUF6M            (0x0040)
-#define IMASK_BUF5M            (0x0020)
-#define IMASK_BUF4M            (0x0010)
-#define IMASK_BUF3M            (0x0008)
-#define IMASK_BUF2M            (0x0004)
-#define IMASK_BUF1M            (0x0002)
-#define IMASK_BUF0M            (0x0001)
-#define IMASK_BUFnM(x)         (0x1<<(x))
-#define IMASK_BUFF_ENABLE_ALL  (0x1111)
-#define IMASK_BUFF_DISABLE_ALL (0x0000)
-
-/*
- *      Interrupt Flag Register
- */
-#define IFLAG_BUF15M           (0x8000)
-#define IFLAG_BUF14M           (0x4000)
-#define IFLAG_BUF13M           (0x2000)
-#define IFLAG_BUF12M           (0x1000)
-#define IFLAG_BUF11M           (0x0800)
-#define IFLAG_BUF10M           (0x0400)
-#define IFLAG_BUF9M            (0x0200)
-#define IFLAG_BUF8M            (0x0100)
-#define IFLAG_BUF7M            (0x0080)
-#define IFLAG_BUF6M            (0x0040)
-#define IFLAG_BUF5M            (0x0020)
-#define IFLAG_BUF4M            (0x0010)
-#define IFLAG_BUF3M            (0x0008)
-#define IFLAG_BUF2M            (0x0004)
-#define IFLAG_BUF1M            (0x0002)
-#define IFLAG_BUF0M            (0x0001)
-#define IFLAG_BUFF_SET_ALL     (0xFFFF)
-#define IFLAG_BUFF_CLEAR_ALL   (0x0000)
-#define IFLAG_BUFnM(x)         (0x1<<(x))
-
-/*
- *      Message Buffers
- */
-#define MB_CNT_CODE(x)         (((x)&0x0F)<<24)
-#define MB_CNT_SRR             (0x00400000)
-#define MB_CNT_IDE             (0x00200000)
-#define MB_CNT_RTR             (0x00100000)
-#define MB_CNT_LENGTH(x)       (((x)&0x0F)<<16)
-#define MB_CNT_TIMESTAMP(x)    ((x)&0xFFFF)
-#define MB_ID_STD(x)           (((x)&0x07FF)<<18)
-#define MB_ID_EXT(x)           ((x)&0x3FFFF)
-
-/*********************************************************************
- *
  * Edge Port Module (EPORT)
- *
- *********************************************************************/
-
-/* Register read/write macros */
+ */
 #define MCFEPORT_EPPAR                (0xFC094000)
 #define MCFEPORT_EPDDR                (0xFC094002)
 #define MCFEPORT_EPIER                (0xFC094003)
 #define MCFEPORT_EPPDR                (0xFC094005)
 #define MCFEPORT_EPFR                 (0xFC094006)
 
-/* Bit definitions and macros for MCF_EPORT_EPPAR */
-#define MCF_EPORT_EPPAR_EPPA1(x)       (((x)&0x0003)<<2)
-#define MCF_EPORT_EPPAR_EPPA2(x)       (((x)&0x0003)<<4)
-#define MCF_EPORT_EPPAR_EPPA3(x)       (((x)&0x0003)<<6)
-#define MCF_EPORT_EPPAR_EPPA4(x)       (((x)&0x0003)<<8)
-#define MCF_EPORT_EPPAR_EPPA5(x)       (((x)&0x0003)<<10)
-#define MCF_EPORT_EPPAR_EPPA6(x)       (((x)&0x0003)<<12)
-#define MCF_EPORT_EPPAR_EPPA7(x)       (((x)&0x0003)<<14)
-#define MCF_EPORT_EPPAR_LEVEL          (0)
-#define MCF_EPORT_EPPAR_RISING         (1)
-#define MCF_EPORT_EPPAR_FALLING        (2)
-#define MCF_EPORT_EPPAR_BOTH           (3)
-#define MCF_EPORT_EPPAR_EPPA7_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA7_RISING   (0x4000)
-#define MCF_EPORT_EPPAR_EPPA7_FALLING  (0x8000)
-#define MCF_EPORT_EPPAR_EPPA7_BOTH     (0xC000)
-#define MCF_EPORT_EPPAR_EPPA6_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA6_RISING   (0x1000)
-#define MCF_EPORT_EPPAR_EPPA6_FALLING  (0x2000)
-#define MCF_EPORT_EPPAR_EPPA6_BOTH     (0x3000)
-#define MCF_EPORT_EPPAR_EPPA5_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA5_RISING   (0x0400)
-#define MCF_EPORT_EPPAR_EPPA5_FALLING  (0x0800)
-#define MCF_EPORT_EPPAR_EPPA5_BOTH     (0x0C00)
-#define MCF_EPORT_EPPAR_EPPA4_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA4_RISING   (0x0100)
-#define MCF_EPORT_EPPAR_EPPA4_FALLING  (0x0200)
-#define MCF_EPORT_EPPAR_EPPA4_BOTH     (0x0300)
-#define MCF_EPORT_EPPAR_EPPA3_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA3_RISING   (0x0040)
-#define MCF_EPORT_EPPAR_EPPA3_FALLING  (0x0080)
-#define MCF_EPORT_EPPAR_EPPA3_BOTH     (0x00C0)
-#define MCF_EPORT_EPPAR_EPPA2_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA2_RISING   (0x0010)
-#define MCF_EPORT_EPPAR_EPPA2_FALLING  (0x0020)
-#define MCF_EPORT_EPPAR_EPPA2_BOTH     (0x0030)
-#define MCF_EPORT_EPPAR_EPPA1_LEVEL    (0x0000)
-#define MCF_EPORT_EPPAR_EPPA1_RISING   (0x0004)
-#define MCF_EPORT_EPPAR_EPPA1_FALLING  (0x0008)
-#define MCF_EPORT_EPPAR_EPPA1_BOTH     (0x000C)
-
-/* Bit definitions and macros for MCF_EPORT_EPDDR */
-#define MCF_EPORT_EPDDR_EPDD1          (0x02)
-#define MCF_EPORT_EPDDR_EPDD2          (0x04)
-#define MCF_EPORT_EPDDR_EPDD3          (0x08)
-#define MCF_EPORT_EPDDR_EPDD4          (0x10)
-#define MCF_EPORT_EPDDR_EPDD5          (0x20)
-#define MCF_EPORT_EPDDR_EPDD6          (0x40)
-#define MCF_EPORT_EPDDR_EPDD7          (0x80)
-
-/* Bit definitions and macros for MCF_EPORT_EPIER */
-#define MCF_EPORT_EPIER_EPIE1          (0x02)
-#define MCF_EPORT_EPIER_EPIE2          (0x04)
-#define MCF_EPORT_EPIER_EPIE3          (0x08)
-#define MCF_EPORT_EPIER_EPIE4          (0x10)
-#define MCF_EPORT_EPIER_EPIE5          (0x20)
-#define MCF_EPORT_EPIER_EPIE6          (0x40)
-#define MCF_EPORT_EPIER_EPIE7          (0x80)
-
-/* Bit definitions and macros for MCF_EPORT_EPDR */
-#define MCF_EPORT_EPDR_EPD1            (0x02)
-#define MCF_EPORT_EPDR_EPD2            (0x04)
-#define MCF_EPORT_EPDR_EPD3            (0x08)
-#define MCF_EPORT_EPDR_EPD4            (0x10)
-#define MCF_EPORT_EPDR_EPD5            (0x20)
-#define MCF_EPORT_EPDR_EPD6            (0x40)
-#define MCF_EPORT_EPDR_EPD7            (0x80)
-
-/* Bit definitions and macros for MCF_EPORT_EPPDR */
-#define MCF_EPORT_EPPDR_EPPD1          (0x02)
-#define MCF_EPORT_EPPDR_EPPD2          (0x04)
-#define MCF_EPORT_EPPDR_EPPD3          (0x08)
-#define MCF_EPORT_EPPDR_EPPD4          (0x10)
-#define MCF_EPORT_EPPDR_EPPD5          (0x20)
-#define MCF_EPORT_EPPDR_EPPD6          (0x40)
-#define MCF_EPORT_EPPDR_EPPD7          (0x80)
-
-/* Bit definitions and macros for MCF_EPORT_EPFR */
-#define MCF_EPORT_EPFR_EPF1            (0x02)
-#define MCF_EPORT_EPFR_EPF2            (0x04)
-#define MCF_EPORT_EPFR_EPF3            (0x08)
-#define MCF_EPORT_EPFR_EPF4            (0x10)
-#define MCF_EPORT_EPFR_EPF5            (0x20)
-#define MCF_EPORT_EPFR_EPF6            (0x40)
-#define MCF_EPORT_EPFR_EPF7            (0x80)
-
 /********************************************************************/
 #endif /* m532xsim_h */
index 79f58dd6a83da3d532d3687d139144999daf3801..a7550bc5cd1e46d8e4ca7cbe6bef3654bf77b354 100644 (file)
 /*
  *     Define the 5407 SIM register set addresses.
  */
-#define        MCFSIM_RSR              0x00            /* Reset Status reg (r/w) */
-#define        MCFSIM_SYPCR            0x01            /* System Protection reg (r/w)*/
-#define        MCFSIM_SWIVR            0x02            /* SW Watchdog intr reg (r/w) */
-#define        MCFSIM_SWSR             0x03            /* SW Watchdog service (r/w) */
-#define        MCFSIM_PAR              0x04            /* Pin Assignment reg (r/w) */
-#define        MCFSIM_IRQPAR           0x06            /* Interrupt Assignment reg (r/w) */
-#define        MCFSIM_PLLCR            0x08            /* PLL Control Reg*/
-#define        MCFSIM_MPARK            0x0C            /* BUS Master Control Reg*/
-#define        MCFSIM_IPR              0x40            /* Interrupt Pend reg (r/w) */
-#define        MCFSIM_IMR              0x44            /* Interrupt Mask reg (r/w) */
-#define        MCFSIM_AVR              0x4b            /* Autovector Ctrl reg (r/w) */
-#define        MCFSIM_ICR0             0x4c            /* Intr Ctrl reg 0 (r/w) */
-#define        MCFSIM_ICR1             0x4d            /* Intr Ctrl reg 1 (r/w) */
-#define        MCFSIM_ICR2             0x4e            /* Intr Ctrl reg 2 (r/w) */
-#define        MCFSIM_ICR3             0x4f            /* Intr Ctrl reg 3 (r/w) */
-#define        MCFSIM_ICR4             0x50            /* Intr Ctrl reg 4 (r/w) */
-#define        MCFSIM_ICR5             0x51            /* Intr Ctrl reg 5 (r/w) */
-#define        MCFSIM_ICR6             0x52            /* Intr Ctrl reg 6 (r/w) */
-#define        MCFSIM_ICR7             0x53            /* Intr Ctrl reg 7 (r/w) */
-#define        MCFSIM_ICR8             0x54            /* Intr Ctrl reg 8 (r/w) */
-#define        MCFSIM_ICR9             0x55            /* Intr Ctrl reg 9 (r/w) */
-#define        MCFSIM_ICR10            0x56            /* Intr Ctrl reg 10 (r/w) */
-#define        MCFSIM_ICR11            0x57            /* Intr Ctrl reg 11 (r/w) */
-
-#define MCFSIM_CSAR0           0x80            /* CS 0 Address 0 reg (r/w) */
-#define MCFSIM_CSMR0           0x84            /* CS 0 Mask 0 reg (r/w) */
-#define MCFSIM_CSCR0           0x8a            /* CS 0 Control reg (r/w) */
-#define MCFSIM_CSAR1           0x8c            /* CS 1 Address reg (r/w) */
-#define MCFSIM_CSMR1           0x90            /* CS 1 Mask reg (r/w) */
-#define MCFSIM_CSCR1           0x96            /* CS 1 Control reg (r/w) */
-
-#define MCFSIM_CSAR2           0x98            /* CS 2 Address reg (r/w) */
-#define MCFSIM_CSMR2           0x9c            /* CS 2 Mask reg (r/w) */
-#define MCFSIM_CSCR2           0xa2            /* CS 2 Control reg (r/w) */
-#define MCFSIM_CSAR3           0xa4            /* CS 3 Address reg (r/w) */
-#define MCFSIM_CSMR3           0xa8            /* CS 3 Mask reg (r/w) */
-#define MCFSIM_CSCR3           0xae            /* CS 3 Control reg (r/w) */
-#define MCFSIM_CSAR4           0xb0            /* CS 4 Address reg (r/w) */
-#define MCFSIM_CSMR4           0xb4            /* CS 4 Mask reg (r/w) */
-#define MCFSIM_CSCR4           0xba            /* CS 4 Control reg (r/w) */
-#define MCFSIM_CSAR5           0xbc            /* CS 5 Address reg (r/w) */
-#define MCFSIM_CSMR5           0xc0            /* CS 5 Mask reg (r/w) */
-#define MCFSIM_CSCR5           0xc6            /* CS 5 Control reg (r/w) */
-#define MCFSIM_CSAR6           0xc8            /* CS 6 Address reg (r/w) */
-#define MCFSIM_CSMR6           0xcc            /* CS 6 Mask reg (r/w) */
-#define MCFSIM_CSCR6           0xd2            /* CS 6 Control reg (r/w) */
-#define MCFSIM_CSAR7           0xd4            /* CS 7 Address reg (r/w) */
-#define MCFSIM_CSMR7           0xd8            /* CS 7 Mask reg (r/w) */
-#define MCFSIM_CSCR7           0xde            /* CS 7 Control reg (r/w) */
+#define        MCFSIM_RSR              (MCF_MBAR + 0x00)       /* Reset Status */
+#define        MCFSIM_SYPCR            (MCF_MBAR + 0x01)       /* System Protection */
+#define        MCFSIM_SWIVR            (MCF_MBAR + 0x02)       /* SW Watchdog intr */
+#define        MCFSIM_SWSR             (MCF_MBAR + 0x03)       /* SW Watchdog service*/
+#define        MCFSIM_PAR              (MCF_MBAR + 0x04)       /* Pin Assignment */
+#define        MCFSIM_IRQPAR           (MCF_MBAR + 0x06)       /* Intr Assignment */
+#define        MCFSIM_PLLCR            (MCF_MBAR + 0x08)       /* PLL Ctrl */
+#define        MCFSIM_MPARK            (MCF_MBAR + 0x0C)       /* BUS Master Ctrl */
+#define        MCFSIM_IPR              (MCF_MBAR + 0x40)       /* Interrupt Pending */
+#define        MCFSIM_IMR              (MCF_MBAR + 0x44)       /* Interrupt Mask */
+#define        MCFSIM_AVR              (MCF_MBAR + 0x4b)       /* Autovector Ctrl */
+#define        MCFSIM_ICR0             (MCF_MBAR + 0x4c)       /* Intr Ctrl reg 0 */
+#define        MCFSIM_ICR1             (MCF_MBAR + 0x4d)       /* Intr Ctrl reg 1 */
+#define        MCFSIM_ICR2             (MCF_MBAR + 0x4e)       /* Intr Ctrl reg 2 */
+#define        MCFSIM_ICR3             (MCF_MBAR + 0x4f)       /* Intr Ctrl reg 3 */
+#define        MCFSIM_ICR4             (MCF_MBAR + 0x50)       /* Intr Ctrl reg 4 */
+#define        MCFSIM_ICR5             (MCF_MBAR + 0x51)       /* Intr Ctrl reg 5 */
+#define        MCFSIM_ICR6             (MCF_MBAR + 0x52)       /* Intr Ctrl reg 6 */
+#define        MCFSIM_ICR7             (MCF_MBAR + 0x53)       /* Intr Ctrl reg 7 */
+#define        MCFSIM_ICR8             (MCF_MBAR + 0x54)       /* Intr Ctrl reg 8 */
+#define        MCFSIM_ICR9             (MCF_MBAR + 0x55)       /* Intr Ctrl reg 9 */
+#define        MCFSIM_ICR10            (MCF_MBAR + 0x56)       /* Intr Ctrl reg 10 */
+#define        MCFSIM_ICR11            (MCF_MBAR + 0x57)       /* Intr Ctrl reg 11 */
+
+#define MCFSIM_CSAR0           (MCF_MBAR + 0x80)       /* CS 0 Address reg */
+#define MCFSIM_CSMR0           (MCF_MBAR + 0x84)       /* CS 0 Mask reg */
+#define MCFSIM_CSCR0           (MCF_MBAR + 0x8a)       /* CS 0 Control reg */
+#define MCFSIM_CSAR1           (MCF_MBAR + 0x8c)       /* CS 1 Address reg */
+#define MCFSIM_CSMR1           (MCF_MBAR + 0x90)       /* CS 1 Mask reg */
+#define MCFSIM_CSCR1           (MCF_MBAR + 0x96)       /* CS 1 Control reg */
+
+#define MCFSIM_CSAR2           (MCF_MBAR + 0x98)       /* CS 2 Address reg */
+#define MCFSIM_CSMR2           (MCF_MBAR + 0x9c)       /* CS 2 Mask reg */
+#define MCFSIM_CSCR2           (MCF_MBAR + 0xa2)       /* CS 2 Control reg */
+#define MCFSIM_CSAR3           (MCF_MBAR + 0xa4)       /* CS 3 Address reg */
+#define MCFSIM_CSMR3           (MCF_MBAR + 0xa8)       /* CS 3 Mask reg */
+#define MCFSIM_CSCR3           (MCF_MBAR + 0xae)       /* CS 3 Control reg */
+#define MCFSIM_CSAR4           (MCF_MBAR + 0xb0)       /* CS 4 Address reg */
+#define MCFSIM_CSMR4           (MCF_MBAR + 0xb4)       /* CS 4 Mask reg */
+#define MCFSIM_CSCR4           (MCF_MBAR + 0xba)       /* CS 4 Control reg */
+#define MCFSIM_CSAR5           (MCF_MBAR + 0xbc)       /* CS 5 Address reg */
+#define MCFSIM_CSMR5           (MCF_MBAR + 0xc0)       /* CS 5 Mask reg */
+#define MCFSIM_CSCR5           (MCF_MBAR + 0xc6)       /* CS 5 Control reg */
+#define MCFSIM_CSAR6           (MCF_MBAR + 0xc8)       /* CS 6 Address reg */
+#define MCFSIM_CSMR6           (MCF_MBAR + 0xcc)       /* CS 6 Mask reg */
+#define MCFSIM_CSCR6           (MCF_MBAR + 0xd2)       /* CS 6 Control reg */
+#define MCFSIM_CSAR7           (MCF_MBAR + 0xd4)       /* CS 7 Address reg */
+#define MCFSIM_CSMR7           (MCF_MBAR + 0xd8)       /* CS 7 Mask reg */
+#define MCFSIM_CSCR7           (MCF_MBAR + 0xde)       /* CS 7 Control reg */
 
 #define MCFSIM_DCR             (MCF_MBAR + 0x100)      /* DRAM Control */
 #define MCFSIM_DACR0           (MCF_MBAR + 0x108)      /* DRAM 0 Addr/Ctrl */
 /*
  * Generic GPIO support
  */
-#define MCFGPIO_PIN_MAX                        16
-#define MCFGPIO_IRQ_MAX                        -1
-#define MCFGPIO_IRQ_VECBASE            -1
+#define MCFGPIO_PIN_MAX                16
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
 
 /*
  *     Some symbol defines for the above...
 /*
  *       Defines for the IRQPAR Register
  */
-#define IRQ5_LEVEL4    0x80
-#define IRQ3_LEVEL6    0x40
-#define IRQ1_LEVEL2    0x20
+#define IRQ5_LEVEL4            0x80
+#define IRQ3_LEVEL6            0x40
+#define IRQ1_LEVEL2            0x20
 
 /*
  *     Define system peripheral IRQ usage.
index df75dd87ae7ac7de805a0d2b56a9a945b5285892..0b69cd1ed0edc3af48077b5f395dddba810e9634 100644 (file)
 *********************************************************************/
 
 /* Register read/write macros */
-#define MCF_GPT_GMS0       0x000800
-#define MCF_GPT_GCIR0      0x000804
-#define MCF_GPT_GPWM0      0x000808
-#define MCF_GPT_GSR0       0x00080C
-#define MCF_GPT_GMS1       0x000810
-#define MCF_GPT_GCIR1      0x000814
-#define MCF_GPT_GPWM1      0x000818
-#define MCF_GPT_GSR1       0x00081C
-#define MCF_GPT_GMS2       0x000820
-#define MCF_GPT_GCIR2      0x000824
-#define MCF_GPT_GPWM2      0x000828
-#define MCF_GPT_GSR2       0x00082C
-#define MCF_GPT_GMS3       0x000830
-#define MCF_GPT_GCIR3      0x000834
-#define MCF_GPT_GPWM3      0x000838
-#define MCF_GPT_GSR3       0x00083C
-#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
-#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
-#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
-#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
+#define MCF_GPT_GMS0       (MCF_MBAR + 0x000800)
+#define MCF_GPT_GCIR0      (MCF_MBAR + 0x000804)
+#define MCF_GPT_GPWM0      (MCF_MBAR + 0x000808)
+#define MCF_GPT_GSR0       (MCF_MBAR + 0x00080C)
+#define MCF_GPT_GMS1       (MCF_MBAR + 0x000810)
+#define MCF_GPT_GCIR1      (MCF_MBAR + 0x000814)
+#define MCF_GPT_GPWM1      (MCF_MBAR + 0x000818)
+#define MCF_GPT_GSR1       (MCF_MBAR + 0x00081C)
+#define MCF_GPT_GMS2       (MCF_MBAR + 0x000820)
+#define MCF_GPT_GCIR2      (MCF_MBAR + 0x000824)
+#define MCF_GPT_GPWM2      (MCF_MBAR + 0x000828)
+#define MCF_GPT_GSR2       (MCF_MBAR + 0x00082C)
+#define MCF_GPT_GMS3       (MCF_MBAR + 0x000830)
+#define MCF_GPT_GCIR3      (MCF_MBAR + 0x000834)
+#define MCF_GPT_GPWM3      (MCF_MBAR + 0x000838)
+#define MCF_GPT_GSR3       (MCF_MBAR + 0x00083C)
+#define MCF_GPT_GMS(x)     (MCF_MBAR + 0x000800 + ((x) * 0x010))
+#define MCF_GPT_GCIR(x)    (MCF_MBAR + 0x000804 + ((x) * 0x010))
+#define MCF_GPT_GPWM(x)    (MCF_MBAR + 0x000808 + ((x) * 0x010))
+#define MCF_GPT_GSR(x)     (MCF_MBAR + 0x00080C + ((x) * 0x010))
 
 /* Bit definitions and macros for MCF_GPT_GMS */
 #define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
index d3c5e0dbdadf7359b3d5539e8ea1ce5282b624db..d3bd83887429b77e19c0a38e7556bab826dfd0e6 100644 (file)
 #define MCF_IRQ_UART2          (MCFINT_VECBASE + 33)
 #define MCF_IRQ_UART3          (MCFINT_VECBASE + 32)
 
+/*
+ *     Slice Timer support.
+ */
+#define MCFSLT_TIMER0          (MCF_MBAR + 0x900)      /* Base addr TIMER0 */
+#define MCFSLT_TIMER1          (MCF_MBAR + 0x910)      /* Base addr TIMER1 */
+
 /*
  *     Generic GPIO support
  */
 #define        MCFEPORT_EPFR           (MCF_MBAR + 0xf0c)      /* Flags */
 
 /*
- *     Some PSC related definitions
+ *     Pin Assignment register definitions
  */
-#define MCF_PAR_PSC(x)         (0x000A4F-((x)&0x3))
+#define MCFGPIO_PAR_FBCTL      (MCF_MBAR + 0xA40)
+#define MCFGPIO_PAR_FBCS       (MCF_MBAR + 0xA42)
+#define MCFGPIO_PAR_DMA                (MCF_MBAR + 0xA43)
+#define MCFGPIO_PAR_FECI2CIRQ  (MCF_MBAR + 0xA44)
+#define MCFGPIO_PAR_PCIBG      (MCF_MBAR + 0xA48)      /* PCI bus grant */
+#define MCFGPIO_PAR_PCIBR      (MCF_MBAR + 0xA4A)      /* PCI */
+#define MCFGPIO_PAR_PSC0       (MCF_MBAR + 0xA4F)
+#define MCFGPIO_PAR_PSC1       (MCF_MBAR + 0xA4E)
+#define MCFGPIO_PAR_PSC2       (MCF_MBAR + 0xA4D)
+#define MCFGPIO_PAR_PSC3       (MCF_MBAR + 0xA4C)
+#define MCFGPIO_PAR_DSPI       (MCF_MBAR + 0xA50)
+#define MCFGPIO_PAR_TIMER      (MCF_MBAR + 0xA52)
+
 #define MCF_PAR_SDA            (0x0008)
 #define MCF_PAR_SCL            (0x0004)
 #define MCF_PAR_PSC_TXD                (0x04)
 #define MCF_PAR_PSC_RXD                (0x08)
-#define MCF_PAR_PSC_RTS(x)     (((x)&0x03)<<4)
-#define MCF_PAR_PSC_CTS(x)     (((x)&0x03)<<6)
 #define MCF_PAR_PSC_CTS_GPIO   (0x00)
 #define MCF_PAR_PSC_CTS_BCLK   (0x80)
 #define MCF_PAR_PSC_CTS_CTS    (0xC0)
@@ -81,7 +97,4 @@
 #define MCF_PAR_PSC_RTS_RTS    (0x30)
 #define MCF_PAR_PSC_CANRX      (0x40)
 
-#define MCF_PAR_PCIBG          (CONFIG_MBAR + 0xa48)   /* PCI bus grant */
-#define MCF_PAR_PCIBR          (CONFIG_MBAR + 0xa4a)   /* PCI */
-
 #endif /* m54xxsim_h */
index d0d0ecba533307c91608d70dcbc2ba5acc8d6755..c2314b6f8caa82b3135bfda004fd6ea016ed3d39 100644 (file)
 #define mcfslt_h
 /****************************************************************************/
 
-/*
- *     Get address specific defines for the 547x.
- */
-#define MCFSLT_TIMER0          0x900   /* Base address of TIMER0 */
-#define MCFSLT_TIMER1          0x910   /* Base address of TIMER1 */
-
-
 /*
  *     Define the SLT timer register set addresses.
  */
index 4dec2d9fb99442e3752a21f6da4f9b25255f9024..2a7a7667d8074f02323bc113100557b559763289 100644 (file)
@@ -21,6 +21,7 @@
 #ifdef CONFIG_COLDFIRE
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
+#include <asm/io.h>
 #endif
 
 /*---------------------------------------------------------------------------*/
@@ -86,16 +87,12 @@ static __inline__ void mcf_setppdata(unsigned int mask, unsigned int bits)
  */
 static __inline__ unsigned int mcf_getppdata(void)
 {
-       volatile unsigned short *pp;
-       pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PBDAT);
-       return((unsigned int) *pp);
+       return readw(MCFSIM_PBDAT);
 }
 
 static __inline__ void mcf_setppdata(unsigned int mask, unsigned int bits)
 {
-       volatile unsigned short *pp;
-       pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PBDAT);
-       *pp = (*pp & ~mask) | bits;
+       write((readw(MCFSIM_PBDAT) & ~mask) | bits, MCFSIM_PBDAT);
 }
 #endif
 
index a49d75e654899a1adb229fb275290943ad0b3b94..816674164682bb9a794cf26f5222f23136c5c672 100644 (file)
@@ -1,11 +1,5 @@
 #
-# Makefile for arch/m68knommu/platform/68VZ328.
+# Makefile for arch/m68k/platform/68VZ328.
 #
 
 obj-y          := config.o
-extra-$(DRAGEN2):= screen.h
-
-$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
-       perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
-
-clean-files := $(obj)/screen.h
index 81f0fb5e51cf441f9936511194c63d182fa1c941..71ea4c02795d45438727059b708731b0babbf220 100644 (file)
@@ -347,12 +347,12 @@ static void __init mcf_uart_set_irq(void)
 {
 #ifdef MCFUART_UIVR
        /* UART0 interrupt setup */
-       writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+       writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCFSIM_UART1ICR);
        writeb(MCF_IRQ_UART0, MCFUART_BASE0 + MCFUART_UIVR);
        mcf_mapirq2imr(MCF_IRQ_UART0, MCFINTC_UART0);
 
        /* UART1 interrupt setup */
-       writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+       writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCFSIM_UART2ICR);
        writeb(MCF_IRQ_UART1, MCFUART_BASE1 + MCFUART_UIVR);
        mcf_mapirq2imr(MCF_IRQ_UART1, MCFINTC_UART1);
 #endif
index b88f5716f357b7acecc2e38a2f1bed8676ced43e..fa31be297b85acf1ba31ca4059f2f48825c91d87 100644 (file)
@@ -60,7 +60,7 @@
 
 #elif defined(CONFIG_M5272)
 .macro GET_MEM_SIZE
-       movel   MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */
+       movel   MCFSIM_CSOR7,%d0        /* get SDRAM address mask */
        andil   #0xfffff000,%d0         /* mask out chip select options */
        negl    %d0                     /* negate bits */
 .endm
index f343bf7bf5b0a090d7423a07d6ec7c367aa156a7..0864b836699af77301bb1b58cd99deab0a3eb523 100644 (file)
 static void intc2_irq_gpio_mask(struct irq_data *d)
 {
        u32 imr;
-       imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+       imr = readl(MCFSIM2_GPIOINTENABLE);
        imr &= ~(0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
-       writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+       writel(imr, MCFSIM2_GPIOINTENABLE);
 }
 
 static void intc2_irq_gpio_unmask(struct irq_data *d)
 {
        u32 imr;
-       imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+       imr = readl(MCFSIM2_GPIOINTENABLE);
        imr |= (0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
-       writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+       writel(imr, MCFSIM2_GPIOINTENABLE);
 }
 
 static void intc2_irq_gpio_ack(struct irq_data *d)
 {
-       writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
+       writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCFSIM2_GPIOINTCLEAR);
 }
 
 static struct irq_chip intc2_irq_gpio_chip = {
index 7160e618b0a96ab64cba71e2eec3fc84b20cff3b..d7b695629a7e3e2014a38189bf71d7bc403bcc1e 100644 (file)
@@ -86,7 +86,7 @@ static void intc_irq_mask(struct irq_data *d)
                u32 v;
                irq -= MCFINT_VECBASE;
                v = 0x8 << intc_irqmap[irq].index;
-               writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+               writel(v, intc_irqmap[irq].icr);
        }
 }
 
@@ -98,7 +98,7 @@ static void intc_irq_unmask(struct irq_data *d)
                u32 v;
                irq -= MCFINT_VECBASE;
                v = 0xd << intc_irqmap[irq].index;
-               writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+               writel(v, intc_irqmap[irq].icr);
        }
 }
 
@@ -111,10 +111,10 @@ static void intc_irq_ack(struct irq_data *d)
                irq -= MCFINT_VECBASE;
                if (intc_irqmap[irq].ack) {
                        u32 v;
-                       v = readl(MCF_MBAR + intc_irqmap[irq].icr);
+                       v = readl(intc_irqmap[irq].icr);
                        v &= (0x7 << intc_irqmap[irq].index);
                        v |= (0x8 << intc_irqmap[irq].index);
-                       writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+                       writel(v, intc_irqmap[irq].icr);
                }
        }
 }
@@ -127,12 +127,12 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
                irq -= MCFINT_VECBASE;
                if (intc_irqmap[irq].ack) {
                        u32 v;
-                       v = readl(MCF_MBAR + MCFSIM_PITR);
+                       v = readl(MCFSIM_PITR);
                        if (type == IRQ_TYPE_EDGE_FALLING)
                                v &= ~(0x1 << (32 - irq));
                        else
                                v |= (0x1 << (32 - irq));
-                       writel(v, MCF_MBAR + MCFSIM_PITR);
+                       writel(v, MCFSIM_PITR);
                }
        }
        return 0;
@@ -163,10 +163,10 @@ void __init init_IRQ(void)
        int irq, edge;
 
        /* Mask all interrupt sources */
-       writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
-       writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
-       writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
-       writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
+       writel(0x88888888, MCFSIM_ICR1);
+       writel(0x88888888, MCFSIM_ICR2);
+       writel(0x88888888, MCFSIM_ICR3);
+       writel(0x88888888, MCFSIM_ICR4);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
                irq_set_chip(irq, &intc_irq_chip);
index 5c0c150b40671c7b5af644fa176493574b6958b5..cce2574203885412b9c5f742405928f74fb0ae3b 100644 (file)
@@ -45,23 +45,23 @@ unsigned char mcf_irq2imr[NR_IRQS];
 void mcf_setimr(int index)
 {
        u16 imr;
-       imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
-       __raw_writew(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readw(MCFSIM_IMR);
+       __raw_writew(imr | (0x1 << index), MCFSIM_IMR);
 }
 
 void mcf_clrimr(int index)
 {
        u16 imr;
-       imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
-       __raw_writew(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readw(MCFSIM_IMR);
+       __raw_writew(imr & ~(0x1 << index), MCFSIM_IMR);
 }
 
 void mcf_maskimr(unsigned int mask)
 {
        u16 imr;
-       imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readw(MCFSIM_IMR);
        imr |= mask;
-       __raw_writew(imr, MCF_MBAR + MCFSIM_IMR);
+       __raw_writew(imr, MCFSIM_IMR);
 }
 
 #else
@@ -69,23 +69,23 @@ void mcf_maskimr(unsigned int mask)
 void mcf_setimr(int index)
 {
        u32 imr;
-       imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
-       __raw_writel(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readl(MCFSIM_IMR);
+       __raw_writel(imr | (0x1 << index), MCFSIM_IMR);
 }
 
 void mcf_clrimr(int index)
 {
        u32 imr;
-       imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
-       __raw_writel(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readl(MCFSIM_IMR);
+       __raw_writel(imr & ~(0x1 << index), MCFSIM_IMR);
 }
 
 void mcf_maskimr(unsigned int mask)
 {
        u32 imr;
-       imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+       imr = __raw_readl(MCFSIM_IMR);
        imr |= mask;
-       __raw_writel(imr, MCF_MBAR + MCFSIM_IMR);
+       __raw_writel(imr, MCFSIM_IMR);
 }
 
 #endif
@@ -104,9 +104,9 @@ void mcf_autovector(int irq)
 #ifdef MCFSIM_AVR
        if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
                u8 avec;
-               avec = __raw_readb(MCF_MBAR + MCFSIM_AVR);
+               avec = __raw_readb(MCFSIM_AVR);
                avec |= (0x1 << (irq - EIRQ1 + 1));
-               __raw_writeb(avec, MCF_MBAR + MCFSIM_AVR);
+               __raw_writeb(avec, MCFSIM_AVR);
        }
 #endif
 }
index d47dfd8f50a2dbfb292933de84f6b764931153c9..ff37fe9553eab8f57eba0f4e375b98daa9173d3a 100644 (file)
@@ -42,14 +42,8 @@ static void __init m523x_qspi_init(void)
 
 static void __init m523x_fec_init(void)
 {
-       u16 par;
-       u8 v;
-
        /* Set multi-function pins to ethernet use */
-       par = readw(MCF_IPSBAR + 0x100082);
-       writew(par | 0xf00, MCF_IPSBAR + 0x100082);
-       v = readb(MCF_IPSBAR + 0x100078);
-       writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
+       writeb(readb(MCFGPIO_PAR_FECI2C) | 0xf0, MCFGPIO_PAR_FECI2C);
 }
 
 /***************************************************************************/
index 300e729a58d0fa2ed0a31b190f1837f43a6ac8c3..23b19cb7ab502ca00925ecea3843a5a3b6870ffe 100644 (file)
@@ -57,7 +57,7 @@ static void __init m5249_qspi_init(void)
 {
        /* QSPI irq setup */
        writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI0,
-              MCF_MBAR + MCFSIM_QSPIICR);
+              MCFSIM_QSPIICR);
        mcf_mapirq2imr(MCF_IRQ_QSPI, MCFINTC_QSPI);
 }
 
@@ -72,11 +72,11 @@ static void __init m5249_smc91x_init(void)
        u32  gpio;
 
        /* Set the GPIO line as interrupt source for smc91x device */
-       gpio = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-       writel(gpio | 0x40, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+       gpio = readl(MCFSIM2_GPIOINTENABLE);
+       writel(gpio | 0x40, MCFSIM2_GPIOINTENABLE);
 
-       gpio = readl(MCF_MBAR2 + MCFSIM2_INTLEVEL5);
-       writel(gpio | 0x04000000, MCF_MBAR2 + MCFSIM2_INTLEVEL5);
+       gpio = readl(MCFSIM2_INTLEVEL5);
+       writel(gpio | 0x04000000, MCFSIM2_INTLEVEL5);
 }
 
 #endif /* CONFIG_M5249C3 */
index 8ce905f9b84fbb4e0de1770c44f89c821f7f6929..fce8f8a45bf0eb6bf739461114942474c632cc5a 100644 (file)
@@ -30,7 +30,7 @@ static void __init m525x_qspi_init(void)
 
        /* QSPI irq setup */
        writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI0,
-              MCF_MBAR + MCFSIM_QSPIICR);
+              MCFSIM_QSPIICR);
        mcf_mapirq2imr(MCF_IRQ_QSPI, MCFINTC_QSPI);
 #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
 }
@@ -42,7 +42,7 @@ static void __init m525x_i2c_init(void)
 
        /* first I2C controller uses regular irq setup */
        writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
-                       MCF_MBAR + MCFSIM_I2CICR);
+               MCFSIM_I2CICR);
        mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
 
        /* second I2C controller is completely different */
index e68bc7a148eb1b15f3b511fbfaf1e94bbc9eca77..45b246d052efb2e1ef74d8d4d43cedea8644abdc 100644 (file)
@@ -35,13 +35,13 @@ static void __init m5272_uarts_init(void)
        u32 v;
 
        /* Enable the output lines for the serial ports */
-       v = readl(MCF_MBAR + MCFSIM_PBCNT);
+       v = readl(MCFSIM_PBCNT);
        v = (v & ~0x000000ff) | 0x00000055;
-       writel(v, MCF_MBAR + MCFSIM_PBCNT);
+       writel(v, MCFSIM_PBCNT);
 
-       v = readl(MCF_MBAR + MCFSIM_PDCNT);
+       v = readl(MCFSIM_PDCNT);
        v = (v & ~0x000003fc) | 0x000002a8;
-       writel(v, MCF_MBAR + MCFSIM_PDCNT);
+       writel(v, MCFSIM_PDCNT);
 }
 
 /***************************************************************************/
@@ -50,9 +50,9 @@ static void m5272_cpu_reset(void)
 {
        local_irq_disable();
        /* Set watchdog to reset, and enabled */
-       __raw_writew(0, MCF_MBAR + MCFSIM_WIRR);
-       __raw_writew(1, MCF_MBAR + MCFSIM_WRRR);
-       __raw_writew(0, MCF_MBAR + MCFSIM_WCR);
+       __raw_writew(0, MCFSIM_WIRR);
+       __raw_writew(1, MCFSIM_WRRR);
+       __raw_writew(0, MCFSIM_WCR);
        for (;;)
                /* wait for watchdog to timeout */;
 }
@@ -62,11 +62,8 @@ static void m5272_cpu_reset(void)
 void __init config_BSP(char *commandp, int size)
 {
 #if defined (CONFIG_MOD5272)
-       volatile unsigned char  *pivrp;
-
        /* Set base of device vectors to be 64 */
-       pivrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_PIVR);
-       *pivrp = 0x40;
+       writeb(0x40, MCFSIM_PIVR);
 #endif
 
 #if defined(CONFIG_NETtel) || defined(CONFIG_SCALES)
index b3cb378c5e942012a07a81fb3837ddfac7acbaa1..1431ba03c602d9b20471dab1f65edd3cac528e22 100644 (file)
@@ -53,9 +53,9 @@ static void __init m527x_uarts_init(void)
        /*
         * External Pin Mask Setting & Enable External Pin for Interface
         */
-       sepmask = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+       sepmask = readw(MCFGPIO_PAR_UART);
        sepmask |= UART0_ENABLE_MASK | UART1_ENABLE_MASK | UART2_ENABLE_MASK;
-       writew(sepmask, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+       writew(sepmask, MCFGPIO_PAR_UART);
 }
 
 /***************************************************************************/
@@ -67,19 +67,19 @@ static void __init m527x_fec_init(void)
 
        /* Set multi-function pins to ethernet mode for fec0 */
 #if defined(CONFIG_M5271)
-       v = readb(MCF_IPSBAR + 0x100047);
-       writeb(v | 0xf0, MCF_IPSBAR + 0x100047);
+       v = readb(MCFGPIO_PAR_FECI2C);
+       writeb(v | 0xf0, MCFGPIO_PAR_FECI2C);
 #else
-       par = readw(MCF_IPSBAR + 0x100082);
-       writew(par | 0xf00, MCF_IPSBAR + 0x100082);
-       v = readb(MCF_IPSBAR + 0x100078);
-       writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
+       par = readw(MCFGPIO_PAR_FECI2C);
+       writew(par | 0xf00, MCFGPIO_PAR_FECI2C);
+       v = readb(MCFGPIO_PAR_FEC0HL);
+       writeb(v | 0xc0, MCFGPIO_PAR_FEC0HL);
 
        /* Set multi-function pins to ethernet mode for fec1 */
-       par = readw(MCF_IPSBAR + 0x100082);
-       writew(par | 0xa0, MCF_IPSBAR + 0x100082);
-       v = readb(MCF_IPSBAR + 0x100079);
-       writeb(v | 0xc0, MCF_IPSBAR + 0x100079);
+       par = readw(MCFGPIO_PAR_FECI2C);
+       writew(par | 0xa0, MCFGPIO_PAR_FECI2C);
+       v = readb(MCFGPIO_PAR_FEC1HL);
+       writeb(v | 0xc0, MCFGPIO_PAR_FEC1HL);
 #endif
 }
 
index f1319e5d25461cb1b90aceadcd1162fafe5e0b55..f9f7e6a13d049977f22d6357ef246bcc6d6b8a3b 100644 (file)
@@ -53,9 +53,9 @@ static void __init m528x_fec_init(void)
        u16 v16;
 
        /* Set multi-function pins to ethernet mode for fec0 */
-       v16 = readw(MCF_IPSBAR + 0x100056);
-       writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
-       writeb(0xc0, MCF_IPSBAR + 0x100058);
+       v16 = readw(MCFGPIO_PASPAR);
+       writew(v16 | 0xf00, MCFGPIO_PASPAR);
+       writeb(0xc0, MCFGPIO_PEHLPAR);
 }
 
 /***************************************************************************/
index 4819a44991edcbf5172dd0f9d361ae15e442a6c2..7951d1d43357a16ac953b584f71c5c7efd6bd526 100644 (file)
@@ -172,7 +172,7 @@ static void __init m532x_clk_init(void)
 static void __init m532x_qspi_init(void)
 {
        /* setup QSPS pins for QSPI with gpio CS control */
-       writew(0x01f0, MCF_GPIO_PAR_QSPI);
+       writew(0x01f0, MCFGPIO_PAR_QSPI);
 }
 
 #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
@@ -182,18 +182,24 @@ static void __init m532x_qspi_init(void)
 static void __init m532x_uarts_init(void)
 {
        /* UART GPIO initialization */
-       MCF_GPIO_PAR_UART |= 0x0FFF;
+       writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
 }
 
 /***************************************************************************/
 
 static void __init m532x_fec_init(void)
 {
+       u8 v;
+
        /* Set multi-function pins to ethernet mode for fec0 */
-       MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
-               MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
-       MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
-               MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
+       v = readb(MCFGPIO_PAR_FECI2C);
+       v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
+               MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
+       writeb(v, MCFGPIO_PAR_FECI2C);
+
+       v = readb(MCFGPIO_PAR_FEC);
+       v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
+       writeb(v, MCFGPIO_PAR_FEC);
 }
 
 /***************************************************************************/
@@ -298,7 +304,7 @@ asmlinkage void __init sysinit(void)
 void wtm_init(void)
 {
        /* Disable watchdog timer */
-       MCF_WTM_WCR = 0;
+       writew(0, MCF_WTM_WCR);
 }
 
 #define MCF_SCM_BCR_GBW                (0x00000100)
@@ -307,53 +313,53 @@ void wtm_init(void)
 void scm_init(void)
 {
        /* All masters are trusted */
-       MCF_SCM_MPR = 0x77777777;
+       writel(0x77777777, MCF_SCM_MPR);
     
        /* Allow supervisor/user, read/write, and trusted/untrusted
           access to all slaves */
-       MCF_SCM_PACRA = 0;
-       MCF_SCM_PACRB = 0;
-       MCF_SCM_PACRC = 0;
-       MCF_SCM_PACRD = 0;
-       MCF_SCM_PACRE = 0;
-       MCF_SCM_PACRF = 0;
+       writel(0, MCF_SCM_PACRA);
+       writel(0, MCF_SCM_PACRB);
+       writel(0, MCF_SCM_PACRC);
+       writel(0, MCF_SCM_PACRD);
+       writel(0, MCF_SCM_PACRE);
+       writel(0, MCF_SCM_PACRF);
 
        /* Enable bursts */
-       MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
+       writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
 }
 
 
 void fbcs_init(void)
 {
-       MCF_GPIO_PAR_CS = 0x0000003E;
+       writeb(0x3E, MCFGPIO_PAR_CS);
 
        /* Latch chip select */
-       MCF_FBCS1_CSAR = 0x10080000;
+       writel(0x10080000, MCF_FBCS1_CSAR);
 
-       MCF_FBCS1_CSCR = 0x002A3780;
-       MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
+       writel(0x002A3780, MCF_FBCS1_CSCR);
+       writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 
        /* Initialize latch to drive signals to inactive states */
-       *((u16 *)(0x10080000)) = 0xFFFF;
+       writew(0xffff, 0x10080000);
 
        /* External SRAM */
-       MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
-       MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
-                       | MCF_FBCS_CSCR_AA
-                       | MCF_FBCS_CSCR_SBM
-                       | MCF_FBCS_CSCR_WS(1));
-       MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
-                       | MCF_FBCS_CSMR_V);
+       writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
+       writel(MCF_FBCS_CSCR_PS_16 |
+               MCF_FBCS_CSCR_AA |
+               MCF_FBCS_CSCR_SBM |
+               MCF_FBCS_CSCR_WS(1),
+               MCF_FBCS1_CSCR);
+       writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
 
        /* Boot Flash connected to FBCS0 */
-       MCF_FBCS0_CSAR = FLASH_ADDRESS;
-       MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
-                       | MCF_FBCS_CSCR_BEM
-                       | MCF_FBCS_CSCR_AA
-                       | MCF_FBCS_CSCR_SBM
-                       | MCF_FBCS_CSCR_WS(7));
-       MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
-                       | MCF_FBCS_CSMR_V);
+       writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
+       writel(MCF_FBCS_CSCR_PS_16 |
+               MCF_FBCS_CSCR_BEM |
+               MCF_FBCS_CSCR_AA |
+               MCF_FBCS_CSCR_SBM |
+               MCF_FBCS_CSCR_WS(7),
+               MCF_FBCS0_CSCR);
+       writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
 }
 
 void sdramc_init(void)
@@ -362,102 +368,102 @@ void sdramc_init(void)
         * Check to see if the SDRAM has already been initialized
         * by a run control tool
         */
-       if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
+       if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
                /* SDRAM chip select initialization */
                
                /* Initialize SDRAM chip select */
-               MCF_SDRAMC_SDCS0 = (0
-                       | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
-                       | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
+               writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
+                       MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
+                       MCF_SDRAMC_SDCS0);
 
        /*
         * Basic configuration and initialization
         */
-       MCF_SDRAMC_SDCFG1 = (0
-               | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
-               | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
-               | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
-               | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
-               | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
-               | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
-               | MCF_SDRAMC_SDCFG1_WTLAT(3));
-       MCF_SDRAMC_SDCFG2 = (0
-               | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
-               | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
-               | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
-               | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
+       writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
+               MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
+               MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
+               MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
+               MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
+               MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
+               MCF_SDRAMC_SDCFG1_WTLAT(3),
+               MCF_SDRAMC_SDCFG1);
+       writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
+               MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
+               MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
+               MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
+               MCF_SDRAMC_SDCFG2);
 
             
        /*
         * Precharge and enable write to SDMR
         */
-        MCF_SDRAMC_SDCR = (0
-               | MCF_SDRAMC_SDCR_MODE_EN
-               | MCF_SDRAMC_SDCR_CKE
-               | MCF_SDRAMC_SDCR_DDR
-               | MCF_SDRAMC_SDCR_MUX(1)
-               | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
-               | MCF_SDRAMC_SDCR_PS_16
-               | MCF_SDRAMC_SDCR_IPALL);            
+       writel(MCF_SDRAMC_SDCR_MODE_EN |
+               MCF_SDRAMC_SDCR_CKE |
+               MCF_SDRAMC_SDCR_DDR |
+               MCF_SDRAMC_SDCR_MUX(1) |
+               MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
+               MCF_SDRAMC_SDCR_PS_16 |
+               MCF_SDRAMC_SDCR_IPALL,
+               MCF_SDRAMC_SDCR);
 
        /*
         * Write extended mode register
         */
-       MCF_SDRAMC_SDMR = (0
-               | MCF_SDRAMC_SDMR_BNKAD_LEMR
-               | MCF_SDRAMC_SDMR_AD(0x0)
-               | MCF_SDRAMC_SDMR_CMD);
+       writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
+               MCF_SDRAMC_SDMR_AD(0x0) |
+               MCF_SDRAMC_SDMR_CMD,
+               MCF_SDRAMC_SDMR);
 
        /*
         * Write mode register and reset DLL
         */
-       MCF_SDRAMC_SDMR = (0
-               | MCF_SDRAMC_SDMR_BNKAD_LMR
-               | MCF_SDRAMC_SDMR_AD(0x163)
-               | MCF_SDRAMC_SDMR_CMD);
+       writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
+               MCF_SDRAMC_SDMR_AD(0x163) |
+               MCF_SDRAMC_SDMR_CMD,
+               MCF_SDRAMC_SDMR);
 
        /*
         * Execute a PALL command
         */
-       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
+       writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
 
        /*
         * Perform two REF cycles
         */
-       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
-       MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+       writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
+       writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
 
        /*
         * Write mode register and clear reset DLL
         */
-       MCF_SDRAMC_SDMR = (0
-               | MCF_SDRAMC_SDMR_BNKAD_LMR
-               | MCF_SDRAMC_SDMR_AD(0x063)
-               | MCF_SDRAMC_SDMR_CMD);
+       writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
+               MCF_SDRAMC_SDMR_AD(0x063) |
+               MCF_SDRAMC_SDMR_CMD,
+               MCF_SDRAMC_SDMR);
                                
        /*
         * Enable auto refresh and lock SDMR
         */
-       MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
-       MCF_SDRAMC_SDCR |= (0
-               | MCF_SDRAMC_SDCR_REF
-               | MCF_SDRAMC_SDCR_DQS_OE(0xC));
+       writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
+               MCF_SDRAMC_SDCR);
+       writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
+               MCF_SDRAMC_SDCR);
        }
 }
 
 void gpio_init(void)
 {
        /* Enable UART0 pins */
-       MCF_GPIO_PAR_UART = ( 0
-               | MCF_GPIO_PAR_UART_PAR_URXD0
-               | MCF_GPIO_PAR_UART_PAR_UTXD0);
-
-       /* Initialize TIN3 as a GPIO output to enable the write
-          half of the latch */
-       MCF_GPIO_PAR_TIMER = 0x00;
-       __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
-       __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
+       writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
+               MCFGPIO_PAR_UART);
 
+       /*
+        * Initialize TIN3 as a GPIO output to enable the write
+        * half of the latch.
+        */
+       writeb(0x00, MCFGPIO_PAR_TIMER);
+       writeb(0x08, MCFGPIO_PDDR_TIMER);
+       writeb(0x00, MCFGPIO_PCLRR_TIMER);
 }
 
 int clock_pll(int fsys, int flags)
@@ -469,7 +475,7 @@ int clock_pll(int fsys, int flags)
         
        if (fsys == 0) {
                /* Return current PLL output */
-               mfd = MCF_PLL_PFDR;
+               mfd = readb(MCF_PLL_PFDR);
 
                return (fref * mfd / (BUSDIV * 4));
        }
@@ -495,9 +501,10 @@ int clock_pll(int fsys, int flags)
         * If it has then the SDRAM needs to be put into self refresh
         * mode before reprogramming the PLL.
         */
-       if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+       if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
                /* Put SDRAM into self refresh mode */
-               MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
+               writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
+                       MCF_SDRAMC_SDCR);
 
        /*
         * Initialize the PLL to generate the new system clock frequency.
@@ -508,11 +515,10 @@ int clock_pll(int fsys, int flags)
        clock_limp(DEFAULT_LPD);
                                        
        /* Reprogram PLL for desired fsys */
-       MCF_PLL_PODR = (0
-               | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
-               | MCF_PLL_PODR_BUSDIV(BUSDIV));
+       writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
+               MCF_PLL_PODR);
                                                
-       MCF_PLL_PFDR = mfd;
+       writeb(mfd, MCF_PLL_PFDR);
                
        /* Exit LIMP mode */
        clock_exit_limp();
@@ -520,12 +526,13 @@ int clock_pll(int fsys, int flags)
        /*
         * Return the SDRAM to normal operation if it is in use.
         */
-       if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+       if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
                /* Exit self refresh mode */
-               MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
+               writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
+                       MCF_SDRAMC_SDCR);
 
        /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
-       MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
+       writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
 
        /* wait for DQS logic to relock */
        for (i = 0; i < 0x200; i++)
@@ -546,14 +553,12 @@ int clock_limp(int div)
     
        /* Save of the current value of the SSIDIV so we don't
           overwrite the value*/
-       temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
+       temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
       
        /* Apply the divider to the system clock */
-       MCF_CCM_CDR = ( 0
-               | MCF_CCM_CDR_LPDIV(div)
-               | MCF_CCM_CDR_SSIDIV(temp));
+       writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
     
-       MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
+       writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
     
        return (FREF/(3*(1 << div)));
 }
@@ -563,10 +568,10 @@ int clock_exit_limp(void)
        int fout;
        
        /* Exit LIMP mode */
-       MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
+       writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
 
        /* Wait for PLL to lock */
-       while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
+       while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
                ;
        
        fout = get_sys_clock();
@@ -579,10 +584,10 @@ int get_sys_clock(void)
        int divider;
        
        /* Test to see if device is in LIMP mode */
-       if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
-               divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
+       if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
+               divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
                return (FREF/(2 << divider));
        }
        else
-               return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
+               return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
 }
index 2081c6cbb3de95f6c5b182e878067dc1952e97bf..b587bf35175be95f20775c88ca92d501583022fd 100644 (file)
 static void __init m54xx_uarts_init(void)
 {
        /* enable io pins */
-       __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD,
-               MCF_MBAR + MCF_PAR_PSC(0));
+       __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD, MCFGPIO_PAR_PSC0);
        __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD | MCF_PAR_PSC_RTS_RTS,
-               MCF_MBAR + MCF_PAR_PSC(1));
+               MCFGPIO_PAR_PSC1);
        __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD | MCF_PAR_PSC_RTS_RTS |
-               MCF_PAR_PSC_CTS_CTS, MCF_MBAR + MCF_PAR_PSC(2));
-       __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD,
-               MCF_MBAR + MCF_PAR_PSC(3));
+               MCF_PAR_PSC_CTS_CTS, MCFGPIO_PAR_PSC2);
+       __raw_writeb(MCF_PAR_PSC_TXD | MCF_PAR_PSC_RXD, MCFGPIO_PAR_PSC3);
 }
 
 /***************************************************************************/
@@ -46,10 +44,10 @@ static void mcf54xx_reset(void)
 {
        /* disable interrupts and enable the watchdog */
        asm("movew #0x2700, %sr\n");
-       __raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
-       __raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+       __raw_writel(0, MCF_GPT_GMS0);
+       __raw_writel(MCF_GPT_GCIR_CNT(1), MCF_GPT_GCIR0);
        __raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
-                                               MCF_MBAR + MCF_GPT_GMS0);
+               MCF_GPT_GMS0);
 }
 
 /***************************************************************************/
index e925ea4602f8e8cf60cf57f4c6ec288f3517b169..ddc48ec1b800300d6496479c8e4d4a1cd5090102 100644 (file)
@@ -121,14 +121,14 @@ static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flasha
 
 static void __init nettel_smc91x_init(void)
 {
-       writew(0x00ec, MCF_MBAR + MCFSIM_PADDR);
+       writew(0x00ec, MCFSIM_PADDR);
        mcf_setppdata(0, 0x0080);
        writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
        writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
        mcf_setppdata(0x0080, 0);
 
        /* Set correct chip select timing for SMC9196 accesses */
-       writew(0x1180, MCF_MBAR + MCFSIM_CSCR3);
+       writew(0x1180, MCFSIM_CSCR3);
 
        /* Set the SMC interrupts to be auto-vectored */
        mcf_autovector(NETTEL_SMC0_IRQ);
index 553210d3d4c13c18017680e21566f0a670098624..8572246db84d3fe35d9075a5157e42a3e0eb1e2e 100644 (file)
@@ -272,8 +272,8 @@ static int __init mcf_pci_init(void)
                PACR_EXTMINTE(0x1f), PACR);
 
        /* Set required multi-function pins for PCI bus use */
-       __raw_writew(0x3ff, MCF_PAR_PCIBG);
-       __raw_writew(0x3ff, MCF_PAR_PCIBR);
+       __raw_writew(0x3ff, MCFGPIO_PAR_PCIBG);
+       __raw_writew(0x3ff, MCFGPIO_PAR_PCIBR);
 
        /* Set up config space for local host bus controller */
        __raw_writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
index 933e54eacc691dfc118d7281683c1c2907ed6887..f30952f0cbe6fee1757de6bd0cb3c186c49a236e 100644 (file)
@@ -27,7 +27,7 @@ static void mcf_cpu_reset(void)
 {
        local_irq_disable();
        /* Set watchdog to soft reset, and enabled */
-       __raw_writeb(0xc0, MCF_MBAR + MCFSIM_SYPCR);
+       __raw_writeb(0xc0, MCFSIM_SYPCR);
        for (;;)
                /* wait for watchdog to timeout */;
 }
index 2027fc20b8761eeb099a218fed8522ea9159fa06..bb5a25ada84872420e1ac518e85ac647dc5aa818 100644 (file)
@@ -32,7 +32,7 @@
 /*
  *     By default use Slice Timer 1 as the profiler clock timer.
  */
-#define        PA(a)   (MCF_MBAR + MCFSLT_TIMER1 + (a))
+#define        PA(a)   (MCFSLT_TIMER1 + (a))
 
 /*
  *     Choose a reasonably fast profile timer. Make it an odd value to
@@ -76,7 +76,7 @@ void mcfslt_profile_init(void)
 /*
  *     By default use Slice Timer 0 as the system clock timer.
  */
-#define        TA(a)   (MCF_MBAR + MCFSLT_TIMER0 + (a))
+#define        TA(a)   (MCFSLT_TIMER0 + (a))
 
 static u32 mcfslt_cycles_per_jiffy;
 static u32 mcfslt_cnt;
index 0a273e75408c18f99deda39d713b1caab026172b..51f6d2af807f8dd2c401138bc3894b8ae920f34d 100644 (file)
@@ -56,13 +56,13 @@ static void init_timer_irq(void)
 #ifdef MCFSIM_ICR_AUTOVEC
        /* Timer1 is always used as system timer */
        writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-               MCF_MBAR + MCFSIM_TIMER1ICR);
+               MCFSIM_TIMER1ICR);
        mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
 
 #ifdef CONFIG_HIGHPROFILE
        /* Timer2 is to be used as a high speed profile timer  */
        writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-               MCF_MBAR + MCFSIM_TIMER2ICR);
+               MCFSIM_TIMER2ICR);
        mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
 #endif
 #endif /* MCFSIM_ICR_AUTOVEC */
index 834849f59ae8a5474e80d2e13cd4a3f0a9e2976f..640ddd4b6a9b2cf6bc58e159a46bf9490069e188 100644 (file)
@@ -116,7 +116,8 @@ do {                                                        \
 } while (0)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 #endif
 
 #endif /* __uClinux__ */
index feb05258a4d1519368a0e7f2395415a4a87e84b1..dd18e4b761a8789fa00fd4fb217f78e5fb83dff5 100644 (file)
@@ -632,7 +632,7 @@ static struct board_info __initdata board_DWVS0 = {
 /*
  * all boards
  */
-static const struct board_info __initdata *bcm963xx_boards[] = {
+static const struct board_info __initconst *bcm963xx_boards[] = {
 #ifdef CONFIG_BCM63XX_CPU_6328
        &board_96328avng,
 #endif
index 368a99e5c3e1e2213928fb27996252614ad7b848..6599a901b63ea20733ad9decf8bbebcc7ee8d8bd 100644 (file)
 
 #include <asm/uaccess.h>
 
-#define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-typedef struct compat_siginfo {
-       int si_signo;
-       int si_code;
-       int si_errno;
-
-       union {
-               int _pad[SI_PAD_SIZE32];
-
-               /* kill() */
-               struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       compat_uid_t _uid;      /* sender's uid */
-               } _kill;
-
-               /* SIGCHLD */
-               struct {
-                       compat_pid_t _pid;      /* which child */
-                       compat_uid_t _uid;      /* sender's uid */
-                       int _status;            /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* IRIX SIGCHLD */
-               struct {
-                       compat_pid_t _pid;      /* which child */
-                       compat_clock_t _utime;
-                       int _status;            /* exit code */
-                       compat_clock_t _stime;
-               } _irix_sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       s32 _addr; /* faulting insn/memory ref. */
-               } _sigfault;
-
-               /* SIGPOLL, SIGXFSZ (To do ...)  */
-               struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-
-               /* POSIX.1b timers */
-               struct {
-                       timer_t _tid;           /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;/* same as below */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       compat_uid_t _uid;      /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-       } _sifields;
-} compat_siginfo_t;
-
 static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
        const sigset_t *s)
 {
index b77df0366ee668296a03896e4ccd096329230dc9..58277e0e9cd4075e001f79e48fcaaf928dd53064 100644 (file)
@@ -43,6 +43,7 @@ typedef s64           compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64            compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -124,6 +125,73 @@ typedef u32                compat_old_sigset_t;    /* at least 32 bits */
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32  (128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_code;
+       int si_errno;
+
+       union {
+               int _pad[SI_PAD_SIZE32];
+
+               /* kill() */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid_t _uid;    /* sender's uid */
+               } _kill;
+
+               /* SIGCHLD */
+               struct {
+                       compat_pid_t _pid;      /* which child */
+                       __compat_uid_t _uid;    /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* IRIX SIGCHLD */
+               struct {
+                       compat_pid_t _pid;      /* which child */
+                       compat_clock_t _utime;
+                       int _status;            /* exit code */
+                       compat_clock_t _stime;
+               } _irix_sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       s32 _addr; /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL, SIGXFSZ (To do ...)  */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+
+               /* POSIX.1b timers */
+               struct {
+                       timer_t _tid;           /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;/* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid_t _uid;    /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -133,7 +201,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef u32            compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index c5dfb2c87d44d480d8a35708a13ae6dfa003b068..4b0c347d7a8241d1279a11efc84c873ee2a85650 100644 (file)
@@ -58,7 +58,7 @@ union octeon_pci_address {
        } s;
 };
 
-int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+int __initconst (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
                                         u8 slot, u8 pin);
 enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
 
index 33188b6e81e4509d060aab524de1d9ac5a54d67d..a3d0fef3b126ba859e5fe0459b1e12658cbebe69 100644 (file)
@@ -26,7 +26,7 @@ CHECKFLAGS    +=
 PROCESSOR      := unset
 UNIT           := unset
 
-KBUILD_CFLAGS  += -mam33 -mmem-funcs -DCPU=AM33
+KBUILD_CFLAGS  += -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,)
 KBUILD_AFLAGS  += -mam33 -DCPU=AM33
 
 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
index 8157c9267f426ac7dabdd6f0dcef9a67bd2ff5a3..4ebd6b3a0a1ebf7bd5aebdd8dc42dac5460fc64a 100644 (file)
@@ -151,7 +151,8 @@ do {                                                \
 #define ELF_PLATFORM  (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 #endif
 
 #endif /* _ASM_ELF_H */
index a8fe2c513070389cdf46c03155123a4ea5531fda..225a7ff320ad565329b7e399c8ce80c9f8cf963c 100644 (file)
@@ -110,7 +110,8 @@ extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
 
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif /* __KERNEL__ */
 #endif
index 89af3ab5c2e9a19691c70af5c533c35ddda8c024..437bdbb61b14ce58372710d7177a8e1ba2fd9bb0 100644 (file)
@@ -16,9 +16,6 @@
  * (at your option) any later version.
  */
 
-#if !defined(__ASM_OPENRISC_UNISTD_H) || defined(__SYSCALL)
-#define __ASM_OPENRISC_UNISTD_H
-
 #define __ARCH_HAVE_MMU
 
 #define sys_mmap2 sys_mmap_pgoff
@@ -27,5 +24,3 @@
 
 #define __NR_or1k_atomic __NR_arch_specific_syscall
 __SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
-
-#endif /* __ASM_OPENRISC_UNISTD_H */
index 3ff21b536f28f6c1e84b06b665e6d7589579f6c9..b87438bb338477e599a85f384b9959eeb3898871 100644 (file)
@@ -13,6 +13,7 @@ config PARISC
        select HAVE_PERF_EVENTS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_GENERIC_HARDIRQS
+       select BROKEN_RODATA
        select GENERIC_IRQ_PROBE
        select GENERIC_PCI_IOMAP
        select IRQ_PER_CPU
index 760f331d4fa3e55c70685812a802dd1d2065259c..db7a662691a8b5cd1e6384a24fe4e19514734449 100644 (file)
@@ -36,6 +36,7 @@ typedef s64   compat_s64;
 typedef u32    compat_uint_t;
 typedef u32    compat_ulong_t;
 typedef u64    compat_u64;
+typedef u32    compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t           tv_sec;
@@ -127,6 +128,63 @@ typedef u32                compat_old_sigset_t;    /* at least 32 bits */
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               int _pad[128/sizeof(int) - 3];
+
+               /* kill() */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;            /* timer id */
+                       int _overrun;           /* overrun count */
+                       char _pad[sizeof(unsigned int) - sizeof(int)];
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       unsigned int _pid;      /* which child */
+                       unsigned int _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       unsigned int _addr;     /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -136,7 +194,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index c7800846422c3ba623372504437ced3ca0961c52..08a88b5349a277d4ed97d522526abb4ef4ed8096 100644 (file)
@@ -55,58 +55,6 @@ struct k_sigaction32 {
        struct compat_sigaction sa;
 };
 
-typedef struct compat_siginfo {
-        int si_signo;
-        int si_errno;
-        int si_code;
-
-        union {
-                int _pad[((128/sizeof(int)) - 3)];
-
-                /* kill() */
-                struct {
-                        unsigned int _pid;      /* sender's pid */
-                        unsigned int _uid;      /* sender's uid */
-                } _kill;
-
-                /* POSIX.1b timers */
-                struct {
-                        compat_timer_t _tid;            /* timer id */
-                        int _overrun;           /* overrun count */
-                        char _pad[sizeof(unsigned int) - sizeof(int)];
-                        compat_sigval_t _sigval;        /* same as below */
-                        int _sys_private;       /* not to be passed to user */
-                } _timer;
-
-                /* POSIX.1b signals */
-                struct {
-                        unsigned int _pid;      /* sender's pid */
-                        unsigned int _uid;      /* sender's uid */
-                        compat_sigval_t _sigval;
-                } _rt;
-
-                /* SIGCHLD */
-                struct {
-                        unsigned int _pid;      /* which child */
-                        unsigned int _uid;      /* sender's uid */
-                        int _status;            /* exit code */
-                        compat_clock_t _utime;
-                        compat_clock_t _stime;
-                } _sigchld;
-
-                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-                struct {
-                        unsigned int _addr;     /* faulting insn/memory ref. */
-                } _sigfault;
-
-                /* SIGPOLL */
-                struct {
-                        int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                        int _fd;
-                } _sigpoll;
-        } _sifields;
-} compat_siginfo_t;
-
 int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
 int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
 
index 352f416269ce245c515e25e0cc5cbcf5a446d2a6..4ce0be32d153fe5a91adcb82d376697f6198d5d6 100644 (file)
@@ -215,7 +215,8 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
        def_bool y
        depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-                  (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
+                  (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+                  || 44x || 40x
 
 config PPC_DCR_NATIVE
        bool
@@ -239,6 +240,9 @@ config PPC_OF_PLATFORM_PCI
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
 
+config ARCH_SUPPORTS_UPROBES
+       def_bool y
+
 config PPC_ADV_DEBUG_REGS
        bool
        depends on 40x || BOOKE
@@ -325,7 +329,8 @@ config SWIOTLB
 
 config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
-       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
+       depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || \
+       PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
        ---help---
          Say Y here to be able to disable and re-enable individual
          CPUs at runtime on SMP machines.
@@ -557,6 +562,14 @@ config SCHED_SMT
          when dealing with POWER5 cpus at a cost of slightly increased
          overhead in some places. If unsure say N here.
 
+config PPC_DENORMALISATION
+       bool "PowerPC denormalisation exception handling"
+       depends on PPC_BOOK3S_64
+       default "n"
+       ---help---
+         Add support for handling denormalisation of single precision
+         values.  Useful for bare metal only.  If unsure say Y here.
+
 config CMDLINE_BOOL
        bool "Default bootloader kernel arguments"
 
index b7d833382be4889e09e7b6e6e62402afb9dd2056..6a15c968d21453230ab469b5921fea28b790dcc5 100644 (file)
@@ -107,6 +107,7 @@ src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
 obj-wlib := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-wlib))))
 obj-plat := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-plat))))
+obj-plat: $(libfdt)
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = sed "s@__used@@;s@<linux/\([^>]*\).*@\"\1\"@" $< > $@
diff --git a/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
new file mode 100644 (file)
index 0000000..870c653
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * e500mc Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/ {
+       cpus {
+               power-isa-version = "2.06";
+               power-isa-b;            // Base
+               power-isa-e;            // Embedded
+               power-isa-atb;          // Alternate Time Base
+               power-isa-cs;           // Cache Specification
+               power-isa-ds;           // Decorated Storage
+               power-isa-e.ed;         // Embedded.Enhanced Debug
+               power-isa-e.pd;         // Embedded.External PID
+               power-isa-e.hv;         // Embedded.Hypervisor
+               power-isa-e.le;         // Embedded.Little-Endian
+               power-isa-e.pm;         // Embedded.Performance Monitor
+               power-isa-e.pc;         // Embedded.Processor Control
+               power-isa-ecl;          // Embedded Cache Locking
+               power-isa-exp;          // External Proxy
+               power-isa-fp;           // Floating Point
+               power-isa-fp.r;         // Floating Point.Record
+               power-isa-mmc;          // Memory Coherence
+               power-isa-scpm;         // Store Conditional Page Mobility
+               power-isa-wt;           // Wait
+               mmu-type = "power-embedded";
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi
new file mode 100644 (file)
index 0000000..f492814
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * e500v2 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/ {
+       cpus {
+               power-isa-version = "2.03";
+               power-isa-b;            // Base
+               power-isa-e;            // Embedded
+               power-isa-atb;          // Alternate Time Base
+               power-isa-cs;           // Cache Specification
+               power-isa-e.le;         // Embedded.Little-Endian
+               power-isa-e.pm;         // Embedded.Performance Monitor
+               power-isa-ecl;          // Embedded Cache Locking
+               power-isa-mmc;          // Memory Coherence
+               power-isa-sp;           // Signal Processing Engine
+               power-isa-sp.fd;        // SPE.Embedded Float Scalar Double
+               power-isa-sp.fs;        // SPE.Embedded Float Scalar Single
+               power-isa-sp.fv;        // SPE.Embedded Float Vector
+               mmu-type = "power-embedded";
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
new file mode 100644 (file)
index 0000000..3230212
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * e5500 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/ {
+       cpus {
+               power-isa-version = "2.06";
+               power-isa-b;            // Base
+               power-isa-e;            // Embedded
+               power-isa-atb;          // Alternate Time Base
+               power-isa-cs;           // Cache Specification
+               power-isa-ds;           // Decorated Storage
+               power-isa-e.ed;         // Embedded.Enhanced Debug
+               power-isa-e.pd;         // Embedded.External PID
+               power-isa-e.hv;         // Embedded.Hypervisor
+               power-isa-e.le;         // Embedded.Little-Endian
+               power-isa-e.pm;         // Embedded.Performance Monitor
+               power-isa-e.pc;         // Embedded.Processor Control
+               power-isa-ecl;          // Embedded Cache Locking
+               power-isa-exp;          // External Proxy
+               power-isa-fp;           // Floating Point
+               power-isa-fp.r;         // Floating Point.Record
+               power-isa-mmc;          // Memory Coherence
+               power-isa-scpm;         // Store Conditional Page Mobility
+               power-isa-wt;           // Wait
+               power-isa-64;           // 64-bit
+               mmu-type = "power-embedded";
+       };
+};
index 7de45a784df6ab28b05f474979faac5d9db7fc4e..152906f98a0fc1c21df225a305e640d0b37429e3 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8536";
        #address-cells = <2>;
index 8777f9239d9edee6440fb258b6e230990ab38d52..5a69bafb652a760d97f6c78bfd684119ec756e4a 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8544";
        #address-cells = <2>;
index 720422d83529092fd9237e8b4b1992522e9d6faa..fc1ce977422bddda2c29a0077cafc157a06b395d 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8548";
        #address-cells = <2>;
index eacd62c5fe6c2372b30790a330713b182d3377a8..122ca3bd0b03ccf23220c4be655c86957ff7b9a8 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8568";
        #address-cells = <2>;
index b07064d1193084fd8cc6b5097d82c240057987df..2cd15a2a04228459b1f1bc2087659ff8aa47cde9 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8569";
        #address-cells = <2>;
index ca188326c2ca9bef36c9ffcc3acb8dcb23c49f50..28c2a862be96e77c92abff3d688a1d116c53c352 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,MPC8572";
        #address-cells = <2>;
index 7354a8f90ea5059d2ccbed0148b754c776bb5b7c..6e76f9b282a10908f7205048b977c2c08287943d 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P1010";
        #address-cells = <2>;
index 6f0376e554ebe3a144495d2a7202c200bff2c189..fed9c4c8d9623b3fd4040799f300bdafe90c368a 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P1020";
        #address-cells = <2>;
index 4abd54bc33084f4ef9b493c7f77cca6d3007952e..36161b5001762dc78cc42be19613fe5ab83ccdf3 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P1021";
        #address-cells = <2>;
index e930f4f7ca89979973239e609eb74e8e44c088ce..1956dea040cca30a980ccdc4490766631135bb6f 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P1022";
        #address-cells = <2>;
index ac45f6d93385916984f55f26e28c83404e816e17..132a1521921a3ae3db6d90fcf2bd8bf5bd716cbe 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P1023";
        #address-cells = <2>;
index 3213288641d1a8ddff7572b3311b34a3ca2ea6be..42bf3c6d25ca350a67f6a7d74db4613c242faa3a 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
        compatible = "fsl,P2020";
        #address-cells = <2>;
index 2d0a40d6b10f9c4df2345aaf11fa699ea4f1462b..7a2697d04549535e74d5b78924c90e2bf193cef5 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
        compatible = "fsl,P2041";
        #address-cells = <2>;
index 136def3536b6caf9ca4c30d804859262f00241a2..c9ca2c305cfecff64052e084d44b35af7ff02ce1 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
        compatible = "fsl,P3041";
        #address-cells = <2>;
index b9556ee3a63975a57e17ad0c90d168dc622e2a37..493d9a056b5caceffbc58c80baf38a2fec8c2f25 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
        compatible = "fsl,P4080";
        #address-cells = <2>;
index ae823a47584eccf5d931e3c67780b784062d7924..0a198b0a77e53a3447600c8180f897a4790b9cf7 100644 (file)
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e5500_power_isa.dtsi"
+
 / {
        compatible = "fsl,P5020";
        #address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
new file mode 100644 (file)
index 0000000..db2c9a7
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * P5040 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+&lbc {
+       compatible = "fsl,p5040-elbc", "fsl,elbc", "simple-bus";
+       interrupts = <25 2 0 0>;
+       #address-cells = <2>;
+       #size-cells = <1>;
+};
+
+/* controller at 0x200000 */
+&pci0 {
+       compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+       device_type = "pci";
+       #size-cells = <2>;
+       #address-cells = <3>;
+       bus-range = <0x0 0xff>;
+       clock-frequency = <33333333>;
+       interrupts = <16 2 1 15>;
+       pcie@0 {
+               reg = <0 0 0 0 0>;
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               interrupts = <16 2 1 15>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0 0 1 &mpic 40 1 0 0
+                       0000 0 0 2 &mpic 1 1 0 0
+                       0000 0 0 3 &mpic 2 1 0 0
+                       0000 0 0 4 &mpic 3 1 0 0
+                       >;
+       };
+};
+
+/* controller at 0x201000 */
+&pci1 {
+       compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+       device_type = "pci";
+       #size-cells = <2>;
+       #address-cells = <3>;
+       bus-range = <0 0xff>;
+       clock-frequency = <33333333>;
+       interrupts = <16 2 1 14>;
+       pcie@0 {
+               reg = <0 0 0 0 0>;
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               interrupts = <16 2 1 14>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0 0 1 &mpic 41 1 0 0
+                       0000 0 0 2 &mpic 5 1 0 0
+                       0000 0 0 3 &mpic 6 1 0 0
+                       0000 0 0 4 &mpic 7 1 0 0
+                       >;
+       };
+};
+
+/* controller at 0x202000 */
+&pci2 {
+       compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+       device_type = "pci";
+       #size-cells = <2>;
+       #address-cells = <3>;
+       bus-range = <0x0 0xff>;
+       clock-frequency = <33333333>;
+       interrupts = <16 2 1 13>;
+       pcie@0 {
+               reg = <0 0 0 0 0>;
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               interrupts = <16 2 1 13>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0 0 1 &mpic 42 1 0 0
+                       0000 0 0 2 &mpic 9 1 0 0
+                       0000 0 0 3 &mpic 10 1 0 0
+                       0000 0 0 4 &mpic 11 1 0 0
+                       >;
+       };
+};
+
+&dcsr {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "fsl,dcsr", "simple-bus";
+
+       dcsr-epu@0 {
+               compatible = "fsl,dcsr-epu";
+               interrupts = <52 2 0 0
+                             84 2 0 0
+                             85 2 0 0>;
+               reg = <0x0 0x1000>;
+       };
+       dcsr-npc {
+               compatible = "fsl,dcsr-npc";
+               reg = <0x1000 0x1000 0x1000000 0x8000>;
+       };
+       dcsr-nxc@2000 {
+               compatible = "fsl,dcsr-nxc";
+               reg = <0x2000 0x1000>;
+       };
+       dcsr-corenet {
+               compatible = "fsl,dcsr-corenet";
+               reg = <0x8000 0x1000 0xB0000 0x1000>;
+       };
+       dcsr-dpaa@9000 {
+               compatible = "fsl,p5040-dcsr-dpaa", "fsl,dcsr-dpaa";
+               reg = <0x9000 0x1000>;
+       };
+       dcsr-ocn@11000 {
+               compatible = "fsl,p5040-dcsr-ocn", "fsl,dcsr-ocn";
+               reg = <0x11000 0x1000>;
+       };
+       dcsr-ddr@12000 {
+               compatible = "fsl,dcsr-ddr";
+               dev-handle = <&ddr1>;
+               reg = <0x12000 0x1000>;
+       };
+       dcsr-ddr@13000 {
+               compatible = "fsl,dcsr-ddr";
+               dev-handle = <&ddr2>;
+               reg = <0x13000 0x1000>;
+       };
+       dcsr-nal@18000 {
+               compatible = "fsl,p5040-dcsr-nal", "fsl,dcsr-nal";
+               reg = <0x18000 0x1000>;
+       };
+       dcsr-rcpm@22000 {
+               compatible = "fsl,p5040-dcsr-rcpm", "fsl,dcsr-rcpm";
+               reg = <0x22000 0x1000>;
+       };
+       dcsr-cpu-sb-proxy@40000 {
+               compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+               cpu-handle = <&cpu0>;
+               reg = <0x40000 0x1000>;
+       };
+       dcsr-cpu-sb-proxy@41000 {
+               compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+               cpu-handle = <&cpu1>;
+               reg = <0x41000 0x1000>;
+       };
+       dcsr-cpu-sb-proxy@42000 {
+               compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+               cpu-handle = <&cpu2>;
+               reg = <0x42000 0x1000>;
+       };
+       dcsr-cpu-sb-proxy@43000 {
+               compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+               cpu-handle = <&cpu3>;
+               reg = <0x43000 0x1000>;
+       };
+};
+
+&soc {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       device_type = "soc";
+       compatible = "simple-bus";
+
+       soc-sram-error {
+               compatible = "fsl,soc-sram-error";
+               interrupts = <16 2 1 29>;
+       };
+
+       corenet-law@0 {
+               compatible = "fsl,corenet-law";
+               reg = <0x0 0x1000>;
+               fsl,num-laws = <32>;
+       };
+
+       ddr1: memory-controller@8000 {
+               compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+               reg = <0x8000 0x1000>;
+               interrupts = <16 2 1 23>;
+       };
+
+       ddr2: memory-controller@9000 {
+               compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller";
+               reg = <0x9000 0x1000>;
+               interrupts = <16 2 1 22>;
+       };
+
+       cpc: l3-cache-controller@10000 {
+               compatible = "fsl,p5040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+               reg = <0x10000 0x1000
+                      0x11000 0x1000>;
+               interrupts = <16 2 1 27
+                             16 2 1 26>;
+       };
+
+       corenet-cf@18000 {
+               compatible = "fsl,corenet-cf";
+               reg = <0x18000 0x1000>;
+               interrupts = <16 2 1 31>;
+               fsl,ccf-num-csdids = <32>;
+               fsl,ccf-num-snoopids = <32>;
+       };
+
+       iommu@20000 {
+               compatible = "fsl,pamu-v1.0", "fsl,pamu";
+               reg = <0x20000 0x5000>;
+               interrupts = <
+                       24 2 0 0
+                       16 2 1 30>;
+       };
+
+/include/ "qoriq-mpic.dtsi"
+
+       guts: global-utilities@e0000 {
+               compatible = "fsl,p5040-device-config", "fsl,qoriq-device-config-1.0";
+               reg = <0xe0000 0xe00>;
+               fsl,has-rstcr;
+               #sleep-cells = <1>;
+               fsl,liodn-bits = <12>;
+       };
+
+       pins: global-utilities@e0e00 {
+               compatible = "fsl,p5040-pin-control", "fsl,qoriq-pin-control-1.0";
+               reg = <0xe0e00 0x200>;
+               #sleep-cells = <2>;
+       };
+
+       clockgen: global-utilities@e1000 {
+               compatible = "fsl,p5040-clockgen", "fsl,qoriq-clockgen-1.0";
+               reg = <0xe1000 0x1000>;
+               clock-frequency = <0>;
+       };
+
+       rcpm: global-utilities@e2000 {
+               compatible = "fsl,p5040-rcpm", "fsl,qoriq-rcpm-1.0";
+               reg = <0xe2000 0x1000>;
+               #sleep-cells = <1>;
+       };
+
+       sfp: sfp@e8000 {
+               compatible = "fsl,p5040-sfp", "fsl,qoriq-sfp-1.0";
+               reg        = <0xe8000 0x1000>;
+       };
+
+       serdes: serdes@ea000 {
+               compatible = "fsl,p5040-serdes";
+               reg        = <0xea000 0x1000>;
+       };
+
+/include/ "qoriq-dma-0.dtsi"
+/include/ "qoriq-dma-1.dtsi"
+/include/ "qoriq-espi-0.dtsi"
+       spi@110000 {
+               fsl,espi-num-chipselects = <4>;
+       };
+
+/include/ "qoriq-esdhc-0.dtsi"
+       sdhc@114000 {
+               sdhci,auto-cmd12;
+       };
+
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+               usb0: usb@210000 {
+                       compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+                       phy_type = "utmi";
+                       port0;
+               };
+
+/include/ "qoriq-usb2-dr-0.dtsi"
+               usb1: usb@211000 {
+                       compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+                       dr_mode = "host";
+                       phy_type = "utmi";
+               };
+
+/include/ "qoriq-sata2-0.dtsi"
+/include/ "qoriq-sata2-1.dtsi"
+/include/ "qoriq-sec5.2-0.dtsi"
+};
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi
new file mode 100644 (file)
index 0000000..40ca943
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * P5040 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/include/ "e5500_power_isa.dtsi"
+
+/ {
+       compatible = "fsl,P5040";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       aliases {
+               ccsr = &soc;
+               dcsr = &dcsr;
+
+               serial0 = &serial0;
+               serial1 = &serial1;
+               serial2 = &serial2;
+               serial3 = &serial3;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               pci2 = &pci2;
+               usb0 = &usb0;
+               usb1 = &usb1;
+               dma0 = &dma0;
+               dma1 = &dma1;
+               sdhc = &sdhc;
+               msi0 = &msi0;
+               msi1 = &msi1;
+               msi2 = &msi2;
+
+               crypto = &crypto;
+               sec_jr0 = &sec_jr0;
+               sec_jr1 = &sec_jr1;
+               sec_jr2 = &sec_jr2;
+               sec_jr3 = &sec_jr3;
+               rtic_a = &rtic_a;
+               rtic_b = &rtic_b;
+               rtic_c = &rtic_c;
+               rtic_d = &rtic_d;
+               sec_mon = &sec_mon;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: PowerPC,e5500@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2_0>;
+                       L2_0: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu1: PowerPC,e5500@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       next-level-cache = <&L2_1>;
+                       L2_1: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu2: PowerPC,e5500@2 {
+                       device_type = "cpu";
+                       reg = <2>;
+                       next-level-cache = <&L2_2>;
+                       L2_2: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+               cpu3: PowerPC,e5500@3 {
+                       device_type = "cpu";
+                       reg = <3>;
+                       next-level-cache = <&L2_3>;
+                       L2_3: l2-cache {
+                               next-level-cache = <&cpc>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi
new file mode 100644 (file)
index 0000000..7b2ab8a
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * QorIQ Sec/Crypto 5.2 device tree stub [ controller @ offset 0x300000 ]
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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.
+ */
+
+crypto: crypto@300000 {
+       compatible = "fsl,sec-v5.2", "fsl,sec-v5.0", "fsl,sec-v4.0";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       reg              = <0x300000 0x10000>;
+       ranges           = <0 0x300000 0x10000>;
+       interrupts       = <92 2 0 0>;
+
+       sec_jr0: jr@1000 {
+               compatible = "fsl,sec-v5.2-job-ring",
+                            "fsl,sec-v5.0-job-ring",
+                            "fsl,sec-v4.0-job-ring";
+               reg = <0x1000 0x1000>;
+               interrupts = <88 2 0 0>;
+       };
+
+       sec_jr1: jr@2000 {
+               compatible = "fsl,sec-v5.2-job-ring",
+                            "fsl,sec-v5.0-job-ring",
+                            "fsl,sec-v4.0-job-ring";
+               reg = <0x2000 0x1000>;
+               interrupts = <89 2 0 0>;
+       };
+
+       sec_jr2: jr@3000 {
+               compatible = "fsl,sec-v5.2-job-ring",
+                            "fsl,sec-v5.0-job-ring",
+                            "fsl,sec-v4.0-job-ring";
+               reg = <0x3000 0x1000>;
+               interrupts = <90 2 0 0>;
+       };
+
+       sec_jr3: jr@4000 {
+               compatible = "fsl,sec-v5.2-job-ring",
+                            "fsl,sec-v5.0-job-ring",
+                            "fsl,sec-v4.0-job-ring";
+               reg = <0x4000 0x1000>;
+               interrupts = <91 2 0 0>;
+       };
+
+       rtic@6000 {
+               compatible = "fsl,sec-v5.2-rtic",
+                            "fsl,sec-v5.0-rtic",
+                            "fsl,sec-v4.0-rtic";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               reg = <0x6000 0x100>;
+               ranges = <0x0 0x6100 0xe00>;
+
+               rtic_a: rtic-a@0 {
+                       compatible = "fsl,sec-v5.2-rtic-memory",
+                                    "fsl,sec-v5.0-rtic-memory",
+                                    "fsl,sec-v4.0-rtic-memory";
+                       reg = <0x00 0x20 0x100 0x80>;
+               };
+
+               rtic_b: rtic-b@20 {
+                       compatible = "fsl,sec-v5.2-rtic-memory",
+                                    "fsl,sec-v5.0-rtic-memory",
+                                    "fsl,sec-v4.0-rtic-memory";
+                       reg = <0x20 0x20 0x200 0x80>;
+               };
+
+               rtic_c: rtic-c@40 {
+                       compatible = "fsl,sec-v5.2-rtic-memory",
+                                    "fsl,sec-v5.0-rtic-memory",
+                                    "fsl,sec-v4.0-rtic-memory";
+                       reg = <0x40 0x20 0x300 0x80>;
+               };
+
+               rtic_d: rtic-d@60 {
+                       compatible = "fsl,sec-v5.2-rtic-memory",
+                                    "fsl,sec-v5.0-rtic-memory",
+                                    "fsl,sec-v4.0-rtic-memory";
+                       reg = <0x60 0x20 0x500 0x80>;
+               };
+       };
+};
+
+sec_mon: sec_mon@314000 {
+       compatible = "fsl,sec-v5.2-mon", "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon";
+       reg = <0x314000 0x1000>;
+       interrupts = <93 2 0 0>;
+};
index d304a2d68c62bfee4faef2d4a85f2e13aabec5bf..7c3dde84d193f18c98a1a8d58e1baaaf3626c36f 100644 (file)
                        reg = <0x68>;
                        interrupts = <0 0x1 0 0>;
                };
+               adt7461@4c {
+                       compatible = "adi,adt7461";
+                       reg = <0x4c>;
+               };
        };
 
        spi@7000 {
index f99fb110c97fb2e1c329e79cd2cdec7f772c6574..2d31863accf5331112d575d6e44bc0152c6e47ab 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
        model = "MPC8540ADS";
        compatible = "MPC8540ADS", "MPC85xxADS";
index 0f5e9391279964be6af6d40d1a60899e395f6894..1c03c2667373b41181552cef1c7d64a3caac6833 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
        model = "MPC8541CDS";
        compatible = "MPC8541CDS", "MPC85xxCDS";
index e934987e882b89bbc5db0be268ba32792e981cad..ed38874c3a367761ddd22e6a1678f498b7a42839 100644 (file)
                reg = <0 0 0 0>;        // Filled by U-Boot
        };
 
-       lbc: localbus@e0005000 {
+       board_lbc: lbc: localbus@e0005000 {
                reg = <0 0xe0005000 0 0x1000>;
+
+               ranges = <0x0 0x0 0x0 0xff800000 0x800000>;
        };
 
        board_soc: soc: soc8544@e0000000 {
index 77ebc9f1d37ca9ff91151dbaff1aaef3f9d9d4f9..b219d035d7943d64a6ca13fb09b3a0c95dfcf01f 100644 (file)
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+&board_lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x800000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       reg = <0x0 0x10000>;
+                       label = "dtb-nor";
+               };
+
+               partition@20000 {
+                       reg = <0x20000 0x30000>;
+                       label = "diagnostic-nor";
+                       read-only;
+               };
+
+               partition@200000 {
+                       reg = <0x200000 0x200000>;
+                       label = "dink-nor";
+                       read-only;
+               };
+
+               partition@400000 {
+                       reg = <0x400000 0x380000>;
+                       label = "kernel-nor";
+               };
+
+               partition@780000 {
+                       reg = <0x780000 0x80000>;
+                       label = "u-boot-nor";
+                       read-only;
+               };
+       };
+};
+
 &board_soc {
        enet0: ethernet@24000 {
                phy-handle = <&phy0>;
index fe10438613d686f5784e65f40a8696034d510c2f..36a7ea138c2f4a5c89e9596e8ec9fd41cb4f9f3c 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
        model = "MPC8555CDS";
        compatible = "MPC8555CDS", "MPC85xxCDS";
index 6e85e1ba08514edaa63eacaec208359b6b3773bb..1a43f5a968f565c1a33787e4ae02d938758f35c1 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
        model = "MPC8560ADS";
        compatible = "MPC8560ADS", "MPC85xxADS";
diff --git a/arch/powerpc/boot/dts/o2d.dts b/arch/powerpc/boot/dts/o2d.dts
new file mode 100644 (file)
index 0000000..9f6dd4d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * O2D Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o2d";
+       compatible = "ifm,o2d";
+
+       memory {
+               reg = <0x00000000 0x08000000>;  // 128MB
+       };
+
+       localbus {
+               ranges = <0 0 0xfc000000 0x02000000
+                         3 0 0xe3000000 0x00100000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x02000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x00060000 0x00260000>;
+                               read-only;
+                       };
+                       /* o2d specific partitions */
+                       partition@2c0000 {
+                               label = "o2d user defined";
+                               reg = <0x002c0000 0x01d40000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi
new file mode 100644 (file)
index 0000000..3444eb8
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * O2D base Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "mpc5200b.dtsi"
+
+/ {
+       model = "ifm,o2d";
+       compatible = "ifm,o2d";
+
+       memory {
+               reg = <0x00000000 0x04000000>;  // 64MB
+       };
+
+       soc5200@f0000000 {
+
+               gpio_simple: gpio@b00 {
+               };
+
+               timer@600 {     // General Purpose Timer
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       fsl,has-wdt;
+                       fsl,wdt-on-boot = <0>;
+               };
+
+               timer@610 {
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+
+               timer7: timer@670 {
+               };
+
+               rtc@800 {
+                       status = "disabled";
+               };
+
+               psc@2000 {              // PSC1
+                       compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+
+                       spidev@0 {
+                               compatible = "spidev";
+                               spi-max-frequency = <250000>;
+                               reg = <0>;
+                       };
+               };
+
+               psc@2200 {              // PSC2
+                       status = "disabled";
+               };
+
+               psc@2400 {              // PSC3
+                       status = "disabled";
+               };
+
+               psc@2600 {              // PSC4
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+               };
+
+               psc@2800 {              // PSC5
+                       compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+               };
+
+               psc@2c00 {              // PSC6
+                       status = "disabled";
+               };
+
+               ethernet@3000 {
+                       phy-handle = <&phy0>;
+               };
+
+               mdio@3000 {
+                       phy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
+               sclpc@3c00 {
+                       compatible = "fsl,mpc5200-lpbfifo";
+                       reg = <0x3c00 0x60>;
+                       interrupts = <3 23 0>;
+               };
+       };
+
+       localbus {
+               ranges = <0 0 0xff000000 0x01000000
+                         3 0 0xe3000000 0x00100000>;
+
+               // flash device at LocalPlus Bus CS0
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x01000000>;
+                       bank-width = <1>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+                       no-unaligned-direct-access;
+
+                       /* common layout for all machines */
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x00000000 0x00040000>;
+                               read-only;
+                       };
+                       partition@40000 {
+                               label = "env";
+                               reg = <0x00040000 0x00020000>;
+                               read-only;
+                       };
+               };
+
+               csi@3,0 {
+                       compatible = "ifm,o2d-csi";
+                       reg = <3 0 0x00100000>;
+                       ifm,csi-clk-handle = <&timer7>;
+                       gpios = <&gpio_simple 23 0      /* imag_capture */
+                                &gpio_simple 26 0      /* imag_reset */
+                                &gpio_simple 29 0>;    /* imag_master_en */
+
+                       interrupts = <1 1 2>;           /* IRQ1, edge falling */
+
+                       ifm,csi-addr-bus-width = <24>;
+                       ifm,csi-data-bus-width = <8>;
+                       ifm,csi-wait-cycles = <0>;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o2d300.dts b/arch/powerpc/boot/dts/o2d300.dts
new file mode 100644 (file)
index 0000000..29affe0
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * O2D300 Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o2d300";
+       compatible = "ifm,o2d";
+
+       localbus {
+               ranges = <0 0 0xfc000000 0x02000000
+                         3 0 0xe3000000 0x00100000>;
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x02000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+
+                       partition@40000 {
+                               label = "env_1";
+                               reg = <0x00040000 0x00020000>;
+                               read-only;
+                       };
+                       partition@60000 {
+                               label = "env_2";
+                               reg = <0x00060000 0x00020000>;
+                               read-only;
+                       };
+                       partition@80000 {
+                               label = "kernel";
+                               reg = <0x00080000 0x00260000>;
+                               read-only;
+                       };
+                       /* o2d300 specific partitions */
+                       partition@2e0000 {
+                               label = "o2d300 user defined";
+                               reg = <0x002e0000 0x01d20000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o2dnt2.dts b/arch/powerpc/boot/dts/o2dnt2.dts
new file mode 100644 (file)
index 0000000..a0f5b97
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * O2DNT2 Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o2dnt2";
+       compatible = "ifm,o2d";
+
+       memory {
+               reg = <0x00000000 0x08000000>;  // 128MB
+       };
+
+       localbus {
+               ranges = <0 0 0xfc000000 0x02000000
+                         3 0 0xe3000000 0x00100000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x02000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x00060000 0x00260000>;
+                               read-only;
+                       };
+
+                       /* o2dnt2 specific partitions */
+                       partition@2c0000 {
+                               label = "o2dnt2 user defined";
+                               reg = <0x002c0000 0x01d40000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o2i.dts b/arch/powerpc/boot/dts/o2i.dts
new file mode 100644 (file)
index 0000000..e3cc99d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * O2I Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o2i";
+       compatible = "ifm,o2d";
+
+       localbus {
+               flash@0,0 {
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x00060000 0x00260000>;
+                               read-only;
+                       };
+                       /* o2i specific partitions */
+                       partition@2c0000 {
+                               label = "o2i user defined";
+                               reg = <0x002c0000 0x00d40000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o2mnt.dts b/arch/powerpc/boot/dts/o2mnt.dts
new file mode 100644 (file)
index 0000000..d91859a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * O2MNT Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o2mnt";
+       compatible = "ifm,o2d";
+
+       localbus {
+               flash@0,0 {
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x00060000 0x00260000>;
+                               read-only;
+                       };
+                       /* add o2mnt specific partitions */
+                       partition@2c0000 {
+                               label = "o2mnt user defined";
+                               reg = <0x002c0000 0x00d40000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/o3dnt.dts b/arch/powerpc/boot/dts/o3dnt.dts
new file mode 100644 (file)
index 0000000..acce493
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * O3DNT Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+       model = "ifm,o3dnt";
+       compatible = "ifm,o2d";
+
+       memory {
+               reg = <0x00000000 0x04000000>;  // 64MB
+       };
+
+       localbus {
+               ranges = <0 0 0xfc000000 0x01000000
+                         3 0 0xe3000000 0x00100000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x01000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x00060000 0x00260000>;
+                               read-only;
+                       };
+
+                       /* o3dnt specific partitions */
+                       partition@2c0000 {
+                               label = "o3dnt user defined";
+                               reg = <0x002c0000 0x00d40000>;
+                       };
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
deleted file mode 100644 (file)
index 41b4585..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * P1020 RDB  Core0 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts file allows core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb,
- * eth1, eth2, sdhc, crypto, global-util, message, pci0, pci1, msi.
- *
- * Please note to add "-b 0" for core0's dts compiling.
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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/ "p1020rdb.dts"
-
-/ {
-       model = "fsl,P1020RDB";
-       compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
-
-       aliases {
-               ethernet1 = &enet1;
-               ethernet2 = &enet2;
-               serial0 = &serial0;
-               pci0 = &pci0;
-               pci1 = &pci1;
-       };
-
-       cpus {
-               PowerPC,P1020@1 {
-                       status = "disabled";
-               };
-       };
-
-       memory {
-               device_type = "memory";
-       };
-
-       localbus@ffe05000 {
-               status = "disabled";
-       };
-
-       soc@ffe00000 {
-               serial1: serial@4600 {
-                       status = "disabled";
-               };
-
-               enet0: ethernet@b0000 {
-                       status = "disabled";
-               };
-
-               mpic: pic@40000 {
-                       protected-sources = <
-                       42 29 30 34     /* serial1, enet0-queue-group0 */
-                       17 18 24 45     /* enet0-queue-group1, crypto */
-                       >;
-               };
-       };
-};
diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
deleted file mode 100644 (file)
index 5174538..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * P1020 RDB Core1 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts allows core1 to have l2, eth0, crypto.
- *
- * Please note to add "-b 1" for core1's dts compiling.
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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/ "p1020rdb.dts"
-
-/ {
-       model = "fsl,P1020RDB";
-       compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
-
-       aliases {
-               ethernet0 = &enet0;
-               serial0 = &serial1;
-               };
-
-       cpus {
-               PowerPC,P1020@0 {
-                       status = "disabled";
-               };
-       };
-
-       memory {
-               device_type = "memory";
-       };
-
-       localbus@ffe05000 {
-               status = "disabled";
-       };
-
-       soc@ffe00000 {
-               ecm-law@0 {
-                       status = "disabled";
-               };
-
-               ecm@1000 {
-                       status = "disabled";
-               };
-
-               memory-controller@2000 {
-                       status = "disabled";
-               };
-
-               i2c@3000 {
-                       status = "disabled";
-               };
-
-               i2c@3100 {
-                       status = "disabled";
-               };
-
-               serial0: serial@4500 {
-                       status = "disabled";
-               };
-
-               spi@7000 {
-                       status = "disabled";
-               };
-
-               gpio: gpio-controller@f000 {
-                       status = "disabled";
-               };
-
-               dma@21300 {
-                       status = "disabled";
-               };
-
-               mdio@24000 {
-                       status = "disabled";
-               };
-
-               mdio@25000 {
-                       status = "disabled";
-               };
-
-               enet1: ethernet@b1000 {
-                       status = "disabled";
-               };
-
-               enet2: ethernet@b2000 {
-                       status = "disabled";
-               };
-
-               usb@22000 {
-                       status = "disabled";
-               };
-
-               sdhci@2e000 {
-                       status = "disabled";
-               };
-
-               mpic: pic@40000 {
-                       protected-sources = <
-                       16              /* ecm, mem, L2, pci0, pci1 */
-                       43 42 59        /* i2c, serial0, spi */
-                       47 63 62        /* gpio, tdm */
-                       20 21 22 23     /* dma */
-                       03 02           /* mdio */
-                       35 36 40        /* enet1-queue-group0 */
-                       51 52 67        /* enet1-queue-group1 */
-                       31 32 33        /* enet2-queue-group0 */
-                       25 26 27        /* enet2-queue-group1 */
-                       28 72 58        /* usb, sdhci, crypto */
-                       0xb0 0xb1 0xb2  /* message */
-                       0xb3 0xb4 0xb5
-                       0xb6 0xb7
-                       0xe0 0xe1 0xe2  /* msi */
-                       0xe3 0xe4 0xe5
-                       0xe6 0xe7               /* sdhci, crypto , pci */
-                       >;
-               };
-
-               msi@41600 {
-                       status = "disabled";
-               };
-
-               global-utilities@e0000 {        //global utilities block
-                       status = "disabled";
-               };
-       };
-
-       pci0: pcie@ffe09000 {
-               status = "disabled";
-       };
-
-       pci1: pcie@ffe0a000 {
-               status = "disabled";
-       };
-};
index c3344b04d8ff5f5aa52542f4c44299bbda851c30..873da350d01ba6556b136c99a49ffe2569428fb3 100644 (file)
                        compatible = "dallas,ds1339";
                        reg = <0x68>;
                };
+               adt7461@4c {
+                       compatible = "adi,adt7461";
+                       reg = <0x4c>;
+               };
        };
 
        spi@7000 {
diff --git a/arch/powerpc/boot/dts/p1022rdk.dts b/arch/powerpc/boot/dts/p1022rdk.dts
new file mode 100644 (file)
index 0000000..51d82de
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * P1022 RDK 32-bit Physical Address Map Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/include/ "fsl/p1022si-pre.dtsi"
+/ {
+       model = "fsl,P1022RDK";
+       compatible = "fsl,P1022RDK";
+
+       memory {
+               device_type = "memory";
+       };
+
+       board_lbc: lbc: localbus@ffe05000 {
+               /* The P1022 RDK does not have any localbus devices */
+               status = "disabled";
+       };
+
+       board_soc: soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+
+               i2c@3100 {
+                       wm8960:codec@1a {
+                               compatible = "wlf,wm8960";
+                               reg = <0x1a>;
+                               /* MCLK source is a stand-alone oscillator */
+                               clock-frequency = <12288000>;
+                       };
+                       rtc@68 {
+                               compatible = "stm,m41t62";
+                               reg = <0x68>;
+                       };
+                       adt7461@4c{
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+                       zl6100@21{
+                               compatible = "isil,zl6100";
+                               reg = <0x21>;
+                       };
+                       zl6100@24{
+                               compatible = "isil,zl6100";
+                               reg = <0x24>;
+                       };
+                       zl6100@26{
+                               compatible = "isil,zl6100";
+                               reg = <0x26>;
+                       };
+                       zl6100@29{
+                               compatible = "isil,zl6100";
+                               reg = <0x29>;
+                       };
+               };
+
+               spi@7000 {
+                       flash@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,m25p80";
+                               reg = <0>;
+                               spi-max-frequency = <1000000>;
+                               partition@0 {
+                                       label = "full-spi-flash";
+                                       reg = <0x00000000 0x00100000>;
+                               };
+                       };
+               };
+
+               ssi@15000 {
+                       fsl,mode = "i2s-slave";
+                       codec-handle = <&wm8960>;
+               };
+
+               usb@22000 {
+                       phy_type = "ulpi";
+               };
+
+               usb@23000 {
+                       phy_type = "ulpi";
+               };
+
+               mdio@24000 {
+                       phy0: ethernet-phy@0 {
+                               interrupts = <3 1 0 0>;
+                               reg = <0x1>;
+                       };
+                       phy1: ethernet-phy@1 {
+                               interrupts = <9 1 0 0>;
+                               reg = <0x2>;
+                       };
+               };
+
+               mdio@25000 {
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               ethernet@b0000 {
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               ethernet@b1000 {
+                       phy-handle = <&phy1>;
+                       tbi-handle = <&tbi0>;
+                       phy-connection-type = "sgmii";
+               };
+       };
+
+       pci0: pcie@ffe09000 {
+               ranges = <0x2000000 0x0 0xe0000000 0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+               reg = <0x0 0xffe09000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               ranges = <0x2000000 0x0 0xe0000000 0 0xc0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+               reg = <0 0xffe0a000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci2: pcie@ffe0b000 {
+               ranges = <0x2000000 0x0 0xe0000000 0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+               reg = <0 0xffe0b000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "fsl/p1022si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
deleted file mode 100644 (file)
index 66aac86..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * P2020 RDB  Core0 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb,
- * eth1, eth2, sdhc, crypto, global-util, pci0.
- *
- * Copyright 2009-2011 Freescale Semiconductor Inc.
- *
- * 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/ "p2020rdb.dts"
-
-/ {
-       model = "fsl,P2020RDB";
-       compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
-
-       cpus {
-               PowerPC,P2020@1 {
-                       status = "disabled";
-               };
-       };
-
-       localbus@ffe05000 {
-               status = "disabled";
-       };
-
-       soc@ffe00000 {
-               serial1: serial@4600 {
-                       status = "disabled";
-               };
-
-               dma@c300 {
-                       status = "disabled";
-               };
-
-               enet0: ethernet@24000 {
-                       status = "disabled";
-               };
-
-               mpic: pic@40000 {
-                       protected-sources = <
-                       42 76 77 78 79 /* serial1 , dma2 */
-                       29 30 34 26 /* enet0, pci1 */
-                       0xe0 0xe1 0xe2 0xe3 /* msi */
-                       0xe4 0xe5 0xe6 0xe7
-                       >;
-               };
-
-               msi@41600 {
-                       status = "disabled";
-               };
-       };
-
-       pci0: pcie@ffe08000 {
-               status = "disabled";
-       };
-
-       pci2: pcie@ffe0a000 {
-               status = "disabled";
-       };
-};
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
deleted file mode 100644 (file)
index 9bd8ef4..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * P2020 RDB Core1 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts allows core1 to have l2, dma2, eth0, pci1, msi.
- *
- * Please note to add "-b 1" for core1's dts compiling.
- *
- * Copyright 2009-2011 Freescale Semiconductor Inc.
- *
- * 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/ "p2020rdb.dts"
-
-/ {
-       model = "fsl,P2020RDB";
-       compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
-
-       cpus {
-               PowerPC,P2020@0 {
-                       status = "disabled";
-               };
-       };
-
-       localbus@ffe05000 {
-               status = "disabled";
-       };
-
-       soc@ffe00000 {
-               ecm-law@0 {
-                       status = "disabled";
-               };
-
-               ecm@1000 {
-                       status = "disabled";
-               };
-
-               memory-controller@2000 {
-                       status = "disabled";
-               };
-
-               i2c@3000 {
-                       status = "disabled";
-               };
-
-               i2c@3100 {
-                       status = "disabled";
-               };
-
-               serial0: serial@4500 {
-                       status = "disabled";
-               };
-
-               spi@7000 {
-                       status = "disabled";
-               };
-
-               gpio: gpio-controller@f000 {
-                       status = "disabled";
-               };
-
-               dma@21300 {
-                       status = "disabled";
-               };
-
-               usb@22000 {
-                       status = "disabled";
-               };
-
-               mdio@24520 {
-                       status = "disabled";
-               };
-
-               mdio@25520 {
-                       status = "disabled";
-               };
-
-               mdio@26520 {
-                       status = "disabled";
-               };
-
-               enet1: ethernet@25000 {
-                       status = "disabled";
-               };
-
-               enet2: ethernet@26000 {
-                       status = "disabled";
-               };
-
-               sdhci@2e000 {
-                       status = "disabled";
-               };
-
-               crypto@30000 {
-                       status = "disabled";
-               };
-
-               mpic: pic@40000 {
-                       protected-sources = <
-                       17 18 43 42 59 47 /*ecm, mem, i2c, serial0, spi,gpio */
-                       16 20 21 22 23 28       /* L2, dma1, USB */
-                       03 35 36 40 31 32 33    /* mdio, enet1, enet2 */
-                       72 45 58 25             /* sdhci, crypto , pci */
-                       >;
-               };
-
-               global-utilities@e0000 {        //global utilities block
-                       status = "disabled";
-               };
-
-       };
-
-       pci0: pcie@ffe08000 {
-               status = "disabled";
-       };
-
-       pci1: pcie@ffe09000 {
-               status = "disabled";
-       };
-};
index baab0347dab0167925a641883c69b320963e765b..d97ad74c72793bf8cac52449829aa72c774afec7 100644 (file)
                                compatible = "pericom,pt7c4338";
                                reg = <0x68>;
                        };
+                       adt7461@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
                };
 
                i2c@118100 {
index 6cdcadc80c3074db1a667a0a52f952e5ce7558c8..2fed3bc0b990daa9d55590e1a64d1b3d671b8eb1 100644 (file)
                                reg = <0x68>;
                                interrupts = <0x1 0x1 0 0>;
                        };
+                       adt7461@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
                };
        };
 
index 3e204609d02e51905183ca21478ab6ae69e99459..1cf6148b8b054785b139433c24c609c7c37aafd9 100644 (file)
                                reg = <0x68>;
                                interrupts = <0x1 0x1 0 0>;
                        };
+                       adt7461@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
                };
 
                usb0: usb@210000 {
index 27c07ed6adc1490921bceabcd6be5dac1cdb58b2..2869fea717dd7fa5b3d470df6452523cf460530b 100644 (file)
                                reg = <0x68>;
                                interrupts = <0x1 0x1 0 0>;
                        };
+                       adt7461@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
                };
        };
 
diff --git a/arch/powerpc/boot/dts/p5040ds.dts b/arch/powerpc/boot/dts/p5040ds.dts
new file mode 100644 (file)
index 0000000..860b5cc
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * P5040DS Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/include/ "fsl/p5040si-pre.dtsi"
+
+/ {
+       model = "fsl,P5040DS";
+       compatible = "fsl,P5040DS";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       memory {
+               device_type = "memory";
+       };
+
+       dcsr: dcsr@f00000000 {
+               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+       };
+
+       soc: soc@ffe000000 {
+               ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+               reg = <0xf 0xfe000000 0 0x00001000>;
+               spi@110000 {
+                       flash@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "spansion,s25sl12801";
+                               reg = <0>;
+                               spi-max-frequency = <40000000>; /* input clock */
+                               partition@u-boot {
+                                       label = "u-boot";
+                                       reg = <0x00000000 0x00100000>;
+                               };
+                               partition@kernel {
+                                       label = "kernel";
+                                       reg = <0x00100000 0x00500000>;
+                               };
+                               partition@dtb {
+                                       label = "dtb";
+                                       reg = <0x00600000 0x00100000>;
+                               };
+                               partition@fs {
+                                       label = "file system";
+                                       reg = <0x00700000 0x00900000>;
+                               };
+                       };
+               };
+
+               i2c@118100 {
+                       eeprom@51 {
+                               compatible = "at24,24c256";
+                               reg = <0x51>;
+                       };
+                       eeprom@52 {
+                               compatible = "at24,24c256";
+                               reg = <0x52>;
+                       };
+               };
+
+               i2c@119100 {
+                       rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                               interrupts = <0x1 0x1 0 0>;
+                       };
+                       adt7461@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+               };
+       };
+
+       lbc: localbus@ffe124000 {
+               reg = <0xf 0xfe124000 0 0x1000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         2 0 0xf 0xffa00000 0x00040000
+                         3 0 0xf 0xffdf0000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x08000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+               };
+
+               nand@2,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,elbc-fcm-nand";
+                       reg = <0x2 0x0 0x40000>;
+
+                       partition@0 {
+                               label = "NAND U-Boot Image";
+                               reg = <0x0 0x02000000>;
+                       };
+
+                       partition@2000000 {
+                               label = "NAND Root File System";
+                               reg = <0x02000000 0x10000000>;
+                       };
+
+                       partition@12000000 {
+                               label = "NAND Compressed RFS Image";
+                               reg = <0x12000000 0x08000000>;
+                       };
+
+                       partition@1a000000 {
+                               label = "NAND Linux Kernel Image";
+                               reg = <0x1a000000 0x04000000>;
+                       };
+
+                       partition@1e000000 {
+                               label = "NAND DTB Image";
+                               reg = <0x1e000000 0x01000000>;
+                       };
+
+                       partition@1f000000 {
+                               label = "NAND Writable User area";
+                               reg = <0x1f000000 0x01000000>;
+                       };
+               };
+
+               board-control@3,0 {
+                       compatible = "fsl,p5040ds-fpga", "fsl,fpga-ngpixis";
+                       reg = <3 0 0x40>;
+               };
+       };
+
+       pci0: pcie@ffe200000 {
+               reg = <0xf 0xfe200000 0 0x1000>;
+               ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+
+       pci1: pcie@ffe201000 {
+               reg = <0xf 0xfe201000 0 0x1000>;
+               ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+
+       pci2: pcie@ffe202000 {
+               reg = <0xf 0xfe202000 0 0x1000>;
+               ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+                         0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+               pcie@0 {
+                       ranges = <0x02000000 0 0xe0000000
+                                 0x02000000 0 0xe0000000
+                                 0 0x20000000
+
+                                 0x01000000 0 0x00000000
+                                 0x01000000 0 0x00000000
+                                 0 0x00010000>;
+               };
+       };
+};
+
+/include/ "fsl/p5040si-post.dtsi"
index 26e541c4662b27ce2c4429a2325083f8f065bf35..b80bcc69d1f79963c9e4595388e8af6bffe35a16 100644 (file)
@@ -112,6 +112,12 @@ CONFIG_SND=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_STORAGE=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
index 8b3d57c1ebe81312673642db4765408a7de5c322..1c0f2432ecdb9b6343851a464e85902808bdcbdd 100644 (file)
@@ -27,6 +27,7 @@ CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
+CONFIG_P5040_DS=y
 CONFIG_HIGHMEM=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
index 0516e22ca3de3c16b89cdf0b4d9c7865e2d791c9..88fa5c46f66f5481e2d62dfc0e4990fff4f782f3 100644 (file)
@@ -23,6 +23,7 @@ CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_P5020_DS=y
+CONFIG_P5040_DS=y
 # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_IRQ_ALL_CPUS=y
index 8b5bda27d248047b43d59ffdd9af22922e599936..cf815e847cdc78f29804ec89f8d096358413ee90 100644 (file)
@@ -30,6 +30,7 @@ CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1022_RDK=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
index b0974e7e98aefc6f4e7b39a0025c3435e5ebafe1..502cd9e027e460bb56a17f818b588907cebf1add 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1022_RDK=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
index de7c4c53f5cf4746659fb646f116c2fa25a964d2..6d03530b75065b96d5c54aacd5a9d991f0d46ec9 100644 (file)
@@ -51,6 +51,7 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_PCCARD=y
 CONFIG_ELECTRA_CF=y
 CONFIG_HOTPLUG_PCI=m
index 9f4a9368f51b11a36d9c0b2d053819a294d3e6f2..1f710a32ffae840e4fca8af13e13b4607410b5c6 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_HOTPLUG_PCI=m
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
diff --git a/arch/powerpc/include/asm/abs_addr.h b/arch/powerpc/include/asm/abs_addr.h
deleted file mode 100644 (file)
index 9d92ba0..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _ASM_POWERPC_ABS_ADDR_H
-#define _ASM_POWERPC_ABS_ADDR_H
-#ifdef __KERNEL__
-
-
-/*
- * c 2001 PPC 64 Team, IBM Corp
- *
- * 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/memblock.h>
-
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/prom.h>
-
-struct mschunks_map {
-        unsigned long num_chunks;
-        unsigned long chunk_size;
-        unsigned long chunk_shift;
-        unsigned long chunk_mask;
-        u32 *mapping;
-};
-
-extern struct mschunks_map mschunks_map;
-
-/* Chunks are 256 KB */
-#define MSCHUNKS_CHUNK_SHIFT   (18)
-#define MSCHUNKS_CHUNK_SIZE    (1UL << MSCHUNKS_CHUNK_SHIFT)
-#define MSCHUNKS_OFFSET_MASK   (MSCHUNKS_CHUNK_SIZE - 1)
-
-static inline unsigned long chunk_to_addr(unsigned long chunk)
-{
-       return chunk << MSCHUNKS_CHUNK_SHIFT;
-}
-
-static inline unsigned long addr_to_chunk(unsigned long addr)
-{
-       return addr >> MSCHUNKS_CHUNK_SHIFT;
-}
-
-static inline unsigned long phys_to_abs(unsigned long pa)
-{
-       return pa;
-}
-
-/* Convenience macros */
-#define virt_to_abs(va) phys_to_abs(__pa(va))
-#define abs_to_virt(aa) __va(aa)
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_ABS_ADDR_H */
index efdc92618b38ddfa7da075a53fb3ba93e9c71dae..dc2cf9c6d9e65cc0a3592ce8275dcb114b6d6401 100644 (file)
@@ -288,6 +288,16 @@ static __inline__ int test_bit_le(unsigned long nr,
        return (tmp[nr >> 3] >> (nr & 7)) & 1;
 }
 
+static inline void set_bit_le(int nr, void *addr)
+{
+       set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+       clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
 static inline void __set_bit_le(int nr, void *addr)
 {
        __set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
index ab9e402518e84bc23ef512b8d431c6fa9775f583..b843e35122e8934d7ea902e71ef0cae36f670611 100644 (file)
@@ -30,6 +30,8 @@ extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
+extern void __flush_disable_L1(void);
+
 extern void __flush_icache_range(unsigned long, unsigned long);
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
index 88e602f6430d0b7575c69d2b109d003adb6d3949..84fdf6857c31d1ccf878911b416f32e104eba8fb 100644 (file)
@@ -38,6 +38,7 @@ typedef s64           compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64            compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -114,6 +115,64 @@ typedef u32                compat_old_sigset_t;
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32  (128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               int _pad[SI_PAD_SIZE32];
+
+               /* kill() */
+               struct {
+                       compat_pid_t _pid;              /* sender's pid */
+                       __compat_uid_t _uid;            /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;            /* timer id */
+                       int _overrun;                   /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;              /* sender's pid */
+                       __compat_uid_t _uid;            /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       compat_pid_t _pid;              /* which child */
+                       __compat_uid_t _uid;            /* sender's uid */
+                       int _status;                    /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+               struct {
+                       unsigned int _addr; /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -123,7 +182,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index 716d2f089eb61966e18f20af66e893cb0543cb49..32de2577bb6d6630ff77e58254df6d1218f0230d 100644 (file)
@@ -44,7 +44,7 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
-extern int set_dabr(unsigned long dabr);
+extern int set_dabr(unsigned long dabr, unsigned long dabrx);
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 extern void do_send_trap(struct pt_regs *regs, unsigned long address,
                         unsigned long error_code, int signal_code, int brkpt);
index d60f99814ffb70ea92c9151211004f4b2cec7802..b0ef73882b3847763117f7b0ccb6a123a227e9a5 100644 (file)
@@ -31,6 +31,46 @@ struct device_node;
 
 #ifdef CONFIG_EEH
 
+/*
+ * The struct is used to trace PE related EEH functionality.
+ * In theory, there will have one instance of the struct to
+ * be created against particular PE. In nature, PEs corelate
+ * to each other. the struct has to reflect that hierarchy in
+ * order to easily pick up those affected PEs when one particular
+ * PE has EEH errors.
+ *
+ * Also, one particular PE might be composed of PCI device, PCI
+ * bus and its subordinate components. The struct also need ship
+ * the information. Further more, one particular PE is only meaingful
+ * in the corresponding PHB. Therefore, the root PEs should be created
+ * against existing PHBs in on-to-one fashion.
+ */
+#define EEH_PE_INVALID (1 << 0)        /* Invalid   */
+#define EEH_PE_PHB     (1 << 1)        /* PHB PE    */
+#define EEH_PE_DEVICE  (1 << 2)        /* Device PE */
+#define EEH_PE_BUS     (1 << 3)        /* Bus PE    */
+
+#define EEH_PE_ISOLATED                (1 << 0)        /* Isolated PE          */
+#define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
+
+struct eeh_pe {
+       int type;                       /* PE type: PHB/Bus/Device      */
+       int state;                      /* PE EEH dependent mode        */
+       int config_addr;                /* Traditional PCI address      */
+       int addr;                       /* PE configuration address     */
+       struct pci_controller *phb;     /* Associated PHB               */
+       int check_count;                /* Times of ignored error       */
+       int freeze_count;               /* Times of froze up            */
+       int false_positives;            /* Times of reported #ff's      */
+       struct eeh_pe *parent;          /* Parent PE                    */
+       struct list_head child_list;    /* Link PE to the child list    */
+       struct list_head edevs;         /* Link list of EEH devices     */
+       struct list_head child;         /* Child PEs                    */
+};
+
+#define eeh_pe_for_each_dev(pe, edev) \
+               list_for_each_entry(edev, &pe->edevs, list)
+
 /*
  * The struct is used to trace EEH state for the associated
  * PCI device node or PCI device. In future, it might
@@ -38,21 +78,16 @@ struct device_node;
  * another tree except the currently existing tree of PCI
  * buses and PCI devices
  */
-#define EEH_MODE_SUPPORTED     (1<<0)  /* EEH supported on the device  */
-#define EEH_MODE_NOCHECK       (1<<1)  /* EEH check should be skipped  */
-#define EEH_MODE_ISOLATED      (1<<2)  /* The device has been isolated */
-#define EEH_MODE_RECOVERING    (1<<3)  /* Recovering the device        */
-#define EEH_MODE_IRQ_DISABLED  (1<<4)  /* Interrupt disabled           */
+#define EEH_DEV_IRQ_DISABLED   (1<<0)  /* Interrupt disabled           */
 
 struct eeh_dev {
        int mode;                       /* EEH mode                     */
        int class_code;                 /* Class code of the device     */
        int config_addr;                /* Config address               */
        int pe_config_addr;             /* PE config address            */
-       int check_count;                /* Times of ignored error       */
-       int freeze_count;               /* Times of froze up            */
-       int false_positives;            /* Times of reported #ff's      */
        u32 config_space[16];           /* Saved PCI config space       */
+       struct eeh_pe *pe;              /* Associated PE                */
+       struct list_head list;          /* Form link list in the PE     */
        struct pci_controller *phb;     /* Associated PHB               */
        struct device_node *dn;         /* Associated device node       */
        struct pci_dev *pdev;           /* Associated PCI device        */
@@ -95,19 +130,51 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
 struct eeh_ops {
        char *name;
        int (*init)(void);
-       int (*set_option)(struct device_node *dn, int option);
-       int (*get_pe_addr)(struct device_node *dn);
-       int (*get_state)(struct device_node *dn, int *state);
-       int (*reset)(struct device_node *dn, int option);
-       int (*wait_state)(struct device_node *dn, int max_wait);
-       int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len);
-       int (*configure_bridge)(struct device_node *dn);
+       void* (*of_probe)(struct device_node *dn, void *flag);
+       void* (*dev_probe)(struct pci_dev *dev, void *flag);
+       int (*set_option)(struct eeh_pe *pe, int option);
+       int (*get_pe_addr)(struct eeh_pe *pe);
+       int (*get_state)(struct eeh_pe *pe, int *state);
+       int (*reset)(struct eeh_pe *pe, int option);
+       int (*wait_state)(struct eeh_pe *pe, int max_wait);
+       int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len);
+       int (*configure_bridge)(struct eeh_pe *pe);
        int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
        int (*write_config)(struct device_node *dn, int where, int size, u32 val);
 };
 
 extern struct eeh_ops *eeh_ops;
 extern int eeh_subsystem_enabled;
+extern struct mutex eeh_mutex;
+extern int eeh_probe_mode;
+
+#define EEH_PROBE_MODE_DEV     (1<<0)  /* From PCI device      */
+#define EEH_PROBE_MODE_DEVTREE (1<<1)  /* From device tree     */
+
+static inline void eeh_probe_mode_set(int flag)
+{
+       eeh_probe_mode = flag;
+}
+
+static inline int eeh_probe_mode_devtree(void)
+{
+       return (eeh_probe_mode == EEH_PROBE_MODE_DEVTREE);
+}
+
+static inline int eeh_probe_mode_dev(void)
+{
+       return (eeh_probe_mode == EEH_PROBE_MODE_DEV);
+}
+
+static inline void eeh_lock(void)
+{
+       mutex_lock(&eeh_mutex);
+}
+
+static inline void eeh_unlock(void)
+{
+       mutex_unlock(&eeh_mutex);
+}
 
 /*
  * Max number of EEH freezes allowed before we consider the device
@@ -115,22 +182,26 @@ extern int eeh_subsystem_enabled;
  */
 #define EEH_MAX_ALLOWED_FREEZES 5
 
+typedef void *(*eeh_traverse_func)(void *data, void *flag);
+int __devinit eeh_phb_pe_create(struct pci_controller *phb);
+int eeh_add_to_parent_pe(struct eeh_dev *edev);
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+               eeh_traverse_func fn, void *flag);
+void eeh_pe_restore_bars(struct eeh_pe *pe);
+struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
+
 void * __devinit eeh_dev_init(struct device_node *dn, void *data);
 void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);
-void __init eeh_dev_phb_init(void);
-void __init eeh_init(void);
-#ifdef CONFIG_PPC_PSERIES
-int __init eeh_pseries_init(void);
-#endif
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
 unsigned long eeh_check_failure(const volatile void __iomem *token,
                                unsigned long val);
-int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);
-void __init pci_addr_cache_build(void);
+int eeh_dev_check_failure(struct eeh_dev *edev);
+void __init eeh_addr_cache_build(void);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
-void eeh_remove_bus_device(struct pci_dev *);
+void eeh_remove_bus_device(struct pci_dev *, int);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -156,34 +227,24 @@ static inline void *eeh_dev_init(struct device_node *dn, void *data)
 
 static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
 
-static inline void eeh_dev_phb_init(void) { }
-
-static inline void eeh_init(void) { }
-
-#ifdef CONFIG_PPC_PSERIES
-static inline int eeh_pseries_init(void)
-{
-       return 0;
-}
-#endif /* CONFIG_PPC_PSERIES */
-
 static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
 {
        return val;
 }
 
-static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
-{
-       return 0;
-}
+#define eeh_dev_check_failure(x) (0)
 
-static inline void pci_addr_cache_build(void) { }
+static inline void eeh_addr_cache_build(void) { }
 
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
 
-static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
+static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
+
+static inline void eeh_lock(void) { }
+static inline void eeh_unlock(void) { }
+
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
 #endif /* CONFIG_EEH */
index c68b012b7797b0144956c951cd90b9cab92713ab..de67d830151be7f9cf3067a2a5768eeb48fed6af 100644 (file)
  */
 struct eeh_event {
        struct list_head        list;   /* to form event queue  */
-       struct eeh_dev          *edev;  /* EEH device           */
+       struct eeh_pe           *pe;    /* EEH PE               */
 };
 
-int eeh_send_failure_event(struct eeh_dev *edev);
-struct eeh_dev *handle_eeh_events(struct eeh_event *);
+int eeh_send_failure_event(struct eeh_pe *pe);
+void eeh_handle_event(struct eeh_pe *pe);
 
 #endif /* __KERNEL__ */
 #endif /* ASM_POWERPC_EEH_EVENT_H */
index ac13addb849582e7dc450d3e9b7a091c1ddcf4de..51fa43e536b917c08c5870525c9a81063c1448e2 100644 (file)
@@ -37,6 +37,7 @@
  * critical data
  */
 
+#define PACA_EXGDBELL PACA_EXGEN
 
 /* We are out of SPRGs so we save some things in the PACA. The normal
  * exception frame is smaller than the CRIT or MC one though
@@ -45,8 +46,9 @@
 #define EX_CR          (1 * 8)
 #define EX_R10         (2 * 8)
 #define EX_R11         (3 * 8)
-#define EX_R14         (4 * 8)
-#define EX_R15         (5 * 8)
+#define EX_R13         (4 * 8)
+#define EX_R14         (5 * 8)
+#define EX_R15         (6 * 8)
 
 /*
  * The TLB miss exception uses different slots.
index aa4c488589ce51b7bbdf1089db7282e69bfaccad..dd5ba2c227712c79ffb574f6ecc2232c0ba91fda 100644 (file)
@@ -48,6 +48,8 @@ struct ccsr_guts {
         __be32  dmuxcr;                /* 0x.0068 - DMA Mux Control Register */
         u8     res06c[0x70 - 0x6c];
        __be32  devdisr;        /* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1  0x00001000
+#define CCSR_GUTS_DEVDISR_TB0  0x00004000
        __be32  devdisr2;       /* 0x.0074 - Device Disable Control 2 */
        u8      res078[0x7c - 0x78];
        __be32  pmjcr;          /* 0x.007c - 4 Power Management Jog Control Register */
index b955012939a2708c7b650347823345f030d2921d..b8a4b9bc50b326b07efda9e6f82e59e16be3e318 100644 (file)
@@ -768,22 +768,24 @@ struct fsl_ifc_gpcm {
  */
 struct fsl_ifc_regs {
        __be32 ifc_rev;
-       u32 res1[0x3];
+       u32 res1[0x2];
        struct {
+               __be32 cspr_ext;
                __be32 cspr;
-               u32 res2[0x2];
+               u32 res2;
        } cspr_cs[FSL_IFC_BANK_COUNT];
-       u32 res3[0x18];
+       u32 res3[0x19];
        struct {
                __be32 amask;
                u32 res4[0x2];
        } amask_cs[FSL_IFC_BANK_COUNT];
-       u32 res5[0x18];
+       u32 res5[0x17];
        struct {
+               __be32 csor_ext;
                __be32 csor;
-               u32 res6[0x2];
+               u32 res6;
        } csor_cs[FSL_IFC_BANK_COUNT];
-       u32 res7[0x18];
+       u32 res7[0x19];
        struct {
                __be32 ftim[4];
                u32 res8[0x8];
index 423cf9eaf4a4fddf35811e62de33dc16363812e5..7a867065db79a8286578180abc2e8a4d36272885 100644 (file)
 #define H_VASI_RESUMED          5
 #define H_VASI_COMPLETED        6
 
-/* DABRX flags */
-#define H_DABRX_HYPERVISOR     (1UL<<(63-61))
-#define H_DABRX_KERNEL         (1UL<<(63-62))
-#define H_DABRX_USER           (1UL<<(63-63))
-
 /* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT          4096
 
index be04330af75194562e3473084fd33ec7589dd696..423424599dad9395a00f15df23ce17676be872ac 100644 (file)
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 
 struct arch_hw_breakpoint {
-       bool            extraneous_interrupt;
-       u8              len; /* length of the target data symbol */
-       int             type;
        unsigned long   address;
+       unsigned long   dabrx;
+       int             type;
+       u8              len; /* length of the target data symbol */
+       bool            extraneous_interrupt;
 };
 
 #include <linux/kdebug.h>
@@ -61,7 +62,7 @@ extern void ptrace_triggered(struct perf_event *bp,
                        struct perf_sample_data *data, struct pt_regs *regs);
 static inline void hw_breakpoint_disable(void)
 {
-       set_dabr(0);
+       set_dabr(0, 0);
 }
 extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
 
index be0171afdc0f513cfff0a8bdb22abc70de29528c..7b6feab6fd26f26cfc3c19456f163845d72db86e 100644 (file)
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
+#include <asm/probes.h>
 
 #define  __ARCH_WANT_KPROBES_INSN_SLOT
 
 struct pt_regs;
 struct kprobe;
 
-typedef unsigned int kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION 0x7fe00008      /* trap */
+typedef ppc_opcode_t kprobe_opcode_t;
 #define MAX_INSN_SIZE 1
 
-#define IS_TW(instr)           (((instr) & 0xfc0007fe) == 0x7c000008)
-#define IS_TD(instr)           (((instr) & 0xfc0007fe) == 0x7c000088)
-#define IS_TDI(instr)          (((instr) & 0xfc000000) == 0x08000000)
-#define IS_TWI(instr)          (((instr) & 0xfc000000) == 0x0c000000)
-
 #ifdef CONFIG_PPC64
 /*
  * 64bit powerpc uses function descriptors.
@@ -72,12 +67,6 @@ typedef unsigned int kprobe_opcode_t;
                addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
        }                                                               \
 }
-
-#define is_trap(instr) (IS_TW(instr) || IS_TD(instr) || \
-                       IS_TWI(instr) || IS_TDI(instr))
-#else
-/* Use stock kprobe_lookup_name since ppc32 doesn't use function descriptors */
-#define is_trap(instr) (IS_TW(instr) || IS_TWI(instr))
 #endif
 
 #define flush_insn_slot(p)     do { } while (0)
index f0e0c6a66d973fdb833138e2433b54be860dc4f3..7aefdb3e1ce405865beb991934dadfac22036724 100644 (file)
@@ -59,7 +59,7 @@ struct hpte_cache {
        struct hlist_node list_vpte;
        struct hlist_node list_vpte_long;
        struct rcu_head rcu_head;
-       u64 host_va;
+       u64 host_vpn;
        u64 pfn;
        ulong slot;
        struct kvmppc_pte pte;
index bfcd00c1485d04474c00461d4f7b9097bd624fb4..88609b23b775460c96a4d9d805feaf49fecf94a3 100644 (file)
@@ -74,7 +74,6 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
-       ulong sprg3;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
index f7706d722b39539c3559e0d858924c7703f529d9..c4231973edd351eacf480dacbdb3d1a529b1b08c 100644 (file)
@@ -34,19 +34,19 @@ struct machdep_calls {
        char            *name;
 #ifdef CONFIG_PPC64
        void            (*hpte_invalidate)(unsigned long slot,
-                                          unsigned long va,
+                                          unsigned long vpn,
                                           int psize, int ssize,
                                           int local);
        long            (*hpte_updatepp)(unsigned long slot, 
                                         unsigned long newpp, 
-                                        unsigned long va,
+                                        unsigned long vpn,
                                         int psize, int ssize,
                                         int local);
        void            (*hpte_updateboltedpp)(unsigned long newpp, 
                                               unsigned long ea,
                                               int psize, int ssize);
        long            (*hpte_insert)(unsigned long hpte_group,
-                                      unsigned long va,
+                                      unsigned long vpn,
                                       unsigned long prpn,
                                       unsigned long rflags,
                                       unsigned long vflags,
@@ -180,7 +180,8 @@ struct machdep_calls {
        void            (*enable_pmcs)(void);
 
        /* Set DABR for this platform, leave empty for default implemenation */
-       int             (*set_dabr)(unsigned long dabr);
+       int             (*set_dabr)(unsigned long dabr,
+                                   unsigned long dabrx);
 
 #ifdef CONFIG_PPC32    /* XXX for now */
        /* A general init function, called by ppc_init in init/main.c.
index 1c65a59881eae6ad5fc237b12f424d47a0caddca..9673f73eb8db2294159a3356266b97c7df6734c2 100644 (file)
 #include <asm/asm-compat.h>
 #include <asm/page.h>
 
+/*
+ * This is necessary to get the definition of PGTABLE_RANGE which we
+ * need for various slices related matters. Note that this isn't the
+ * complete pgtable.h but only a portion of it.
+ */
+#include <asm/pgtable-ppc64.h>
+
 /*
  * Segment table
  */
@@ -154,9 +161,25 @@ struct mmu_psize_def
 #define MMU_SEGSIZE_256M       0
 #define MMU_SEGSIZE_1T         1
 
+/*
+ * encode page number shift.
+ * in order to fit the 78 bit va in a 64 bit variable we shift the va by
+ * 12 bits. This enable us to address upto 76 bit va.
+ * For hpt hash from a va we can ignore the page size bits of va and for
+ * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
+ * we work in all cases including 4k page size.
+ */
+#define VPN_SHIFT      12
 
 #ifndef __ASSEMBLY__
 
+static inline int segment_shift(int ssize)
+{
+       if (ssize == MMU_SEGSIZE_256M)
+               return SID_SHIFT;
+       return SID_SHIFT_1T;
+}
+
 /*
  * The current system page and segment sizes
  */
@@ -179,19 +202,40 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
  */
 extern int mmu_ci_restrictions;
 
+/*
+ * This computes the AVPN and B fields of the first dword of a HPTE,
+ * for use when we want to match an existing PTE.  The bottom 7 bits
+ * of the returned value are zero.
+ */
+static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
+                                            int ssize)
+{
+       unsigned long v;
+       /*
+        * The AVA field omits the low-order 23 bits of the 78 bits VA.
+        * These bits are not needed in the PTE, because the
+        * low-order b of these bits are part of the byte offset
+        * into the virtual page and, if b < 23, the high-order
+        * 23-b of these bits are always used in selecting the
+        * PTEGs to be searched
+        */
+       v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
+       v <<= HPTE_V_AVPN_SHIFT;
+       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+       return v;
+}
+
 /*
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * for the page size
  */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize,
-                                         int ssize)
+static inline unsigned long hpte_encode_v(unsigned long vpn,
+                                         int psize, int ssize)
 {
        unsigned long v;
-       v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-       v <<= HPTE_V_AVPN_SHIFT;
+       v = hpte_encode_avpn(vpn, psize, ssize);
        if (psize != MMU_PAGE_4K)
                v |= HPTE_V_LARGE;
-       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
        return v;
 }
 
@@ -216,30 +260,37 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
 }
 
 /*
- * Build a VA given VSID, EA and segment size
+ * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
  */
-static inline unsigned long hpt_va(unsigned long ea, unsigned long vsid,
-                                  int ssize)
+static inline unsigned long hpt_vpn(unsigned long ea,
+                                   unsigned long vsid, int ssize)
 {
-       if (ssize == MMU_SEGSIZE_256M)
-               return (vsid << 28) | (ea & 0xfffffffUL);
-       return (vsid << 40) | (ea & 0xffffffffffUL);
+       unsigned long mask;
+       int s_shift = segment_shift(ssize);
+
+       mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
+       return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
 }
 
 /*
  * This hashes a virtual address
  */
-
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift,
-                                    int ssize)
+static inline unsigned long hpt_hash(unsigned long vpn,
+                                    unsigned int shift, int ssize)
 {
+       int mask;
        unsigned long hash, vsid;
 
+       /* VPN_SHIFT can be atmost 12 */
        if (ssize == MMU_SEGSIZE_256M) {
-               hash = (va >> 28) ^ ((va & 0x0fffffffUL) >> shift);
+               mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
+               hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT));
        } else {
-               vsid = va >> 40;
-               hash = vsid ^ (vsid << 25) ^ ((va & 0xffffffffffUL) >> shift);
+               mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
+               vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
+               hash = vsid ^ (vsid << 25) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT)) ;
        }
        return hash & 0x7fffffffffUL;
 }
@@ -280,63 +331,61 @@ extern void slb_set_size(u16 size);
 #endif /* __ASSEMBLY__ */
 
 /*
- * VSID allocation
+ * VSID allocation (256MB segment)
+ *
+ * We first generate a 38-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID | 1 << 37, for user addresses it is:
+ *     (context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
  *
- * We first generate a 36-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- *     (context << 15) | (esid & 0x7fff)
+ * This splits the proto-VSID into the below range
+ *  0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range
+ *  2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range
  *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
+ * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1
+ * That is, we assign half of the space to user processes and half
+ * to the kernel.
  *
  * The proto-VSIDs are then scrambled into real VSIDs with the
  * multiplicative hash:
  *
  *     VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *     where   VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- *             VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
  *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * VSID_MULTIPLIER is prime, so in particular it is
  * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
  * Because the modulus is 2^n-1 we can compute it efficiently without
  * a divide or extra multiply (see below).
  *
  * This scheme has several advantages over older methods:
  *
- *     - We have VSIDs allocated for every kernel address
+ *     - We have VSIDs allocated for every kernel address
  * (i.e. everything above 0xC000000000000000), except the very top
  * segment, which simplifies several things.
  *
- *     - We allow for 16 significant bits of ESID and 19 bits of
- * context for user addresses.  i.e. 16T (44 bits) of address space for
- * up to half a million contexts.
+ *     - We allow for USER_ESID_BITS significant bits of ESID and
+ * CONTEXT_BITS  bits of context for user addresses.
+ *  i.e. 64T (46 bits) of address space for up to half a million contexts.
  *
- *     - The scramble function gives robust scattering in the hash
+ *     - The scramble function gives robust scattering in the hash
  * table (at least based on some initial results).  The previous
  * method was more susceptible to pathological cases giving excessive
  * hash collisions.
  */
+
 /*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate (slb_low.S), do_stab_bolted
- * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ * This should be computed such that protovosid * vsid_mulitplier
+ * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
  */
-
-#define VSID_MULTIPLIER_256M   ASM_CONST(200730139)    /* 28-bit prime */
-#define VSID_BITS_256M         36
+#define VSID_MULTIPLIER_256M   ASM_CONST(12538073)     /* 24-bit prime */
+#define VSID_BITS_256M         38
 #define VSID_MODULUS_256M      ((1UL<<VSID_BITS_256M)-1)
 
 #define VSID_MULTIPLIER_1T     ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_1T           24
+#define VSID_BITS_1T           26
 #define VSID_MODULUS_1T                ((1UL<<VSID_BITS_1T)-1)
 
 #define CONTEXT_BITS           19
-#define USER_ESID_BITS         16
-#define USER_ESID_BITS_1T      4
+#define USER_ESID_BITS         18
+#define USER_ESID_BITS_1T      6
 
 #define USER_VSID_RANGE        (1UL << (USER_ESID_BITS + SID_SHIFT))
 
@@ -372,6 +421,8 @@ extern void slb_set_size(u16 size);
        srdi    rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */   \
        add     rt,rt,rx
 
+/* 4 bits per slice and we have one slice per 1TB */
+#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
 
 #ifndef __ASSEMBLY__
 
@@ -416,7 +467,7 @@ typedef struct {
 
 #ifdef CONFIG_PPC_MM_SLICES
        u64 low_slices_psize;   /* SLB page size encodings */
-       u64 high_slices_psize;  /* 4 bits per slice for now */
+       unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
 #else
        u16 sllp;               /* SLB page size encoding */
 #endif
@@ -452,12 +503,32 @@ typedef struct {
        })
 #endif /* 1 */
 
-/* This is only valid for addresses >= PAGE_OFFSET */
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ * The proto-VSID space is divided into two class
+ * User:   0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
+ * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
+ *
+ * With KERNEL_START at 0xc000000000000000, the proto vsid for
+ * the kernel ends up with 0xc00000000 (36 bits). With 64TB
+ * support we need to have kernel proto-VSID in the
+ * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
+ */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
-       if (ssize == MMU_SEGSIZE_256M)
-               return vsid_scramble(ea >> SID_SHIFT, 256M);
-       return vsid_scramble(ea >> SID_SHIFT_1T, 1T);
+       unsigned long proto_vsid;
+       /*
+        * We need to make sure proto_vsid for the kernel is
+        * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
+        */
+       if (ssize == MMU_SEGSIZE_256M) {
+               proto_vsid = ea >> SID_SHIFT;
+               proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
+               return vsid_scramble(proto_vsid, 256M);
+       }
+       proto_vsid = ea >> SID_SHIFT_1T;
+       proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
+       return vsid_scramble(proto_vsid, 1T);
 }
 
 /* Returns the segment size indicator for a user address */
index e8a26db2e8f320920123c4e0c0eed0eab8eb60d8..5e38eedea2186e679e989b2d8a8fd35aef897978 100644 (file)
@@ -146,6 +146,15 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 extern u64 ppc64_rma_size;
 #endif /* CONFIG_PPC64 */
 
+struct mm_struct;
+#ifdef CONFIG_DEBUG_VM
+extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
+#else /* CONFIG_DEBUG_VM */
+static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
+{
+}
+#endif /* !CONFIG_DEBUG_VM */
+
 #endif /* !__ASSEMBLY__ */
 
 /* The kernel use the constants below to index in the page sizes array.
index 1f41382eda3824b6792eedfcad1453b1c53ad4f0..0acc7c7c28d1fb0379532e951501a7e4146bf86a 100644 (file)
@@ -307,6 +307,7 @@ struct mpc52xx_lpbfifo_request {
        size_t size;
        size_t pos;     /* current position of transfer */
        int flags;
+       int defer_xfer_start;
 
        /* What to do when finished */
        void (*callback)(struct mpc52xx_lpbfifo_request *);
@@ -323,6 +324,7 @@ struct mpc52xx_lpbfifo_request {
 extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req);
 extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req);
 extern void mpc52xx_lpbfifo_poll(void);
+extern int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req);
 
 /* mpc52xx_pic.c */
 extern void mpc52xx_init_irq(void);
index c9f698a994be246860ee6cfdd6895d27d68cea7b..c0f9ef90f0b8407a22987dfe4c83c73ed0cbc1d3 100644 (file)
@@ -63,6 +63,7 @@
  */
 #define MPIC_TIMER_BASE                        0x01100
 #define MPIC_TIMER_STRIDE              0x40
+#define MPIC_TIMER_GROUP_STRIDE                0x1000
 
 #define MPIC_TIMER_CURRENT_CNT         0x00000
 #define MPIC_TIMER_BASE_CNT            0x00010
 #define        MPIC_VECPRI_SENSE_MASK                  0x00400000
 #define MPIC_IRQ_DESTINATION           0x00010
 
+#define MPIC_FSL_BRR1                  0x00000
+#define        MPIC_FSL_BRR1_VER                       0x0000ffff
+
 #define MPIC_MAX_IRQ_SOURCES   2048
 #define MPIC_MAX_CPUS          32
 #define MPIC_MAX_ISU           32
 
+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
 /*
  * Tsi108 implementation of MPIC has many differences from the original one
  */
@@ -266,6 +273,7 @@ struct mpic
        struct irq_chip         hc_ipi;
 #endif
        struct irq_chip         hc_tm;
+       struct irq_chip         hc_err;
        const char              *name;
        /* Flags */
        unsigned int            flags;
@@ -279,6 +287,8 @@ struct mpic
        /* vector numbers used for internal sources (ipi/timers) */
        unsigned int            ipi_vecs[4];
        unsigned int            timer_vecs[8];
+       /* vector numbers used for FSL MPIC error interrupts */
+       unsigned int            err_int_vecs[MPIC_MAX_ERR];
 
        /* Spurious vector to program into unused sources */
        unsigned int            spurious_vec;
@@ -296,11 +306,15 @@ struct mpic
        phys_addr_t paddr;
 
        /* The various ioremap'ed bases */
+       struct mpic_reg_bank    thiscpuregs;
        struct mpic_reg_bank    gregs;
        struct mpic_reg_bank    tmregs;
        struct mpic_reg_bank    cpuregs[MPIC_MAX_CPUS];
        struct mpic_reg_bank    isus[MPIC_MAX_ISU];
 
+       /* ioremap'ed base for error interrupt registers */
+       u32 __iomem     *err_regs;
+
        /* Protected sources */
        unsigned long           *protected;
 
@@ -365,6 +379,11 @@ struct mpic
 #define MPIC_NO_RESET                  0x00004000
 /* Freescale MPIC (compatible includes "fsl,mpic") */
 #define MPIC_FSL                       0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register).
+ * This flag is set for MPIC version >= 4.1 (version determined
+ * from the BRR1 register).
+*/
+#define MPIC_FSL_HAS_EIMR              0x00010000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK               0xf0000000
index daf813fea91fa6998322ff4d0fba63b2398f52e0..e9e7a6999bb8ed4aff7e02da633b69a606b3b264 100644 (file)
@@ -100,7 +100,7 @@ struct paca_struct {
        /* SLB related definitions */
        u16 vmalloc_sllp;
        u16 slb_cache_ptr;
-       u16 slb_cache[SLB_CACHE_ENTRIES];
+       u32 slb_cache[SLB_CACHE_ENTRIES];
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_PPC_BOOK3E
@@ -136,6 +136,7 @@ struct paca_struct {
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
        u8 nap_state_lost;              /* NV GPR values lost in power7_idle */
+       u64 sprg3;                      /* Saved user-visible sprg */
 
 #ifdef CONFIG_PPC_POWERNV
        /* Pointer to OPAL machine check event structure set by the
index fed85e6290e12c1c9cfe0249120596494b1a3fcf..cd915d6b093d9693be8a1c372d8225aca5b06103 100644 (file)
@@ -78,11 +78,19 @@ extern u64 ppc64_pft_size;
 #define GET_LOW_SLICE_INDEX(addr)      ((addr) >> SLICE_LOW_SHIFT)
 #define GET_HIGH_SLICE_INDEX(addr)     ((addr) >> SLICE_HIGH_SHIFT)
 
+/*
+ * 1 bit per slice and we have one slice per 1TB
+ * Right now we support only 64TB.
+ * IF we change this we will have to change the type
+ * of high_slices
+ */
+#define SLICE_MASK_SIZE 8
+
 #ifndef __ASSEMBLY__
 
 struct slice_mask {
        u16 low_slices;
-       u16 high_slices;
+       u64 high_slices;
 };
 
 struct mm_struct;
index 8cccbee615198881125bdde527d4e4dad1fbb2e3..025a130729bc4daab6c0ec812ec2bb7e14741468 100644 (file)
@@ -182,14 +182,25 @@ static inline int pci_device_from_OF_node(struct device_node *np,
 #if defined(CONFIG_EEH)
 static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 {
+       /*
+        * For those OF nodes whose parent isn't PCI bridge, they
+        * don't have PCI_DN actually. So we have to skip them for
+        * any EEH operations.
+        */
+       if (!dn || !PCI_DN(dn))
+               return NULL;
+
        return PCI_DN(dn)->edev;
 }
+#else
+#define of_node_to_eeh_dev(x) (NULL)
 #endif
 
 /** Find the bus corresponding to the indicated device node */
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
+extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe);
 extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
index 078019b5b353c916f49dd0d71087260302569c60..9710be3a2d1753e7fef95287d182811e5ce5a0ba 100644 (file)
@@ -49,6 +49,7 @@ struct power_pmu {
 #define PPMU_ALT_SIPR          2       /* uses alternate posn for SIPR/HV */
 #define PPMU_NO_SIPR           4       /* no SIPR/HV in MMCRA at all */
 #define PPMU_NO_CONT_SAMPLING  8       /* no continuous sampling */
+#define PPMU_SIAR_VALID                16      /* Processor has SIAR Valid bit */
 
 /*
  * Values for flags to get_alternatives()
index 6eefdcffa359fc7dd01d6abfa9d932f3c8c69605..12798c9d4b4ba5401c77c41bc605e722a11b6266 100644 (file)
@@ -7,7 +7,7 @@
  */
 #define PTE_INDEX_SIZE  9
 #define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  7
+#define PUD_INDEX_SIZE  9
 #define PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
@@ -19,7 +19,7 @@
 
 #define PTRS_PER_PTE   (1 << PTE_INDEX_SIZE)
 #define PTRS_PER_PMD   (1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PUD   (1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD   (1 << PUD_INDEX_SIZE)
 #define PTRS_PER_PGD   (1 << PGD_INDEX_SIZE)
 
 /* PMD_SHIFT determines what a second-level page table entry can map */
index 90533ddcd7035241cb14372fb8f0b2a284a64c5a..be4e2878fbc012b1443f27c08031aac6450d3d7e 100644 (file)
@@ -7,7 +7,7 @@
 #define PTE_INDEX_SIZE  12
 #define PMD_INDEX_SIZE  12
 #define PUD_INDEX_SIZE 0
-#define PGD_INDEX_SIZE  4
+#define PGD_INDEX_SIZE  6
 
 #ifndef __ASSEMBLY__
 #define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE)
index c4205616dfb50c1598b7c0446efa86a8414fcec7..0182c203e41157520866b57f0a5d1760bfe054cc 100644 (file)
 #define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
 
-/* Some sanity checking */
-#if TASK_SIZE_USER64 > PGTABLE_RANGE
-#error TASK_SIZE_USER64 exceeds pagetable range
-#endif
-
-#ifdef CONFIG_PPC_STD_MMU_64
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
-#error TASK_SIZE_USER64 exceeds user VSID range
-#endif
-#endif
-
 /*
  * Define the address range of the kernel non-linear virtual area
  */
@@ -41,7 +30,7 @@
 #else
 #define KERN_VIRT_START ASM_CONST(0xD000000000000000)
 #endif
-#define KERN_VIRT_SIZE PGTABLE_RANGE
+#define KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
 
 /*
  * The vmalloc space starts at the beginning of that region, and
 
 #ifndef __ASSEMBLY__
 
-#include <linux/stddef.h>
-#include <asm/tlbflush.h>
-
 /*
  * This is the default implementation of various PTE accessors, it's
  * used in all cases except Book3S with 64K pages where we have a
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
+extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
+                           pte_t *ptep, unsigned long pte, int huge);
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(struct mm_struct *mm,
index 2e0e4110f7ae7da0c195615fad0bda8d56ba1293..a9cbd3ba5c33936d8c1885e33bd60450adb52998 100644 (file)
@@ -9,14 +9,6 @@
 
 struct mm_struct;
 
-#ifdef CONFIG_DEBUG_VM
-extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
-#else /* CONFIG_DEBUG_VM */
-static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
-{
-}
-#endif /* !CONFIG_DEBUG_VM */
-
 #endif /* !__ASSEMBLY__ */
 
 #if defined(CONFIG_PPC64)
@@ -27,6 +19,8 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 
 #ifndef __ASSEMBLY__
 
+#include <asm/tlbflush.h>
+
 /* Generic accessors to PTE bits */
 static inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_DIRTY; }
index 4c25319f2fbcf010e8b8763f93f09fcc47014a84..5f73ce63fcaeb79a6a10d7d77b92d82ad26331db 100644 (file)
 #define PPC_INST_TLBIVAX               0x7c000624
 #define PPC_INST_TLBSRX_DOT            0x7c0006a5
 #define PPC_INST_XXLOR                 0xf0000510
+#define PPC_INST_XVCPSGNDP             0xf0000780
 
 #define PPC_INST_NAP                   0x4c000364
 #define PPC_INST_SLEEP                 0x4c0003a4
                                               VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)         stringify_in_c(.long PPC_INST_XXLOR | \
                                               VSX_XX3((t), a, b))
+#define XVCPSGNDP(t, a, b)     stringify_in_c(.long (PPC_INST_XVCPSGNDP | \
+                                              VSX_XX3((t), (a), (b))))
 
 #define PPC_NAP                        stringify_in_c(.long PPC_INST_NAP)
 #define PPC_SLEEP              stringify_in_c(.long PPC_INST_SLEEP)
index 80fa704d410fe5105bd7776776a5af9a257147ac..ed57fa7920c88dd123fcf139353489fcef4746c0 100644 (file)
@@ -47,19 +47,17 @@ extern int rtas_setup_phb(struct pci_controller *phb);
 
 #ifdef CONFIG_EEH
 
-void pci_addr_cache_build(void);
-void pci_addr_cache_insert_device(struct pci_dev *dev);
-void pci_addr_cache_remove_device(struct pci_dev *dev);
-struct pci_dev *pci_addr_cache_get_device(unsigned long addr);
-void eeh_slot_error_detail(struct eeh_dev *edev, int severity);
-int eeh_pci_enable(struct eeh_dev *edev, int function);
-int eeh_reset_pe(struct eeh_dev *);
-void eeh_restore_bars(struct eeh_dev *);
+void eeh_addr_cache_insert_dev(struct pci_dev *dev);
+void eeh_addr_cache_rmv_dev(struct pci_dev *dev);
+struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
+void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
+int eeh_pci_enable(struct eeh_pe *pe, int function);
+int eeh_reset_pe(struct eeh_pe *);
+void eeh_save_bars(struct eeh_dev *edev);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
-void eeh_mark_slot(struct device_node *dn, int mode_flag);
-void eeh_clear_slot(struct device_node *dn, int mode_flag);
-struct device_node *eeh_find_device_pe(struct device_node *dn);
+void eeh_pe_state_mark(struct eeh_pe *pe, int state);
+void eeh_pe_state_clear(struct eeh_pe *pe, int state);
 
 void eeh_sysfs_add_device(struct pci_dev *pdev);
 void eeh_sysfs_remove_device(struct pci_dev *pdev);
diff --git a/arch/powerpc/include/asm/probes.h b/arch/powerpc/include/asm/probes.h
new file mode 100644 (file)
index 0000000..5f1e15b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _ASM_POWERPC_PROBES_H
+#define _ASM_POWERPC_PROBES_H
+#ifdef __KERNEL__
+/*
+ * Definitions common to probes files
+ *
+ * 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.
+ *
+ * Copyright IBM Corporation, 2012
+ */
+#include <linux/types.h>
+
+typedef u32 ppc_opcode_t;
+#define BREAKPOINT_INSTRUCTION 0x7fe00008      /* trap */
+
+/* Trap definitions per ISA */
+#define IS_TW(instr)           (((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TD(instr)           (((instr) & 0xfc0007fe) == 0x7c000088)
+#define IS_TDI(instr)          (((instr) & 0xfc000000) == 0x08000000)
+#define IS_TWI(instr)          (((instr) & 0xfc000000) == 0x0c000000)
+
+#ifdef CONFIG_PPC64
+#define is_trap(instr)         (IS_TW(instr) || IS_TD(instr) || \
+                               IS_TWI(instr) || IS_TDI(instr))
+#else
+#define is_trap(instr)         (IS_TW(instr) || IS_TWI(instr))
+#endif /* CONFIG_PPC64 */
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_PROBES_H */
index 54b73a28c20579f4f6923e4f9711b5d7dc062205..9dc5cd1fde1a9107614709d1082270361ac71882 100644 (file)
@@ -97,8 +97,8 @@ extern struct task_struct *last_task_used_spe;
 #endif
 
 #ifdef CONFIG_PPC64
-/* 64-bit user address space is 44-bits (16TB user VM) */
-#define TASK_SIZE_USER64 (0x0000100000000000UL)
+/* 64-bit user address space is 46-bits (64TB user VM) */
+#define TASK_SIZE_USER64 (0x0000400000000000UL)
 
 /* 
  * 32-bit user address space is 4GB - 1 page 
@@ -219,6 +219,8 @@ struct thread_struct {
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
        unsigned long   dabr;           /* Data address breakpoint register */
+       unsigned long   dabrx;          /*      ... extension  */
+       unsigned long   trap_nr;        /* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
        /* Complete AltiVec register set */
        vector128       vr[32] __attribute__((aligned(16)));
index 59247e816ac5edcc133defc45e37991dcd269ded..eedf427c9124f3c7fc4e13d5dd293b41dafd5f82 100644 (file)
 /* Trick: we set __end to va + 64k, which happens works for
  * a 16M page as well as we want only one iteration
  */
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)         \
-        do {                                                                \
-                unsigned long __end = va + PAGE_SIZE;                       \
-                unsigned __split = (psize == MMU_PAGE_4K ||                 \
-                                   psize == MMU_PAGE_64K_AP);              \
-                shift = mmu_psize_defs[psize].shift;                        \
-               for (index = 0; va < __end; index++, va += (1L << shift)) { \
-                       if (!__split || __rpte_sub_valid(rpte, index)) do { \
+#define pte_iterate_hashed_subpages(rpte, psize, vpn, index, shift)    \
+       do {                                                            \
+               unsigned long __end = vpn + (1UL << (PAGE_SHIFT - VPN_SHIFT));  \
+               unsigned __split = (psize == MMU_PAGE_4K ||             \
+                                   psize == MMU_PAGE_64K_AP);          \
+               shift = mmu_psize_defs[psize].shift;                    \
+               for (index = 0; vpn < __end; index++,                   \
+                            vpn += (1L << (shift - VPN_SHIFT))) {      \
+                       if (!__split || __rpte_sub_valid(rpte, index))  \
+                               do {
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
index 638608677e2a53679128800323d26d5caa53cd44..d24c14163966599ed3a78f559f80191f7cd53693 100644 (file)
 #define SPRN_DABRX     0x3F7   /* Data Address Breakpoint Register Extension */
 #define   DABRX_USER   (1UL << 0)
 #define   DABRX_KERNEL (1UL << 1)
+#define   DABRX_HYP    (1UL << 2)
+#define   DABRX_BTI    (1UL << 3)
+#define   DABRX_ALL     (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER)
 #define SPRN_DAR       0x013   /* Data Address Register */
 #define SPRN_DBCR      0x136   /* e300 Data Breakpoint Control Reg */
 #define SPRN_DSISR     0x012   /* Data Storage Interrupt Status Register */
 
 #define SPRN_HSRR0     0x13A   /* Save/Restore Register 0 */
 #define SPRN_HSRR1     0x13B   /* Save/Restore Register 1 */
+#define   HSRR1_DENORM         0x00100000 /* Denorm exception */
 
 #define SPRN_TBCTL     0x35f   /* PA6T Timebase control register */
 #define   TBCTL_FREEZE         0x0000000000000000ull /* Freeze all tbs */
 #define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
 #define   POWER6_MMCRA_THRM    0x00000020UL
 #define   POWER6_MMCRA_OTHER   0x0000000EUL
+
+#define   POWER7P_MMCRA_SIAR_VALID 0x10000000  /* P7+ SIAR contents valid */
+#define   POWER7P_MMCRA_SDAR_VALID 0x08000000  /* P7+ SDAR contents valid */
+
 #define SPRN_PMC1      787
 #define SPRN_PMC2      788
 #define SPRN_PMC3      789
  * 64-bit embedded
  *     - SPRG0 generic exception scratch
  *     - SPRG2 TLB exception stack
- *     - SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
+ *     - SPRG3 critical exception scratch and
+ *        CPU and NUMA node for VDSO getcpu (user visible)
  *     - SPRG4 unused (user visible)
  *     - SPRG6 TLB miss scratch (user visible, sorry !)
  *     - SPRG7 critical exception scratch
 
 #ifdef CONFIG_PPC_BOOK3E_64
 #define SPRN_SPRG_MC_SCRATCH   SPRN_SPRG8
-#define SPRN_SPRG_CRIT_SCRATCH SPRN_SPRG7
+#define SPRN_SPRG_CRIT_SCRATCH SPRN_SPRG3
 #define SPRN_SPRG_DBG_SCRATCH  SPRN_SPRG9
 #define SPRN_SPRG_TLB_EXFRAME  SPRN_SPRG2
 #define SPRN_SPRG_TLB_SCRATCH  SPRN_SPRG6
 #define SPRN_SPRG_GEN_SCRATCH  SPRN_SPRG0
+#define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
 
 #define SET_PACA(rX)   mtspr   SPRN_SPRG_PACA,rX
 #define GET_PACA(rX)   mfspr   rX,SPRN_SPRG_PACA
 #define PVR_VER(pvr)   (((pvr) >>  16) & 0xFFFF)       /* Version field */
 #define PVR_REV(pvr)   (((pvr) >>   0) & 0xFFFF)       /* Revison field */
 
-#define __is_processor(pv)     (PVR_VER(mfspr(SPRN_PVR)) == (pv))
+#define pvr_version_is(pvr)    (PVR_VER(mfspr(SPRN_PVR)) == (pvr))
 
 /*
  * IBM has further subdivided the standard PowerPC 16-bit version and
 #define PVR_476_ISS    0x00052000
 
 /* 64-bit processors */
-/* XXX the prefix should be PVR_, we'll do a global sweep to fix it one day */
-#define PV_NORTHSTAR   0x0033
-#define PV_PULSAR      0x0034
-#define PV_POWER4      0x0035
-#define PV_ICESTAR     0x0036
-#define PV_SSTAR       0x0037
-#define PV_POWER4p     0x0038
-#define PV_970         0x0039
-#define PV_POWER5      0x003A
-#define PV_POWER5p     0x003B
-#define PV_970FX       0x003C
-#define PV_POWER6      0x003E
-#define PV_POWER7      0x003F
-#define PV_630         0x0040
-#define PV_630p        0x0041
-#define PV_970MP       0x0044
-#define PV_970GX       0x0045
-#define PV_BE          0x0070
-#define PV_PA6T                0x0090
+#define PVR_NORTHSTAR  0x0033
+#define PVR_PULSAR     0x0034
+#define PVR_POWER4     0x0035
+#define PVR_ICESTAR    0x0036
+#define PVR_SSTAR      0x0037
+#define PVR_POWER4p    0x0038
+#define PVR_970                0x0039
+#define PVR_POWER5     0x003A
+#define PVR_POWER5p    0x003B
+#define PVR_970FX      0x003C
+#define PVR_POWER6     0x003E
+#define PVR_POWER7     0x003F
+#define PVR_630                0x0040
+#define PVR_630p       0x0041
+#define PVR_970MP      0x0044
+#define PVR_970GX      0x0045
+#define PVR_POWER7p    0x004A
+#define PVR_BE         0x0070
+#define PVR_PA6T       0x0090
 
 /* Macros for setting and retrieving special purpose registers */
 #ifndef __ASSEMBLY__
index d084ce195fc3af11b6c37443ae3ecc37c59fa3d4..8b9a306260b2cf7c7bc664d09ba2926bc1ac6dda 100644 (file)
@@ -9,7 +9,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
 extern unsigned int rtas_data;
 extern int mem_init_done;      /* set on boot once kmalloc can be called */
 extern int init_bootmem_done;  /* set once bootmem is available */
-extern phys_addr_t memory_limit;
+extern unsigned long long memory_limit;
 extern unsigned long klimit;
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
index 49495b0534edaf8499ab4e614dffef7819850dec..ccce3ef5cd8655a4bfbfba6e2e0153dae2651461 100644 (file)
@@ -10,7 +10,6 @@
 
 #ifdef __powerpc64__
 #    define __ARCH_SI_PREAMBLE_SIZE    (4 * sizeof(int))
-#    define SI_PAD_SIZE32              ((SI_MAX_SIZE/sizeof(int)) - 3)
 #endif
 
 #include <asm-generic/siginfo.h>
index ebc24dc5b1a13433aaeb1f5f21a8e48192d1d3cc..e807e9d8e3f7ea60b184da83176d54b3bbb40dcd 100644 (file)
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+void generic_set_cpu_up(unsigned int cpu);
 int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
@@ -190,6 +191,7 @@ extern unsigned long __secondary_hold_spinloop;
 extern unsigned long __secondary_hold_acknowledge;
 extern char __secondary_hold;
 
+extern void __early_start(void);
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 0c5fa3145615c28074208ca64e79fdac12b06170..f6fc0ee813d7afad1cd4572674b363fa5b9e0430 100644 (file)
@@ -10,8 +10,8 @@
  */
 #define SECTION_SIZE_BITS       24
 
-#define MAX_PHYSADDR_BITS       44
-#define MAX_PHYSMEM_BITS        44
+#define MAX_PHYSADDR_BITS       46
+#define MAX_PHYSMEM_BITS        46
 
 #endif /* CONFIG_SPARSEMEM */
 
index 8979d4cd3d70500fc1f0dbada65b9f834e020faa..de99d6e29430341623fd8a0f6ee3d3a4c4e1a768 100644 (file)
@@ -22,4 +22,10 @@ int __init swiotlb_setup_bus_notifier(void);
 
 extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
+#ifdef CONFIG_SWIOTLB
+void swiotlb_detect_4g(void);
+#else
+static inline void swiotlb_detect_4g(void) {}
+#endif
+
 #endif /* __ASM_SWIOTLB_H */
index faf93529cbf087876049790c2e1ef30fb29c5cd7..8ceea14d6fe44a20d0d807e28a4ca63477f18863 100644 (file)
@@ -102,7 +102,10 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_RESTOREALL         11      /* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR            12      /* Force successful syscall return */
 #define TIF_NOTIFY_RESUME      13      /* callback before returning to user */
+#define TIF_UPROBE             14      /* breakpointed or single-stepping */
 #define TIF_SYSCALL_TRACEPOINT 15      /* syscall tracepoint instrumentation */
+#define TIF_EMULATE_STACK_STORE        16      /* Is an instruction emulation
+                                               for stack store? */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -118,12 +121,14 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_RESTOREALL                (1<<TIF_RESTOREALL)
 #define _TIF_NOERROR           (1<<TIF_NOERROR)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE            (1<<TIF_UPROBE)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_EMULATE_STACK_STORE       (1<<TIF_EMULATE_STACK_STORE)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
                                 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
-                                _TIF_NOTIFY_RESUME)
+                                _TIF_NOTIFY_RESUME | _TIF_UPROBE)
 #define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR)
 
 /* Bits in local_flags */
index 81143fcbd1133af42b8589093c58ec15ffce8826..61a59271665b4b7e1b9d9a794eb67680c2ed1107 100644 (file)
@@ -95,7 +95,7 @@ struct ppc64_tlb_batch {
        unsigned long           index;
        struct mm_struct        *mm;
        real_pte_t              pte[PPC64_TLB_BATCH_NR];
-       unsigned long           vaddr[PPC64_TLB_BATCH_NR];
+       unsigned long           vpn[PPC64_TLB_BATCH_NR];
        unsigned int            psize;
        int                     ssize;
 };
@@ -103,9 +103,6 @@ DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 
 extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
 
-extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
-                           pte_t *ptep, unsigned long pte, int huge);
-
 #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 
 static inline void arch_enter_lazy_mmu_mode(void)
@@ -127,7 +124,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
 #define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 
-extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize,
+extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
                            int ssize, int local);
 extern void flush_hash_range(unsigned long number, int local);
 
index 17bb40cad5bfbaade0efaf0211baafeb49351e04..4db49590acf5d797af733fd15d7f3141a465a839 100644 (file)
@@ -98,11 +98,6 @@ struct exception_table_entry {
  * PowerPC, we can just do these as direct assignments.  (Of course, the
  * exception handling means that it's no longer "just"...)
  *
- * The "user64" versions of the user access functions are versions that
- * allow access of 64-bit data. The "get_user" functions do not
- * properly handle 64-bit data because the value gets down cast to a long.
- * The "put_user" functions already handle 64-bit data properly but we add
- * "user64" versions for completeness
  */
 #define get_user(x, ptr) \
        __get_user_check((x), (ptr), sizeof(*(ptr)))
@@ -114,12 +109,6 @@ struct exception_table_entry {
 #define __put_user(x, ptr) \
        __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
 
-#ifndef __powerpc64__
-#define __get_user64(x, ptr) \
-       __get_user64_nocheck((x), (ptr), sizeof(*(ptr)))
-#define __put_user64(x, ptr) __put_user(x, ptr)
-#endif
-
 #define __get_user_inatomic(x, ptr) \
        __get_user_nosleep((x), (ptr), sizeof(*(ptr)))
 #define __put_user_inatomic(x, ptr) \
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
new file mode 100644 (file)
index 0000000..b532060
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * 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.
+ *
+ * Copyright IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+
+#include <linux/notifier.h>
+#include <asm/probes.h>
+
+typedef ppc_opcode_t uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES                4
+#define UPROBE_XOL_SLOT_BYTES  (MAX_UINSN_BYTES)
+
+/* The following alias is needed for reference from arch-agnostic code */
+#define UPROBE_SWBP_INSN       BREAKPOINT_INSTRUCTION
+#define UPROBE_SWBP_INSN_SIZE  4 /* swbp insn size in bytes */
+
+struct arch_uprobe {
+       union {
+               u8      insn[MAX_UINSN_BYTES];
+               u32     ainsn;
+       };
+};
+
+struct arch_uprobe_task {
+       unsigned long   saved_trap_nr;
+};
+
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+#endif /* _ASM_UPROBES_H */
index bb282dd81612171b5b3545b7924db7ed907100d2..cde12f8a4ebc4e98342491a2fcb91bd31fb26f05 100644 (file)
@@ -96,6 +96,7 @@ obj-$(CONFIG_MODULES)         += ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)       += btext.o
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_UPROBES)          += uprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)   += legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_SWIOTLB)          += dma-swiotlb.o
index e8995727b1c15207757969ca9e4cd5b7990c2d17..7523539cfe9f88e0a49e4b8a5715e8dff7a64fc7 100644 (file)
@@ -206,6 +206,7 @@ int main(void)
        DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
        DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
        DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
+       DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3));
 #endif /* CONFIG_PPC64 */
 
        /* RTAS */
@@ -534,7 +535,6 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
-       HSTATE_FIELD(HSTATE_SPRG3, sprg3);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index 69fdd2322a6676c27e5e67fad4c5eefff3f9e1b5..dcd881937f7a9217c2c6b7843d218a1d6b777970 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
+#include <asm/mmu-book3e.h>
+#include <asm/asm-offsets.h>
 
 _GLOBAL(__e500_icache_setup)
        mfspr   r0, SPRN_L1CSR1
@@ -73,27 +75,81 @@ _GLOBAL(__setup_cpu_e500v2)
        mtlr    r4
        blr
 _GLOBAL(__setup_cpu_e500mc)
-       mr      r5, r4
-       mflr    r4
+_GLOBAL(__setup_cpu_e5500)
+       mflr    r5
        bl      __e500_icache_setup
        bl      __e500_dcache_setup
        bl      __setup_e500mc_ivors
-       mtlr    r4
+       /*
+        * We only want to touch IVOR38-41 if we're running on hardware
+        * that supports category E.HV.  The architectural way to determine
+        * this is MMUCFG[LPIDSIZE].
+        */
+       mfspr   r3, SPRN_MMUCFG
+       rlwinm. r3, r3, 0, MMUCFG_LPIDSIZE
+       beq     1f
+       bl      __setup_ehv_ivors
+       b       2f
+1:
+       lwz     r3, CPU_SPEC_FEATURES(r4)
+       /* We need this check as cpu_setup is also called for
+        * the secondary cores. So, if we have already cleared
+        * the feature on the primary core, avoid doing it on the
+        * secondary core.
+        */
+       andis.  r6, r3, CPU_FTR_EMB_HV@h
+       beq     2f
+       rlwinm  r3, r3, 0, ~CPU_FTR_EMB_HV
+       stw     r3, CPU_SPEC_FEATURES(r4)
+2:
+       mtlr    r5
        blr
 #endif
-/* Right now, restore and setup are the same thing */
+
+#ifdef CONFIG_PPC_BOOK3E_64
 _GLOBAL(__restore_cpu_e5500)
-_GLOBAL(__setup_cpu_e5500)
        mflr    r4
        bl      __e500_icache_setup
        bl      __e500_dcache_setup
-#ifdef CONFIG_PPC_BOOK3E_64
        bl      .__setup_base_ivors
        bl      .setup_perfmon_ivor
        bl      .setup_doorbell_ivors
+       /*
+        * We only want to touch IVOR38-41 if we're running on hardware
+        * that supports category E.HV.  The architectural way to determine
+        * this is MMUCFG[LPIDSIZE].
+        */
+       mfspr   r10,SPRN_MMUCFG
+       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
+       beq     1f
        bl      .setup_ehv_ivors
-#else
-       bl      __setup_e500mc_ivors
-#endif
+1:
        mtlr    r4
        blr
+
+_GLOBAL(__setup_cpu_e5500)
+       mflr    r5
+       bl      __e500_icache_setup
+       bl      __e500_dcache_setup
+       bl      .__setup_base_ivors
+       bl      .setup_perfmon_ivor
+       bl      .setup_doorbell_ivors
+       /*
+        * We only want to touch IVOR38-41 if we're running on hardware
+        * that supports category E.HV.  The architectural way to determine
+        * this is MMUCFG[LPIDSIZE].
+        */
+       mfspr   r10,SPRN_MMUCFG
+       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
+       beq     1f
+       bl      .setup_ehv_ivors
+       b       2f
+1:
+       ld      r10,CPU_SPEC_FEATURES(r4)
+       LOAD_REG_IMMEDIATE(r9,CPU_FTR_EMB_HV)
+       andc    r10,r10,r9
+       std     r10,CPU_SPEC_FEATURES(r4)
+2:
+       mtlr    r5
+       blr
+#endif
index 455faa389876e51f3afaa732f74949b6859ae95c..0514c21f138bee013812ab5bcffde2ddb84da60a 100644 (file)
@@ -2016,7 +2016,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc/e500mc",
                .oprofile_type          = PPC_OPROFILE_FSL_EMB,
                .cpu_setup              = __setup_cpu_e5500,
+#ifndef CONFIG_PPC32
                .cpu_restore            = __restore_cpu_e5500,
+#endif
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce5500",
        },
@@ -2034,7 +2036,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc/e6500",
                .oprofile_type          = PPC_OPROFILE_FSL_EMB,
                .cpu_setup              = __setup_cpu_e5500,
+#ifndef CONFIG_PPC32
                .cpu_restore            = __restore_cpu_e5500,
+#endif
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce6500",
        },
index 46943651da23ba25b3e1093ea346fb31e154243c..bd1a2aba599f59aaee4d31d9d971f5afb9d5bca4 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/memblock.h>
 #include <linux/pfn.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -20,7 +21,6 @@
 #include <asm/machdep.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-#include <asm/abs_addr.h>
 
 unsigned int ppc_swiotlb_enable;
 
@@ -105,3 +105,23 @@ int __init swiotlb_setup_bus_notifier(void)
                              &ppc_swiotlb_plat_bus_notifier);
        return 0;
 }
+
+void swiotlb_detect_4g(void)
+{
+       if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
+               ppc_swiotlb_enable = 1;
+}
+
+static int __init swiotlb_late_init(void)
+{
+       if (ppc_swiotlb_enable) {
+               swiotlb_print_info();
+               set_pci_dma_ops(&swiotlb_dma_ops);
+               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+       } else {
+               swiotlb_free();
+       }
+
+       return 0;
+}
+subsys_initcall(swiotlb_late_init);
index 355b9d84b0f8149efd45ed9b5b0035c3b70fac11..8032b97ccdcb6668f01dc9c2026c0080f0a14449 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/pci.h>
 #include <asm/vio.h>
 #include <asm/bug.h>
-#include <asm/abs_addr.h>
 #include <asm/machdep.h>
 
 /*
@@ -50,7 +49,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                return NULL;
        ret = page_address(page);
        memset(ret, 0, size);
-       *dma_handle = virt_to_abs(ret) + get_dma_offset(dev);
+       *dma_handle = __pa(ret) + get_dma_offset(dev);
 
        return ret;
 #endif
index ead5016b02d020c32741e5f6d122736eb907d083..af37528da49fff06ef7b47fb2e9add01dd6b1caa 100644 (file)
@@ -831,19 +831,56 @@ restore_user:
        bnel-   load_dbcr0
 #endif
 
-#ifdef CONFIG_PREEMPT
        b       restore
 
 /* N.B. the only way to get here is from the beq following ret_from_except. */
 resume_kernel:
-       /* check current_thread_info->preempt_count */
+       /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
        CURRENT_THREAD_INFO(r9, r1)
+       lwz     r8,TI_FLAGS(r9)
+       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       beq+    1f
+
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+
+       lwz     r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+
+       /* Copy from the original to the trampoline. */
+       li      r5,INT_FRAME_SIZE/4     /* size: INT_FRAME_SIZE */
+       li      r6,0                    /* start offset: 0 */
+       mtctr   r5
+2:     lwzx    r0,r6,r4
+       stwx    r0,r6,r3
+       addi    r6,r6,4
+       bdnz    2b
+
+       /* Do real store operation to complete stwu */
+       lwz     r5,GPR1(r1)
+       stw     r8,0(r5)
+
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+       lis     r11,_TIF_EMULATE_STACK_STORE@h
+       addi    r5,r9,TI_FLAGS
+0:     lwarx   r8,0,r5
+       andc    r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+       dcbt    0,r5
+#endif
+       stwcx.  r8,0,r5
+       bne-    0b
+1:
+
+#ifdef CONFIG_PREEMPT
+       /* check current_thread_info->preempt_count */
        lwz     r0,TI_PREEMPT(r9)
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
        bne     restore
-       lwz     r0,TI_FLAGS(r9)
-       andi.   r0,r0,_TIF_NEED_RESCHED
+       andi.   r8,r8,_TIF_NEED_RESCHED
        beq+    restore
+       lwz     r3,_MSR(r1)
        andi.   r0,r3,MSR_EE    /* interrupts off? */
        beq     restore         /* don't schedule if so */
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -864,8 +901,6 @@ resume_kernel:
         */
        bl      trace_hardirqs_on
 #endif
-#else
-resume_kernel:
 #endif /* CONFIG_PREEMPT */
 
        /* interrupts are hard-disabled at this point */
index b40e0b4815b3f5297154fa9c6e8a66fa4ce7c574..0e931aaffca20ad2213c1fb0dd2923e409cf75c9 100644 (file)
@@ -593,6 +593,41 @@ _GLOBAL(ret_from_except_lite)
        b       .ret_from_except
 
 resume_kernel:
+       /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
+       CURRENT_THREAD_INFO(r9, r1)
+       ld      r8,TI_FLAGS(r9)
+       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       beq+    1f
+
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+
+       lwz     r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+
+       /* Copy from the original to the trampoline. */
+       li      r5,INT_FRAME_SIZE/8     /* size: INT_FRAME_SIZE */
+       li      r6,0                    /* start offset: 0 */
+       mtctr   r5
+2:     ldx     r0,r6,r4
+       stdx    r0,r6,r3
+       addi    r6,r6,8
+       bdnz    2b
+
+       /* Do real store operation to complete stwu */
+       lwz     r5,GPR1(r1)
+       std     r8,0(r5)
+
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+       lis     r11,_TIF_EMULATE_STACK_STORE@h
+       addi    r5,r9,TI_FLAGS
+       ldarx   r4,0,r5
+       andc    r4,r4,r11
+       stdcx.  r4,0,r5
+       bne-    0b
+1:
+
 #ifdef CONFIG_PREEMPT
        /* Check if we need to preempt */
        andi.   r0,r4,_TIF_NEED_RESCHED
index 98be7f0cd227019cbe6b6a07ad989327b8e36979..4684e33a26c3a156ec8d7130a0776034f88c4b5b 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/ppc-opcode.h>
 #include <asm/mmu.h>
 #include <asm/hw_irq.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
 
 /* XXX This will ultimately add space for a special exception save
  *     structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
 #define        SPECIAL_EXC_FRAME_SIZE  INT_FRAME_SIZE
 
 /* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, addition)                                \
+#define EXCEPTION_PROLOG(n, intnum, type, addition)                        \
        mtspr   SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */   \
        mfspr   r13,SPRN_SPRG_PACA;     /* get PACA */                      \
        std     r10,PACA_EX##type+EX_R10(r13);                              \
        std     r11,PACA_EX##type+EX_R11(r13);                              \
+       PROLOG_STORE_RESTORE_SCRATCH_##type;                                \
        mfcr    r10;                    /* save CR */                       \
+       mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
+       DO_KVM  intnum,SPRN_##type##_SRR1;    /* KVM hook */                \
+       stw     r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
        addition;                       /* additional code for that exc. */ \
        std     r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */  \
-       stw     r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
-       mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
        type##_SET_KSTACK;              /* get special stack if necessary */\
        andi.   r10,r11,MSR_PR;         /* save stack pointer */            \
        beq     1f;                     /* branch around if supervisor */   \
 #define SPRN_GEN_SRR0  SPRN_SRR0
 #define SPRN_GEN_SRR1  SPRN_SRR1
 
+#define        GDBELL_SET_KSTACK       GEN_SET_KSTACK
+#define SPRN_GDBELL_SRR0       SPRN_GSRR0
+#define SPRN_GDBELL_SRR1       SPRN_GSRR1
+
 #define CRIT_SET_KSTACK                                                            \
        ld      r1,PACA_CRIT_STACK(r13);                                    \
        subi    r1,r1,SPECIAL_EXC_FRAME_SIZE;
 #define SPRN_MC_SRR0   SPRN_MCSRR0
 #define SPRN_MC_SRR1   SPRN_MCSRR1
 
-#define NORMAL_EXCEPTION_PROLOG(n, addition)                               \
-       EXCEPTION_PROLOG(n, GEN, addition##_GEN(n))
+#define NORMAL_EXCEPTION_PROLOG(n, intnum, addition)                       \
+       EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n))
+
+#define CRIT_EXCEPTION_PROLOG(n, intnum, addition)                         \
+       EXCEPTION_PROLOG(n, intnum, CRIT, addition##_CRIT(n))
 
-#define CRIT_EXCEPTION_PROLOG(n, addition)                                 \
-       EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n))
+#define DBG_EXCEPTION_PROLOG(n, intnum, addition)                          \
+       EXCEPTION_PROLOG(n, intnum, DBG, addition##_DBG(n))
 
-#define DBG_EXCEPTION_PROLOG(n, addition)                                  \
-       EXCEPTION_PROLOG(n, DBG, addition##_DBG(n))
+#define MC_EXCEPTION_PROLOG(n, intnum, addition)                           \
+       EXCEPTION_PROLOG(n, intnum, MC, addition##_MC(n))
 
-#define MC_EXCEPTION_PROLOG(n, addition)                                   \
-       EXCEPTION_PROLOG(n, MC, addition##_MC(n))
+#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)                       \
+       EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
 
+/*
+ * Store user-visible scratch in PACA exception slots and restore proper value
+ */
+#define PROLOG_STORE_RESTORE_SCRATCH_GEN
+#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
+#define PROLOG_STORE_RESTORE_SCRATCH_DBG
+#define PROLOG_STORE_RESTORE_SCRATCH_MC
+
+#define PROLOG_STORE_RESTORE_SCRATCH_CRIT                                  \
+       mfspr   r10,SPRN_SPRG_CRIT_SCRATCH;     /* get r13 */               \
+       std     r10,PACA_EXCRIT+EX_R13(r13);                                \
+       ld      r11,PACA_SPRG3(r13);                                        \
+       mtspr   SPRN_SPRG_CRIT_SCRATCH,r11;
 
 /* Variants of the "addition" argument for the prolog
  */
 #define PROLOG_ADDITION_NONE_GEN(n)
+#define PROLOG_ADDITION_NONE_GDBELL(n)
 #define PROLOG_ADDITION_NONE_CRIT(n)
 #define PROLOG_ADDITION_NONE_DBG(n)
 #define PROLOG_ADDITION_NONE_MC(n)
 
 #define PROLOG_ADDITION_MASKABLE_GEN(n)                                            \
-       lbz     r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
-       cmpwi   cr0,r11,0;              /* yes -> go out of line */         \
+       lbz     r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
+       cmpwi   cr0,r10,0;              /* yes -> go out of line */         \
        beq     masked_interrupt_book3e_##n
 
 #define PROLOG_ADDITION_2REGS_GEN(n)                                       \
@@ -233,9 +258,9 @@ exc_##n##_bad_stack:                                                            \
 1:
 
 
-#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack)                  \
+#define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)          \
        START_EXCEPTION(label);                                         \
-       NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE)      \
+       NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
        EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE)             \
        ack(r8);                                                        \
        CHECK_NAPPING();                                                \
@@ -286,7 +311,8 @@ interrupt_end_book3e:
 
 /* Critical Input Interrupt */
        START_EXCEPTION(critical_input);
-       CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -297,7 +323,8 @@ interrupt_end_book3e:
 
 /* Machine Check Interrupt */
        START_EXCEPTION(machine_check);
-       CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
+       MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
+                           PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
 //     bl      special_reg_save_mc
 //     addi    r3,r1,STACK_FRAME_OVERHEAD
@@ -308,7 +335,8 @@ interrupt_end_book3e:
 
 /* Data Storage Interrupt */
        START_EXCEPTION(data_storage)
-       NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
+                               PROLOG_ADDITION_2REGS)
        mfspr   r14,SPRN_DEAR
        mfspr   r15,SPRN_ESR
        EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
@@ -316,18 +344,21 @@ interrupt_end_book3e:
 
 /* Instruction Storage Interrupt */
        START_EXCEPTION(instruction_storage);
-       NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
+                               PROLOG_ADDITION_2REGS)
        li      r15,0
        mr      r14,r10
        EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
        b       storage_fault_common
 
 /* External Input Interrupt */
-       MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE)
+       MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
+                          external_input, .do_IRQ, ACK_NONE)
 
 /* Alignment */
        START_EXCEPTION(alignment);
-       NORMAL_EXCEPTION_PROLOG(0x600, PROLOG_ADDITION_2REGS)
+       NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
+                               PROLOG_ADDITION_2REGS)
        mfspr   r14,SPRN_DEAR
        mfspr   r15,SPRN_ESR
        EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
@@ -335,7 +366,8 @@ interrupt_end_book3e:
 
 /* Program Interrupt */
        START_EXCEPTION(program);
-       NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG)
+       NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
+                               PROLOG_ADDITION_1REG)
        mfspr   r14,SPRN_ESR
        EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
        std     r14,_DSISR(r1)
@@ -347,7 +379,8 @@ interrupt_end_book3e:
 
 /* Floating Point Unavailable Interrupt */
        START_EXCEPTION(fp_unavailable);
-       NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
+                               PROLOG_ADDITION_NONE)
        /* we can probably do a shorter exception entry for that one... */
        EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
        ld      r12,_MSR(r1)
@@ -362,14 +395,17 @@ interrupt_end_book3e:
        b       .ret_from_except
 
 /* Decrementer Interrupt */
-       MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC)
+       MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
+                          decrementer, .timer_interrupt, ACK_DEC)
 
 /* Fixed Interval Timer Interrupt */
-       MASKABLE_EXCEPTION(0x980, fixed_interval, .unknown_exception, ACK_FIT)
+       MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
+                          fixed_interval, .unknown_exception, ACK_FIT)
 
 /* Watchdog Timer Interrupt */
        START_EXCEPTION(watchdog);
-       CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -388,7 +424,8 @@ interrupt_end_book3e:
 
 /* Auxiliary Processor Unavailable Interrupt */
        START_EXCEPTION(ap_unavailable);
-       NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
@@ -397,7 +434,8 @@ interrupt_end_book3e:
 
 /* Debug exception as a critical interrupt*/
        START_EXCEPTION(debug_crit);
-       CRIT_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
+       CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+                             PROLOG_ADDITION_2REGS)
 
        /*
         * If there is a single step or branch-taken exception in an
@@ -431,7 +469,7 @@ interrupt_end_book3e:
        mtcr    r10
        ld      r10,PACA_EXCRIT+EX_R10(r13)     /* restore registers */
        ld      r11,PACA_EXCRIT+EX_R11(r13)
-       mfspr   r13,SPRN_SPRG_CRIT_SCRATCH
+       ld      r13,PACA_EXCRIT+EX_R13(r13)
        rfci
 
        /* Normal debug exception */
@@ -444,7 +482,7 @@ interrupt_end_book3e:
        /* Now we mash up things to make it look like we are coming on a
         * normal exception
         */
-       mfspr   r15,SPRN_SPRG_CRIT_SCRATCH
+       ld      r15,PACA_EXCRIT+EX_R13(r13)
        mtspr   SPRN_SPRG_GEN_SCRATCH,r15
        mfspr   r14,SPRN_DBSR
        EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
@@ -462,7 +500,8 @@ kernel_dbg_exc:
 
 /* Debug exception as a debug interrupt*/
        START_EXCEPTION(debug_debug);
-       DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS)
+       DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+                                                PROLOG_ADDITION_2REGS)
 
        /*
         * If there is a single step or branch-taken exception in an
@@ -523,18 +562,21 @@ kernel_dbg_exc:
        b       .ret_from_except
 
        START_EXCEPTION(perfmon);
-       NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .performance_monitor_exception
        b       .ret_from_except_lite
 
 /* Doorbell interrupt */
-       MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE)
+       MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
+                          doorbell, .doorbell_exception, ACK_NONE)
 
 /* Doorbell critical Interrupt */
        START_EXCEPTION(doorbell_crit);
-       CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -543,12 +585,24 @@ kernel_dbg_exc:
 //     b       ret_from_crit_except
        b       .
 
-/* Guest Doorbell */
-       MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
+/*
+ *     Guest doorbell interrupt
+ *     This general exception use GSRRx save/restore registers
+ */
+       START_EXCEPTION(guest_doorbell);
+       GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
+                               PROLOG_ADDITION_NONE)
+       EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .save_nvgprs
+       INTS_RESTORE_HARD
+       bl      .unknown_exception
+       b       .ret_from_except
 
 /* Guest Doorbell critical Interrupt */
        START_EXCEPTION(guest_doorbell_crit);
-       CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE)
+       CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
+                             PROLOG_ADDITION_NONE)
 //     EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
 //     bl      special_reg_save_crit
 //     CHECK_NAPPING();
@@ -559,7 +613,8 @@ kernel_dbg_exc:
 
 /* Hypervisor call */
        START_EXCEPTION(hypercall);
-       NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .save_nvgprs
@@ -569,7 +624,8 @@ kernel_dbg_exc:
 
 /* Embedded Hypervisor priviledged  */
        START_EXCEPTION(ehpriv);
-       NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
+       NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
+                               PROLOG_ADDITION_NONE)
        EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .save_nvgprs
@@ -582,44 +638,42 @@ kernel_dbg_exc:
  * accordingly and if the interrupt is level sensitive, we hard disable
  */
 
+.macro masked_interrupt_book3e paca_irq full_mask
+       lbz     r10,PACAIRQHAPPENED(r13)
+       ori     r10,r10,\paca_irq
+       stb     r10,PACAIRQHAPPENED(r13)
+
+       .if \full_mask == 1
+       rldicl  r10,r11,48,1            /* clear MSR_EE */
+       rotldi  r11,r10,16
+       mtspr   SPRN_SRR1,r11
+       .endif
+
+       lwz     r11,PACA_EXGEN+EX_CR(r13)
+       mtcr    r11
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       ld      r11,PACA_EXGEN+EX_R11(r13)
+       mfspr   r13,SPRN_SPRG_GEN_SCRATCH
+       rfi
+       b       .
+.endm
+
 masked_interrupt_book3e_0x500:
-       /* XXX When adding support for EPR, use PACA_IRQ_EE_EDGE */
-       li      r11,PACA_IRQ_EE
-       b       masked_interrupt_book3e_full_mask
+       // XXX When adding support for EPR, use PACA_IRQ_EE_EDGE
+       masked_interrupt_book3e PACA_IRQ_EE 1
 
 masked_interrupt_book3e_0x900:
-       ACK_DEC(r11);
-       li      r11,PACA_IRQ_DEC
-       b       masked_interrupt_book3e_no_mask
+       ACK_DEC(r10);
+       masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x980:
-       ACK_FIT(r11);
-       li      r11,PACA_IRQ_DEC
-       b       masked_interrupt_book3e_no_mask
+       ACK_FIT(r10);
+       masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x280:
 masked_interrupt_book3e_0x2c0:
-       li      r11,PACA_IRQ_DBELL
-       b       masked_interrupt_book3e_no_mask
+       masked_interrupt_book3e PACA_IRQ_DBELL 0
 
-masked_interrupt_book3e_no_mask:
-       mtcr    r10
-       lbz     r10,PACAIRQHAPPENED(r13)
-       or      r10,r10,r11
-       stb     r10,PACAIRQHAPPENED(r13)
-       b       1f
-masked_interrupt_book3e_full_mask:
-       mtcr    r10
-       lbz     r10,PACAIRQHAPPENED(r13)
-       or      r10,r10,r11
-       stb     r10,PACAIRQHAPPENED(r13)
-       mfspr   r10,SPRN_SRR1
-       rldicl  r11,r10,48,1            /* clear MSR_EE */
-       rotldi  r10,r11,16
-       mtspr   SPRN_SRR1,r10
-1:     ld      r10,PACA_EXGEN+EX_R10(r13);
-       ld      r11,PACA_EXGEN+EX_R11(r13);
-       mfspr   r13,SPRN_SPRG_GEN_SCRATCH;
-       rfi
-       b       .
 /*
  * Called from arch_local_irq_enable when an interrupt needs
  * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280
@@ -1302,25 +1356,11 @@ _GLOBAL(setup_perfmon_ivor)
 _GLOBAL(setup_doorbell_ivors)
        SET_IVOR(36, 0x280) /* Processor Doorbell */
        SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
-
-       /* Check MMUCFG[LPIDSIZE] to determine if we have category E.HV */
-       mfspr   r10,SPRN_MMUCFG
-       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
-       beqlr
-
-       SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
-       SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
        blr
 
 _GLOBAL(setup_ehv_ivors)
-       /*
-        * We may be running as a guest and lack E.HV even on a chip
-        * that normally has it.
-        */
-       mfspr   r10,SPRN_MMUCFG
-       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
-       beqlr
-
        SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
        SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
+       SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
+       SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
        blr
index 39aa97d3ff883a2ed5121e1cc11afd5ffae0f898..10b658ad65e16b455d7239670d42c0ae5c0b4d3b 100644 (file)
@@ -275,6 +275,31 @@ vsx_unavailable_pSeries_1:
        STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
        KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
 
+       . = 0x1500
+       .global denorm_Hypervisor
+denorm_exception_hv:
+       HMT_MEDIUM
+       mtspr   SPRN_SPRG_HSCRATCH0,r13
+       mfspr   r13,SPRN_SPRG_HPACA
+       std     r9,PACA_EXGEN+EX_R9(r13)
+       std     r10,PACA_EXGEN+EX_R10(r13)
+       std     r11,PACA_EXGEN+EX_R11(r13)
+       std     r12,PACA_EXGEN+EX_R12(r13)
+       mfspr   r9,SPRN_SPRG_HSCRATCH0
+       std     r9,PACA_EXGEN+EX_R13(r13)
+       mfcr    r9
+
+#ifdef CONFIG_PPC_DENORMALISATION
+       mfspr   r10,SPRN_HSRR1
+       mfspr   r11,SPRN_HSRR0          /* save HSRR0 */
+       andis.  r10,r10,(HSRR1_DENORM)@h /* denorm? */
+       addi    r11,r11,-4              /* HSRR0 is next instruction */
+       bne+    denorm_assist
+#endif
+
+       EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1500)
+
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
        KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
@@ -336,6 +361,103 @@ do_stab_bolted_pSeries:
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
        KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
 
+#ifdef CONFIG_PPC_DENORMALISATION
+denorm_assist:
+BEGIN_FTR_SECTION
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER6 do that here for all FP regs.
+ */
+       mfmsr   r10
+       ori     r10,r10,(MSR_FP|MSR_FE0|MSR_FE1)
+       xori    r10,r10,(MSR_FE0|MSR_FE1)
+       mtmsrd  r10
+       sync
+       fmr     0,0
+       fmr     1,1
+       fmr     2,2
+       fmr     3,3
+       fmr     4,4
+       fmr     5,5
+       fmr     6,6
+       fmr     7,7
+       fmr     8,8
+       fmr     9,9
+       fmr     10,10
+       fmr     11,11
+       fmr     12,12
+       fmr     13,13
+       fmr     14,14
+       fmr     15,15
+       fmr     16,16
+       fmr     17,17
+       fmr     18,18
+       fmr     19,19
+       fmr     20,20
+       fmr     21,21
+       fmr     22,22
+       fmr     23,23
+       fmr     24,24
+       fmr     25,25
+       fmr     26,26
+       fmr     27,27
+       fmr     28,28
+       fmr     29,29
+       fmr     30,30
+       fmr     31,31
+FTR_SECTION_ELSE
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER7 do that here for the first 32 VSX registers only.
+ */
+       mfmsr   r10
+       oris    r10,r10,MSR_VSX@h
+       mtmsrd  r10
+       sync
+       XVCPSGNDP(0,0,0)
+       XVCPSGNDP(1,1,1)
+       XVCPSGNDP(2,2,2)
+       XVCPSGNDP(3,3,3)
+       XVCPSGNDP(4,4,4)
+       XVCPSGNDP(5,5,5)
+       XVCPSGNDP(6,6,6)
+       XVCPSGNDP(7,7,7)
+       XVCPSGNDP(8,8,8)
+       XVCPSGNDP(9,9,9)
+       XVCPSGNDP(10,10,10)
+       XVCPSGNDP(11,11,11)
+       XVCPSGNDP(12,12,12)
+       XVCPSGNDP(13,13,13)
+       XVCPSGNDP(14,14,14)
+       XVCPSGNDP(15,15,15)
+       XVCPSGNDP(16,16,16)
+       XVCPSGNDP(17,17,17)
+       XVCPSGNDP(18,18,18)
+       XVCPSGNDP(19,19,19)
+       XVCPSGNDP(20,20,20)
+       XVCPSGNDP(21,21,21)
+       XVCPSGNDP(22,22,22)
+       XVCPSGNDP(23,23,23)
+       XVCPSGNDP(24,24,24)
+       XVCPSGNDP(25,25,25)
+       XVCPSGNDP(26,26,26)
+       XVCPSGNDP(27,27,27)
+       XVCPSGNDP(28,28,28)
+       XVCPSGNDP(29,29,29)
+       XVCPSGNDP(30,30,30)
+       XVCPSGNDP(31,31,31)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
+       mtspr   SPRN_HSRR0,r11
+       mtcrf   0x80,r9
+       ld      r9,PACA_EXGEN+EX_R9(r13)
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       ld      r11,PACA_EXGEN+EX_R11(r13)
+       ld      r12,PACA_EXGEN+EX_R12(r13)
+       ld      r13,PACA_EXGEN+EX_R13(r13)
+       HRFID
+       b       .
+#endif
+
        .align  7
        /* moved from 0xe00 */
        STD_EXCEPTION_HV(., 0xe02, h_data_storage)
@@ -495,6 +617,7 @@ machine_check_common:
         STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
        STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
        STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
+       STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
 #ifdef CONFIG_ALTIVEC
        STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
 #else
@@ -960,7 +1083,9 @@ _GLOBAL(do_stab_bolted)
        rldimi  r10,r11,7,52    /* r10 = first ste of the group */
 
        /* Calculate VSID */
-       /* This is a kernel address, so protovsid = ESID */
+       /* This is a kernel address, so protovsid = ESID | 1 << 37 */
+       li      r9,0x1
+       rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
        ASM_VSID_SCRAMBLE(r11, r9, 256M)
        rldic   r9,r11,12,16    /* r9 = vsid << 12 */
 
index 18bdf74fa164042e0e3b07a7dd0867faf8d6069c..06c8202a69cf43a1689a8a98323d398872f80df1 100644 (file)
@@ -289,8 +289,7 @@ int __init fadump_reserve_mem(void)
                else
                        memory_limit = memblock_end_of_DRAM();
                printk(KERN_INFO "Adjusted memory_limit for firmware-assisted"
-                               " dump, now %#016llx\n",
-                               (unsigned long long)memory_limit);
+                               " dump, now %#016llx\n", memory_limit);
        }
        if (memory_limit)
                memory_boundary = memory_limit;
index 0f59863c3adeb3f220ef63093af71b1ce2bb23e4..6f62a737f607164d4bd63e9a1992e30df8f16334 100644 (file)
@@ -895,15 +895,11 @@ _GLOBAL(__setup_e500mc_ivors)
        mtspr   SPRN_IVOR36,r3
        li      r3,CriticalDoorbell@l
        mtspr   SPRN_IVOR37,r3
+       sync
+       blr
 
-       /*
-        * We only want to touch IVOR38-41 if we're running on hardware
-        * that supports category E.HV.  The architectural way to determine
-        * this is MMUCFG[LPIDSIZE].
-        */
-       mfspr   r3, SPRN_MMUCFG
-       andis.  r3, r3, MMUCFG_LPIDSIZE@h
-       beq     no_hv
+/* setup ehv ivors for */
+_GLOBAL(__setup_ehv_ivors)
        li      r3,GuestDoorbell@l
        mtspr   SPRN_IVOR38,r3
        li      r3,CriticalGuestDoorbell@l
@@ -912,14 +908,8 @@ _GLOBAL(__setup_e500mc_ivors)
        mtspr   SPRN_IVOR40,r3
        li      r3,Ehvpriv@l
        mtspr   SPRN_IVOR41,r3
-skip_hv_ivors:
        sync
        blr
-no_hv:
-       lwz     r3, CPU_SPEC_FEATURES(r5)
-       rlwinm  r3, r3, 0, ~CPU_FTR_EMB_HV
-       stw     r3, CPU_SPEC_FEATURES(r5)
-       b       skip_hv_ivors
 
 #ifdef CONFIG_SPE
 /*
@@ -1043,6 +1033,34 @@ _GLOBAL(flush_dcache_L1)
 
        blr
 
+/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
+_GLOBAL(__flush_disable_L1)
+       mflr    r10
+       bl      flush_dcache_L1 /* Flush L1 d-cache */
+       mtlr    r10
+
+       mfspr   r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
+       li      r5, 2
+       rlwimi  r4, r5, 0, 3
+
+       msync
+       isync
+       mtspr   SPRN_L1CSR0, r4
+       isync
+
+1:     mfspr   r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
+       andi.   r4, r4, 2
+       bne     1b
+
+       mfspr   r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
+       li      r5, 2
+       rlwimi  r4, r5, 0, 3
+
+       mtspr   SPRN_L1CSR1, r4
+       isync
+
+       blr
+
 #ifdef CONFIG_SMP
 /* When we get here, r24 needs to hold the CPU # */
        .globl __secondary_start
index 956a4c496de942d93853f42f2db1067f45cf0085..a89cae481b0439a0b8bfe594d70dae6502c27a27 100644 (file)
@@ -73,7 +73,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
         * If so, DABR will be populated in single_step_dabr_instruction().
         */
        if (current->thread.last_hit_ubp != bp)
-               set_dabr(info->address | info->type | DABR_TRANSLATION);
+               set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 
        return 0;
 }
@@ -97,7 +97,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
        }
 
        *slot = NULL;
-       set_dabr(0);
+       set_dabr(0, 0);
 }
 
 /*
@@ -170,6 +170,13 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 
        info->address = bp->attr.bp_addr;
        info->len = bp->attr.bp_len;
+       info->dabrx = DABRX_ALL;
+       if (bp->attr.exclude_user)
+               info->dabrx &= ~DABRX_USER;
+       if (bp->attr.exclude_kernel)
+               info->dabrx &= ~DABRX_KERNEL;
+       if (bp->attr.exclude_hv)
+               info->dabrx &= ~DABRX_HYP;
 
        /*
         * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
@@ -197,7 +204,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
 
        info = counter_arch_bp(tsk->thread.last_hit_ubp);
        regs->msr &= ~MSR_SE;
-       set_dabr(info->address | info->type | DABR_TRANSLATION);
+       set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
        tsk->thread.last_hit_ubp = NULL;
 }
 
@@ -215,7 +222,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
        unsigned long dar = regs->dar;
 
        /* Disable breakpoints during exception handling */
-       set_dabr(0);
+       set_dabr(0, 0);
 
        /*
         * The counter may be concurrently released but that can only
@@ -281,7 +288,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
        if (!info->extraneous_interrupt)
                perf_bp_event(bp, regs);
 
-       set_dabr(info->address | info->type | DABR_TRANSLATION);
+       set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 out:
        rcu_read_unlock();
        return rc;
@@ -294,7 +301,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
 {
        struct pt_regs *regs = args->regs;
        struct perf_event *bp = NULL;
-       struct arch_hw_breakpoint *bp_info;
+       struct arch_hw_breakpoint *info;
 
        bp = current->thread.last_hit_ubp;
        /*
@@ -304,16 +311,16 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
        if (!bp)
                return NOTIFY_DONE;
 
-       bp_info = counter_arch_bp(bp);
+       info = counter_arch_bp(bp);
 
        /*
         * We shall invoke the user-defined callback function in the single
         * stepping handler to confirm to 'trigger-after-execute' semantics
         */
-       if (!bp_info->extraneous_interrupt)
+       if (!info->extraneous_interrupt)
                perf_bp_event(bp, regs);
 
-       set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
+       set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
        current->thread.last_hit_ubp = NULL;
 
        /*
index b01d14eeca8da2633711d2b114a860a257eea427..8220baa46faf8ced3c383bb5de46b310b802cbbf 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/stat.h>
 #include <linux/of_platform.h>
 #include <asm/ibmebus.h>
-#include <asm/abs_addr.h>
 
 static struct device ibmebus_bus_device = { /* fake "parent" device */
        .init_name = "ibmebus",
index ff5a6ce027b88e88df6dbf7aa32519f2d08e6d7c..8226c6cb348afbf09fc287367637b835dced2100 100644 (file)
@@ -215,7 +215,8 @@ static unsigned long iommu_range_alloc(struct device *dev,
        spin_lock_irqsave(&(pool->lock), flags);
 
 again:
-       if ((pass == 0) && handle && *handle)
+       if ((pass == 0) && handle && *handle &&
+           (*handle >= pool->start) && (*handle < pool->end))
                start = *handle;
        else
                start = pool->hint;
@@ -236,7 +237,9 @@ again:
                 * but on second pass, start at 0 in pool 0.
                 */
                if ((start & mask) >= limit || pass > 0) {
+                       spin_unlock(&(pool->lock));
                        pool = &(tbl->pools[0]);
+                       spin_lock(&(pool->lock));
                        start = pool->start;
                } else {
                        start &= mask;
index 1f017bb7a7cebfc3278fecfd7abe8f3dfaada107..71413f41278f5dfb706d2e8669e6d70cafe7ce9b 100644 (file)
@@ -489,10 +489,10 @@ void do_IRQ(struct pt_regs *regs)
        struct pt_regs *old_regs = set_irq_regs(regs);
        unsigned int irq;
 
-       trace_irq_entry(regs);
-
        irq_enter();
 
+       trace_irq_entry(regs);
+
        check_stack_overflow();
 
        /*
@@ -511,10 +511,10 @@ void do_IRQ(struct pt_regs *regs)
        else
                __get_cpu_var(irq_stat).spurious_irqs++;
 
+       trace_irq_exit(regs);
+
        irq_exit();
        set_irq_regs(old_regs);
-
-       trace_irq_exit(regs);
 }
 
 void __init init_IRQ(void)
index 5df777794403d49a3820add9ba6409701b295da4..fa9f6c72f557026aaf2a4c7c7e763fb45cb7805d 100644 (file)
@@ -165,7 +165,7 @@ void __init reserve_crashkernel(void)
        if (memory_limit && memory_limit <= crashk_res.end) {
                memory_limit = crashk_res.end + 1;
                printk("Adjusted memory limit for crashkernel, now 0x%llx\n",
-                      (unsigned long long)memory_limit);
+                      memory_limit);
        }
 
        printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
@@ -204,6 +204,12 @@ static struct property crashk_size_prop = {
        .value = &crashk_size,
 };
 
+static struct property memory_limit_prop = {
+       .name = "linux,memory-limit",
+       .length = sizeof(unsigned long long),
+       .value = &memory_limit,
+};
+
 static void __init export_crashk_values(struct device_node *node)
 {
        struct property *prop;
@@ -223,6 +229,12 @@ static void __init export_crashk_values(struct device_node *node)
                crashk_size = resource_size(&crashk_res);
                prom_add_property(node, &crashk_size_prop);
        }
+
+       /*
+        * memory_limit is required by the kexec-tools to limit the
+        * crash regions to the actual memory used.
+        */
+       prom_update_property(node, &memory_limit_prop);
 }
 
 static int __init kexec_setup(void)
index fbe1a12dc7f1ae8a2c4cdee3d2225f846f24ba15..cd6da855090c6661310bc2321cd9f33554a52170 100644 (file)
@@ -142,6 +142,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
        new_paca->hw_cpu_id = 0xffff;
        new_paca->kexec_state = KEXEC_STATE_NONE;
        new_paca->__current = &init_task;
+       new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
 #ifdef CONFIG_PPC_STD_MMU_64
        new_paca->slb_shadow_ptr = &slb_shadow[cpu];
 #endif /* CONFIG_PPC_STD_MMU_64 */
index 43fea543d68649d93e9eb734c89b13b3eb7c5a1b..7f94f760dd0c68c8dd031d8fcc8826b759f5420f 100644 (file)
@@ -980,13 +980,14 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
                if (i >= 3 && bus->self->transparent)
                        continue;
 
-               /* If we are going to re-assign everything, mark the resource
-                * as unset and move it down to 0
+               /* If we're going to reassign everything, we can
+                * shrink the P2P resource to have size as being
+                * of 0 in order to save space.
                 */
                if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
                        res->flags |= IORESOURCE_UNSET;
-                       res->end -= res->start;
                        res->start = 0;
+                       res->end = -1;
                        continue;
                }
 
@@ -1248,7 +1249,14 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                pr_warning("PCI: Cannot allocate resource region "
                           "%d of PCI bridge %d, will remap\n", i, bus->number);
        clear_resource:
-               res->start = res->end = 0;
+               /* The resource might be figured out when doing
+                * reassignment based on the resources required
+                * by the downstream PCI devices. Here we set
+                * the size of the resource to be 0 in order to
+                * save more space.
+                */
+               res->start = 0;
+               res->end = -1;
                res->flags = 0;
        }
 
index dc16aefe1dd09876b5a98bffab73869ec52d860b..02fb0ee26093f53c07c494c3a1766bb267dca0de 100644 (file)
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
-typedef struct compat_siginfo {
-       int si_signo;
-       int si_errno;
-       int si_code;
-
-       union {
-               int _pad[SI_PAD_SIZE32];
-
-               /* kill() */
-               struct {
-                       compat_pid_t _pid;              /* sender's pid */
-                       compat_uid_t _uid;              /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;                    /* timer id */
-                       int _overrun;                   /* overrun count */
-                       compat_sigval_t _sigval;                /* same as below */
-                       int _sys_private;               /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       compat_pid_t _pid;              /* sender's pid */
-                       compat_uid_t _uid;              /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       compat_pid_t _pid;              /* which child */
-                       compat_uid_t _uid;              /* sender's uid */
-                       int _status;                    /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-               struct {
-                       unsigned int _addr; /* faulting insn/memory ref. */
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-       } _sifields;
-} compat_siginfo_t;
-
 #define __old_sigaction32      old_sigaction32
 
 struct __old_sigaction32 {
index e9cb51f5f80185024b50d3e8036f3163f7fc3f17..d5ad666efd8b9a5fde3b93541fb774ae8459881f 100644 (file)
@@ -258,6 +258,7 @@ void do_send_trap(struct pt_regs *regs, unsigned long address,
 {
        siginfo_t info;
 
+       current->thread.trap_nr = signal_code;
        if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
                        11, SIGSEGV) == NOTIFY_STOP)
                return;
@@ -275,6 +276,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 {
        siginfo_t info;
 
+       current->thread.trap_nr = TRAP_HWBKPT;
        if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
                        11, SIGSEGV) == NOTIFY_STOP)
                return;
@@ -283,7 +285,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
                return;
 
        /* Clear the DABR */
-       set_dabr(0);
+       set_dabr(0, 0);
 
        /* Deliver the signal to userspace */
        info.si_signo = SIGTRAP;
@@ -364,18 +366,19 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 {
        if (thread->dabr) {
                thread->dabr = 0;
-               set_dabr(0);
+               thread->dabrx = 0;
+               set_dabr(0, 0);
        }
 }
 #endif /* !CONFIG_HAVE_HW_BREAKPOINT */
 #endif /* CONFIG_PPC_ADV_DEBUG_REGS */
 
-int set_dabr(unsigned long dabr)
+int set_dabr(unsigned long dabr, unsigned long dabrx)
 {
        __get_cpu_var(current_dabr) = dabr;
 
        if (ppc_md.set_dabr)
-               return ppc_md.set_dabr(dabr);
+               return ppc_md.set_dabr(dabr, dabrx);
 
        /* XXX should we have a CPU_FTR_HAS_DABR ? */
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -385,9 +388,8 @@ int set_dabr(unsigned long dabr)
 #endif
 #elif defined(CONFIG_PPC_BOOK3S)
        mtspr(SPRN_DABR, dabr);
+       mtspr(SPRN_DABRX, dabrx);
 #endif
-
-
        return 0;
 }
 
@@ -480,7 +482,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
  */
 #ifndef CONFIG_HAVE_HW_BREAKPOINT
        if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
-               set_dabr(new->thread.dabr);
+               set_dabr(new->thread.dabr, new->thread.dabrx);
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
 
index f191bf02943a839dc243e0b9dcbbabe8f874eff1..37725e86651e99bcce696665ba7199fad3445363 100644 (file)
@@ -78,7 +78,7 @@ static int __init early_parse_mem(char *p)
                return 1;
 
        memory_limit = PAGE_ALIGN(memparse(p, &p));
-       DBG("memory limit = 0x%llx\n", (unsigned long long)memory_limit);
+       DBG("memory limit = 0x%llx\n", memory_limit);
 
        return 0;
 }
@@ -661,7 +661,7 @@ void __init early_init_devtree(void *params)
 
        /* make sure we've parsed cmdline for mem= before this */
        if (memory_limit)
-               first_memblock_size = min(first_memblock_size, memory_limit);
+               first_memblock_size = min_t(u64, first_memblock_size, memory_limit);
        setup_initial_memory_limit(memstart_addr, first_memblock_size);
        /* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
        memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
index 47834a3f49381c47f6efd22eb26e17e4e03b242f..cb6c123722a214691d7c99519a08a5aa27e95577 100644 (file)
@@ -1748,7 +1748,7 @@ static void __init prom_initialize_tce_table(void)
                 * else will impact performance, so we always allocate 8MB.
                 * Anton
                 */
-               if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
+               if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
                        minsize = 8UL << 20;
                else
                        minsize = 4UL << 20;
index c10fc28b90920120a12c4bc6cc5c39dbf2780e6a..79d8e56470df8105c9119aee7f01f4938101acc8 100644 (file)
@@ -960,6 +960,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                thread->ptrace_bps[0] = bp;
                ptrace_put_breakpoints(task);
                thread->dabr = data;
+               thread->dabrx = DABRX_ALL;
                return 0;
        }
 
@@ -983,6 +984,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 
        /* Move contents to the DABR register */
        task->thread.dabr = data;
+       task->thread.dabrx = DABRX_ALL;
 #else /* CONFIG_PPC_ADV_DEBUG_REGS */
        /* As described above, it was assumed 3 bits were passed with the data
         *  address, but we will assume only the mode bits will be passed
@@ -1397,6 +1399,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
                dabr |= DABR_DATA_WRITE;
 
        child->thread.dabr = dabr;
+       child->thread.dabrx = DABRX_ALL;
 
        return 1;
 #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
index 2c0ee6405633f7f7240d3a20c464daab8146ea45..20b0120db0c341682f0d15710b690ca6b379b516 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
-#include <asm/abs_addr.h>
 
 #define MODULE_VERS "1.0"
 #define MODULE_NAME "rtas_flash"
@@ -582,7 +581,7 @@ static void rtas_flash_firmware(int reboot_type)
        flist = (struct flash_block_list *)&rtas_data_buf[0];
        flist->num_blocks = 0;
        flist->next = rtas_firmware_flash_list;
-       rtas_block_list = virt_to_abs(flist);
+       rtas_block_list = __pa(flist);
        if (rtas_block_list >= 4UL*1024*1024*1024) {
                printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
                spin_unlock(&rtas_data_buf_lock);
@@ -596,13 +595,13 @@ static void rtas_flash_firmware(int reboot_type)
        for (f = flist; f; f = next) {
                /* Translate data addrs to absolute */
                for (i = 0; i < f->num_blocks; i++) {
-                       f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
+                       f->blocks[i].data = (char *)__pa(f->blocks[i].data);
                        image_size += f->blocks[i].length;
                }
                next = f->next;
                /* Don't translate NULL pointer for last entry */
                if (f->next)
-                       f->next = (struct flash_block_list *)virt_to_abs(f->next);
+                       f->next = (struct flash_block_list *)__pa(f->next);
                else
                        f->next = NULL;
                /* make num_blocks into the version/length field */
index 179af906dcda5685d77a118f0b5afe99db67286e..6de63e3250bb1af364e1b412ed511d1f50092f9c 100644 (file)
@@ -81,7 +81,7 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        if (returnval == EEH_IO_ERROR_VALUE(size) &&
-           eeh_dn_check_failure (pdn->node, NULL))
+           eeh_dev_check_failure(of_node_to_eeh_dev(pdn->node)))
                return PCIBIOS_DEVICE_NOT_FOUND;
 
        return PCIBIOS_SUCCESSFUL;
@@ -275,9 +275,6 @@ void __init find_and_init_phbs(void)
        of_node_put(root);
        pci_devs_phb_init();
 
-       /* Create EEH devices for all PHBs */
-       eeh_dev_phb_init();
-
        /*
         * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties
         * in chosen.
index 389bd4f0cdb10496f1d478fc44181612123f30d1..efb6a41b3131bc1f115ba0b15ec82dba8392b31a 100644 (file)
@@ -208,6 +208,8 @@ void __init early_setup(unsigned long dt_ptr)
 
        /* Fix up paca fields required for the boot cpu */
        get_paca()->cpu_start = 1;
+       /* Allow percpu accesses to "work" until we setup percpu data */
+       get_paca()->data_offset = 0;
 
        /* Probe the machine type */
        probe_machine();
index 5c023c9cf16ee70a7a3b281af2ad9807028c3b13..a2dc75793bd56b2d09786f9cbf3400b0f6051e51 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/tracehook.h>
 #include <linux/signal.h>
+#include <linux/uprobes.h>
 #include <linux/key.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
@@ -130,7 +131,7 @@ static int do_signal(struct pt_regs *regs)
         * triggered inside the kernel.
         */
        if (current->thread.dabr)
-               set_dabr(current->thread.dabr);
+               set_dabr(current->thread.dabr, current->thread.dabrx);
 #endif
        /* Re-enable the breakpoints for the signal stack */
        thread_change_pc(current, regs);
@@ -157,6 +158,11 @@ static int do_signal(struct pt_regs *regs)
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
+       if (thread_info_flags & _TIF_UPROBE) {
+               clear_thread_flag(TIF_UPROBE);
+               uprobe_notify_resume(regs);
+       }
+
        if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
index 8d4214afc21d6934fef8d12b582073c64a6ff7f3..2b952b5386fd5eae72bcf6a7c8320d1768156277 100644 (file)
@@ -102,7 +102,7 @@ int __devinit smp_generic_kick_cpu(int nr)
         * Ok it's not there, so it might be soft-unplugged, let's
         * try to bring it back
         */
-       per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+       generic_set_cpu_up(nr);
        smp_wmb();
        smp_send_reschedule(nr);
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -171,7 +171,7 @@ int smp_request_message_ipi(int virq, int msg)
        }
 #endif
        err = request_irq(virq, smp_ipi_action[msg],
-                         IRQF_PERCPU | IRQF_NO_THREAD,
+                         IRQF_PERCPU | IRQF_NO_THREAD | IRQF_NO_SUSPEND,
                          smp_ipi_name[msg], 0);
        WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
                virq, smp_ipi_name[msg], err);
@@ -413,6 +413,16 @@ void generic_set_cpu_dead(unsigned int cpu)
        per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
 
+/*
+ * The cpu_state should be set to CPU_UP_PREPARE in kick_cpu(), otherwise
+ * the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(),
+ * which makes the delay in generic_cpu_die() not happen.
+ */
+void generic_set_cpu_up(unsigned int cpu)
+{
+       per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+}
+
 int generic_check_cpu_restart(unsigned int cpu)
 {
        return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
index eaa9d0e6abca6747e72acb6e1f69d5475a7c672b..c9986fd400d89947966d4e94746f8d8c9913b7a2 100644 (file)
@@ -508,8 +508,6 @@ void timer_interrupt(struct pt_regs * regs)
         */
        may_hard_irq_enable();
 
-       trace_timer_interrupt_entry(regs);
-
        __get_cpu_var(irq_stat).timer_irqs++;
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
@@ -520,6 +518,8 @@ void timer_interrupt(struct pt_regs * regs)
        old_regs = set_irq_regs(regs);
        irq_enter();
 
+       trace_timer_interrupt_entry(regs);
+
        if (test_irq_work_pending()) {
                clear_irq_work_pending();
                irq_work_run();
@@ -544,10 +544,10 @@ void timer_interrupt(struct pt_regs * regs)
        }
 #endif
 
+       trace_timer_interrupt_exit(regs);
+
        irq_exit();
        set_irq_regs(old_regs);
-
-       trace_timer_interrupt_exit(regs);
 }
 
 /*
index ae0843fa7a61f64540214b2fbf658265d24879df..32518401af68d274be52d52cf9249505496d07a9 100644 (file)
@@ -251,6 +251,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
        if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
                local_irq_enable();
 
+       current->thread.trap_nr = code;
        memset(&info, 0, sizeof(info));
        info.si_signo = signr;
        info.si_code = code;
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
new file mode 100644 (file)
index 0000000..d2d46d1
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * 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.
+ *
+ * Copyright IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+#include <linux/kdebug.h>
+
+#include <asm/sstep.h>
+
+#define UPROBE_TRAP_NR UINT_MAX
+
+/**
+ * arch_uprobe_analyze_insn
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: vaddr to probe.
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
+               struct mm_struct *mm, unsigned long addr)
+{
+       if (addr & 0x03)
+               return -EINVAL;
+
+       /*
+        * We currently don't support a uprobe on an already
+        * existing breakpoint instruction underneath
+        */
+       if (is_trap(auprobe->ainsn))
+               return -ENOTSUPP;
+       return 0;
+}
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       struct arch_uprobe_task *autask = &current->utask->autask;
+
+       autask->saved_trap_nr = current->thread.trap_nr;
+       current->thread.trap_nr = UPROBE_TRAP_NR;
+       regs->nip = current->utask->xol_vaddr;
+       return 0;
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+       return instruction_pointer(regs);
+}
+
+/*
+ * If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc),
+ * then detect the case where a singlestepped instruction jumps back to its
+ * own address. It is assumed that anything like do_page_fault/do_trap/etc
+ * sets thread.trap_nr != UINT_MAX.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == UINT_MAX set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+       if (t->thread.trap_nr != UPROBE_TRAP_NR)
+               return true;
+
+       return false;
+}
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       struct uprobe_task *utask = current->utask;
+
+       WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
+
+       current->thread.trap_nr = utask->autask.saved_trap_nr;
+
+       /*
+        * On powerpc, except for loads and stores, most instructions
+        * including ones that alter code flow (branches, calls, returns)
+        * are emulated in the kernel. We get here only if the emulation
+        * support doesn't exist and have to fix-up the next instruction
+        * to be executed.
+        */
+       regs->nip = utask->vaddr + MAX_UINSN_BYTES;
+       return 0;
+}
+
+/* callback routine for handling exceptions. */
+int arch_uprobe_exception_notify(struct notifier_block *self,
+                               unsigned long val, void *data)
+{
+       struct die_args *args = data;
+       struct pt_regs *regs = args->regs;
+
+       /* regs == NULL is a kernel bug */
+       if (WARN_ON(!regs))
+               return NOTIFY_DONE;
+
+       /* We are only interested in userspace traps */
+       if (!user_mode(regs))
+               return NOTIFY_DONE;
+
+       switch (val) {
+       case DIE_BPT:
+               if (uprobe_pre_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+               break;
+       case DIE_SSTEP:
+               if (uprobe_post_sstep_notifier(regs))
+                       return NOTIFY_STOP;
+       default:
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal, so reset the instruction pointer to its
+ * probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       struct uprobe_task *utask = current->utask;
+
+       current->thread.trap_nr = utask->autask.saved_trap_nr;
+       instruction_pointer_set(regs, utask->vaddr);
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+       int ret;
+
+       /*
+        * emulate_step() returns 1 if the insn was successfully emulated.
+        * For all other cases, we need to single-step in hardware.
+        */
+       ret = emulate_step(regs, auprobe->ainsn);
+       if (ret > 0)
+               return true;
+
+       return false;
+}
index b67db22e102dd93dc11ec131ac7e942cf6de3d5c..1b2076f049cecaf954b111df7a6a07b964258c52 100644 (file)
@@ -723,9 +723,7 @@ int __cpuinit vdso_getcpu_init(void)
 
        val = (cpu & 0xfff) | ((node & 0xffff) << 16);
        mtspr(SPRN_SPRG3, val);
-#ifdef CONFIG_KVM_BOOK3S_HANDLER
-       get_paca()->kvm_hstate.sprg3 = val;
-#endif
+       get_paca()->sprg3 = val;
 
        put_cpu();
 
index 02b32216bbc3bb28de3a22b307f6f19aab2cd0a9..201ba59738be93fefc95786336a7ebe57c0a1ed6 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/prom.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 #include <asm/page.h>
 #include <asm/hvcall.h>
 
index 837f13e7b6bfc1be3f7ed65a1000964f04825ebe..00aa61268e0d6e66f34c9625365951ce29403990 100644 (file)
@@ -141,7 +141,7 @@ extern char etext[];
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
        pfn_t hpaddr;
-       u64 va;
+       u64 vpn;
        u64 vsid;
        struct kvmppc_sid_map *map;
        volatile u32 *pteg;
@@ -173,7 +173,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        BUG_ON(!map);
 
        vsid = map->host_vsid;
-       va = (vsid << SID_SHIFT) | (eaddr & ~ESID_MASK);
+       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
 
 next_pteg:
        if (rr == 16) {
@@ -244,11 +244,11 @@ next_pteg:
        dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%llx (0x%llx) -> %lx\n",
                    orig_pte->may_write ? 'w' : '-',
                    orig_pte->may_execute ? 'x' : '-',
-                   orig_pte->eaddr, (ulong)pteg, va,
+                   orig_pte->eaddr, (ulong)pteg, vpn,
                    orig_pte->vpage, hpaddr);
 
        pte->slot = (ulong)&pteg[rr];
-       pte->host_va = va;
+       pte->host_vpn = vpn;
        pte->pte = *orig_pte;
        pte->pfn = hpaddr >> PAGE_SHIFT;
 
index 0688b6b3958594fce84a62cfbd2f3564b5650781..4d72f9ebc554bddf331ac9d9201b10cd0d3e484f 100644 (file)
@@ -33,7 +33,7 @@
 
 void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
-       ppc_md.hpte_invalidate(pte->slot, pte->host_va,
+       ppc_md.hpte_invalidate(pte->slot, pte->host_vpn,
                               MMU_PAGE_4K, MMU_SEGSIZE_256M,
                               false);
 }
@@ -80,8 +80,9 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
 
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
+       unsigned long vpn;
        pfn_t hpaddr;
-       ulong hash, hpteg, va;
+       ulong hash, hpteg;
        u64 vsid;
        int ret;
        int rflags = 0x192;
@@ -117,7 +118,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        }
 
        vsid = map->host_vsid;
-       va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
+       vpn = hpt_vpn(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
 
        if (!orig_pte->may_write)
                rflags |= HPTE_R_PP;
@@ -129,7 +130,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        else
                kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
 
-       hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
+       hash = hpt_hash(vpn, PTE_SIZE, MMU_SEGSIZE_256M);
 
 map_again:
        hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
@@ -141,7 +142,8 @@ map_again:
                        goto out;
                }
 
-       ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
+       ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags,
+                                MMU_PAGE_4K, MMU_SEGSIZE_256M);
 
        if (ret < 0) {
                /* If we couldn't map a primary PTE, try a secondary */
@@ -152,7 +154,8 @@ map_again:
        } else {
                struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu);
 
-               trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte);
+               trace_kvm_book3s_64_mmu_map(rflags, hpteg,
+                                           vpn, hpaddr, orig_pte);
 
                /* The ppc_md code may give us a secondary entry even though we
                   asked for a primary. Fix up. */
@@ -162,7 +165,7 @@ map_again:
                }
 
                pte->slot = hpteg + (ret & 7);
-               pte->host_va = va;
+               pte->host_vpn = vpn;
                pte->pte = *orig_pte;
                pte->pfn = hpaddr >> PAGE_SHIFT;
 
index 44b72feaff7d9876fad230253be42c1aee6e8af7..74a24bbb963762cdb89eac53e9a302c184084c35 100644 (file)
@@ -1065,7 +1065,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
        mtspr   SPRN_DABRX,r6
 
        /* Restore SPRG3 */
-       ld      r3,HSTATE_SPRG3(r13)
+       ld      r3,PACA_SPRG3(r13)
        mtspr   SPRN_SPRG3,r3
 
        /*
index 877186b7b1c360c5deae3905b076166f6843e21c..ddb6a2149d4460c067da161de4672f3cbaf4a97a 100644 (file)
@@ -189,7 +189,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
        TP_ARGS(pte),
 
        TP_STRUCT__entry(
-               __field(        u64,            host_v        )
+               __field(        u64,            host_vpn        )
                __field(        u64,            pfn             )
                __field(        ulong,          eaddr           )
                __field(        u64,            vpage           )
@@ -198,7 +198,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
        ),
 
        TP_fast_assign(
-               __entry->host_va        = pte->host_va;
+               __entry->host_vpn       = pte->host_vpn;
                __entry->pfn            = pte->pfn;
                __entry->eaddr          = pte->pte.eaddr;
                __entry->vpage          = pte->pte.vpage;
@@ -208,8 +208,8 @@ TRACE_EVENT(kvm_book3s_mmu_map,
                                          (pte->pte.may_execute ? 0x1 : 0);
        ),
 
-       TP_printk("Map: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-                 __entry->host_va, __entry->pfn, __entry->eaddr,
+       TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
+                 __entry->host_vpn, __entry->pfn, __entry->eaddr,
                  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
@@ -218,7 +218,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        TP_ARGS(pte),
 
        TP_STRUCT__entry(
-               __field(        u64,            host_v        )
+               __field(        u64,            host_vpn        )
                __field(        u64,            pfn             )
                __field(        ulong,          eaddr           )
                __field(        u64,            vpage           )
@@ -227,7 +227,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        ),
 
        TP_fast_assign(
-               __entry->host_va        = pte->host_va;
+               __entry->host_vpn       = pte->host_vpn;
                __entry->pfn            = pte->pfn;
                __entry->eaddr          = pte->pte.eaddr;
                __entry->vpage          = pte->pte.vpage;
@@ -238,7 +238,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        ),
 
        TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-                 __entry->host_va, __entry->pfn, __entry->eaddr,
+                 __entry->host_vpn, __entry->pfn, __entry->eaddr,
                  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
index 7ba6c96de77856e426fe5cf83ff360280e239194..0663630baf3b46373905d60d96e989fee6637aa8 100644 (file)
@@ -239,8 +239,8 @@ _GLOBAL(memcpy_power7)
        ori     r9,r9,1         /* stream=1 */
 
        srdi    r7,r5,7         /* length in cachelines, capped at 0x3FF */
-       cmpldi  cr1,r7,0x3FF
-       ble     cr1,1f
+       cmpldi  r7,0x3FF
+       ble     1f
        li      r7,0x3FF
 1:     lis     r0,0x0E00       /* depth=7 */
        sldi    r7,r7,7
index 9a52349874ee182e79c3fff1863caf0e603178c5..e15c521846ca924291bca5b9dc923ec5275d3e69 100644 (file)
@@ -566,7 +566,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
        unsigned long int ea;
        unsigned int cr, mb, me, sh;
        int err;
-       unsigned long old_ra;
+       unsigned long old_ra, val3;
        long ival;
 
        opcode = instr >> 26;
@@ -1486,11 +1486,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                goto ldst_done;
 
        case 36:        /* stw */
-       case 37:        /* stwu */
                val = regs->gpr[rd];
                err = write_mem(val, dform_ea(instr, regs), 4, regs);
                goto ldst_done;
 
+       case 37:        /* stwu */
+               val = regs->gpr[rd];
+               val3 = dform_ea(instr, regs);
+               /*
+                * For PPC32 we always use stwu to change stack point with r1. So
+                * this emulated store may corrupt the exception frame, now we
+                * have to provide the exception frame trampoline, which is pushed
+                * below the kprobed function stack. So we only update gpr[1] but
+                * don't emulate the real store operation. We will do real store
+                * operation safely in exception return code by checking this flag.
+                */
+               if ((ra == 1) && !(regs->msr & MSR_PR) \
+                       && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
+                       /*
+                        * Check if we will touch kernel sack overflow
+                        */
+                       if (val3 - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) {
+                               printk(KERN_CRIT "Can't kprobe this since Kernel stack overflow.\n");
+                               err = -EINVAL;
+                               break;
+                       }
+
+                       /*
+                        * Check if we already set since that means we'll
+                        * lose the previous value.
+                        */
+                       WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
+                       set_thread_flag(TIF_EMULATE_STACK_STORE);
+                       err = 0;
+               } else
+                       err = write_mem(val, val3, 4, regs);
+               goto ldst_done;
+
        case 38:        /* stb */
        case 39:        /* stbu */
                val = regs->gpr[rd];
index e5f028b5794e6a69498184f9b3b7b617b0701bbb..5495ebe983a23489403be6fc8388e7434a47f769 100644 (file)
@@ -133,6 +133,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address)
        up_read(&current->mm->mmap_sem);
 
        if (user_mode(regs)) {
+               current->thread.trap_nr = BUS_ADRERR;
                info.si_signo = SIGBUS;
                info.si_errno = 0;
                info.si_code = BUS_ADRERR;
index 602aeb06d298b1eccc72089b0251443dff397163..56585086413a4f9876c70eb6b6ea9f3cf1c1ef69 100644 (file)
@@ -63,7 +63,7 @@ _GLOBAL(__hash_page_4K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
@@ -111,10 +111,10 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28
-       rldicl  r3,r3,0,36
-       or      r29,r3,r29
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -122,14 +122,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * calculate hash value for primary slot and
+        * store it in r28 for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -185,7 +190,7 @@ htab_insert_pte:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -208,7 +213,7 @@ _GLOBAL(htab_call_hpte_insert1)
        
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -278,7 +283,7 @@ htab_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_4K          /* page size */
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
@@ -339,7 +344,7 @@ _GLOBAL(__hash_page_4K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         * r26 is the hidx mask
@@ -394,10 +399,14 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28         /* r29 = (vsid << 28) */
-       rldicl  r3,r3,0,36              /* r3 = (ea & 0x0fffffff) */
-       or      r29,r3,r29              /* r29 = va */
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       /*
+        * clrldi r3,r3,64 - SID_SHIFT -->  ea & 0xfffffff
+        * srdi  r28,r3,VPN_SHIFT
+        */
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -405,14 +414,23 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       /*
+        * clrldi r3,r3,64 - SID_SHIFT_1T -->  ea & 0xffffffffff
+        * srdi r28,r3,VPN_SHIFT
+        */
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * Calculate hash value for primary slot and
+        * store it in r28  for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -488,7 +506,7 @@ htab_special_pfn:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -515,7 +533,7 @@ _GLOBAL(htab_call_hpte_insert1)
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -547,7 +565,7 @@ _GLOBAL(htab_call_hpte_remove)
         * useless now that the segment has been switched to 4k pages.
         */
 htab_inval_old_hpte:
-       mr      r3,r29                  /* virtual addr */
+       mr      r3,r29                  /* vpn */
        mr      r4,r31                  /* PTE.pte */
        li      r5,0                    /* PTE.hidx */
        li      r6,MMU_PAGE_64K         /* psize */
@@ -620,7 +638,7 @@ htab_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_4K          /* page size */
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
@@ -676,7 +694,7 @@ _GLOBAL(__hash_page_64K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
@@ -729,10 +747,10 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28
-       rldicl  r3,r3,0,36
-       or      r29,r3,r29
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -740,14 +758,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * calculate hash value for primary slot and
+        * store it in r28 for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-16,40          /* (ea >> 16) & 0xffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -806,7 +829,7 @@ ht64_insert_pte:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_64K
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -829,7 +852,7 @@ _GLOBAL(ht64_call_hpte_insert1)
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_64K
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -899,7 +922,7 @@ ht64_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_64K
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
index 90039bc64119902c5bf85b79b4dd8bab31fd0e10..ffc1e00f7a22f706f9c364601643328a8918ceb6 100644 (file)
 
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
+#include <linux/of.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
 
-#include <asm/abs_addr.h>
 #include <asm/machdep.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 
 DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
-static inline void __tlbie(unsigned long va, int psize, int ssize)
+static inline void __tlbie(unsigned long vpn, int psize, int ssize)
 {
+       unsigned long va;
        unsigned int penc;
 
-       /* clear top 16 bits, non SLS segment */
+       /*
+        * We need 14 to 65 bits of va for a tlibe of 4K page
+        * With vpn we ignore the lower VPN_SHIFT bits already.
+        * And top two bits are already ignored because we can
+        * only accomadate 76 bits in a 64 bit vpn with a VPN_SHIFT
+        * of 12.
+        */
+       va = vpn << VPN_SHIFT;
+       /*
+        * clear top 16 bits of 64bit va, non SLS segment
+        * Older versions of the architecture (2.02 and earler) require the
+        * masking of the top 16 bits.
+        */
        va &= ~(0xffffULL << 48);
 
        switch (psize) {
        case MMU_PAGE_4K:
-               va &= ~0xffful;
                va |= ssize << 8;
                asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
                             : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
                             : "memory");
                break;
        default:
+               /* We need 14 to 14 + i bits of va */
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
                va |= penc << 12;
@@ -67,21 +80,28 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
        }
 }
 
-static inline void __tlbiel(unsigned long va, int psize, int ssize)
+static inline void __tlbiel(unsigned long vpn, int psize, int ssize)
 {
+       unsigned long va;
        unsigned int penc;
 
-       /* clear top 16 bits, non SLS segment */
+       /* VPN_SHIFT can be atmost 12 */
+       va = vpn << VPN_SHIFT;
+       /*
+        * clear top 16 bits of 64 bit va, non SLS segment
+        * Older versions of the architecture (2.02 and earler) require the
+        * masking of the top 16 bits.
+        */
        va &= ~(0xffffULL << 48);
 
        switch (psize) {
        case MMU_PAGE_4K:
-               va &= ~0xffful;
                va |= ssize << 8;
                asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
                             : : "r"(va) : "memory");
                break;
        default:
+               /* We need 14 to 14 + i bits of va */
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
                va |= penc << 12;
@@ -94,7 +114,7 @@ static inline void __tlbiel(unsigned long va, int psize, int ssize)
 
 }
 
-static inline void tlbie(unsigned long va, int psize, int ssize, int local)
+static inline void tlbie(unsigned long vpn, int psize, int ssize, int local)
 {
        unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL);
        int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
@@ -105,10 +125,10 @@ static inline void tlbie(unsigned long va, int psize, int ssize, int local)
                raw_spin_lock(&native_tlbie_lock);
        asm volatile("ptesync": : :"memory");
        if (use_local) {
-               __tlbiel(va, psize, ssize);
+               __tlbiel(vpn, psize, ssize);
                asm volatile("ptesync": : :"memory");
        } else {
-               __tlbie(va, psize, ssize);
+               __tlbie(vpn, psize, ssize);
                asm volatile("eieio; tlbsync; ptesync": : :"memory");
        }
        if (lock_tlbie && !use_local)
@@ -134,7 +154,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)
        clear_bit_unlock(HPTE_LOCK_BIT, word);
 }
 
-static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
                        unsigned long pa, unsigned long rflags,
                        unsigned long vflags, int psize, int ssize)
 {
@@ -143,9 +163,9 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
        int i;
 
        if (!(vflags & HPTE_V_BOLTED)) {
-               DBG_LOW("    insert(group=%lx, va=%016lx, pa=%016lx,"
+               DBG_LOW("    insert(group=%lx, vpn=%016lx, pa=%016lx,"
                        " rflags=%lx, vflags=%lx, psize=%d)\n",
-                       hpte_group, va, pa, rflags, vflags, psize);
+                       hpte_group, vpn, pa, rflags, vflags, psize);
        }
 
        for (i = 0; i < HPTES_PER_GROUP; i++) {
@@ -163,7 +183,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
        if (i == HPTES_PER_GROUP)
                return -1;
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED)) {
@@ -225,17 +245,17 @@ static long native_hpte_remove(unsigned long hpte_group)
 }
 
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
-                                unsigned long va, int psize, int ssize,
+                                unsigned long vpn, int psize, int ssize,
                                 int local)
 {
        struct hash_pte *hptep = htab_address + slot;
        unsigned long hpte_v, want_v;
        int ret = 0;
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
-       DBG_LOW("    update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
-               va, want_v & HPTE_V_AVPN, slot, newpp);
+       DBG_LOW("    update(vpn=%016lx, avpnv=%016lx, group=%lx, newpp=%lx)",
+               vpn, want_v & HPTE_V_AVPN, slot, newpp);
 
        native_lock_hpte(hptep);
 
@@ -254,12 +274,12 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
        native_unlock_hpte(hptep);
 
        /* Ensure it is out of the tlb too. */
-       tlbie(va, psize, ssize, local);
+       tlbie(vpn, psize, ssize, local);
 
        return ret;
 }
 
-static long native_hpte_find(unsigned long va, int psize, int ssize)
+static long native_hpte_find(unsigned long vpn, int psize, int ssize)
 {
        struct hash_pte *hptep;
        unsigned long hash;
@@ -267,8 +287,8 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-       want_v = hpte_encode_v(va, psize, ssize);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
        /* Bolted mappings are only ever in the primary group */
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -295,14 +315,15 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
 static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
                                       int psize, int ssize)
 {
-       unsigned long vsid, va;
+       unsigned long vpn;
+       unsigned long vsid;
        long slot;
        struct hash_pte *hptep;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = native_hpte_find(va, psize, ssize);
+       slot = native_hpte_find(vpn, psize, ssize);
        if (slot == -1)
                panic("could not find page to bolt\n");
        hptep = htab_address + slot;
@@ -312,10 +333,10 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
                (newpp & (HPTE_R_PP | HPTE_R_N));
 
        /* Ensure it is out of the tlb too. */
-       tlbie(va, psize, ssize, 0);
+       tlbie(vpn, psize, ssize, 0);
 }
 
-static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                   int psize, int ssize, int local)
 {
        struct hash_pte *hptep = htab_address + slot;
@@ -325,9 +346,9 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 
        local_irq_save(flags);
 
-       DBG_LOW("    invalidate(va=%016lx, hash: %x)\n", va, slot);
+       DBG_LOW("    invalidate(vpn=%016lx, hash: %lx)\n", vpn, slot);
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
        native_lock_hpte(hptep);
        hpte_v = hptep->v;
 
@@ -339,7 +360,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
                hptep->v = 0;
 
        /* Invalidate the TLB */
-       tlbie(va, psize, ssize, local);
+       tlbie(vpn, psize, ssize, local);
 
        local_irq_restore(flags);
 }
@@ -349,11 +370,12 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 #define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
 
 static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
-                       int *psize, int *ssize, unsigned long *va)
+                       int *psize, int *ssize, unsigned long *vpn)
 {
+       unsigned long avpn, pteg, vpi;
        unsigned long hpte_r = hpte->r;
        unsigned long hpte_v = hpte->v;
-       unsigned long avpn;
+       unsigned long vsid, seg_off;
        int i, size, shift, penc;
 
        if (!(hpte_v & HPTE_V_LARGE))
@@ -380,32 +402,38 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
        }
 
        /* This works for all page sizes, and for 256M and 1T segments */
+       *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
        shift = mmu_psize_defs[size].shift;
-       avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23;
-
-       if (shift < 23) {
-               unsigned long vpi, vsid, pteg;
 
-               pteg = slot / HPTES_PER_GROUP;
-               if (hpte_v & HPTE_V_SECONDARY)
-                       pteg = ~pteg;
-               switch (hpte_v >> HPTE_V_SSIZE_SHIFT) {
-               case MMU_SEGSIZE_256M:
-                       vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
-                       break;
-               case MMU_SEGSIZE_1T:
-                       vsid = avpn >> 40;
+       avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
+       pteg = slot / HPTES_PER_GROUP;
+       if (hpte_v & HPTE_V_SECONDARY)
+               pteg = ~pteg;
+
+       switch (*ssize) {
+       case MMU_SEGSIZE_256M:
+               /* We only have 28 - 23 bits of seg_off in avpn */
+               seg_off = (avpn & 0x1f) << 23;
+               vsid    =  avpn >> 5;
+               /* We can find more bits from the pteg value */
+               if (shift < 23) {
+                       vpi = (vsid ^ pteg) & htab_hash_mask;
+                       seg_off |= vpi << shift;
+               }
+               *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+       case MMU_SEGSIZE_1T:
+               /* We only have 40 - 23 bits of seg_off in avpn */
+               seg_off = (avpn & 0x1ffff) << 23;
+               vsid    = avpn >> 17;
+               if (shift < 23) {
                        vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
-                       break;
-               default:
-                       avpn = vpi = size = 0;
+                       seg_off |= vpi << shift;
                }
-               avpn |= (vpi << mmu_psize_defs[size].shift);
+               *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+       default:
+               *vpn = size = 0;
        }
-
-       *va = avpn;
        *psize = size;
-       *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 }
 
 /*
@@ -418,9 +446,10 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
  */
 static void native_hpte_clear(void)
 {
+       unsigned long vpn = 0;
        unsigned long slot, slots, flags;
        struct hash_pte *hptep = htab_address;
-       unsigned long hpte_v, va;
+       unsigned long hpte_v;
        unsigned long pteg_count;
        int psize, ssize;
 
@@ -448,9 +477,9 @@ static void native_hpte_clear(void)
                 * already hold the native_tlbie_lock.
                 */
                if (hpte_v & HPTE_V_VALID) {
-                       hpte_decode(hptep, slot, &psize, &ssize, &va);
+                       hpte_decode(hptep, slot, &psize, &ssize, &vpn);
                        hptep->v = 0;
-                       __tlbie(va, psize, ssize);
+                       __tlbie(vpn, psize, ssize);
                }
        }
 
@@ -465,7 +494,8 @@ static void native_hpte_clear(void)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-       unsigned long va, hash, index, hidx, shift, slot;
+       unsigned long vpn;
+       unsigned long hash, index, hidx, shift, slot;
        struct hash_pte *hptep;
        unsigned long hpte_v;
        unsigned long want_v;
@@ -479,18 +509,18 @@ static void native_flush_hash_range(unsigned long number, int local)
        local_irq_save(flags);
 
        for (i = 0; i < number; i++) {
-               va = batch->vaddr[i];
+               vpn = batch->vpn[i];
                pte = batch->pte[i];
 
-               pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-                       hash = hpt_hash(va, shift, ssize);
+               pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+                       hash = hpt_hash(vpn, shift, ssize);
                        hidx = __rpte_to_hidx(pte, index);
                        if (hidx & _PTEIDX_SECONDARY)
                                hash = ~hash;
                        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                        slot += hidx & _PTEIDX_GROUP_IX;
                        hptep = htab_address + slot;
-                       want_v = hpte_encode_v(va, psize, ssize);
+                       want_v = hpte_encode_v(vpn, psize, ssize);
                        native_lock_hpte(hptep);
                        hpte_v = hptep->v;
                        if (!HPTE_V_COMPARE(hpte_v, want_v) ||
@@ -505,12 +535,12 @@ static void native_flush_hash_range(unsigned long number, int local)
            mmu_psize_defs[psize].tlbiel && local) {
                asm volatile("ptesync":::"memory");
                for (i = 0; i < number; i++) {
-                       va = batch->vaddr[i];
+                       vpn = batch->vpn[i];
                        pte = batch->pte[i];
 
-                       pte_iterate_hashed_subpages(pte, psize, va, index,
-                                                   shift) {
-                               __tlbiel(va, psize, ssize);
+                       pte_iterate_hashed_subpages(pte, psize,
+                                                   vpn, index, shift) {
+                               __tlbiel(vpn, psize, ssize);
                        } pte_iterate_hashed_end();
                }
                asm volatile("ptesync":::"memory");
@@ -522,12 +552,12 @@ static void native_flush_hash_range(unsigned long number, int local)
 
                asm volatile("ptesync":::"memory");
                for (i = 0; i < number; i++) {
-                       va = batch->vaddr[i];
+                       vpn = batch->vpn[i];
                        pte = batch->pte[i];
 
-                       pte_iterate_hashed_subpages(pte, psize, va, index,
-                                                   shift) {
-                               __tlbie(va, psize, ssize);
+                       pte_iterate_hashed_subpages(pte, psize,
+                                                   vpn, index, shift) {
+                               __tlbie(vpn, psize, ssize);
                        } pte_iterate_hashed_end();
                }
                asm volatile("eieio; tlbsync; ptesync":::"memory");
@@ -539,29 +569,6 @@ static void native_flush_hash_range(unsigned long number, int local)
        local_irq_restore(flags);
 }
 
-#ifdef CONFIG_PPC_PSERIES
-/* Disable TLB batching on nighthawk */
-static inline int tlb_batching_enabled(void)
-{
-       struct device_node *root = of_find_node_by_path("/");
-       int enabled = 1;
-
-       if (root) {
-               const char *model = of_get_property(root, "model", NULL);
-               if (model && !strcmp(model, "IBM,9076-N81"))
-                       enabled = 0;
-               of_node_put(root);
-       }
-
-       return enabled;
-}
-#else
-static inline int tlb_batching_enabled(void)
-{
-       return 1;
-}
-#endif
-
 void __init hpte_init_native(void)
 {
        ppc_md.hpte_invalidate  = native_hpte_invalidate;
@@ -570,6 +577,5 @@ void __init hpte_init_native(void)
        ppc_md.hpte_insert      = native_hpte_insert;
        ppc_md.hpte_remove      = native_hpte_remove;
        ppc_md.hpte_clear_all   = native_hpte_clear;
-       if (tlb_batching_enabled())
-               ppc_md.flush_hash_range = native_flush_hash_range;
+       ppc_md.flush_hash_range = native_flush_hash_range;
 }
index 377e5cbedbbb8c962d7d5f9b0fae7473b22b1481..3a292be2e07912b903075d6c6bf70ee0e02641d9 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/abs_addr.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
 #include <asm/eeh.h>
@@ -192,18 +191,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
             vaddr += step, paddr += step) {
                unsigned long hash, hpteg;
                unsigned long vsid = get_kernel_vsid(vaddr, ssize);
-               unsigned long va = hpt_va(vaddr, vsid, ssize);
+               unsigned long vpn  = hpt_vpn(vaddr, vsid, ssize);
                unsigned long tprot = prot;
 
                /* Make kernel text executable */
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
 
-               hash = hpt_hash(va, shift, ssize);
+               hash = hpt_hash(vpn, shift, ssize);
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
                BUG_ON(!ppc_md.hpte_insert);
-               ret = ppc_md.hpte_insert(hpteg, va, paddr, tprot,
+               ret = ppc_md.hpte_insert(hpteg, vpn, paddr, tprot,
                                         HPTE_V_BOLTED, psize, ssize);
 
                if (ret < 0)
@@ -651,7 +650,7 @@ static void __init htab_initialize(void)
                DBG("Hash table allocated at %lx, size: %lx\n", table,
                    htab_size_bytes);
 
-               htab_address = abs_to_virt(table);
+               htab_address = __va(table);
 
                /* htab absolute addr + encoded htabsize */
                _SDR1 = table + __ilog2(pteg_count) - 11;
@@ -804,16 +803,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 #ifdef CONFIG_PPC_MM_SLICES
 unsigned int get_paca_psize(unsigned long addr)
 {
-       unsigned long index, slices;
+       u64 lpsizes;
+       unsigned char *hpsizes;
+       unsigned long index, mask_index;
 
        if (addr < SLICE_LOW_TOP) {
-               slices = get_paca()->context.low_slices_psize;
+               lpsizes = get_paca()->context.low_slices_psize;
                index = GET_LOW_SLICE_INDEX(addr);
-       } else {
-               slices = get_paca()->context.high_slices_psize;
-               index = GET_HIGH_SLICE_INDEX(addr);
+               return (lpsizes >> (index * 4)) & 0xF;
        }
-       return (slices >> (index * 4)) & 0xF;
+       hpsizes = get_paca()->context.high_slices_psize;
+       index = GET_HIGH_SLICE_INDEX(addr);
+       mask_index = index & 0x1;
+       return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xF;
 }
 
 #else
@@ -1153,21 +1155,21 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 /* WARNING: This is called from hash_low_64.S, if you change this prototype,
  *          do not forget to update the assembly call site !
  */
-void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
+void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
                     int local)
 {
        unsigned long hash, index, shift, hidx, slot;
 
-       DBG_LOW("flush_hash_page(va=%016lx)\n", va);
-       pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-               hash = hpt_hash(va, shift, ssize);
+       DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
+       pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+               hash = hpt_hash(vpn, shift, ssize);
                hidx = __rpte_to_hidx(pte, index);
                if (hidx & _PTEIDX_SECONDARY)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += hidx & _PTEIDX_GROUP_IX;
                DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
-               ppc_md.hpte_invalidate(slot, va, psize, ssize, local);
+               ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local);
        } pte_iterate_hashed_end();
 }
 
@@ -1181,7 +1183,7 @@ void flush_hash_range(unsigned long number, int local)
                        &__get_cpu_var(ppc64_tlb_batch);
 
                for (i = 0; i < number; i++)
-                       flush_hash_page(batch->vaddr[i], batch->pte[i],
+                       flush_hash_page(batch->vpn[i], batch->pte[i],
                                        batch->psize, batch->ssize, local);
        }
 }
@@ -1208,14 +1210,14 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
 {
        unsigned long hash, hpteg;
        unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-       unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+       unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
        unsigned long mode = htab_convert_pte_flags(PAGE_KERNEL);
        int ret;
 
-       hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+       hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
        hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-       ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr),
+       ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
                                 mode, HPTE_V_BOLTED,
                                 mmu_linear_psize, mmu_kernel_ssize);
        BUG_ON (ret < 0);
@@ -1229,9 +1231,9 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
 {
        unsigned long hash, hidx, slot;
        unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-       unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+       unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
 
-       hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+       hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
        spin_lock(&linear_map_hash_lock);
        BUG_ON(!(linear_map_hash_slots[lmi] & 0x80));
        hidx = linear_map_hash_slots[lmi] & 0x7f;
@@ -1241,7 +1243,7 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
                hash = ~hash;
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
        slot += hidx & _PTEIDX_GROUP_IX;
-       ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, mmu_kernel_ssize, 0);
+       ppc_md.hpte_invalidate(slot, vpn, mmu_linear_psize, mmu_kernel_ssize, 0);
 }
 
 void kernel_map_pages(struct page *page, int numpages, int enable)
index cc5c273086cf833e28bc89a91bb814b09c16a4e4..cecad348f604a05941fbce6d91d50267fa2d0c4f 100644 (file)
@@ -18,14 +18,15 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                     pte_t *ptep, unsigned long trap, int local, int ssize,
                     unsigned int shift, unsigned int mmu_psize)
 {
+       unsigned long vpn;
        unsigned long old_pte, new_pte;
-       unsigned long va, rflags, pa, sz;
+       unsigned long rflags, pa, sz;
        long slot;
 
        BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
 
        /* Search the Linux page table for a match with va */
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
        /* At this point, we have a pte (old_pte) which can be used to build
         * or update an HPTE. There are 2 cases:
@@ -69,19 +70,19 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                /* There MIGHT be an HPTE for this pte */
                unsigned long hash, slot;
 
-               hash = hpt_hash(va, shift, ssize);
+               hash = hpt_hash(vpn, shift, ssize);
                if (old_pte & _PAGE_F_SECOND)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += (old_pte & _PAGE_F_GIX) >> 12;
 
-               if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize,
+               if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
                                         ssize, local) == -1)
                        old_pte &= ~_PAGE_HPTEFLAGS;
        }
 
        if (likely(!(old_pte & _PAGE_HASHPTE))) {
-               unsigned long hash = hpt_hash(va, shift, ssize);
+               unsigned long hash = hpt_hash(vpn, shift, ssize);
                unsigned long hpte_group;
 
                pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
@@ -101,14 +102,14 @@ repeat:
                                      _PAGE_COHERENT | _PAGE_GUARDED));
 
                /* Insert into the hash table, primary slot */
-               slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
+               slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
                                          mmu_psize, ssize);
 
                /* Primary is full, try the secondary */
                if (unlikely(slot == -1)) {
                        hpte_group = ((~hash & htab_hash_mask) *
                                      HPTES_PER_GROUP) & ~0x7UL;
-                       slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
+                       slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags,
                                                  HPTE_V_SECONDARY,
                                                  mmu_psize, ssize);
                        if (slot == -1) {
index 620b7acd2fdfed444e71abf3f080c709482e95d1..95a45293e5ac0dd2c6b343f1aa7a81ed8b69b666 100644 (file)
@@ -62,7 +62,6 @@
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/iommu.h>
-#include <asm/abs_addr.h>
 #include <asm/vdso.h>
 
 #include "mmu_decl.h"
index fbdad0e3929a8ddfbcb0f714a6480f0ca33ba6f6..0dba5066c22ac4f59578c3663c212f8a07ca3a78 100644 (file)
@@ -62,7 +62,7 @@
 
 int init_bootmem_done;
 int mem_init_done;
-phys_addr_t memory_limit;
+unsigned long long memory_limit;
 
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
@@ -300,8 +300,7 @@ void __init mem_init(void)
        unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
 
 #ifdef CONFIG_SWIOTLB
-       if (ppc_swiotlb_enable)
-               swiotlb_init(1);
+       swiotlb_init(0);
 #endif
 
        num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT;
index 40677aa0190e53b4013ddb535a181cda13390e63..40bc5b0ace54354aea6944d77b6ef07e6f7f7b3d 100644 (file)
@@ -30,11 +30,13 @@ static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
 /*
- * The proto-VSID space has 2^35 - 1 segments available for user mappings.
- * Each segment contains 2^28 bytes.  Each context maps 2^44 bytes,
- * so we can support 2^19-1 contexts (19 == 35 + 28 - 44).
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
+ * available for user mappings. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
  */
-#define MAX_CONTEXT    ((1UL << 19) - 1)
+#define MAX_CONTEXT    ((1UL << CONTEXT_BITS) - 1)
 
 int __init_new_context(void)
 {
index 249a0631c4dbc63ca8cdf0ca422b8663b9a6299f..e212a271c7a4bdadac512efd24da89de6c9ddd77 100644 (file)
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IOREMAP_BASE;
+/* Some sanity checking */
+#if TASK_SIZE_USER64 > PGTABLE_RANGE
+#error TASK_SIZE_USER64 exceeds pagetable range
+#endif
+
+#ifdef CONFIG_PPC_STD_MMU_64
+#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#error TASK_SIZE_USER64 exceeds user VSID range
+#endif
+#endif
 
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 #ifdef CONFIG_PPC_MMU_NOHASH
 static void *early_alloc_pgtable(unsigned long size)
index b9ee79ce2200998012e18cf95f462aebbb85e748..1a16ca2277575fef9c0614df84f6e4f93df376f1 100644 (file)
@@ -56,6 +56,12 @@ _GLOBAL(slb_allocate_realmode)
         */
 _GLOBAL(slb_miss_kernel_load_linear)
        li      r11,0
+       li      r9,0x1
+       /*
+        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+        * the necessary adjustment
+        */
+       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -85,6 +91,12 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
        _GLOBAL(slb_miss_kernel_load_io)
        li      r11,0
 6:
+       li      r9,0x1
+       /*
+        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+        * the necessary adjustment
+        */
+       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -108,17 +120,31 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
         * between 4k and 64k standard page size
         */
 #ifdef CONFIG_PPC_MM_SLICES
+       /* r10 have esid */
        cmpldi  r10,16
-
-       /* Get the slice index * 4 in r11 and matching slice size mask in r9 */
-       ld      r9,PACALOWSLICESPSIZE(r13)
-       sldi    r11,r10,2
+       /* below SLICE_LOW_TOP */
        blt     5f
-       ld      r9,PACAHIGHSLICEPSIZE(r13)
-       srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
-       andi.   r11,r11,0x3c
+       /*
+        * Handle hpsizes,
+        * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
+        */
+       srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */
+       addi    r9,r11,PACAHIGHSLICEPSIZE
+       lbzx    r9,r13,r9               /* r9 is hpsizes[r11] */
+       /* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */
+       rldicl  r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63
+       b       6f
 
-5:     /* Extract the psize and multiply to get an array offset */
+5:
+       /*
+        * Handle lpsizes
+        * r9 is get_paca()->context.low_slices_psize, r11 is index
+        */
+       ld      r9,PACALOWSLICESPSIZE(r13)
+       mr      r11,r10
+6:
+       sldi    r11,r11,2  /* index * 4 */
+       /* Extract the psize and multiply to get an array offset */
        srd     r9,r9,r11
        andi.   r9,r9,0xf
        mulli   r9,r9,MMUPSIZEDEFSIZE
@@ -209,7 +235,11 @@ _GLOBAL(slb_allocate_user)
  */
 slb_finish_load:
        ASM_VSID_SCRAMBLE(r10,r9,256M)
-       rldimi  r11,r10,SLB_VSID_SHIFT,16       /* combine VSID and flags */
+       /*
+        * bits above VSID_BITS_256M need to be ignored from r10
+        * also combine VSID and flags
+        */
+       rldimi  r11,r10,SLB_VSID_SHIFT,(64 - (SLB_VSID_SHIFT + VSID_BITS_256M))
 
        /* r3 = EA, r11 = VSID data */
        /*
@@ -252,10 +282,10 @@ _GLOBAL(slb_compare_rr_to_size)
        bge     1f
 
        /* still room in the slb cache */
-       sldi    r11,r3,1                /* r11 = offset * sizeof(u16) */
-       rldicl  r10,r10,36,28           /* get low 16 bits of the ESID */
-       add     r11,r11,r13             /* r11 = (u16 *)paca + offset */
-       sth     r10,PACASLBCACHE(r11)   /* paca->slb_cache[offset] = esid */
+       sldi    r11,r3,2                /* r11 = offset * sizeof(u32) */
+       srdi    r10,r10,28              /* get the 36 bits of the ESID */
+       add     r11,r11,r13             /* r11 = (u32 *)paca + offset */
+       stw     r10,PACASLBCACHE(r11)   /* paca->slb_cache[offset] = esid */
        addi    r3,r3,1                 /* offset++ */
        b       2f
 1:                                     /* offset >= SLB_CACHE_ENTRIES */
@@ -273,7 +303,11 @@ _GLOBAL(slb_compare_rr_to_size)
 slb_finish_load_1T:
        srdi    r10,r10,40-28           /* get 1T ESID */
        ASM_VSID_SCRAMBLE(r10,r9,1T)
-       rldimi  r11,r10,SLB_VSID_SHIFT_1T,16    /* combine VSID and flags */
+       /*
+        * bits above VSID_BITS_1T need to be ignored from r10
+        * also combine VSID and flags
+        */
+       rldimi  r11,r10,SLB_VSID_SHIFT_1T,(64 - (SLB_VSID_SHIFT_1T + VSID_BITS_1T))
        li      r10,MMU_SEGSIZE_1T
        rldimi  r11,r10,SLB_VSID_SSIZE_SHIFT,0  /* insert segment size */
 
index 73709f7ce92c2a1c98a7060e9ef8de00616792ad..5829d2a950d48e4150b9c51510835c983a8854ad 100644 (file)
 #include <asm/mmu.h>
 #include <asm/spu.h>
 
+/* some sanity checks */
+#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
+#error PGTABLE_RANGE exceeds slice_mask high_slices size
+#endif
+
 static DEFINE_SPINLOCK(slice_convert_lock);
 
 
@@ -42,7 +47,7 @@ int _slice_debug = 1;
 
 static void slice_print_mask(const char *label, struct slice_mask mask)
 {
-       char    *p, buf[16 + 3 + 16 + 1];
+       char    *p, buf[16 + 3 + 64 + 1];
        int     i;
 
        if (!_slice_debug)
@@ -54,7 +59,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
        *(p++) = '-';
        *(p++) = ' ';
        for (i = 0; i < SLICE_NUM_HIGH; i++)
-               *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0';
+               *(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
        *(p++) = 0;
 
        printk(KERN_DEBUG "%s:%s\n", label, buf);
@@ -84,8 +89,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
        }
 
        if ((start + len) > SLICE_LOW_TOP)
-               ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1))
-                       - (1u << GET_HIGH_SLICE_INDEX(start));
+               ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
+                       - (1ul << GET_HIGH_SLICE_INDEX(start));
 
        return ret;
 }
@@ -135,26 +140,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
 
        for (i = 0; i < SLICE_NUM_HIGH; i++)
                if (!slice_high_has_vma(mm, i))
-                       ret.high_slices |= 1u << i;
+                       ret.high_slices |= 1ul << i;
 
        return ret;
 }
 
 static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
 {
+       unsigned char *hpsizes;
+       int index, mask_index;
        struct slice_mask ret = { 0, 0 };
        unsigned long i;
-       u64 psizes;
+       u64 lpsizes;
 
-       psizes = mm->context.low_slices_psize;
+       lpsizes = mm->context.low_slices_psize;
        for (i = 0; i < SLICE_NUM_LOW; i++)
-               if (((psizes >> (i * 4)) & 0xf) == psize)
+               if (((lpsizes >> (i * 4)) & 0xf) == psize)
                        ret.low_slices |= 1u << i;
 
-       psizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (((psizes >> (i * 4)) & 0xf) == psize)
-                       ret.high_slices |= 1u << i;
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
+                       ret.high_slices |= 1ul << i;
+       }
 
        return ret;
 }
@@ -183,8 +193,10 @@ static void slice_flush_segments(void *parm)
 
 static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
 {
+       int index, mask_index;
        /* Write the new slice psize bits */
-       u64 lpsizes, hpsizes;
+       unsigned char *hpsizes;
+       u64 lpsizes;
        unsigned long i, flags;
 
        slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +213,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
                        lpsizes = (lpsizes & ~(0xful << (i * 4))) |
                                (((unsigned long)psize) << (i * 4));
 
-       hpsizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (mask.high_slices & (1u << i))
-                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-                               (((unsigned long)psize) << (i * 4));
-
+       /* Assign the value back */
        mm->context.low_slices_psize = lpsizes;
-       mm->context.high_slices_psize = hpsizes;
+
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (mask.high_slices & (1ul << i))
+                       hpsizes[index] = (hpsizes[index] &
+                                         ~(0xf << (mask_index * 4))) |
+                               (((unsigned long)psize) << (mask_index * 4));
+       }
 
        slice_dbg(" lsps=%lx, hsps=%lx\n",
                  mm->context.low_slices_psize,
@@ -587,18 +603,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 
 unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
-       u64 psizes;
-       int index;
+       unsigned char *hpsizes;
+       int index, mask_index;
 
        if (addr < SLICE_LOW_TOP) {
-               psizes = mm->context.low_slices_psize;
+               u64 lpsizes;
+               lpsizes = mm->context.low_slices_psize;
                index = GET_LOW_SLICE_INDEX(addr);
-       } else {
-               psizes = mm->context.high_slices_psize;
-               index = GET_HIGH_SLICE_INDEX(addr);
+               return (lpsizes >> (index * 4)) & 0xf;
        }
-
-       return (psizes >> (index * 4)) & 0xf;
+       hpsizes = mm->context.high_slices_psize;
+       index = GET_HIGH_SLICE_INDEX(addr);
+       mask_index = index & 0x1;
+       return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
 }
 EXPORT_SYMBOL_GPL(get_slice_psize);
 
@@ -618,7 +635,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
  */
 void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 {
-       unsigned long flags, lpsizes, hpsizes;
+       int index, mask_index;
+       unsigned char *hpsizes;
+       unsigned long flags, lpsizes;
        unsigned int old_psize;
        int i;
 
@@ -639,15 +658,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
                if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
                        lpsizes = (lpsizes & ~(0xful << (i * 4))) |
                                (((unsigned long)psize) << (i * 4));
+       /* Assign the value back */
+       mm->context.low_slices_psize = lpsizes;
 
        hpsizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
-                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-                               (((unsigned long)psize) << (i * 4));
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
+                       hpsizes[index] = (hpsizes[index] &
+                                         ~(0xf << (mask_index * 4))) |
+                               (((unsigned long)psize) << (mask_index * 4));
+       }
+
+
 
-       mm->context.low_slices_psize = lpsizes;
-       mm->context.high_slices_psize = hpsizes;
 
        slice_dbg(" lsps=%lx, hsps=%lx\n",
                  mm->context.low_slices_psize,
@@ -660,18 +685,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 void slice_set_psize(struct mm_struct *mm, unsigned long address,
                     unsigned int psize)
 {
+       unsigned char *hpsizes;
        unsigned long i, flags;
-       u64 *p;
+       u64 *lpsizes;
 
        spin_lock_irqsave(&slice_convert_lock, flags);
        if (address < SLICE_LOW_TOP) {
                i = GET_LOW_SLICE_INDEX(address);
-               p = &mm->context.low_slices_psize;
+               lpsizes = &mm->context.low_slices_psize;
+               *lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
+                       ((unsigned long) psize << (i * 4));
        } else {
+               int index, mask_index;
                i = GET_HIGH_SLICE_INDEX(address);
-               p = &mm->context.high_slices_psize;
+               hpsizes = mm->context.high_slices_psize;
+               mask_index = i & 0x1;
+               index = i >> 1;
+               hpsizes[index] = (hpsizes[index] &
+                                 ~(0xf << (mask_index * 4))) |
+                       (((unsigned long)psize) << (mask_index * 4));
        }
-       *p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));
+
        spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 #ifdef CONFIG_SPU_BASE
index 9106ebb118f52e516e1053b2d0b9fe88367a442c..3f8efa6f29975183faa304a156f50d3360883123 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/paca.h>
 #include <asm/cputable.h>
 #include <asm/prom.h>
-#include <asm/abs_addr.h>
 
 struct stab_entry {
        unsigned long esid_data;
@@ -257,7 +256,7 @@ void __init stabs_alloc(void)
                memset((void *)newstab, 0, HW_PAGE_SIZE);
 
                paca[cpu].stab_addr = newstab;
-               paca[cpu].stab_real = virt_to_abs(newstab);
+               paca[cpu].stab_real = __pa(newstab);
                printk(KERN_INFO "Segment table for CPU %d at 0x%llx "
                       "virtual, 0x%llx absolute\n",
                       cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
index e4f8f1fc81a570a38e2ab4e63a35023558633309..7c415ddde948b9dcf3ad11c54ad94c647da278b1 100644 (file)
@@ -95,7 +95,8 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len)
        struct mm_struct *mm = current->mm;
        struct subpage_prot_table *spt = &mm->context.spt;
        u32 **spm, *spp;
-       int i, nw;
+       unsigned long i;
+       size_t nw;
        unsigned long next, limit;
 
        down_write(&mm->mmap_sem);
@@ -144,7 +145,8 @@ long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map)
        struct mm_struct *mm = current->mm;
        struct subpage_prot_table *spt = &mm->context.spt;
        u32 **spm, *spp;
-       int i, nw;
+       unsigned long i;
+       size_t nw;
        unsigned long next, limit;
        int err;
 
index 31f18207970ba6aa01d7370784bf2d810465f413..ae758b3ff72cef57d702ac74f416116b752f44ec 100644 (file)
@@ -42,8 +42,9 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                     pte_t *ptep, unsigned long pte, int huge)
 {
+       unsigned long vpn;
        struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
-       unsigned long vsid, vaddr;
+       unsigned long vsid;
        unsigned int psize;
        int ssize;
        real_pte_t rpte;
@@ -86,7 +87,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
                ssize = mmu_kernel_ssize;
        }
-       vaddr = hpt_va(addr, vsid, ssize);
+       vpn = hpt_vpn(addr, vsid, ssize);
        rpte = __real_pte(__pte(pte), ptep);
 
        /*
@@ -96,7 +97,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
         * and decide to use local invalidates instead...
         */
        if (!batch->active) {
-               flush_hash_page(vaddr, rpte, psize, ssize, 0);
+               flush_hash_page(vpn, rpte, psize, ssize, 0);
                put_cpu_var(ppc64_tlb_batch);
                return;
        }
@@ -122,7 +123,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                batch->ssize = ssize;
        }
        batch->pte[i] = rpte;
-       batch->vaddr[i] = vaddr;
+       batch->vpn[i] = vpn;
        batch->index = ++i;
        if (i >= PPC64_TLB_BATCH_NR)
                __flush_tlb_pending(batch);
@@ -146,7 +147,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
        if (cpumask_equal(mm_cpumask(batch->mm), tmp))
                local = 1;
        if (i == 1)
-               flush_hash_page(batch->vaddr[0], batch->pte[0],
+               flush_hash_page(batch->vpn[0], batch->pte[0],
                                batch->psize, batch->ssize, local);
        else
                flush_hash_range(i, local);
index f09d48e3268d9bab371f31e616147bb53894c69a..b4113bf863538adbf6d0bffdaa3aabe090270064 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/exception-64e.h>
 #include <asm/ppc-opcode.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
 
 #ifdef CONFIG_PPC_64K_PAGES
 #define VPTE_PMD_SHIFT (PTE_INDEX_SIZE+1)
  *                                                                    *
  **********************************************************************/
 
-.macro tlb_prolog_bolted addr
-       mtspr   SPRN_SPRG_TLB_SCRATCH,r13
+.macro tlb_prolog_bolted intnum addr
+       mtspr   SPRN_SPRG_GEN_SCRATCH,r13
        mfspr   r13,SPRN_SPRG_PACA
        std     r10,PACA_EXTLB+EX_TLB_R10(r13)
        mfcr    r10
        std     r11,PACA_EXTLB+EX_TLB_R11(r13)
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+       mfspr   r11, SPRN_SRR1
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#endif
+       DO_KVM  \intnum, SPRN_SRR1
        std     r16,PACA_EXTLB+EX_TLB_R16(r13)
        mfspr   r16,\addr               /* get faulting address */
        std     r14,PACA_EXTLB+EX_TLB_R14(r13)
        ld      r15,PACA_EXTLB+EX_TLB_R15(r13)
        TLB_MISS_RESTORE_STATS_BOLTED
        ld      r16,PACA_EXTLB+EX_TLB_R16(r13)
-       mfspr   r13,SPRN_SPRG_TLB_SCRATCH
+       mfspr   r13,SPRN_SPRG_GEN_SCRATCH
 .endm
 
 /* Data TLB miss */
        START_EXCEPTION(data_tlb_miss_bolted)
-       tlb_prolog_bolted SPRN_DEAR
+       tlb_prolog_bolted BOOKE_INTERRUPT_DTLB_MISS SPRN_DEAR
 
        /* We need _PAGE_PRESENT and  _PAGE_ACCESSED set */
 
@@ -214,7 +222,7 @@ itlb_miss_fault_bolted:
 
 /* Instruction TLB miss */
        START_EXCEPTION(instruction_tlb_miss_bolted)
-       tlb_prolog_bolted SPRN_SRR0
+       tlb_prolog_bolted BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR0
 
        rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
        srdi    r15,r16,60              /* get region */
index 95ae77dec3f6ada8e2fc6fc58a223ed235d0032a..315f9495e9b2b5aa42a6c9aaba5a6307ac03ddde 100644 (file)
 #include <asm/reg.h>
 
 #define dbg(args...)
+#define OPROFILE_PM_PMCSEL_MSK      0xffULL
+#define OPROFILE_PM_UNIT_SHIFT      60
+#define OPROFILE_PM_UNIT_MSK        0xfULL
+#define OPROFILE_MAX_PMC_NUM        3
+#define OPROFILE_PMSEL_FIELD_WIDTH  8
+#define OPROFILE_UNIT_FIELD_WIDTH   4
+#define MMCRA_SIAR_VALID_MASK       0x10000000ULL
 
 static unsigned long reset_value[OP_MAX_COUNTER];
 
@@ -31,6 +38,61 @@ static int use_slot_nums;
 static u32 mmcr0_val;
 static u64 mmcr1_val;
 static u64 mmcra_val;
+static u32 cntr_marked_events;
+
+static int power7_marked_instr_event(u64 mmcr1)
+{
+       u64 psel, unit;
+       int pmc, cntr_marked_events = 0;
+
+       /* Given the MMCR1 value, look at the field for each counter to
+        * determine if it is a marked event.  Code based on the function
+        * power7_marked_instr_event() in file arch/powerpc/perf/power7-pmu.c.
+        */
+       for (pmc = 0; pmc < 4; pmc++) {
+               psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK
+                               << (OPROFILE_MAX_PMC_NUM - pmc)
+                               * OPROFILE_MAX_PMC_NUM);
+               psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc)
+                                * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL;
+               unit = mmcr1 & (OPROFILE_PM_UNIT_MSK
+                               << (OPROFILE_PM_UNIT_SHIFT
+                                   - (pmc * OPROFILE_PMSEL_FIELD_WIDTH )));
+               unit = unit >> (OPROFILE_PM_UNIT_SHIFT
+                               - (pmc * OPROFILE_PMSEL_FIELD_WIDTH));
+
+               switch (psel >> 4) {
+               case 2:
+                       cntr_marked_events |= (pmc == 1 || pmc == 3) << pmc;
+                       break;
+               case 3:
+                       if (psel == 0x3c) {
+                               cntr_marked_events |= (pmc == 0) << pmc;
+                               break;
+                       }
+
+                       if (psel == 0x3e) {
+                               cntr_marked_events |= (pmc != 1) << pmc;
+                               break;
+                       }
+
+                       cntr_marked_events |= 1 << pmc;
+                       break;
+               case 4:
+               case 5:
+                       cntr_marked_events |= (unit == 0xd) << pmc;
+                       break;
+               case 6:
+                       if (psel == 0x64)
+                               cntr_marked_events |= (pmc >= 2) << pmc;
+                       break;
+               case 8:
+                       cntr_marked_events |= (unit == 0xd) << pmc;
+                       break;
+               }
+       }
+       return cntr_marked_events;
+}
 
 static int power4_reg_setup(struct op_counter_config *ctr,
                             struct op_system_config *sys,
@@ -47,6 +109,23 @@ static int power4_reg_setup(struct op_counter_config *ctr,
        mmcr1_val = sys->mmcr1;
        mmcra_val = sys->mmcra;
 
+       /* Power 7+ and newer architectures:
+        * Determine which counter events in the group (the group of events is
+        * specified by the bit settings in the MMCR1 register) are marked
+        * events for use in the interrupt handler.  Do the calculation once
+        * before OProfile starts.  Information is used in the interrupt
+        * handler.  Starting with Power 7+ we only record the sample for
+        * marked events if the SIAR valid bit is set.  For non marked events
+        * the sample is always recorded.
+        */
+       if (pvr_version_is(PVR_POWER7p))
+               cntr_marked_events = power7_marked_instr_event(mmcr1_val);
+       else
+               cntr_marked_events = 0; /* For older processors, set the bit map
+                                        * to zero so the sample will always be
+                                        * be recorded.
+                                        */
+
        for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
                reset_value[i] = 0x80000000UL - ctr[i].count;
 
@@ -61,10 +140,10 @@ static int power4_reg_setup(struct op_counter_config *ctr,
        else
                mmcr0_val |= MMCR0_PROBLEM_DISABLE;
 
-       if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
-           __is_processor(PV_970) || __is_processor(PV_970FX) ||
-           __is_processor(PV_970MP) || __is_processor(PV_970GX) ||
-           __is_processor(PV_POWER5) || __is_processor(PV_POWER5p))
+       if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) ||
+           pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) ||
+           pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX) ||
+           pvr_version_is(PVR_POWER5) || pvr_version_is(PVR_POWER5p))
                use_slot_nums = 1;
 
        return 0;
@@ -84,9 +163,9 @@ extern void ppc_enable_pmcs(void);
  */
 static inline int mmcra_must_set_sample(void)
 {
-       if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
-           __is_processor(PV_970) || __is_processor(PV_970FX) ||
-           __is_processor(PV_970MP) || __is_processor(PV_970GX))
+       if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) ||
+           pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) ||
+           pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX))
                return 1;
 
        return 0;
@@ -276,7 +355,7 @@ static bool pmc_overflow(unsigned long val)
         * PMCs because a user might set a period of less than 256 and we
         * don't want to mistakenly reset them.
         */
-       if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+       if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256))
                return true;
 
        return false;
@@ -291,6 +370,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
        int i;
        unsigned int mmcr0;
        unsigned long mmcra;
+       bool siar_valid = false;
 
        mmcra = mfspr(SPRN_MMCRA);
 
@@ -300,11 +380,29 @@ static void power4_handle_interrupt(struct pt_regs *regs,
        /* set the PMM bit (see comment below) */
        mtmsrd(mfmsr() | MSR_PMM);
 
+       /* Check that the SIAR  valid bit in MMCRA is set to 1. */
+       if ((mmcra & MMCRA_SIAR_VALID_MASK) == MMCRA_SIAR_VALID_MASK)
+               siar_valid = true;
+
        for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
                val = classic_ctr_read(i);
                if (pmc_overflow(val)) {
                        if (oprofile_running && ctr[i].enabled) {
-                               oprofile_add_ext_sample(pc, regs, i, is_kernel);
+                               /* Power 7+ and newer architectures:
+                                * If the event is a marked event, then only
+                                * save the sample if the SIAR valid bit is
+                                * set.  If the event is not marked, then
+                                * always save the sample.
+                                * Note, the Sample enable bit in the MMCRA
+                                * register must be set to 1 if the group
+                                * contains a marked event.
+                                */
+                               if ((siar_valid &&
+                                    (cntr_marked_events & (1 << i)))
+                                   || !(cntr_marked_events & (1 << i)))
+                                       oprofile_add_ext_sample(pc, regs, i,
+                                                               is_kernel);
+
                                classic_ctr_write(i, reset_value[i]);
                        } else {
                                classic_ctr_write(i, 0);
index 7cd2dbd6e4c4fa615ae4442c5d00af106f3e17dd..0db88f501f91c953c86dcbef4ab2d768be126f9d 100644 (file)
@@ -82,6 +82,11 @@ static inline int perf_intr_is_nmi(struct pt_regs *regs)
        return 0;
 }
 
+static inline int siar_valid(struct pt_regs *regs)
+{
+       return 1;
+}
+
 #endif /* CONFIG_PPC32 */
 
 /*
@@ -106,14 +111,20 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
  * If we're not doing instruction sampling, give them the SDAR
  * (sampled data address).  If we are doing instruction sampling, then
  * only give them the SDAR if it corresponds to the instruction
- * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC
- * bit in MMCRA.
+ * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC or
+ * the [POWER7P_]MMCRA_SDAR_VALID bit in MMCRA.
  */
 static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
 {
        unsigned long mmcra = regs->dsisr;
-       unsigned long sdsync = (ppmu->flags & PPMU_ALT_SIPR) ?
-               POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC;
+       unsigned long sdsync;
+
+       if (ppmu->flags & PPMU_SIAR_VALID)
+               sdsync = POWER7P_MMCRA_SDAR_VALID;
+       else if (ppmu->flags & PPMU_ALT_SIPR)
+               sdsync = POWER6_MMCRA_SDSYNC;
+       else
+               sdsync = MMCRA_SDSYNC;
 
        if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync))
                *addrp = mfspr(SPRN_SDAR);
@@ -230,6 +241,24 @@ static inline int perf_intr_is_nmi(struct pt_regs *regs)
        return !regs->softe;
 }
 
+/*
+ * On processors like P7+ that have the SIAR-Valid bit, marked instructions
+ * must be sampled only if the SIAR-valid bit is set.
+ *
+ * For unmarked instructions and for processors that don't have the SIAR-Valid
+ * bit, assume that SIAR is valid.
+ */
+static inline int siar_valid(struct pt_regs *regs)
+{
+       unsigned long mmcra = regs->dsisr;
+       int marked = mmcra & MMCRA_SAMPLE_ENABLE;
+
+       if ((ppmu->flags & PPMU_SIAR_VALID) && marked)
+               return mmcra & POWER7P_MMCRA_SIAR_VALID;
+
+       return 1;
+}
+
 #endif /* CONFIG_PPC64 */
 
 static void perf_event_interrupt(struct pt_regs *regs);
@@ -1291,6 +1320,7 @@ struct pmu power_pmu = {
        .event_idx      = power_pmu_event_idx,
 };
 
+
 /*
  * A counter has overflowed; update its count and record
  * things if requested.  Note that interrupts are hard-disabled
@@ -1324,7 +1354,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                        left += period;
                        if (left <= 0)
                                left = period;
-                       record = 1;
+                       record = siar_valid(regs);
                        event->hw.last_period = event->hw.sample_period;
                }
                if (left < 0x80000000LL)
@@ -1374,8 +1404,10 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
        unsigned long use_siar = regs->result;
 
-       if (use_siar)
+       if (use_siar && siar_valid(regs))
                return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
+       else if (use_siar)
+               return 0;               // no valid instruction pointer
        else
                return regs->nip;
 }
@@ -1396,7 +1428,7 @@ static bool pmc_overflow(unsigned long val)
         * PMCs because a user might set a period of less than 256 and we
         * don't want to mistakenly reset them.
         */
-       if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+       if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256))
                return true;
 
        return false;
index 1251e4d7e2627b891475cea5231c5f977ef819e7..441af08edf434cc9729d0df344e422f32f487962 100644 (file)
@@ -373,6 +373,9 @@ static int __init init_power7_pmu(void)
            strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
                return -ENODEV;
 
+       if (pvr_version_is(PVR_POWER7p))
+               power7_pmu.flags |= PPMU_SIAR_VALID;
+
        return register_power_pmu(&power7_pmu);
 }
 
index 97612068fae303cac93604ed01c7d5353ca86b61..969dddcf33203aab139798f4b5f3dcdf99804f67 100644 (file)
@@ -50,7 +50,7 @@ machine_device_initcall(ppc40x_simple, ppc40x_device_probe);
  * Again, if your board needs to do things differently then create a
  * board.c file for it rather than adding it to this list.
  */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "amcc,acadia",
        "amcc,haleakala",
        "amcc,kilauea",
index 9f6c33d63a42c207a80444650646c1b3a1af7d08..6bd89a0e0dead4dcf112baca8aca5a0380f84a8c 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/rtc.h>
@@ -159,13 +158,8 @@ static void __init ppc47x_setup_arch(void)
 
        /* No need to check the DMA config as we /know/ our windows are all of
         * RAM.  Lets hope that doesn't change */
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > 0xffffffff) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       swiotlb_detect_4g();
+
        ppc47x_smp_init();
 }
 
index c16999802ecff6a5b960a1ffae9fba5c83c60f1f..b62508b113dbf0c3ec7467a917b3e04f99be78bf 100644 (file)
@@ -2,6 +2,7 @@ config PPC_MPC512x
        bool "512x-based boards"
        depends on 6xx
        select FSL_SOC
+       select FB_FSL_DIU
        select IPIC
        select PPC_CLOCK
        select PPC_PCI_CHOICE
index 1d8700ff60b0ec1b35eb2f989ea8ef33e2992d07..9f771e05457c78f263843247c49588dae021e911 100644 (file)
@@ -54,14 +54,16 @@ static DEFINE_MUTEX(clocks_mutex);
 static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
-       int dev_match = 0;
-       int id_match = 0;
+       int dev_match;
+       int id_match;
 
        if (dev == NULL || id == NULL)
                return clk;
 
        mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
+               dev_match = id_match = 0;
+
                if (dev == p->dev)
                        dev_match++;
                if (strcmp(id, p->name) == 0)
index 926731f1ff01b587901cf88feab77161b4194849..ca1ca66699908a633e971814bda1ddf3ee87ca1b 100644 (file)
@@ -26,7 +26,7 @@
 /*
  * list of supported boards
  */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "prt,prtlvt",
        NULL
 };
index cfe958e94e1ef6b741ef4783a0790f20adbb67fa..1650e090ef3ad5b97ac1bde0ae2e53b00edaf473 100644 (file)
@@ -191,8 +191,6 @@ mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
 
-#if defined(CONFIG_FB_FSL_DIU) || \
-    defined(CONFIG_FB_FSL_DIU_MODULE)
 static inline void mpc512x_free_bootmem(struct page *page)
 {
        __ClearPageReserved(page);
@@ -220,7 +218,6 @@ void mpc512x_release_bootmem(void)
        }
        diu_ops.release_bootmem = NULL;
 }
-#endif
 
 /*
  * Check if DIU was pre-initialized. If so, perform steps
@@ -323,15 +320,12 @@ void __init mpc512x_setup_diu(void)
                }
        }
 
-#if defined(CONFIG_FB_FSL_DIU) || \
-    defined(CONFIG_FB_FSL_DIU_MODULE)
        diu_ops.get_pixel_format        = mpc512x_get_pixel_format;
        diu_ops.set_gamma_table         = mpc512x_set_gamma_table;
        diu_ops.set_monitor_port        = mpc512x_set_monitor_port;
        diu_ops.set_pixel_clock         = mpc512x_set_pixel_clock;
        diu_ops.valid_monitor_port      = mpc512x_valid_monitor_port;
        diu_ops.release_bootmem         = mpc512x_release_bootmem;
-#endif
 }
 
 void __init mpc512x_init_IRQ(void)
index 01ffa64d2aa7faf06582db473c96d4ac305621bd..448d862bcf3d76cfbfca3fba68d8b21c1a821ff4 100644 (file)
@@ -172,7 +172,7 @@ static void __init lite5200_setup_arch(void)
        mpc52xx_setup_pci();
 }
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "fsl,lite5200",
        "fsl,lite5200b",
        NULL,
index 17d91b7da315a512eea94803752a0efecdd6b57a..070d315dd6cd18359a4b62bb0927ca3681f84998 100644 (file)
@@ -232,7 +232,7 @@ static void __init media5200_setup_arch(void)
 }
 
 /* list of the supported boards */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "fsl,media5200",
        NULL
 };
index c0aa04068d6936bc195bfe271acf21758f494e0b..9cf36020cf0d85e3e30a77629bbede3ea8f2262a 100644 (file)
@@ -52,6 +52,7 @@ static void __init mpc5200_simple_setup_arch(void)
 static const char *board[] __initdata = {
        "anonymous,a4m072",
        "anon,charon",
+       "ifm,o2d",
        "intercontrol,digsy-mtc",
        "manroland,mucmc52",
        "manroland,uc101",
index d61fb1c0c1a05cecff284de0ac89b48f4625d0a1..2351f9e0fb6fc19730867fb370c2cea0da877c19 100644 (file)
@@ -170,7 +170,8 @@ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req)
        out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields);
 
        /* Kick it off */
-       out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
+       if (!lpbfifo.req->defer_xfer_start)
+               out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
        if (dma)
                bcom_enable(lpbfifo.bcom_cur_task);
 }
@@ -421,6 +422,38 @@ int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req)
 }
 EXPORT_SYMBOL(mpc52xx_lpbfifo_submit);
 
+int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req)
+{
+       unsigned long flags;
+
+       if (!lpbfifo.regs)
+               return -ENODEV;
+
+       spin_lock_irqsave(&lpbfifo.lock, flags);
+
+       /*
+        * If the req pointer is already set and a transfer was
+        * started on submit, then this transfer is in progress
+        */
+       if (lpbfifo.req && !lpbfifo.req->defer_xfer_start) {
+               spin_unlock_irqrestore(&lpbfifo.lock, flags);
+               return -EBUSY;
+       }
+
+       /*
+        * If the req was previously submitted but not
+        * started, start it now
+        */
+       if (lpbfifo.req && lpbfifo.req == req &&
+           lpbfifo.req->defer_xfer_start) {
+               out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
+       }
+
+       spin_unlock_irqrestore(&lpbfifo.lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(mpc52xx_lpbfifo_start_xfer);
+
 void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req)
 {
        unsigned long flags;
index 16c9c9cbbb7fa48967219dcd3d4a0a7fe4a0c66d..eca1f0960fffac31e23307ddfe6f3010ddc481c4 100644 (file)
@@ -60,7 +60,7 @@ static void __init mpc837x_rdb_setup_arch(void)
 
 machine_device_initcall(mpc837x_rdb, mpc83xx_declare_of_platform_devices);
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "fsl,mpc8377rdb",
        "fsl,mpc8378rdb",
        "fsl,mpc8379rdb",
index 159c01e914635d3cc025a502e88767f0d679d286..02d02a09942d2e53cf064d48aedce863fabcd9f7 100644 (file)
@@ -104,6 +104,13 @@ config P1022_DS
        help
          This option enables support for the Freescale P1022DS reference board.
 
+config P1022_RDK
+       bool "Freescale / iVeia P1022 RDK"
+       select DEFAULT_UIMAGE
+       help
+         This option enables support for the Freescale / iVeia P1022RDK
+         reference board.
+
 config P1023_RDS
        bool "Freescale P1023 RDS"
        select DEFAULT_UIMAGE
@@ -254,6 +261,20 @@ config P5020_DS
        help
          This option enables support for the P5020 DS board
 
+config P5040_DS
+       bool "Freescale P5040 DS"
+       select DEFAULT_UIMAGE
+       select E500
+       select PPC_E500MC
+       select PHYS_64BIT
+       select SWIOTLB
+       select ARCH_REQUIRE_GPIOLIB
+       select GPIO_MPC8XXX
+       select HAS_RAPIDIO
+       select PPC_EPAPR_HV_PIC
+       help
+         This option enables support for the P5040 DS board
+
 config PPC_QEMU_E500
        bool "QEMU generic e500 platform"
        depends on EXPERIMENTAL
index 3dfe81175036bb794dc5f3648b22571d001a7c02..76f679cb04a0d4f78ee128edad6f84fff06d3337 100644 (file)
@@ -15,11 +15,13 @@ obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
+obj-$(CONFIG_P1022_RDK)   += p1022_rdk.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
 obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
+obj-$(CONFIG_P5040_DS)    += p5040_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
 obj-$(CONFIG_TQM85xx)    += tqm85xx.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
index 67dac22b4363c07f5add4b0c56c06af0d3225ba9..d0861a0d836067ff9c3897eb9e1101917ba78e06 100644 (file)
@@ -27,6 +27,16 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
        { .compatible = "fsl,mpc8548-guts", },
        /* Probably unnecessary? */
        { .compatible = "gpio-leds", },
+       /* For all PCI controllers */
+       { .compatible = "fsl,mpc8540-pci", },
+       { .compatible = "fsl,mpc8548-pcie", },
+       { .compatible = "fsl,p1022-pcie", },
+       { .compatible = "fsl,p1010-pcie", },
+       { .compatible = "fsl,p1023-pcie", },
+       { .compatible = "fsl,p4080-pcie", },
+       { .compatible = "fsl,qoriq-pcie-v2.4", },
+       { .compatible = "fsl,qoriq-pcie-v2.3", },
+       { .compatible = "fsl,qoriq-pcie-v2.2", },
        {},
 };
 
index 925b02874233fe52dc118eec691a334d3be5fde8..ed69c9250717d19721924a50e7a6b3934bf5a1a5 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -52,37 +51,16 @@ void __init corenet_ds_pic_init(void)
  */
 void __init corenet_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-       struct pci_controller *hose;
-#endif
-       dma_addr_t max = 0xffffffff;
-
        mpc85xx_smp_init();
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
-                   of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2")) {
-                       fsl_add_bridge(np, 0);
-                       hose = pci_find_hose_for_OF_device(np);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
-               }
-       }
-
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PCI) && defined(CONFIG_PPC64)
        pci_devs_phb_init();
 #endif
-#endif
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       fsl_pci_assign_primary();
+
+       swiotlb_detect_4g();
+
        pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
 }
 
@@ -99,6 +77,12 @@ static const struct of_device_id of_device_ids[] __devinitconst = {
        {
                .compatible     = "fsl,qoriq-pcie-v2.2",
        },
+       {
+               .compatible     = "fsl,qoriq-pcie-v2.3",
+       },
+       {
+               .compatible     = "fsl,qoriq-pcie-v2.4",
+       },
        /* The following two are for the Freescale hypervisor */
        {
                .name           = "hypervisor",
index b6a728b0a8ca0aae6427e619046633b94a35cd25..e6285ae6f4239d5e12ada123c937c272964f4e67 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -84,53 +83,39 @@ void __init ge_imp3a_pic_init(void)
        of_node_put(cascade_node);
 }
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif /* CONFIG_PCI */
-
-/*
- * Setup the architecture
- */
-static void __init ge_imp3a_setup_arch(void)
+static void ge_imp3a_pci_assign_primary(void)
 {
-       struct device_node *regs;
 #ifdef CONFIG_PCI
        struct device_node *np;
-       struct pci_controller *hose;
-#endif
-       dma_addr_t max = 0xffffffff;
+       struct resource rsrc;
 
-       if (ppc_md.progress)
-               ppc_md.progress("ge_imp3a_setup_arch()", 0);
-
-#ifdef CONFIG_PCI
        for_each_node_by_type(np, "pci") {
                if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
                    of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
                    of_device_is_compatible(np, "fsl,p2020-pcie")) {
-                       struct resource rsrc;
                        of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == primary_phb_addr)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-
-                       hose = pci_find_hose_for_OF_device(np);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
+                       if ((rsrc.start & 0xfffff) == 0x9000)
+                               fsl_pci_primary = np;
                }
        }
 #endif
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init ge_imp3a_setup_arch(void)
+{
+       struct device_node *regs;
+
+       if (ppc_md.progress)
+               ppc_md.progress("ge_imp3a_setup_arch()", 0);
 
        mpc85xx_smp_init();
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       ge_imp3a_pci_assign_primary();
+
+       swiotlb_detect_4g();
 
        /* Remap basic board registers */
        regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs");
@@ -215,17 +200,10 @@ static int __init ge_imp3a_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "ge,IMP3A")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0x9000;
-#endif
-               return 1;
-       }
-
-       return 0;
+       return of_flat_dt_is_compatible(root, "ge,IMP3A");
 }
 
-machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices);
+machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
 
index 767c7cf18a9c978f7b9b70f700ed5ca496fdfd73..15ce4b55f117896b2f96cd3dd0bab994a8310613 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -46,46 +45,17 @@ void __init mpc8536_ds_pic_init(void)
  */
 static void __init mpc8536_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-       struct pci_controller *hose;
-#endif
-       dma_addr_t max = 0xffffffff;
-
        if (ppc_md.progress)
                ppc_md.progress("mpc8536_ds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == 0x8000)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-
-                       hose = pci_find_hose_for_OF_device(np);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
-               }
-       }
-
-#endif
+       fsl_pci_assign_primary();
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       swiotlb_detect_4g();
 
        printk("MPC8536 DS board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
 
index 29ee8fcd75a25046d3124beeda43c02cdb5434c2..7d12a19aa7eecddddb58cff630478faa8f87893d 100644 (file)
@@ -137,10 +137,6 @@ static void __init init_ioports(void)
 
 static void __init mpc85xx_ads_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
 
@@ -150,11 +146,10 @@ static void __init mpc85xx_ads_setup_arch(void)
 #endif
 
 #ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-               fsl_add_bridge(np, 1);
-
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
+
+       fsl_pci_assign_primary();
 }
 
 static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -173,7 +168,7 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
index 11156fb53d831089f896b2c4ebbf3f94d614df06..c474505ad0d06c39ec340d8373c507eba509b1ac 100644 (file)
@@ -276,6 +276,33 @@ machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
 
 #endif /* CONFIG_PPC_I8259 */
 
+static void mpc85xx_cds_pci_assign_primary(void)
+{
+#ifdef CONFIG_PCI
+       struct device_node *np;
+
+       if (fsl_pci_primary)
+               return;
+
+       /*
+        * MPC85xx_CDS has ISA bridge but unfortunately there is no
+        * isa node in device tree. We now looking for i8259 node as
+        * a workaround for such a broken device tree. This routine
+        * is for complying to all device trees.
+        */
+       np = of_find_node_by_name(NULL, "i8259");
+       while ((fsl_pci_primary = of_get_parent(np))) {
+               of_node_put(np);
+               np = fsl_pci_primary;
+
+               if ((of_device_is_compatible(np, "fsl,mpc8540-pci") ||
+                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) &&
+                   of_device_is_available(np))
+                       return;
+       }
+#endif
+}
+
 /*
  * Setup the architecture
  */
@@ -309,21 +336,12 @@ static void __init mpc85xx_cds_setup_arch(void)
        }
 
 #ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == 0x8000)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-               }
-       }
-
        ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
        ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
+
+       mpc85xx_cds_pci_assign_primary();
+       fsl_pci_assign_primary();
 }
 
 static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -355,7 +373,7 @@ static int __init mpc85xx_cds_probe(void)
         return of_flat_dt_is_compatible(root, "MPC85xxCDS");
 }
 
-machine_device_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
 
 define_machine(mpc85xx_cds) {
        .name           = "MPC85xx CDS",
index 6d3265fe7718c7ff71785329133013ec1382c979..9ebb91ed96a332e1683ec364f3e7ba2a5e0cd982 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -129,13 +128,11 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
 }
 #endif /* CONFIG_PCI */
 
-static void __init mpc85xx_ds_pci_init(void)
+static void __init mpc85xx_ds_uli_init(void)
 {
 #ifdef CONFIG_PCI
        struct device_node *node;
 
-       fsl_pci_init();
-
        /* See if we have a ULI under the primary */
 
        node = of_find_node_by_name(NULL, "uli1575");
@@ -159,7 +156,9 @@ static void __init mpc85xx_ds_setup_arch(void)
        if (ppc_md.progress)
                ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
 
-       mpc85xx_ds_pci_init();
+       swiotlb_detect_4g();
+       fsl_pci_assign_primary();
+       mpc85xx_ds_uli_init();
        mpc85xx_smp_init();
 
        printk("MPC85xx DS board from Freescale Semiconductor\n");
@@ -175,9 +174,9 @@ static int __init mpc8544_ds_probe(void)
        return !!of_flat_dt_is_compatible(root, "MPC8544DS");
 }
 
-machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
index 8e4b094c553b49d142bceba1f29cf48c0805ed18..8498f7323470c8447ef827440fe5355652f2c20d 100644 (file)
@@ -327,44 +327,16 @@ static void __init mpc85xx_mds_qeic_init(void) { }
 
 static void __init mpc85xx_mds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct pci_controller *hose;
-       struct device_node *np;
-#endif
-       dma_addr_t max = 0xffffffff;
-
        if (ppc_md.progress)
                ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == 0x8000)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-
-                       hose = pci_find_hose_for_OF_device(np);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
-               }
-       }
-#endif
-
        mpc85xx_smp_init();
 
        mpc85xx_mds_qe_init();
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       fsl_pci_assign_primary();
+
+       swiotlb_detect_4g();
 }
 
 
@@ -409,9 +381,9 @@ static int __init mpc85xx_publish_devices(void)
        return mpc85xx_common_publish_devices();
 }
 
-machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
-machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
-machine_device_initcall(p1021_mds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8568_mds, mpc85xx_publish_devices);
+machine_arch_initcall(mpc8569_mds, mpc85xx_publish_devices);
+machine_arch_initcall(p1021_mds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
index 1910fdcb75b2479558564fd08cb4031f553d34f2..ede8771d6f02d259a68a20dbb93469bcce87e981 100644 (file)
@@ -86,23 +86,17 @@ void __init mpc85xx_rdb_pic_init(void)
  */
 static void __init mpc85xx_rdb_setup_arch(void)
 {
-#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
+#ifdef CONFIG_QUICC_ENGINE
        struct device_node *np;
 #endif
 
        if (ppc_md.progress)
                ppc_md.progress("mpc85xx_rdb_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8548-pcie"))
-                       fsl_add_bridge(np, 0);
-       }
-
-#endif
-
        mpc85xx_smp_init();
 
+       fsl_pci_assign_primary();
+
 #ifdef CONFIG_QUICC_ENGINE
        np = of_find_compatible_node(NULL, NULL, "fsl,qe");
        if (!np) {
@@ -161,15 +155,15 @@ qe_fail:
        printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1024_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1025_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1024_rdb, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
index dbaf44354f0d33a549a9ac4ed1eb0d96b24c9008..0252961392d53f308c326b3afab18ef90b68cdbd 100644 (file)
@@ -46,25 +46,15 @@ void __init p1010_rdb_pic_init(void)
  */
 static void __init p1010_rdb_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("p1010_rdb_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,p1010-pcie"))
-                       fsl_add_bridge(np, 0);
-       }
-
-#endif
+       fsl_pci_assign_primary();
 
        printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(p1010_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1010_rdb, mpc85xx_common_publish_devices);
 machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
 
 /*
index 3c732acf331dcda708bbc8cc08b28567f5596c44..848a3e98e1c1a187a8ddb96797af932681c2b6ab 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/pci.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 #include <asm/div64.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
@@ -507,32 +506,9 @@ early_param("video", early_video_setup);
  */
 static void __init p1022_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-       dma_addr_t max = 0xffffffff;
-
        if (ppc_md.progress)
                ppc_md.progress("p1022_ds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
-               struct resource rsrc;
-               struct pci_controller *hose;
-
-               of_address_to_resource(np, 0, &rsrc);
-
-               if ((rsrc.start & 0xfffff) == 0x8000)
-                       fsl_add_bridge(np, 1);
-               else
-                       fsl_add_bridge(np, 0);
-
-               hose = pci_find_hose_for_OF_device(np);
-               max = min(max, hose->dma_window_base_cur +
-                         hose->dma_window_size);
-       }
-#endif
-
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
        diu_ops.get_pixel_format        = p1022ds_get_pixel_format;
        diu_ops.set_gamma_table         = p1022ds_set_gamma_table;
@@ -601,18 +577,14 @@ static void __init p1022_ds_setup_arch(void)
 
        mpc85xx_smp_init();
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       fsl_pci_assign_primary();
+
+       swiotlb_detect_4g();
 
        pr_info("Freescale P1022 DS reference board\n");
 }
 
-machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
new file mode 100644 (file)
index 0000000..55ffa1c
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * P1022 RDK board specific routines
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Based on p1022_ds.c
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/pci.h>
+#include <linux/of_platform.h>
+#include <asm/div64.h>
+#include <asm/mpic.h>
+#include <asm/swiotlb.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/udbg.h>
+#include <asm/fsl_guts.h>
+#include "smp.h"
+
+#include "mpc85xx.h"
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN         0x80000000
+#define CLKDVDR_PXCKINV                0x10000000
+#define CLKDVDR_PXCKDLY                0x06000000
+#define CLKDVDR_PXCLK_MASK     0x00FF0000
+
+/**
+ * p1022rdk_set_monitor_port: switch the output to a different monitor port
+ */
+static void p1022rdk_set_monitor_port(enum fsl_diu_monitor_port port)
+{
+       if (port != FSL_DIU_PORT_DVI) {
+               pr_err("p1022rdk: unsupported monitor port %i\n", port);
+               return;
+       }
+}
+
+/**
+ * p1022rdk_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
+void p1022rdk_set_pixel_clock(unsigned int pixclock)
+{
+       struct device_node *guts_np = NULL;
+       struct ccsr_guts __iomem *guts;
+       unsigned long freq;
+       u64 temp;
+       u32 pxclk;
+
+       /* Map the global utilities registers. */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (!guts_np) {
+               pr_err("p1022rdk: missing global utilties device node\n");
+               return;
+       }
+
+       guts = of_iomap(guts_np, 0);
+       of_node_put(guts_np);
+       if (!guts) {
+               pr_err("p1022rdk: could not map global utilties device\n");
+               return;
+       }
+
+       /* Convert pixclock from a wavelength to a frequency */
+       temp = 1000000000000ULL;
+       do_div(temp, pixclock);
+       freq = temp;
+
+       /*
+        * 'pxclk' is the ratio of the platform clock to the pixel clock.
+        * This number is programmed into the CLKDVDR register, and the valid
+        * range of values is 2-255.
+        */
+       pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+       pxclk = clamp_t(u32, pxclk, 2, 255);
+
+       /* Disable the pixel clock, and set it to non-inverted and no delay */
+       clrbits32(&guts->clkdvdr,
+                 CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+       /* Enable the clock and set the pxclk */
+       setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+       iounmap(guts);
+}
+
+/**
+ * p1022rdk_valid_monitor_port: set the monitor port for sysfs
+ */
+enum fsl_diu_monitor_port
+p1022rdk_valid_monitor_port(enum fsl_diu_monitor_port port)
+{
+       return FSL_DIU_PORT_DVI;
+}
+
+#endif
+
+void __init p1022_rdk_pic_init(void)
+{
+       struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+               MPIC_SINGLE_DEST_CPU,
+               0, 256, " OpenPIC  ");
+       BUG_ON(mpic == NULL);
+       mpic_init(mpic);
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init p1022_rdk_setup_arch(void)
+{
+       if (ppc_md.progress)
+               ppc_md.progress("p1022_rdk_setup_arch()", 0);
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+       diu_ops.set_monitor_port        = p1022rdk_set_monitor_port;
+       diu_ops.set_pixel_clock         = p1022rdk_set_pixel_clock;
+       diu_ops.valid_monitor_port      = p1022rdk_valid_monitor_port;
+#endif
+
+       mpc85xx_smp_init();
+
+       fsl_pci_assign_primary();
+
+       swiotlb_detect_4g();
+
+       pr_info("Freescale / iVeia P1022 RDK reference board\n");
+}
+
+machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices);
+
+machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p1022_rdk_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,p1022rdk");
+}
+
+define_machine(p1022_rdk) {
+       .name                   = "P1022 RDK",
+       .probe                  = p1022_rdk_probe,
+       .setup_arch             = p1022_rdk_setup_arch,
+       .init_IRQ               = p1022_rdk_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index 2990e8b13dc957850b0820ede1bf2633317f80ff..9cc60a73883424893022f4343f6eddeabefe2aeb 100644 (file)
@@ -80,15 +80,12 @@ static void __init mpc85xx_rds_setup_arch(void)
                }
        }
 
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
-               fsl_add_bridge(np, 0);
-#endif
-
        mpc85xx_smp_init();
+
+       fsl_pci_assign_primary();
 }
 
-machine_device_initcall(p1023_rds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1023_rds, mpc85xx_common_publish_devices);
 
 static void __init mpc85xx_rds_pic_init(void)
 {
index 6541fa2630c0114d83275cb1413d4822ddbe1b8a..000c0892fc40ec532222c781fd9c0ffe45dc2e3c 100644 (file)
@@ -80,7 +80,7 @@ define_machine(p2041_rdb) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
+machine_arch_initcall(p2041_rdb, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
index f238efa75891e2099a9c5d695035292fcab853d6..b3edc205daa9acd4afddf5932d69a397ddadd90c 100644 (file)
@@ -82,7 +82,7 @@ define_machine(p3041_ds) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p3041_ds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
index c92417dc657412e2a62c9de968d8f02c8777ec70..54df10632aeab45a71909c463d5cc461a57ffe57 100644 (file)
@@ -81,7 +81,7 @@ define_machine(p4080_ds) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p4080_ds, corenet_ds_publish_devices);
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
 #endif
index 17bef15a85eda1cdce2a8acbc4353047c12c8d39..753a42c29d4dfd75f8fe640b80d4f368e7648cb0 100644 (file)
@@ -91,7 +91,7 @@ define_machine(p5020_ds) {
 #endif
 };
 
-machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p5020_ds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p5040_ds.c b/arch/powerpc/platforms/85xx/p5040_ds.c
new file mode 100644 (file)
index 0000000..1138185
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * P5040 DS Setup
+ *
+ * Copyright 2009-2010 Freescale Semiconductor Inc.
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_fdt.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p5040_ds_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+       extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+       if (of_flat_dt_is_compatible(root, "fsl,P5040DS"))
+               return 1;
+
+       /* Check if we're running under the Freescale hypervisor */
+       if (of_flat_dt_is_compatible(root, "fsl,P5040DS-hv")) {
+               ppc_md.init_IRQ = ehv_pic_init;
+               ppc_md.get_irq = ehv_pic_get_irq;
+               ppc_md.restart = fsl_hv_restart;
+               ppc_md.power_off = fsl_hv_halt;
+               ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+               /*
+                * Disable the timebase sync operations because we can't write
+                * to the timebase registers under the hypervisor.
+                 */
+               smp_85xx_ops.give_timebase = NULL;
+               smp_85xx_ops.take_timebase = NULL;
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+define_machine(p5040_ds) {
+       .name                   = "P5040 DS",
+       .probe                  = p5040_ds_probe,
+       .setup_arch             = corenet_ds_setup_arch,
+       .init_IRQ               = corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+       .get_irq                = mpic_get_irq,
+#else
+       .get_irq                = mpic_get_coreint_irq,
+#endif
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+#ifdef CONFIG_PPC64
+       .power_save             = book3e_idle,
+#else
+       .power_save             = e500_idle,
+#endif
+};
+
+machine_arch_initcall(p5040_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p5040_ds, swiotlb_setup_bus_notifier);
+#endif
index 95a2e53af71b6ee66fcbf0013aa1020c85068692..f6ea5618c7331acfe5daf3dde5a2a17a9e243bdd 100644 (file)
@@ -41,7 +41,8 @@ static void __init qemu_e500_setup_arch(void)
 {
        ppc_md.progress("qemu_e500_setup_arch()", 0);
 
-       fsl_pci_init();
+       fsl_pci_assign_primary();
+       swiotlb_detect_4g();
        mpc85xx_smp_init();
 }
 
@@ -55,7 +56,7 @@ static int __init qemu_e500_probe(void)
        return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500");
 }
 
-machine_device_initcall(qemu_e500, mpc85xx_common_publish_devices);
+machine_arch_initcall(qemu_e500, mpc85xx_common_publish_devices);
 
 define_machine(qemu_e500) {
        .name                   = "QEMU e500",
index cd3a66bdb54bcc696cf42ddcc60a744127dbf686..f62121825914d952add0d638adfc470551e6e0da 100644 (file)
@@ -88,26 +88,11 @@ static int __init sbc8548_hw_rev(void)
  */
 static void __init sbc8548_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("sbc8548_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == 0x8000)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-               }
-       }
-#endif
+       fsl_pci_assign_primary();
+
        sbc_rev = sbc8548_hw_rev();
 }
 
@@ -128,7 +113,7 @@ static void sbc8548_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(sbc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
index ff4249044a3ce3929771d0b1d69a502868644b5d..6fcfa12e5c56dd42a2b1335fe1d6a0a35d0bfeda 100644 (file)
@@ -2,7 +2,7 @@
  * Author: Andy Fleming <afleming@freescale.com>
  *        Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2006-2008, 2011 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
  *
  * 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
@@ -17,6 +17,7 @@
 #include <linux/of.h>
 #include <linux/kexec.h>
 #include <linux/highmem.h>
+#include <linux/cpu.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
 #include "smp.h"
 
-extern void __early_start(void);
-
-#define BOOT_ENTRY_ADDR_UPPER  0
-#define BOOT_ENTRY_ADDR_LOWER  1
-#define BOOT_ENTRY_R3_UPPER    2
-#define BOOT_ENTRY_R3_LOWER    3
-#define BOOT_ENTRY_RESV                4
-#define BOOT_ENTRY_PIR         5
-#define BOOT_ENTRY_R6_UPPER    6
-#define BOOT_ENTRY_R6_LOWER    7
-#define NUM_BOOT_ENTRY         8
-#define SIZE_BOOT_ENTRY                (NUM_BOOT_ENTRY * sizeof(u32))
-
-static int __init
-smp_85xx_kick_cpu(int nr)
+struct epapr_spin_table {
+       u32     addr_h;
+       u32     addr_l;
+       u32     r3_h;
+       u32     r3_l;
+       u32     reserved;
+       u32     pir;
+};
+
+static struct ccsr_guts __iomem *guts;
+static u64 timebase;
+static int tb_req;
+static int tb_valid;
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+       uint32_t mask;
+
+       mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
+       if (freeze)
+               setbits32(&guts->devdisr, mask);
+       else
+               clrbits32(&guts->devdisr, mask);
+
+       in_be32(&guts->devdisr);
+}
+
+static void mpc85xx_give_timebase(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       while (!tb_req)
+               barrier();
+       tb_req = 0;
+
+       mpc85xx_timebase_freeze(1);
+       timebase = get_tb();
+       mb();
+       tb_valid = 1;
+
+       while (tb_valid)
+               barrier();
+
+       mpc85xx_timebase_freeze(0);
+
+       local_irq_restore(flags);
+}
+
+static void mpc85xx_take_timebase(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       tb_req = 1;
+       while (!tb_valid)
+               barrier();
+
+       set_tb(timebase >> 32, timebase & 0xffffffff);
+       isync();
+       tb_valid = 0;
+
+       local_irq_restore(flags);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+       unsigned int cpu = smp_processor_id();
+       u32 tmp;
+
+       local_irq_disable();
+       idle_task_exit();
+       generic_set_cpu_dead(cpu);
+       mb();
+
+       mtspr(SPRN_TCR, 0);
+
+       __flush_disable_L1();
+       tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
+       mtspr(SPRN_HID0, tmp);
+       isync();
+
+       /* Enter NAP mode. */
+       tmp = mfmsr();
+       tmp |= MSR_WE;
+       mb();
+       mtmsr(tmp);
+       isync();
+
+       while (1)
+               ;
+}
+#endif
+
+static int __cpuinit smp_85xx_kick_cpu(int nr)
 {
        unsigned long flags;
        const u64 *cpu_rel_addr;
-       __iomem u32 *bptr_vaddr;
+       __iomem struct epapr_spin_table *spin_table;
        struct device_node *np;
-       int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
+       int hw_cpu = get_hard_smp_processor_id(nr);
        int ioremappable;
+       int ret = 0;
 
        WARN_ON(nr < 0 || nr >= NR_CPUS);
        WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
@@ -75,46 +161,81 @@ smp_85xx_kick_cpu(int nr)
 
        /* Map the spin table */
        if (ioremappable)
-               bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
+               spin_table = ioremap(*cpu_rel_addr,
+                               sizeof(struct epapr_spin_table));
        else
-               bptr_vaddr = phys_to_virt(*cpu_rel_addr);
+               spin_table = phys_to_virt(*cpu_rel_addr);
 
        local_irq_save(flags);
-
-       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
-       out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
+#ifdef CONFIG_HOTPLUG_CPU
+       /* Corresponding to generic_set_cpu_dead() */
+       generic_set_cpu_up(nr);
+
+       if (system_state == SYSTEM_RUNNING) {
+               out_be32(&spin_table->addr_l, 0);
+
+               /*
+                * We don't set the BPTR register here since it already points
+                * to the boot page properly.
+                */
+               mpic_reset_core(hw_cpu);
+
+               /* wait until core is ready... */
+               if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1,
+                                               10000, 100)) {
+                       pr_err("%s: timeout waiting for core %d to reset\n",
+                                                       __func__, hw_cpu);
+                       ret = -ENOENT;
+                       goto out;
+               }
+
+               /*  clear the acknowledge status */
+               __secondary_hold_acknowledge = -1;
+       }
+#endif
+       out_be32(&spin_table->pir, hw_cpu);
+       out_be32(&spin_table->addr_l, __pa(__early_start));
 
        if (!ioremappable)
-               flush_dcache_range((ulong)bptr_vaddr,
-                               (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+               flush_dcache_range((ulong)spin_table,
+                       (ulong)spin_table + sizeof(struct epapr_spin_table));
 
        /* Wait a bit for the CPU to ack. */
-       while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
-               mdelay(1);
+       if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
+                                       10000, 100)) {
+               pr_err("%s: timeout waiting for core %d to ack\n",
+                                               __func__, hw_cpu);
+               ret = -ENOENT;
+               goto out;
+       }
+out:
 #else
        smp_generic_kick_cpu(nr);
 
-       out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
-               __pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+       out_be32(&spin_table->pir, hw_cpu);
+       out_be64((u64 *)(&spin_table->addr_h),
+         __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
 
        if (!ioremappable)
-               flush_dcache_range((ulong)bptr_vaddr,
-                               (ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+               flush_dcache_range((ulong)spin_table,
+                       (ulong)spin_table + sizeof(struct epapr_spin_table));
 #endif
 
        local_irq_restore(flags);
 
        if (ioremappable)
-               iounmap(bptr_vaddr);
-
-       pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
+               iounmap(spin_table);
 
-       return 0;
+       return ret;
 }
 
 struct smp_ops_t smp_85xx_ops = {
        .kick_cpu = smp_85xx_kick_cpu,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_disable    = generic_cpu_disable,
+       .cpu_die        = generic_cpu_die,
+#endif
 #ifdef CONFIG_KEXEC
        .give_timebase  = smp_generic_give_timebase,
        .take_timebase  = smp_generic_take_timebase,
@@ -218,8 +339,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 }
 #endif /* CONFIG_KEXEC */
 
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
+static void __cpuinit smp_85xx_setup_cpu(int cpu_nr)
 {
        if (smp_85xx_ops.probe == smp_mpic_probe)
                mpic_setup_this_cpu();
@@ -228,6 +348,16 @@ smp_85xx_setup_cpu(int cpu_nr)
                doorbell_setup_this_cpu();
 }
 
+static const struct of_device_id mpc85xx_smp_guts_ids[] = {
+       { .compatible = "fsl,mpc8572-guts", },
+       { .compatible = "fsl,p1020-guts", },
+       { .compatible = "fsl,p1021-guts", },
+       { .compatible = "fsl,p1022-guts", },
+       { .compatible = "fsl,p1023-guts", },
+       { .compatible = "fsl,p2020-guts", },
+       {},
+};
+
 void __init mpc85xx_smp_init(void)
 {
        struct device_node *np;
@@ -249,6 +379,22 @@ void __init mpc85xx_smp_init(void)
                smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
        }
 
+       np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
+       if (np) {
+               guts = of_iomap(np, 0);
+               of_node_put(np);
+               if (!guts) {
+                       pr_err("%s: Could not map guts node address\n",
+                                                               __func__);
+                       return;
+               }
+               smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
+               smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
+#ifdef CONFIG_HOTPLUG_CPU
+               ppc_md.cpu_die = smp_85xx_mach_cpu_die;
+#endif
+       }
+
        smp_ops = &smp_85xx_ops;
 
 #ifdef CONFIG_KEXEC
index b9c6daa07b66a8440123b28d5acade808ec0b83d..ae368e0e1076e0376aa2a3147c03504d926184a3 100644 (file)
@@ -66,20 +66,13 @@ static void __init socrates_pic_init(void)
  */
 static void __init socrates_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("socrates_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-               fsl_add_bridge(np, 1);
-#endif
+       fsl_pci_assign_primary();
 }
 
-machine_device_initcall(socrates, mpc85xx_common_publish_devices);
+machine_arch_initcall(socrates, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
index e0508002b0861437021443838bcda14be97c4e43..6f4939b6309e2efa7780f7e09c7f716c2281243a 100644 (file)
@@ -60,21 +60,14 @@ static void __init stx_gp3_pic_init(void)
  */
 static void __init stx_gp3_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("stx_gp3_setup_arch()", 0);
 
+       fsl_pci_assign_primary();
+
 #ifdef CONFIG_CPM2
        cpm2_reset();
 #endif
-
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-               fsl_add_bridge(np, 1);
-#endif
 }
 
 static void stx_gp3_show_cpuinfo(struct seq_file *m)
@@ -93,7 +86,7 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(stx_gp3, mpc85xx_common_publish_devices);
+machine_arch_initcall(stx_gp3, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
index 3e70a2035e53c50b68e3625b87d5634b8041fffb..b4e58cdc09a53cc3cd9e998a2a1efe0443457eb2 100644 (file)
@@ -59,10 +59,6 @@ static void __init tqm85xx_pic_init(void)
  */
 static void __init tqm85xx_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("tqm85xx_setup_arch()", 0);
 
@@ -70,20 +66,7 @@ static void __init tqm85xx_setup_arch(void)
        cpm2_reset();
 #endif
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       if (!of_address_to_resource(np, 0, &rsrc)) {
-                               if ((rsrc.start & 0xfffff) == 0x8000)
-                                       fsl_add_bridge(np, 1);
-                               else
-                                       fsl_add_bridge(np, 0);
-                       }
-               }
-       }
-#endif
+       fsl_pci_assign_primary();
 }
 
 static void tqm85xx_show_cpuinfo(struct seq_file *m)
@@ -123,9 +106,9 @@ static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520,
                tqm85xx_ti1520_fixup);
 
-machine_device_initcall(tqm85xx, mpc85xx_common_publish_devices);
+machine_arch_initcall(tqm85xx, mpc85xx_common_publish_devices);
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
        "tqc,tqm8540",
        "tqc,tqm8541",
        "tqc,tqm8548",
index 41c687550ea7e4f26a95bd252e901a6ea9f83f12..dcbf7e42dce79100881ac66ea4ab93e9a8b5571c 100644 (file)
@@ -111,18 +111,11 @@ static void xes_mpc85xx_fixups(void)
        }
 }
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
 /*
  * Setup the architecture
  */
 static void __init xes_mpc85xx_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
        struct device_node *root;
        const char *model = "Unknown";
 
@@ -137,26 +130,14 @@ static void __init xes_mpc85xx_setup_arch(void)
 
        xes_mpc85xx_fixups();
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == primary_phb_addr)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-               }
-       }
-#endif
-
        mpc85xx_smp_init();
+
+       fsl_pci_assign_primary();
 }
 
-machine_device_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -165,42 +146,21 @@ static int __init xes_mpc8572_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "xes,MPC8572")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0x8000;
-#endif
-               return 1;
-       } else {
-               return 0;
-       }
+       return of_flat_dt_is_compatible(root, "xes,MPC8572");
 }
 
 static int __init xes_mpc8548_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "xes,MPC8548")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0xb000;
-#endif
-               return 1;
-       } else {
-               return 0;
-       }
+       return of_flat_dt_is_compatible(root, "xes,MPC8548");
 }
 
 static int __init xes_mpc8540_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "xes,MPC8540")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0xb000;
-#endif
-               return 1;
-       } else {
-               return 0;
-       }
+       return of_flat_dt_is_compatible(root, "xes,MPC8540");
 }
 
 define_machine(xes_mpc8572) {
index 563aafa8629cfa8a6afd5e5d57442a58adccc2a7..bf5338754c5a301d83d8dbd9fc652fa482912b9f 100644 (file)
@@ -73,13 +73,6 @@ static void __init gef_ppc9a_init_irq(void)
 static void __init gef_ppc9a_setup_arch(void)
 {
        struct device_node *regs;
-#ifdef CONFIG_PCI
-       struct device_node *np;
-
-       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
-               fsl_add_bridge(np, 1);
-       }
-#endif
 
        printk(KERN_INFO "GE Intelligent Platforms PPC9A 6U VME SBC\n");
 
@@ -87,6 +80,8 @@ static void __init gef_ppc9a_setup_arch(void)
        mpc86xx_smp_init();
 #endif
 
+       fsl_pci_assign_primary();
+
        /* Remap basic board registers */
        regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
        if (regs) {
@@ -221,6 +216,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
        { .compatible = "simple-bus", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
@@ -231,7 +227,7 @@ static int __init declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
+machine_arch_initcall(gef_ppc9a, declare_of_platform_devices);
 
 define_machine(gef_ppc9a) {
        .name                   = "GE PPC9A",
index cc6a91ae0889c262519208e506d3081dca113191..0b7851330a07aebb9f9f1f5e83252347d4901c57 100644 (file)
@@ -73,20 +73,14 @@ static void __init gef_sbc310_init_irq(void)
 static void __init gef_sbc310_setup_arch(void)
 {
        struct device_node *regs;
-#ifdef CONFIG_PCI
-       struct device_node *np;
-
-       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
-               fsl_add_bridge(np, 1);
-       }
-#endif
-
        printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n");
 
 #ifdef CONFIG_SMP
        mpc86xx_smp_init();
 #endif
 
+       fsl_pci_assign_primary();
+
        /* Remap basic board registers */
        regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
        if (regs) {
@@ -209,6 +203,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
        { .compatible = "simple-bus", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
@@ -219,7 +214,7 @@ static int __init declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(gef_sbc310, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc310, declare_of_platform_devices);
 
 define_machine(gef_sbc310) {
        .name                   = "GE SBC310",
index aead6b337f4a3a9969330469048f61d7bc459a8d..b9eb174897b16c621c3cee6fa8dcabd911f12744 100644 (file)
@@ -73,13 +73,6 @@ static void __init gef_sbc610_init_irq(void)
 static void __init gef_sbc610_setup_arch(void)
 {
        struct device_node *regs;
-#ifdef CONFIG_PCI
-       struct device_node *np;
-
-       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
-               fsl_add_bridge(np, 1);
-       }
-#endif
 
        printk(KERN_INFO "GE Intelligent Platforms SBC610 6U VPX SBC\n");
 
@@ -87,6 +80,8 @@ static void __init gef_sbc610_setup_arch(void)
        mpc86xx_smp_init();
 #endif
 
+       fsl_pci_assign_primary();
+
        /* Remap basic board registers */
        regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
        if (regs) {
@@ -198,6 +193,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
        { .compatible = "simple-bus", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
@@ -208,7 +204,7 @@ static int __init declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(gef_sbc610, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc610, declare_of_platform_devices);
 
 define_machine(gef_sbc610) {
        .name                   = "GE SBC610",
index 62cd3c555bfbcf80a57dc29f1450786b5aa41ae4..a817398a56da7c6b86c5a070cd58819b42bcdd63 100644 (file)
@@ -91,6 +91,9 @@ static struct of_device_id __initdata mpc8610_ids[] = {
        { .compatible = "simple-bus", },
        /* So that the DMA channel nodes can be probed individually: */
        { .compatible = "fsl,eloplus-dma", },
+       /* PCI controllers */
+       { .compatible = "fsl,mpc8610-pci", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {}
 };
 
@@ -107,7 +110,7 @@ static int __init mpc8610_declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 
@@ -278,25 +281,13 @@ mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 static void __init mpc86xx_hpcd_setup_arch(void)
 {
        struct resource r;
-       struct device_node *np;
        unsigned char *pixis;
 
        if (ppc_md.progress)
                ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8610-pci")
-                   || of_device_is_compatible(np, "fsl,mpc8641-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == 0xa000)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-               }
-        }
-#endif
+       fsl_pci_assign_primary();
+
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
        diu_ops.get_pixel_format        = mpc8610hpcd_get_pixel_format;
        diu_ops.set_gamma_table         = mpc8610hpcd_set_gamma_table;
index 817245bc02195a37917b5dd341d7790ba5a50737..e8bf3fae56060dfa2645701db57839e8092f8e28 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -51,15 +50,8 @@ extern int uli_exclude_device(struct pci_controller *hose,
 static int mpc86xx_exclude_device(struct pci_controller *hose,
                                   u_char bus, u_char devfn)
 {
-       struct device_node* node;       
-       struct resource rsrc;
-
-       node = hose->dn;
-       of_address_to_resource(node, 0, &rsrc);
-
-       if ((rsrc.start & 0xfffff) == 0x8000) {
+       if (hose->dn == fsl_pci_primary)
                return uli_exclude_device(hose, bus, devfn);
-       }
 
        return PCIBIOS_SUCCESSFUL;
 }
@@ -69,30 +61,11 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
 static void __init
 mpc86xx_hpcn_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-       struct pci_controller *hose;
-#endif
-       dma_addr_t max = 0xffffffff;
-
        if (ppc_md.progress)
                ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
-               struct resource rsrc;
-               of_address_to_resource(np, 0, &rsrc);
-               if ((rsrc.start & 0xfffff) == 0x8000)
-                       fsl_add_bridge(np, 1);
-               else
-                       fsl_add_bridge(np, 0);
-               hose = pci_find_hose_for_OF_device(np);
-               max = min(max, hose->dma_window_base_cur +
-                         hose->dma_window_size);
-       }
-
        ppc_md.pci_exclude_device = mpc86xx_exclude_device;
-
 #endif
 
        printk("MPC86xx HPCN board from Freescale Semiconductor\n");
@@ -101,13 +74,9 @@ mpc86xx_hpcn_setup_arch(void)
        mpc86xx_smp_init();
 #endif
 
-#ifdef CONFIG_SWIOTLB
-       if ((memblock_end_of_DRAM() - 1) > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       fsl_pci_assign_primary();
+
+       swiotlb_detect_4g();
 }
 
 
@@ -162,6 +131,7 @@ static __initdata struct of_device_id of_bus_ids[] = {
        { .compatible = "simple-bus", },
        { .compatible = "fsl,srio", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
@@ -171,7 +141,7 @@ static int __init declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcn, declare_of_platform_devices);
 machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
 
 define_machine(mpc86xx_hpcn) {
index e7007d0d949e0ae73e655dc62d36fe8c4bbc02a5..b47a8fd0f3d30ad4d2d3e1bfa45a43761bc9e8f1 100644 (file)
 static void __init
 sbc8641_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
        if (ppc_md.progress)
                ppc_md.progress("sbc8641_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
-               fsl_add_bridge(np, 0);
-#endif
-
        printk("SBC8641 board from Wind River\n");
 
 #ifdef CONFIG_SMP
        mpc86xx_smp_init();
 #endif
+
+       fsl_pci_assign_primary();
 }
 
 
@@ -102,6 +95,7 @@ mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
        { .compatible = "simple-bus", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
@@ -111,7 +105,7 @@ static int __init declare_of_platform_devices(void)
 
        return 0;
 }
-machine_device_initcall(sbc8641, declare_of_platform_devices);
+machine_arch_initcall(sbc8641, declare_of_platform_devices);
 
 define_machine(sbc8641) {
        .name                   = "SBC8641D",
index 852592b2b7128e0fd72b41dca54f123e827240df..affcf566d460039ba0fd416ffad7f6ca77427ec3 100644 (file)
@@ -136,9 +136,9 @@ ssize_t beat_nvram_get_size(void)
        return BEAT_NVRAM_SIZE;
 }
 
-int beat_set_xdabr(unsigned long dabr)
+int beat_set_xdabr(unsigned long dabr, unsigned long dabrx)
 {
-       if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
+       if (beat_set_dabr(dabr, dabrx))
                return -1;
        return 0;
 }
index 32c8efcedc8091ed673592456a2249d73dbd3c83..bfcb8e351ae5e944207e99f920a12839aa40970c 100644 (file)
@@ -32,7 +32,7 @@ void beat_get_rtc_time(struct rtc_time *);
 ssize_t beat_nvram_get_size(void);
 ssize_t beat_nvram_read(char *, size_t, loff_t *);
 ssize_t beat_nvram_write(char *, size_t, loff_t *);
-int beat_set_xdabr(unsigned long);
+int beat_set_xdabr(unsigned long, unsigned long);
 void beat_power_save(void);
 void beat_kexec_cpu_down(int, int);
 
index 943c9d39aa16f613e45d0363d4c10cc4451daca5..0f6f83988b3d8e0b8a75dc095579536985f0af7e 100644 (file)
@@ -88,7 +88,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group)
 }
 
 static long beat_lpar_hpte_insert(unsigned long hpte_group,
-                                 unsigned long va, unsigned long pa,
+                                 unsigned long vpn, unsigned long pa,
                                  unsigned long rflags, unsigned long vflags,
                                  int psize, int ssize)
 {
@@ -103,7 +103,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
                        "rflags=%lx, vflags=%lx, psize=%d)\n",
                hpte_group, va, pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+       hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
                vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -184,14 +184,14 @@ static void beat_lpar_hptab_clear(void)
  */
 static long beat_lpar_hpte_updatepp(unsigned long slot,
                                    unsigned long newpp,
-                                   unsigned long va,
+                                   unsigned long vpn,
                                    int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        u64 dummy0, dummy1;
        unsigned long want_v;
 
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        DBG_LOW("    update: "
                "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
@@ -220,15 +220,15 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
        return 0;
 }
 
-static long beat_lpar_hpte_find(unsigned long va, int psize)
+static long beat_lpar_hpte_find(unsigned long vpn, int psize)
 {
        unsigned long hash;
        unsigned long i, j;
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        for (j = 0; j < 2; j++) {
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -255,14 +255,15 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
                                          unsigned long ea,
                                          int psize, int ssize)
 {
-       unsigned long lpar_rc, slot, vsid, va;
+       unsigned long vpn;
+       unsigned long lpar_rc, slot, vsid;
        u64 dummy0, dummy1;
 
        vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
-       va = (vsid << 28) | (ea & 0x0fffffff);
+       vpn = hpt_vpn(ea, vsid, MMU_SEGSIZE_256M);
 
        raw_spin_lock(&beat_htab_lock);
-       slot = beat_lpar_hpte_find(va, psize);
+       slot = beat_lpar_hpte_find(vpn, psize);
        BUG_ON(slot == -1);
 
        lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
@@ -272,7 +273,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
        BUG_ON(lpar_rc != 0);
 }
 
-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
@@ -282,7 +283,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 
        DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
                slot, va, psize, local);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        raw_spin_lock_irqsave(&beat_htab_lock, flags);
        dummy1 = beat_lpar_hpte_getword0(slot);
@@ -311,7 +312,7 @@ void __init hpte_init_beat(void)
 }
 
 static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
-                                 unsigned long va, unsigned long pa,
+                                 unsigned long vpn, unsigned long pa,
                                  unsigned long rflags, unsigned long vflags,
                                  int psize, int ssize)
 {
@@ -322,11 +323,11 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
                return -1;
 
        if (!(vflags & HPTE_V_BOLTED))
-               DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+               DBG_LOW("hpte_insert(group=%lx, vpn=%016lx, pa=%016lx, "
                        "rflags=%lx, vflags=%lx, psize=%d)\n",
-               hpte_group, va, pa, rflags, vflags, psize);
+               hpte_group, vpn, pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+       hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
                vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -364,14 +365,14 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
  */
 static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
                                    unsigned long newpp,
-                                   unsigned long va,
+                                   unsigned long vpn,
                                    int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        unsigned long want_v;
        unsigned long pss;
 
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
        pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
        DBG_LOW("    update: "
@@ -392,16 +393,16 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
        return 0;
 }
 
-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
        unsigned long lpar_rc;
        unsigned long pss;
 
-       DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-               slot, va, psize, local);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       DBG_LOW("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+               slot, vpn, psize, local);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
        pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
        lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
index 14943ef01918ac7443657be39798e94d9ba69527..7d2d036754b5b56ecf5df1ddeb6367d2cc6b223c 100644 (file)
 
 #undef DEBUG
 
+#include <linux/memblock.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #define IOBMAP_PAGE_SHIFT      12
@@ -99,7 +99,7 @@ static int iobmap_build(struct iommu_table *tbl, long index,
        ip = ((u32 *)tbl->it_base) + index;
 
        while (npages--) {
-               rpn = virt_to_abs(uaddr) >> IOBMAP_PAGE_SHIFT;
+               rpn = __pa(uaddr) >> IOBMAP_PAGE_SHIFT;
 
                *(ip++) = IOBMAP_L2E_V | rpn;
                /* invalidate tlb, can be optimized more */
@@ -258,7 +258,7 @@ void __init alloc_iobmap_l2(void)
        return;
 #endif
        /* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */
-       iob_l2_base = (u32 *)abs_to_virt(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
+       iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
 
        printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base);
 }
index 0e7eccc0f88d7ededee728a1dbbd55287253b436..471aa3ccd9fd32411948e2226cf085b4ac9e4c0b 100644 (file)
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 
 #include "powernv.h"
 #include "pci.h"
 
-struct resource_wrap {
-       struct list_head        link;
-       resource_size_t         size;
-       resource_size_t         align;
-       struct pci_dev          *dev;   /* Set if it's a device */
-       struct pci_bus          *bus;   /* Set if it's a bridge */
-};
-
 static int __pe_printk(const char *level, const struct pnv_ioda_pe *pe,
                       struct va_format *vaf)
 {
@@ -78,273 +69,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
 define_pe_printk_level(pe_warn, KERN_WARNING);
 define_pe_printk_level(pe_info, KERN_INFO);
 
-
-/* Calculate resource usage & alignment requirement of a single
- * device. This will also assign all resources within the device
- * for a given type starting at 0 for the biggest one and then
- * assigning in decreasing order of size.
- */
-static void __devinit pnv_ioda_calc_dev(struct pci_dev *dev, unsigned int flags,
-                                       resource_size_t *size,
-                                       resource_size_t *align)
-{
-       resource_size_t start;
-       struct resource *r;
-       int i;
-
-       pr_devel("  -> CDR %s\n", pci_name(dev));
-
-       *size = *align = 0;
-
-       /* Clear the resources out and mark them all unset */
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               r = &dev->resource[i];
-               if (!(r->flags & flags))
-                   continue;
-               if (r->start) {
-                       r->end -= r->start;
-                       r->start = 0;
-               }
-               r->flags |= IORESOURCE_UNSET;
-       }
-
-       /* We currently keep all memory resources together, we
-        * will handle prefetch & 64-bit separately in the future
-        * but for now we stick everybody in M32
-        */
-       start = 0;
-       for (;;) {
-               resource_size_t max_size = 0;
-               int max_no = -1;
-
-               /* Find next biggest resource */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       r = &dev->resource[i];
-                       if (!(r->flags & IORESOURCE_UNSET) ||
-                           !(r->flags & flags))
-                               continue;
-                       if (resource_size(r) > max_size) {
-                               max_size = resource_size(r);
-                               max_no = i;
-                       }
-               }
-               if (max_no < 0)
-                       break;
-               r = &dev->resource[max_no];
-               if (max_size > *align)
-                       *align = max_size;
-               *size += max_size;
-               r->start = start;
-               start += max_size;
-               r->end = r->start + max_size - 1;
-               r->flags &= ~IORESOURCE_UNSET;
-               pr_devel("  ->     R%d %016llx..%016llx\n",
-                        max_no, r->start, r->end);
-       }
-       pr_devel("  <- CDR %s size=%llx align=%llx\n",
-                pci_name(dev), *size, *align);
-}
-
-/* Allocate a resource "wrap" for a given device or bridge and
- * insert it at the right position in the sorted list
- */
-static void __devinit pnv_ioda_add_wrap(struct list_head *list,
-                                       struct pci_bus *bus,
-                                       struct pci_dev *dev,
-                                       resource_size_t size,
-                                       resource_size_t align)
-{
-       struct resource_wrap *w1, *w = kzalloc(sizeof(*w), GFP_KERNEL);
-
-       w->size = size;
-       w->align = align;
-       w->dev = dev;
-       w->bus = bus;
-
-       list_for_each_entry(w1, list, link) {
-               if (w1->align < align) {
-                       list_add_tail(&w->link, &w1->link);
-                       return;
-               }
-       }
-       list_add_tail(&w->link, list);
-}
-
-/* Offset device resources of a given type */
-static void __devinit pnv_ioda_offset_dev(struct pci_dev *dev,
-                                         unsigned int flags,
-                                         resource_size_t offset)
-{
-       struct resource *r;
-       int i;
-
-       pr_devel("  -> ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               r = &dev->resource[i];
-               if (r->flags & flags) {
-                       dev->resource[i].start += offset;
-                       dev->resource[i].end += offset;
-               }
-       }
-
-       pr_devel("  <- ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-}
-
-/* Offset bus resources (& all children) of a given type */
-static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus,
-                                         unsigned int flags,
-                                         resource_size_t offset)
-{
-       struct resource *r;
-       struct pci_dev *dev;
-       struct pci_bus *cbus;
-       int i;
-
-       pr_devel("  -> OBR %s [%x] +%016llx\n",
-                bus->self ? pci_name(bus->self) : "root", flags, offset);
-
-       pci_bus_for_each_resource(bus, r, i) {
-               if (r && (r->flags & flags)) {
-                       r->start += offset;
-                       r->end += offset;
-               }
-       }
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               pnv_ioda_offset_dev(dev, flags, offset);
-       list_for_each_entry(cbus, &bus->children, node)
-               pnv_ioda_offset_bus(cbus, flags, offset);
-
-       pr_devel("  <- OBR %s [%x]\n",
-                bus->self ? pci_name(bus->self) : "root", flags);
-}
-
-/* This is the guts of our IODA resource allocation. This is called
- * recursively for each bus in the system. It calculates all the
- * necessary size and requirements for children and assign them
- * resources such that:
- *
- *   - Each function fits in it's own contiguous set of IO/M32
- *     segment
- *
- *   - All segments behind a P2P bridge are contiguous and obey
- *     alignment constraints of those bridges
- */
-static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
-                                       resource_size_t *size,
-                                       resource_size_t *align)
-{
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pnv_phb *phb = hose->private_data;
-       resource_size_t dev_size, dev_align, start;
-       resource_size_t min_align, min_balign;
-       struct pci_dev *cdev;
-       struct pci_bus *cbus;
-       struct list_head head;
-       struct resource_wrap *w;
-       unsigned int bres;
-
-       *size = *align = 0;
-
-       pr_devel("-> CBR %s [%x]\n",
-                bus->self ? pci_name(bus->self) : "root", flags);
-
-       /* Calculate alignment requirements based on the type
-        * of resource we are working on
-        */
-       if (flags & IORESOURCE_IO) {
-               bres = 0;
-               min_align = phb->ioda.io_segsize;
-               min_balign = 0x1000;
-       } else {
-               bres = 1;
-               min_align = phb->ioda.m32_segsize;
-               min_balign = 0x100000;
-       }
-
-       /* Gather all our children resources ordered by alignment */
-       INIT_LIST_HEAD(&head);
-
-       /*   - Busses */
-       list_for_each_entry(cbus, &bus->children, node) {
-               pnv_ioda_calc_bus(cbus, flags, &dev_size, &dev_align);
-               pnv_ioda_add_wrap(&head, cbus, NULL, dev_size, dev_align);
-       }
-
-       /*   - Devices */
-       list_for_each_entry(cdev, &bus->devices, bus_list) {
-               pnv_ioda_calc_dev(cdev, flags, &dev_size, &dev_align);
-               /* Align them to segment size */
-               if (dev_align < min_align)
-                       dev_align = min_align;
-               pnv_ioda_add_wrap(&head, NULL, cdev, dev_size, dev_align);
-       }
-       if (list_empty(&head))
-               goto empty;
-
-       /* Now we can do two things: assign offsets to them within that
-        * level and get our total alignment & size requirements. The
-        * assignment algorithm is going to be uber-trivial for now, we
-        * can try to be smarter later at filling out holes.
-        */
-       if (bus->self) {
-               /* No offset for downstream bridges */
-               start = 0;
-       } else {
-               /* Offset from the root */
-               if (flags & IORESOURCE_IO)
-                       /* Don't hand out IO 0 */
-                       start = hose->io_resource.start + 0x1000;
-               else
-                       start = hose->mem_resources[0].start;
-       }
-       while(!list_empty(&head)) {
-               w = list_first_entry(&head, struct resource_wrap, link);
-               list_del(&w->link);
-               if (w->size) {
-                       if (start) {
-                               start = ALIGN(start, w->align);
-                               if (w->dev)
-                                       pnv_ioda_offset_dev(w->dev,flags,start);
-                               else if (w->bus)
-                                       pnv_ioda_offset_bus(w->bus,flags,start);
-                       }
-                       if (w->align > *align)
-                               *align = w->align;
-               }
-               start += w->size;
-               kfree(w);
-       }
-       *size = start;
-
-       /* Align and setup bridge resources */
-       *align = max_t(resource_size_t, *align,
-                      max_t(resource_size_t, min_align, min_balign));
-       *size = ALIGN(*size,
-                     max_t(resource_size_t, min_align, min_balign));
- empty:
-       /* Only setup P2P's, not the PHB itself */
-       if (bus->self) {
-               struct resource *res = bus->resource[bres];
-
-               if (WARN_ON(res == NULL))
-                       return;
-
-               /*
-                * FIXME: We should probably export and call
-                * pci_bridge_check_ranges() to properly re-initialize
-                * the PCI portion of the flags here, and to detect
-                * what the bridge actually supports.
-                */
-               res->start = 0;
-               res->flags = (*size) ? flags : 0;
-               res->end = (*size) ? (*size - 1) : 0;
-       }
-
-       pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
-                bus->self ? pci_name(bus->self) : "root", flags,*size,*align);
-}
-
 static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
 {
        struct device_node *np;
@@ -355,172 +79,6 @@ static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
        return PCI_DN(np);
 }
 
-static void __devinit pnv_ioda_setup_pe_segments(struct pci_dev *dev)
-{
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
-       unsigned int pe, i;
-       resource_size_t pos;
-       struct resource io_res;
-       struct resource m32_res;
-       struct pci_bus_region region;
-       int rc;
-
-       /* Anything not referenced in the device-tree gets PE#0 */
-       pe = pdn ? pdn->pe_number : 0;
-
-       /* Calculate the device min/max */
-       io_res.start = m32_res.start = (resource_size_t)-1;
-       io_res.end = m32_res.end = 0;
-       io_res.flags = IORESOURCE_IO;
-       m32_res.flags = IORESOURCE_MEM;
-
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               struct resource *r = NULL;
-               if (dev->resource[i].flags & IORESOURCE_IO)
-                       r = &io_res;
-               if (dev->resource[i].flags & IORESOURCE_MEM)
-                       r = &m32_res;
-               if (!r)
-                       continue;
-               if (dev->resource[i].start < r->start)
-                       r->start = dev->resource[i].start;
-               if (dev->resource[i].end > r->end)
-                       r->end = dev->resource[i].end;
-       }
-
-       /* Setup IO segments */
-       if (io_res.start < io_res.end) {
-               pcibios_resource_to_bus(dev, &region, &io_res);
-               pos = region.start;
-               i = pos / phb->ioda.io_segsize;
-               while(i < phb->ioda.total_pe && pos <= region.end) {
-                       if (phb->ioda.io_segmap[i]) {
-                               pr_err("%s: Trying to use IO seg #%d which is"
-                                      " already used by PE# %d\n",
-                                      pci_name(dev), i,
-                                      phb->ioda.io_segmap[i]);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       phb->ioda.io_segmap[i] = pe;
-                       rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-                                                        OPAL_IO_WINDOW_TYPE,
-                                                        0, i);
-                       if (rc != OPAL_SUCCESS) {
-                               pr_err("%s: OPAL error %d setting up mapping"
-                                      " for IO seg# %d\n",
-                                      pci_name(dev), rc, i);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       pos += phb->ioda.io_segsize;
-                       i++;
-               };
-       }
-
-       /* Setup M32 segments */
-       if (m32_res.start < m32_res.end) {
-               pcibios_resource_to_bus(dev, &region, &m32_res);
-               pos = region.start;
-               i = pos / phb->ioda.m32_segsize;
-               while(i < phb->ioda.total_pe && pos <= region.end) {
-                       if (phb->ioda.m32_segmap[i]) {
-                               pr_err("%s: Trying to use M32 seg #%d which is"
-                                      " already used by PE# %d\n",
-                                      pci_name(dev), i,
-                                      phb->ioda.m32_segmap[i]);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       phb->ioda.m32_segmap[i] = pe;
-                       rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-                                                        OPAL_M32_WINDOW_TYPE,
-                                                        0, i);
-                       if (rc != OPAL_SUCCESS) {
-                               pr_err("%s: OPAL error %d setting up mapping"
-                                      " for M32 seg# %d\n",
-                                      pci_name(dev), rc, i);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       pos += phb->ioda.m32_segsize;
-                       i++;
-               }
-       }
-}
-
-/* Check if a resource still fits in the total IO or M32 range
- * for a given PHB
- */
-static int __devinit pnv_ioda_resource_fit(struct pci_controller *hose,
-                                          struct resource *r)
-{
-       struct resource *bounds;
-
-       if (r->flags & IORESOURCE_IO)
-               bounds = &hose->io_resource;
-       else if (r->flags & IORESOURCE_MEM)
-               bounds = &hose->mem_resources[0];
-       else
-               return 1;
-
-       if (r->start >= bounds->start && r->end <= bounds->end)
-               return 1;
-       r->flags = 0;
-       return 0;
-}
-
-static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
-{
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pci_bus *cbus;
-       struct pci_dev *cdev;
-       unsigned int i;
-
-       /* We used to clear all device enables here. However it looks like
-        * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
-        * and shoot fatal errors to the PHB which in turns fences itself
-        * and we can't recover from that ... yet. So for now, let's leave
-        * the enables as-is and hope for the best.
-        */
-
-       /* Check if bus resources fit in our IO or M32 range */
-       for (i = 0; bus->self && (i < 2); i++) {
-               struct resource *r = bus->resource[i];
-               if (r && !pnv_ioda_resource_fit(hose, r))
-                       pr_err("%s: Bus %d resource %d disabled, no room\n",
-                              pci_name(bus->self), bus->number, i);
-       }
-
-       /* Update self if it's not a PHB */
-       if (bus->self)
-               pci_setup_bridge(bus);
-
-       /* Update child devices */
-       list_for_each_entry(cdev, &bus->devices, bus_list) {
-               /* Check if resource fits, if not, disabled it */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       struct resource *r = &cdev->resource[i];
-                       if (!pnv_ioda_resource_fit(hose, r))
-                               pr_err("%s: Resource %d disabled, no room\n",
-                                      pci_name(cdev), i);
-               }
-
-               /* Assign segments */
-               pnv_ioda_setup_pe_segments(cdev);
-
-               /* Update HW BARs */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++)
-                       pci_update_resource(cdev, i);
-       }
-
-       /* Update child busses */
-       list_for_each_entry(cbus, &bus->children, node)
-               pnv_ioda_update_resources(cbus);
-}
-
 static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
        unsigned long pe;
@@ -548,7 +106,7 @@ static void __devinit pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
  * but in the meantime, we need to protect them to avoid warnings
  */
 #ifdef CONFIG_PCI_MSI
-static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
+static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
@@ -560,19 +118,6 @@ static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
                return NULL;
        return &phb->ioda.pe_array[pdn->pe_number];
 }
-
-static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
-{
-       struct pnv_ioda_pe *pe = __pnv_ioda_get_one_pe(dev);
-
-       while (!pe && dev->bus->self) {
-               dev = dev->bus->self;
-               pe = __pnv_ioda_get_one_pe(dev);
-               if (pe)
-                       pe = pe->bus_pe;
-       }
-       return pe;
-}
 #endif /* CONFIG_PCI_MSI */
 
 static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
@@ -589,7 +134,11 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
                dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
                fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
                parent = pe->pbus->self;
-               count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+               if (pe->flags & PNV_IODA_PE_BUS_ALL)
+                       count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+               else
+                       count = 1;
+
                switch(count) {
                case  1: bcomp = OpalPciBusAll;         break;
                case  2: bcomp = OpalPciBus7Bits;       break;
@@ -666,13 +215,13 @@ static void __devinit pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
 {
        struct pnv_ioda_pe *lpe;
 
-       list_for_each_entry(lpe, &phb->ioda.pe_list, link) {
+       list_for_each_entry(lpe, &phb->ioda.pe_dma_list, dma_link) {
                if (lpe->dma_weight < pe->dma_weight) {
-                       list_add_tail(&pe->link, &lpe->link);
+                       list_add_tail(&pe->dma_link, &lpe->dma_link);
                        return;
                }
        }
-       list_add_tail(&pe->link, &phb->ioda.pe_list);
+       list_add_tail(&pe->dma_link, &phb->ioda.pe_dma_list);
 }
 
 static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
@@ -699,6 +248,7 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
        return 10;
 }
 
+#if 0
 static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -767,6 +317,7 @@ static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 
        return pe;
 }
+#endif /* Useful for SRIOV case */
 
 static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
 {
@@ -784,34 +335,33 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
                pdn->pcidev = dev;
                pdn->pe_number = pe->pe_number;
                pe->dma_weight += pnv_ioda_dma_weight(dev);
-               if (dev->subordinate)
+               if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
                        pnv_ioda_setup_same_PE(dev->subordinate, pe);
        }
 }
 
-static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
-                                           struct pnv_ioda_pe *ppe)
+/*
+ * There're 2 types of PCI bus sensitive PEs: One that is compromised of
+ * single PCI bus. Another one that contains the primary PCI bus and its
+ * subordinate PCI devices and buses. The second type of PE is normally
+ * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports.
+ */
+static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
 {
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct pci_controller *hose = pci_bus_to_host(bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_bus *bus = dev->subordinate;
        struct pnv_ioda_pe *pe;
        int pe_num;
 
-       if (!bus) {
-               pr_warning("%s: Bridge without a subordinate bus !\n",
-                          pci_name(dev));
-               return;
-       }
        pe_num = pnv_ioda_alloc_pe(phb);
        if (pe_num == IODA_INVALID_PE) {
-               pr_warning("%s: Not enough PE# available, disabling bus\n",
-                          pci_name(dev));
+               pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
+                       __func__, pci_domain_nr(bus), bus->number);
                return;
        }
 
        pe = &phb->ioda.pe_array[pe_num];
-       ppe->bus_pe = pe;
+       pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
        pe->pbus = bus;
        pe->pdev = NULL;
        pe->tce32_seg = -1;
@@ -819,8 +369,12 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
        pe->rid = bus->busn_res.start << 8;
        pe->dma_weight = 0;
 
-       pe_info(pe, "Secondary busses %pR associated with PE\n",
-               &bus->busn_res);
+       if (all)
+               pe_info(pe, "Secondary bus %d..%d associated with PE#%d\n",
+                       bus->busn_res.start, bus->busn_res.end, pe_num);
+       else
+               pe_info(pe, "Secondary bus %d associated with PE#%d\n",
+                       bus->busn_res.start, pe_num);
 
        if (pnv_ioda_configure_pe(phb, pe)) {
                /* XXX What do we do here ? */
@@ -833,6 +387,9 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
        /* Associate it with all child devices */
        pnv_ioda_setup_same_PE(bus, pe);
 
+       /* Put PE to the list */
+       list_add_tail(&pe->list, &phb->ioda.pe_list);
+
        /* Account for one DMA PE if at least one DMA capable device exist
         * below the bridge
         */
@@ -848,17 +405,33 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus)
 {
        struct pci_dev *dev;
-       struct pnv_ioda_pe *pe;
+
+       pnv_ioda_setup_bus_PE(bus, 0);
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               pe = pnv_ioda_setup_dev_PE(dev);
-               if (pe == NULL)
-                       continue;
-               /* Leaving the PCIe domain ... single PE# */
-               if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)
-                       pnv_ioda_setup_bus_PE(dev, pe);
-               else if (dev->subordinate)
-                       pnv_ioda_setup_PEs(dev->subordinate);
+               if (dev->subordinate) {
+                       if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)
+                               pnv_ioda_setup_bus_PE(dev->subordinate, 1);
+                       else
+                               pnv_ioda_setup_PEs(dev->subordinate);
+               }
+       }
+}
+
+/*
+ * Configure PEs so that the downstream PCI buses and devices
+ * could have their associated PE#. Unfortunately, we didn't
+ * figure out the way to identify the PLX bridge yet. So we
+ * simply put the PCI bus and the subordinate behind the root
+ * port to PE# here. The game rule here is expected to be changed
+ * as soon as we can detected PLX bridge correctly.
+ */
+static void __devinit pnv_pci_ioda_setup_PEs(void)
+{
+       struct pci_controller *hose, *tmp;
+
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               pnv_ioda_setup_PEs(hose->bus);
        }
 }
 
@@ -1000,7 +573,7 @@ static void __devinit pnv_ioda_setup_dma(struct pnv_phb *phb)
        remaining = phb->ioda.tce32_count;
        tw = phb->ioda.dma_weight;
        base = 0;
-       list_for_each_entry(pe, &phb->ioda.pe_list, link) {
+       list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
                if (!pe->dma_weight)
                        continue;
                if (!remaining) {
@@ -1109,36 +682,115 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
 static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { }
 #endif /* CONFIG_PCI_MSI */
 
-/* This is the starting point of our IODA specific resource
- * allocation process
+/*
+ * This function is supposed to be called on basis of PE from top
+ * to bottom style. So the the I/O or MMIO segment assigned to
+ * parent PE could be overrided by its child PEs if necessary.
  */
-static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
+static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose,
+                               struct pnv_ioda_pe *pe)
 {
-       resource_size_t size, align;
-       struct pci_bus *child;
+       struct pnv_phb *phb = hose->private_data;
+       struct pci_bus_region region;
+       struct resource *res;
+       int i, index;
+       int rc;
 
-       /* Associate PEs per functions */
-       pnv_ioda_setup_PEs(hose->bus);
+       /*
+        * NOTE: We only care PCI bus based PE for now. For PCI
+        * device based PE, for example SRIOV sensitive VF should
+        * be figured out later.
+        */
+       BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)));
 
-       /* Calculate all resources */
-       pnv_ioda_calc_bus(hose->bus, IORESOURCE_IO, &size, &align);
-       pnv_ioda_calc_bus(hose->bus, IORESOURCE_MEM, &size, &align);
+       pci_bus_for_each_resource(pe->pbus, res, i) {
+               if (!res || !res->flags ||
+                   res->start > res->end)
+                       continue;
 
-       /* Apply then to HW */
-       pnv_ioda_update_resources(hose->bus);
+               if (res->flags & IORESOURCE_IO) {
+                       region.start = res->start - phb->ioda.io_pci_base;
+                       region.end   = res->end - phb->ioda.io_pci_base;
+                       index = region.start / phb->ioda.io_segsize;
+
+                       while (index < phb->ioda.total_pe &&
+                              region.start <= region.end) {
+                               phb->ioda.io_segmap[index] = pe->pe_number;
+                               rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+                                       pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
+                               if (rc != OPAL_SUCCESS) {
+                                       pr_err("%s: OPAL error %d when mapping IO "
+                                              "segment #%d to PE#%d\n",
+                                              __func__, rc, index, pe->pe_number);
+                                       break;
+                               }
+
+                               region.start += phb->ioda.io_segsize;
+                               index++;
+                       }
+               } else if (res->flags & IORESOURCE_MEM) {
+                       region.start = res->start -
+                                      hose->pci_mem_offset -
+                                      phb->ioda.m32_pci_base;
+                       region.end   = res->end -
+                                      hose->pci_mem_offset -
+                                      phb->ioda.m32_pci_base;
+                       index = region.start / phb->ioda.m32_segsize;
+
+                       while (index < phb->ioda.total_pe &&
+                              region.start <= region.end) {
+                               phb->ioda.m32_segmap[index] = pe->pe_number;
+                               rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+                                       pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
+                               if (rc != OPAL_SUCCESS) {
+                                       pr_err("%s: OPAL error %d when mapping M32 "
+                                              "segment#%d to PE#%d",
+                                              __func__, rc, index, pe->pe_number);
+                                       break;
+                               }
+
+                               region.start += phb->ioda.m32_segsize;
+                               index++;
+                       }
+               }
+       }
+}
 
-       /* Setup DMA */
-       pnv_ioda_setup_dma(hose->private_data);
+static void __devinit pnv_pci_ioda_setup_seg(void)
+{
+       struct pci_controller *tmp, *hose;
+       struct pnv_phb *phb;
+       struct pnv_ioda_pe *pe;
 
-       /* Configure PCI Express settings */
-       list_for_each_entry(child, &hose->bus->children, node) {
-               struct pci_dev *self = child->self;
-               if (!self)
-                       continue;
-               pcie_bus_configure_settings(child, self->pcie_mpss);
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               phb = hose->private_data;
+               list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+                       pnv_ioda_setup_pe_seg(hose, pe);
+               }
+       }
+}
+
+static void __devinit pnv_pci_ioda_setup_DMA(void)
+{
+       struct pci_controller *hose, *tmp;
+       struct pnv_phb *phb;
+
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               pnv_ioda_setup_dma(hose->private_data);
+
+               /* Mark the PHB initialization done */
+               phb = hose->private_data;
+               phb->initialized = 1;
        }
 }
 
+static void __devinit pnv_pci_ioda_fixup(void)
+{
+       pnv_pci_ioda_setup_PEs();
+       pnv_pci_ioda_setup_seg();
+       pnv_pci_ioda_setup_DMA();
+}
+
 /*
  * Returns the alignment for I/O or memory windows for P2P
  * bridges. That actually depends on how PEs are segmented.
@@ -1182,10 +834,22 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
  */
 static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
 {
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct pci_dn *pdn;
 
+       /* The function is probably called while the PEs have
+        * not be created yet. For example, resource reassignment
+        * during PCI probe period. We just skip the check if
+        * PEs isn't ready.
+        */
+       if (!phb->initialized)
+               return 0;
+
+       pdn = pnv_ioda_get_pdn(dev);
        if (!pdn || pdn->pe_number == IODA_INVALID_PE)
                return -EINVAL;
+
        return 0;
 }
 
@@ -1276,9 +940,9 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        /* Allocate aux data & arrays */
        size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
        m32map_off = size;
-       size += phb->ioda.total_pe;
+       size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
        iomap_off = size;
-       size += phb->ioda.total_pe;
+       size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
        pemap_off = size;
        size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe);
        aux = alloc_bootmem(size);
@@ -1289,6 +953,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        phb->ioda.pe_array = aux + pemap_off;
        set_bit(0, phb->ioda.pe_alloc);
 
+       INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
        INIT_LIST_HEAD(&phb->ioda.pe_list);
 
        /* Calculate how many 32-bit TCE segments we have */
@@ -1337,15 +1002,17 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        /* Setup MSI support */
        pnv_pci_init_ioda_msis(phb);
 
-       /* We set both PCI_PROBE_ONLY and PCI_REASSIGN_ALL_RSRC. This is an
-        * odd combination which essentially means that we skip all resource
-        * fixups and assignments in the generic code, and do it all
-        * ourselves here
+       /*
+        * We pass the PCI probe flag PCI_REASSIGN_ALL_RSRC here
+        * to let the PCI core do resource assignment. It's supposed
+        * that the PCI core will do correct I/O and MMIO alignment
+        * for the P2P bridge bars so that each PCI bus (excluding
+        * the child P2P bridges) can form individual PE.
         */
-       ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
+       ppc_md.pcibios_fixup = pnv_pci_ioda_fixup;
        ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
        ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
-       pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);
+       pci_add_flags(PCI_REASSIGN_ALL_RSRC);
 
        /* Reset IODA tables to a clean state */
        rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
index 264967770c3ab7cf1272e7a69fd20cb12dda0b18..6b4bef4e9d821aa2519cf2a4eecdb7ada4d5f57a 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 
 #include "powernv.h"
 #include "pci.h"
index be3cfc5ceabbfb316a55c34a4fb5da18e41dd66e..c01688a1a741f40ff423fe40761d2fd783a46799 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #include "powernv.h"
@@ -447,6 +446,11 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
                pnv_tce_invalidate(tbl, tces, tcep - 1);
 }
 
+static unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
+{
+       return ((u64 *)tbl->it_base)[index - tbl->it_offset];
+}
+
 void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
                               void *tce_mem, u64 tce_size,
                               u64 dma_offset)
@@ -597,6 +601,7 @@ void __init pnv_pci_init(void)
        ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
        ppc_md.tce_build = pnv_tce_build;
        ppc_md.tce_free = pnv_tce_free;
+       ppc_md.tce_get = pnv_tce_get;
        ppc_md.pci_probe_mode = pnv_pci_probe_mode;
        set_pci_dma_ops(&dma_iommu_ops);
 
index 8bc47963464315ea2a72bbe722d5eb3613d5d928..7cfb7c883deb175248b444e869eabaa818197399 100644 (file)
@@ -17,9 +17,14 @@ enum pnv_phb_model {
 };
 
 #define PNV_PCI_DIAG_BUF_SIZE  4096
+#define PNV_IODA_PE_DEV                (1 << 0)        /* PE has single PCI device     */
+#define PNV_IODA_PE_BUS                (1 << 1)        /* PE has primary PCI bus       */
+#define PNV_IODA_PE_BUS_ALL    (1 << 2)        /* PE has subordinate buses     */
 
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_ioda_pe {
+       unsigned long           flags;
+
        /* A PE can be associated with a single device or an
         * entire bus (& children). In the former case, pdev
         * is populated, in the later case, pbus is.
@@ -40,11 +45,6 @@ struct pnv_ioda_pe {
         */
        unsigned int            dma_weight;
 
-       /* This is a PCI-E -> PCI-X bridge, this points to the
-        * corresponding bus PE
-        */
-       struct pnv_ioda_pe      *bus_pe;
-
        /* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */
        int                     tce32_seg;
        int                     tce32_segcount;
@@ -59,7 +59,8 @@ struct pnv_ioda_pe {
        int                     mve_number;
 
        /* Link in list of PE#s */
-       struct list_head        link;
+       struct list_head        dma_link;
+       struct list_head        list;
 };
 
 struct pnv_phb {
@@ -68,6 +69,7 @@ struct pnv_phb {
        enum pnv_phb_model      model;
        u64                     opal_id;
        void __iomem            *regs;
+       int                     initialized;
        spinlock_t              lock;
 
 #ifdef CONFIG_PCI_MSI
@@ -107,6 +109,11 @@ struct pnv_phb {
                        unsigned int            *io_segmap;
                        struct pnv_ioda_pe      *pe_array;
 
+                       /* Sorted list of used PE's based
+                        * on the sequence of creation
+                        */
+                       struct list_head        pe_list;
+
                        /* Reverse map of PEs, will have to extend if
                         * we are to support more than 256 PEs, indexed
                         * bus { bus, devfn }
@@ -125,7 +132,7 @@ struct pnv_phb {
                        /* Sorted list of used PE's, sorted at
                         * boot for resource allocation purposes
                         */
-                       struct list_head        pe_list;
+                       struct list_head        pe_dma_list;
                } ioda;
        };
 
index 3124cf791ebb5504d842c494c345b7754ddbb851..d00d7b0a3bda4c457417aee7a68720df92310317 100644 (file)
@@ -43,7 +43,7 @@ enum ps3_lpar_vas_id {
 
 static DEFINE_SPINLOCK(ps3_htab_lock);
 
-static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn,
        unsigned long pa, unsigned long rflags, unsigned long vflags,
        int psize, int ssize)
 {
@@ -61,7 +61,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
         */
        vflags &= ~HPTE_V_SECONDARY;
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags;
 
        spin_lock_irqsave(&ps3_htab_lock, flags);
@@ -75,8 +75,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
 
        if (result) {
                /* all entries bolted !*/
-               pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
-                       __func__, result, va, pa, hpte_group, hpte_v, hpte_r);
+               pr_info("%s:result=%d vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
+                       __func__, result, vpn, pa, hpte_group, hpte_v, hpte_r);
                BUG();
        }
 
@@ -107,7 +107,7 @@ static long ps3_hpte_remove(unsigned long hpte_group)
 }
 
 static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
-       unsigned long va, int psize, int ssize, int local)
+       unsigned long vpn, int psize, int ssize, int local)
 {
        int result;
        u64 hpte_v, want_v, hpte_rs;
@@ -115,7 +115,7 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
        unsigned long flags;
        long ret;
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
        spin_lock_irqsave(&ps3_htab_lock, flags);
 
@@ -125,8 +125,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
                                       &hpte_rs);
 
        if (result) {
-               pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n",
-                       __func__, result, va, slot, psize);
+               pr_info("%s: res=%d read vpn=%lx slot=%lx psize=%d\n",
+                       __func__, result, vpn, slot, psize);
                BUG();
        }
 
@@ -159,7 +159,7 @@ static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
        panic("ps3_hpte_updateboltedpp() not implemented");
 }
 
-static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
+static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn,
        int psize, int ssize, int local)
 {
        unsigned long flags;
@@ -170,8 +170,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
        result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
 
        if (result) {
-               pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n",
-                       __func__, result, va, slot, psize);
+               pr_info("%s: res=%d vpn=%lx slot=%lx psize=%d\n",
+                       __func__, result, vpn, slot, psize);
                BUG();
        }
 
index 2d664c5a83b0230918979585af4eb06adea17ab9..3f509f86432c1b28df128b984793df50789a06f3 100644 (file)
@@ -184,11 +184,15 @@ early_param("ps3flash", early_parse_ps3flash);
 #define prealloc_ps3flash_bounce_buffer()      do { } while (0)
 #endif
 
-static int ps3_set_dabr(unsigned long dabr)
+static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx)
 {
-       enum {DABR_USER = 1, DABR_KERNEL = 2,};
+       /* Have to set at least one bit in the DABRX */
+       if (dabrx == 0 && dabr == 0)
+               dabrx = DABRX_USER;
+       /* hypervisor only allows us to set BTI, Kernel and user */
+       dabrx &= DABRX_BTI | DABRX_KERNEL | DABRX_USER;
 
-       return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0;
+       return lv1_set_dabr(dabr, dabrx) ? -1 : 0;
 }
 
 static void __init ps3_setup_arch(void)
index c222189f5bb230e1467103681ba0cb3923ebf275..890622b87c8f009feda9bb8bd36ac5768c6e3af9 100644 (file)
@@ -6,8 +6,9 @@ obj-y                   := lpar.o hvCall.o nvram.o reconfig.o \
                           firmware.o power.o dlpar.o mobility.o
 obj-$(CONFIG_SMP)      += smp.o
 obj-$(CONFIG_SCANLOG)  += scanlog.o
-obj-$(CONFIG_EEH)      += eeh.o eeh_dev.o eeh_cache.o eeh_driver.o \
-                          eeh_event.o eeh_sysfs.o eeh_pseries.o
+obj-$(CONFIG_EEH)      += eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \
+                          eeh_driver.o eeh_event.o eeh_sysfs.o \
+                          eeh_pseries.o
 obj-$(CONFIG_KEXEC)    += kexec.o
 obj-$(CONFIG_PCI)      += pci.o pci_dlpar.o
 obj-$(CONFIG_PSERIES_MSI)      += msi.o
index ecd394cf34e604b24b71138d481f570cd0d926ac..9a04322b1736f0c9edb49249217fb03aa2f96be2 100644 (file)
@@ -92,6 +92,20 @@ struct eeh_ops *eeh_ops = NULL;
 int eeh_subsystem_enabled;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
 
+/*
+ * EEH probe mode support. The intention is to support multiple
+ * platforms for EEH. Some platforms like pSeries do PCI emunation
+ * based on device tree. However, other platforms like powernv probe
+ * PCI devices from hardware. The flag is used to distinguish that.
+ * In addition, struct eeh_ops::probe would be invoked for particular
+ * OF node or PCI device so that the corresponding PE would be created
+ * there.
+ */
+int eeh_probe_mode;
+
+/* Global EEH mutex */
+DEFINE_MUTEX(eeh_mutex);
+
 /* Lock to avoid races due to multiple reports of an error */
 static DEFINE_RAW_SPINLOCK(confirm_error_lock);
 
@@ -204,22 +218,12 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
                }
        }
 
-       /* Gather status on devices under the bridge */
-       if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
-               struct device_node *child;
-
-               for_each_child_of_node(dn, child) {
-                       if (of_node_to_eeh_dev(child))
-                               n += eeh_gather_pci_data(of_node_to_eeh_dev(child), buf+n, len-n);
-               }
-       }
-
        return n;
 }
 
 /**
  * eeh_slot_error_detail - Generate combined log including driver log and error log
- * @edev: device to report error log for
+ * @pe: EEH PE
  * @severity: temporary or permanent error log
  *
  * This routine should be called to generate the combined log, which
@@ -227,17 +231,22 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
  * out from the config space of the corresponding PCI device, while
  * the error log is fetched through platform dependent function call.
  */
-void eeh_slot_error_detail(struct eeh_dev *edev, int severity)
+void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 {
        size_t loglen = 0;
-       pci_regs_buf[0] = 0;
+       struct eeh_dev *edev;
 
-       eeh_pci_enable(edev, EEH_OPT_THAW_MMIO);
-       eeh_ops->configure_bridge(eeh_dev_to_of_node(edev));
-       eeh_restore_bars(edev);
-       loglen = eeh_gather_pci_data(edev, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
+       eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
+       eeh_ops->configure_bridge(pe);
+       eeh_pe_restore_bars(pe);
 
-       eeh_ops->get_log(eeh_dev_to_of_node(edev), severity, pci_regs_buf, loglen);
+       pci_regs_buf[0] = 0;
+       eeh_pe_for_each_dev(pe, edev) {
+               loglen += eeh_gather_pci_data(edev, pci_regs_buf,
+                               EEH_PCI_REGS_LOG_LEN);
+        }
+
+       eeh_ops->get_log(pe, severity, pci_regs_buf, loglen);
 }
 
 /**
@@ -261,126 +270,8 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
 }
 
 /**
- * eeh_find_device_pe - Retrieve the PE for the given device
- * @dn: device node
- *
- * Return the PE under which this device lies
- */
-struct device_node *eeh_find_device_pe(struct device_node *dn)
-{
-       while (dn->parent && of_node_to_eeh_dev(dn->parent) &&
-              (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
-               dn = dn->parent;
-       }
-       return dn;
-}
-
-/**
- * __eeh_mark_slot - Mark all child devices as failed
- * @parent: parent device
- * @mode_flag: failure flag
- *
- * Mark all devices that are children of this device as failed.
- * Mark the device driver too, so that it can see the failure
- * immediately; this is critical, since some drivers poll
- * status registers in interrupts ... If a driver is polling,
- * and the slot is frozen, then the driver can deadlock in
- * an interrupt context, which is bad.
- */
-static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
-{
-       struct device_node *dn;
-
-       for_each_child_of_node(parent, dn) {
-               if (of_node_to_eeh_dev(dn)) {
-                       /* Mark the pci device driver too */
-                       struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
-
-                       of_node_to_eeh_dev(dn)->mode |= mode_flag;
-
-                       if (dev && dev->driver)
-                               dev->error_state = pci_channel_io_frozen;
-
-                       __eeh_mark_slot(dn, mode_flag);
-               }
-       }
-}
-
-/**
- * eeh_mark_slot - Mark the indicated device and its children as failed
- * @dn: parent device
- * @mode_flag: failure flag
- *
- * Mark the indicated device and its child devices as failed.
- * The device drivers are marked as failed as well.
- */
-void eeh_mark_slot(struct device_node *dn, int mode_flag)
-{
-       struct pci_dev *dev;
-       dn = eeh_find_device_pe(dn);
-
-       /* Back up one, since config addrs might be shared */
-       if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-               dn = dn->parent;
-
-       of_node_to_eeh_dev(dn)->mode |= mode_flag;
-
-       /* Mark the pci device too */
-       dev = of_node_to_eeh_dev(dn)->pdev;
-       if (dev)
-               dev->error_state = pci_channel_io_frozen;
-
-       __eeh_mark_slot(dn, mode_flag);
-}
-
-/**
- * __eeh_clear_slot - Clear failure flag for the child devices
- * @parent: parent device
- * @mode_flag: flag to be cleared
- *
- * Clear failure flag for the child devices.
- */
-static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
-{
-       struct device_node *dn;
-
-       for_each_child_of_node(parent, dn) {
-               if (of_node_to_eeh_dev(dn)) {
-                       of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
-                       of_node_to_eeh_dev(dn)->check_count = 0;
-                       __eeh_clear_slot(dn, mode_flag);
-               }
-       }
-}
-
-/**
- * eeh_clear_slot - Clear failure flag for the indicated device and its children
- * @dn: parent device
- * @mode_flag: flag to be cleared
- *
- * Clear failure flag for the indicated device and its children.
- */
-void eeh_clear_slot(struct device_node *dn, int mode_flag)
-{
-       unsigned long flags;
-       raw_spin_lock_irqsave(&confirm_error_lock, flags);
-       
-       dn = eeh_find_device_pe(dn);
-       
-       /* Back up one, since config addrs might be shared */
-       if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-               dn = dn->parent;
-
-       of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
-       of_node_to_eeh_dev(dn)->check_count = 0;
-       __eeh_clear_slot(dn, mode_flag);
-       raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
-}
-
-/**
- * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
- * @dn: device node
- * @dev: pci device, if known
+ * eeh_dev_check_failure - Check if all 1's data is due to EEH slot freeze
+ * @edev: eeh device
  *
  * Check for an EEH failure for the given device node.  Call this
  * routine if the result of a read was all 0xff's and you want to
@@ -392,11 +283,13 @@ void eeh_clear_slot(struct device_node *dn, int mode_flag)
  *
  * It is safe to call this routine in an interrupt context.
  */
-int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
+int eeh_dev_check_failure(struct eeh_dev *edev)
 {
        int ret;
        unsigned long flags;
-       struct eeh_dev *edev;
+       struct device_node *dn;
+       struct pci_dev *dev;
+       struct eeh_pe *pe;
        int rc = 0;
        const char *location;
 
@@ -405,23 +298,23 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
        if (!eeh_subsystem_enabled)
                return 0;
 
-       if (!dn) {
+       if (!edev) {
                eeh_stats.no_dn++;
                return 0;
        }
-       dn = eeh_find_device_pe(dn);
-       edev = of_node_to_eeh_dev(dn);
+       dn = eeh_dev_to_of_node(edev);
+       dev = eeh_dev_to_pci_dev(edev);
+       pe = edev->pe;
 
        /* Access to IO BARs might get this far and still not want checking. */
-       if (!(edev->mode & EEH_MODE_SUPPORTED) ||
-           edev->mode & EEH_MODE_NOCHECK) {
+       if (!pe) {
                eeh_stats.ignored_check++;
-               pr_debug("EEH: Ignored check (%x) for %s %s\n",
-                       edev->mode, eeh_pci_name(dev), dn->full_name);
+               pr_debug("EEH: Ignored check for %s %s\n",
+                       eeh_pci_name(dev), dn->full_name);
                return 0;
        }
 
-       if (!edev->config_addr && !edev->pe_config_addr) {
+       if (!pe->addr && !pe->config_addr) {
                eeh_stats.no_cfg_addr++;
                return 0;
        }
@@ -434,13 +327,13 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
         */
        raw_spin_lock_irqsave(&confirm_error_lock, flags);
        rc = 1;
-       if (edev->mode & EEH_MODE_ISOLATED) {
-               edev->check_count++;
-               if (edev->check_count % EEH_MAX_FAILS == 0) {
+       if (pe->state & EEH_PE_ISOLATED) {
+               pe->check_count++;
+               if (pe->check_count % EEH_MAX_FAILS == 0) {
                        location = of_get_property(dn, "ibm,loc-code", NULL);
                        printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
                                "location=%s driver=%s pci addr=%s\n",
-                               edev->check_count, location,
+                               pe->check_count, location,
                                eeh_driver_name(dev), eeh_pci_name(dev));
                        printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
                                eeh_driver_name(dev));
@@ -456,7 +349,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
         * function zero of a multi-function device.
         * In any case they must share a common PHB.
         */
-       ret = eeh_ops->get_state(dn, NULL);
+       ret = eeh_ops->get_state(pe, NULL);
 
        /* Note that config-io to empty slots may fail;
         * they are empty when they don't have children.
@@ -469,7 +362,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
            (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
            (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
                eeh_stats.false_positives++;
-               edev->false_positives ++;
+               pe->false_positives++;
                rc = 0;
                goto dn_unlock;
        }
@@ -480,10 +373,10 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
         * with other functions on this device, and functions under
         * bridges.
         */
-       eeh_mark_slot(dn, EEH_MODE_ISOLATED);
+       eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
        raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
 
-       eeh_send_failure_event(edev);
+       eeh_send_failure_event(pe);
 
        /* Most EEH events are due to device driver bugs.  Having
         * a stack trace will help the device-driver authors figure
@@ -497,7 +390,7 @@ dn_unlock:
        return rc;
 }
 
-EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
+EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
 
 /**
  * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
@@ -514,21 +407,19 @@ EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
 unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
 {
        unsigned long addr;
-       struct pci_dev *dev;
-       struct device_node *dn;
+       struct eeh_dev *edev;
 
        /* Finding the phys addr + pci device; this is pretty quick. */
        addr = eeh_token_to_phys((unsigned long __force) token);
-       dev = pci_addr_cache_get_device(addr);
-       if (!dev) {
+       edev = eeh_addr_cache_get_dev(addr);
+       if (!edev) {
                eeh_stats.no_device++;
                return val;
        }
 
-       dn = pci_device_to_OF_node(dev);
-       eeh_dn_check_failure(dn, dev);
+       eeh_dev_check_failure(edev);
 
-       pci_dev_put(dev);
+       pci_dev_put(eeh_dev_to_pci_dev(edev));
        return val;
 }
 
@@ -537,23 +428,22 @@ EXPORT_SYMBOL(eeh_check_failure);
 
 /**
  * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
- * @edev: pci device node
+ * @pe: EEH PE
  *
  * This routine should be called to reenable frozen MMIO or DMA
  * so that it would work correctly again. It's useful while doing
  * recovery or log collection on the indicated device.
  */
-int eeh_pci_enable(struct eeh_dev *edev, int function)
+int eeh_pci_enable(struct eeh_pe *pe, int function)
 {
        int rc;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
 
-       rc = eeh_ops->set_option(dn, function);
+       rc = eeh_ops->set_option(pe, function);
        if (rc)
-               printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",
-                       function, rc, dn->full_name);
+               pr_warning("%s: Unexpected state change %d on PHB#%d-PE#%x, err=%d\n",
+                       __func__, function, pe->phb->global_number, pe->addr, rc);
 
-       rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
+       rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
        if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
           (function == EEH_OPT_THAW_MMIO))
                return 0;
@@ -571,17 +461,24 @@ int eeh_pci_enable(struct eeh_dev *edev, int function)
  */
 int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
 {
-       struct device_node *dn = pci_device_to_OF_node(dev);
+       struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
+       struct eeh_pe *pe = edev->pe;
+
+       if (!pe) {
+               pr_err("%s: No PE found on PCI device %s\n",
+                       __func__, pci_name(dev));
+               return -EINVAL;
+       }
 
        switch (state) {
        case pcie_deassert_reset:
-               eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
+               eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
                break;
        case pcie_hot_reset:
-               eeh_ops->reset(dn, EEH_RESET_HOT);
+               eeh_ops->reset(pe, EEH_RESET_HOT);
                break;
        case pcie_warm_reset:
-               eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
+               eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
                break;
        default:
                return -EINVAL;
@@ -591,66 +488,37 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
 }
 
 /**
- * __eeh_set_pe_freset - Check the required reset for child devices
- * @parent: parent device
- * @freset: return value
- *
- * Each device might have its preferred reset type: fundamental or
- * hot reset. The routine is used to collect the information from
- * the child devices so that they could be reset accordingly.
- */
-void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
-{
-       struct device_node *dn;
-
-       for_each_child_of_node(parent, dn) {
-               if (of_node_to_eeh_dev(dn)) {
-                       struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
-
-                       if (dev && dev->driver)
-                               *freset |= dev->needs_freset;
-
-                       __eeh_set_pe_freset(dn, freset);
-               }
-       }
-}
-
-/**
- * eeh_set_pe_freset - Check the required reset for the indicated device and its children
- * @dn: parent device
- * @freset: return value
+ * eeh_set_pe_freset - Check the required reset for the indicated device
+ * @data: EEH device
+ * @flag: return value
  *
  * Each device might have its preferred reset type: fundamental or
  * hot reset. The routine is used to collected the information for
  * the indicated device and its children so that the bunch of the
  * devices could be reset properly.
  */
-void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
+static void *eeh_set_dev_freset(void *data, void *flag)
 {
        struct pci_dev *dev;
-       dn = eeh_find_device_pe(dn);
-
-       /* Back up one, since config addrs might be shared */
-       if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-               dn = dn->parent;
+       unsigned int *freset = (unsigned int *)flag;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
 
-       dev = of_node_to_eeh_dev(dn)->pdev;
+       dev = eeh_dev_to_pci_dev(edev);
        if (dev)
                *freset |= dev->needs_freset;
 
-       __eeh_set_pe_freset(dn, freset);
+       return NULL;
 }
 
 /**
  * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
- * @edev: pci device node to be reset.
+ * @pe: EEH PE
  *
  * Assert the PCI #RST line for 1/4 second.
  */
-static void eeh_reset_pe_once(struct eeh_dev *edev)
+static void eeh_reset_pe_once(struct eeh_pe *pe)
 {
        unsigned int freset = 0;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
 
        /* Determine type of EEH reset required for
         * Partitionable Endpoint, a hot-reset (1)
@@ -658,12 +526,12 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
         * A fundamental reset required by any device under
         * Partitionable Endpoint trumps hot-reset.
         */
-       eeh_set_pe_freset(dn, &freset);
+       eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
 
        if (freset)
-               eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
+               eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
        else
-               eeh_ops->reset(dn, EEH_RESET_HOT);
+               eeh_ops->reset(pe, EEH_RESET_HOT);
 
        /* The PCI bus requires that the reset be held high for at least
         * a 100 milliseconds. We wait a bit longer 'just in case'.
@@ -675,9 +543,9 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
         * pci slot reset line is dropped. Make sure we don't miss
         * these, and clear the flag now.
         */
-       eeh_clear_slot(dn, EEH_MODE_ISOLATED);
+       eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
 
-       eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
+       eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
 
        /* After a PCI slot has been reset, the PCI Express spec requires
         * a 1.5 second idle time for the bus to stabilize, before starting
@@ -689,116 +557,36 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
 
 /**
  * eeh_reset_pe - Reset the indicated PE
- * @edev: PCI device associated EEH device
+ * @pe: EEH PE
  *
  * This routine should be called to reset indicated device, including
  * PE. A PE might include multiple PCI devices and sometimes PCI bridges
  * might be involved as well.
  */
-int eeh_reset_pe(struct eeh_dev *edev)
+int eeh_reset_pe(struct eeh_pe *pe)
 {
        int i, rc;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
 
        /* Take three shots at resetting the bus */
        for (i=0; i<3; i++) {
-               eeh_reset_pe_once(edev);
+               eeh_reset_pe_once(pe);
 
-               rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
+               rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
                if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
                        return 0;
 
                if (rc < 0) {
-                       printk(KERN_ERR "EEH: unrecoverable slot failure %s\n",
-                              dn->full_name);
+                       pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
+                               __func__, pe->phb->global_number, pe->addr);
                        return -1;
                }
-               printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n",
-                      i+1, dn->full_name, rc);
+               pr_err("EEH: bus reset %d failed on PHB#%d-PE#%x, rc=%d\n",
+                       i+1, pe->phb->global_number, pe->addr, rc);
        }
 
        return -1;
 }
 
-/** Save and restore of PCI BARs
- *
- * Although firmware will set up BARs during boot, it doesn't
- * set up device BAR's after a device reset, although it will,
- * if requested, set up bridge configuration. Thus, we need to
- * configure the PCI devices ourselves.  
- */
-
-/**
- * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
- * @edev: PCI device associated EEH device
- *
- * Loads the PCI configuration space base address registers,
- * the expansion ROM base address, the latency timer, and etc.
- * from the saved values in the device node.
- */
-static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)
-{
-       int i;
-       u32 cmd;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
-
-       if (!edev->phb)
-               return;
-
-       for (i=4; i<10; i++) {
-               eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
-       }
-
-       /* 12 == Expansion ROM Address */
-       eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
-
-#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
-#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
-
-       eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
-                   SAVED_BYTE(PCI_CACHE_LINE_SIZE));
-
-       eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
-                   SAVED_BYTE(PCI_LATENCY_TIMER));
-
-       /* max latency, min grant, interrupt pin and line */
-       eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
-
-       /* Restore PERR & SERR bits, some devices require it,
-        * don't touch the other command bits
-        */
-       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
-       if (edev->config_space[1] & PCI_COMMAND_PARITY)
-               cmd |= PCI_COMMAND_PARITY;
-       else
-               cmd &= ~PCI_COMMAND_PARITY;
-       if (edev->config_space[1] & PCI_COMMAND_SERR)
-               cmd |= PCI_COMMAND_SERR;
-       else
-               cmd &= ~PCI_COMMAND_SERR;
-       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
-}
-
-/**
- * eeh_restore_bars - Restore the PCI config space info
- * @edev: EEH device
- *
- * This routine performs a recursive walk to the children
- * of this device as well.
- */
-void eeh_restore_bars(struct eeh_dev *edev)
-{
-       struct device_node *dn;
-       if (!edev)
-               return;
-       
-       if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))
-               eeh_restore_one_device_bars(edev);
-
-       for_each_child_of_node(eeh_dev_to_of_node(edev), dn)
-               eeh_restore_bars(of_node_to_eeh_dev(dn));
-}
-
 /**
  * eeh_save_bars - Save device bars
  * @edev: PCI device associated EEH device
@@ -808,7 +596,7 @@ void eeh_restore_bars(struct eeh_dev *edev)
  * PCI devices are added individually; but, for the restore,
  * an entire slot is reset at a time.
  */
-static void eeh_save_bars(struct eeh_dev *edev)
+void eeh_save_bars(struct eeh_dev *edev)
 {
        int i;
        struct device_node *dn;
@@ -821,102 +609,6 @@ static void eeh_save_bars(struct eeh_dev *edev)
                eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);
 }
 
-/**
- * eeh_early_enable - Early enable EEH on the indicated device
- * @dn: device node
- * @data: BUID
- *
- * Enable EEH functionality on the specified PCI device. The function
- * is expected to be called before real PCI probing is done. However,
- * the PHBs have been initialized at this point.
- */
-static void *eeh_early_enable(struct device_node *dn, void *data)
-{
-       int ret;
-       const u32 *class_code = of_get_property(dn, "class-code", NULL);
-       const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
-       const u32 *device_id = of_get_property(dn, "device-id", NULL);
-       const u32 *regs;
-       int enable;
-       struct eeh_dev *edev = of_node_to_eeh_dev(dn);
-
-       edev->class_code = 0;
-       edev->mode = 0;
-       edev->check_count = 0;
-       edev->freeze_count = 0;
-       edev->false_positives = 0;
-
-       if (!of_device_is_available(dn))
-               return NULL;
-
-       /* Ignore bad nodes. */
-       if (!class_code || !vendor_id || !device_id)
-               return NULL;
-
-       /* There is nothing to check on PCI to ISA bridges */
-       if (dn->type && !strcmp(dn->type, "isa")) {
-               edev->mode |= EEH_MODE_NOCHECK;
-               return NULL;
-       }
-       edev->class_code = *class_code;
-
-       /* Ok... see if this device supports EEH.  Some do, some don't,
-        * and the only way to find out is to check each and every one.
-        */
-       regs = of_get_property(dn, "reg", NULL);
-       if (regs) {
-               /* First register entry is addr (00BBSS00)  */
-               /* Try to enable eeh */
-               ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE);
-
-               enable = 0;
-               if (ret == 0) {
-                       edev->config_addr = regs[0];
-
-                       /* If the newer, better, ibm,get-config-addr-info is supported, 
-                        * then use that instead.
-                        */
-                       edev->pe_config_addr = eeh_ops->get_pe_addr(dn);
-
-                       /* Some older systems (Power4) allow the
-                        * ibm,set-eeh-option call to succeed even on nodes
-                        * where EEH is not supported. Verify support
-                        * explicitly.
-                        */
-                       ret = eeh_ops->get_state(dn, NULL);
-                       if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
-                               enable = 1;
-               }
-
-               if (enable) {
-                       eeh_subsystem_enabled = 1;
-                       edev->mode |= EEH_MODE_SUPPORTED;
-
-                       pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
-                                dn->full_name, edev->config_addr,
-                                edev->pe_config_addr);
-               } else {
-
-                       /* This device doesn't support EEH, but it may have an
-                        * EEH parent, in which case we mark it as supported.
-                        */
-                       if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
-                           (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
-                               /* Parent supports EEH. */
-                               edev->mode |= EEH_MODE_SUPPORTED;
-                               edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
-                               return NULL;
-                       }
-               }
-       } else {
-               printk(KERN_WARNING "EEH: %s: unable to get reg property.\n",
-                      dn->full_name);
-       }
-
-       eeh_save_bars(edev);
-       return NULL;
-}
-
 /**
  * eeh_ops_register - Register platform dependent EEH operations
  * @ops: platform dependent EEH operations
@@ -982,7 +674,7 @@ int __exit eeh_ops_unregister(const char *name)
  * Even if force-off is set, the EEH hardware is still enabled, so that
  * newer systems can boot.
  */
-void __init eeh_init(void)
+static int __init eeh_init(void)
 {
        struct pci_controller *hose, *tmp;
        struct device_node *phb;
@@ -992,27 +684,34 @@ void __init eeh_init(void)
        if (!eeh_ops) {
                pr_warning("%s: Platform EEH operation not found\n",
                        __func__);
-               return;
+               return -EEXIST;
        } else if ((ret = eeh_ops->init())) {
                pr_warning("%s: Failed to call platform init function (%d)\n",
                        __func__, ret);
-               return;
+               return ret;
        }
 
        raw_spin_lock_init(&confirm_error_lock);
 
        /* Enable EEH for all adapters */
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               phb = hose->dn;
-               traverse_pci_devices(phb, eeh_early_enable, NULL);
+       if (eeh_probe_mode_devtree()) {
+               list_for_each_entry_safe(hose, tmp,
+                       &hose_list, list_node) {
+                       phb = hose->dn;
+                       traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
+               }
        }
 
        if (eeh_subsystem_enabled)
-               printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
+               pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
        else
-               printk(KERN_WARNING "EEH: No capable adapters found\n");
+               pr_warning("EEH: No capable adapters found\n");
+
+       return ret;
 }
 
+core_initcall_sync(eeh_init);
+
 /**
  * eeh_add_device_early - Enable EEH for the indicated device_node
  * @dn: device node for which to set up EEH
@@ -1029,7 +728,7 @@ static void eeh_add_device_early(struct device_node *dn)
 {
        struct pci_controller *phb;
 
-       if (!dn || !of_node_to_eeh_dev(dn))
+       if (!of_node_to_eeh_dev(dn))
                return;
        phb = of_node_to_eeh_dev(dn)->phb;
 
@@ -1037,7 +736,8 @@ static void eeh_add_device_early(struct device_node *dn)
        if (NULL == phb || 0 == phb->buid)
                return;
 
-       eeh_early_enable(dn, NULL);
+       /* FIXME: hotplug support on POWERNV */
+       eeh_ops->of_probe(dn, NULL);
 }
 
 /**
@@ -1087,7 +787,7 @@ static void eeh_add_device_late(struct pci_dev *dev)
        edev->pdev = dev;
        dev->dev.archdata.edev = edev;
 
-       pci_addr_cache_insert_device(dev);
+       eeh_addr_cache_insert_dev(dev);
        eeh_sysfs_add_device(dev);
 }
 
@@ -1117,6 +817,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 /**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
+ * @purge_pe: remove the PE or not
  *
  * This routine should be called when a device is removed from
  * a running system (e.g. by hotplug or dlpar).  It unregisters
@@ -1124,7 +825,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
  * this device will no longer be detected after this call; thus,
  * i/o errors affecting this slot may leave this device unusable.
  */
-static void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev, int purge_pe)
 {
        struct eeh_dev *edev;
 
@@ -1143,28 +844,30 @@ static void eeh_remove_device(struct pci_dev *dev)
        dev->dev.archdata.edev = NULL;
        pci_dev_put(dev);
 
-       pci_addr_cache_remove_device(dev);
+       eeh_rmv_from_parent_pe(edev, purge_pe);
+       eeh_addr_cache_rmv_dev(dev);
        eeh_sysfs_remove_device(dev);
 }
 
 /**
  * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
  * @dev: PCI device
+ * @purge_pe: remove the corresponding PE or not
  *
  * This routine must be called when a device is removed from the
  * running system through hotplug or dlpar. The corresponding
  * PCI address cache will be removed.
  */
-void eeh_remove_bus_device(struct pci_dev *dev)
+void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe)
 {
        struct pci_bus *bus = dev->subordinate;
        struct pci_dev *child, *tmp;
 
-       eeh_remove_device(dev);
+       eeh_remove_device(dev, purge_pe);
 
        if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
-                        eeh_remove_bus_device(child);
+                        eeh_remove_bus_device(child, purge_pe);
        }
 }
 EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
index e5ae1c687c669e27e1f03c6007295e53e750eff6..5a4c87903057f46c6bfb7466ca87fdbc653cb1c0 100644 (file)
@@ -50,6 +50,7 @@ struct pci_io_addr_range {
        struct rb_node rb_node;
        unsigned long addr_lo;
        unsigned long addr_hi;
+       struct eeh_dev *edev;
        struct pci_dev *pcidev;
        unsigned int flags;
 };
@@ -59,7 +60,7 @@ static struct pci_io_addr_cache {
        spinlock_t piar_lock;
 } pci_io_addr_cache_root;
 
-static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
+static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr)
 {
        struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
 
@@ -74,7 +75,7 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
                                n = n->rb_right;
                        } else {
                                pci_dev_get(piar->pcidev);
-                               return piar->pcidev;
+                               return piar->edev;
                        }
                }
        }
@@ -83,7 +84,7 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
 }
 
 /**
- * pci_addr_cache_get_device - Get device, given only address
+ * eeh_addr_cache_get_dev - Get device, given only address
  * @addr: mmio (PIO) phys address or i/o port number
  *
  * Given an mmio phys address, or a port number, find a pci device
@@ -92,15 +93,15 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
  * from zero (that is, they do *not* have pci_io_addr added in).
  * It is safe to call this function within an interrupt.
  */
-struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
+struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr)
 {
-       struct pci_dev *dev;
+       struct eeh_dev *edev;
        unsigned long flags;
 
        spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-       dev = __pci_addr_cache_get_device(addr);
+       edev = __eeh_addr_cache_get_device(addr);
        spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-       return dev;
+       return edev;
 }
 
 #ifdef DEBUG
@@ -108,7 +109,7 @@ struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
  * Handy-dandy debug print routine, does nothing more
  * than print out the contents of our addr cache.
  */
-static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
+static void eeh_addr_cache_print(struct pci_io_addr_cache *cache)
 {
        struct rb_node *n;
        int cnt = 0;
@@ -117,7 +118,7 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
        while (n) {
                struct pci_io_addr_range *piar;
                piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-               printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n",
+               pr_debug("PCI: %s addr range %d [%lx-%lx]: %s\n",
                       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
                       piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
                cnt++;
@@ -128,7 +129,7 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
 
 /* Insert address range into the rb tree. */
 static struct pci_io_addr_range *
-pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
                      unsigned long ahi, unsigned int flags)
 {
        struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
@@ -146,23 +147,24 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
                } else {
                        if (dev != piar->pcidev ||
                            alo != piar->addr_lo || ahi != piar->addr_hi) {
-                               printk(KERN_WARNING "PIAR: overlapping address range\n");
+                               pr_warning("PIAR: overlapping address range\n");
                        }
                        return piar;
                }
        }
-       piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+       piar = kzalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
        if (!piar)
                return NULL;
 
        pci_dev_get(dev);
        piar->addr_lo = alo;
        piar->addr_hi = ahi;
+       piar->edev = pci_dev_to_eeh_dev(dev);
        piar->pcidev = dev;
        piar->flags = flags;
 
 #ifdef DEBUG
-       printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
+       pr_debug("PIAR: insert range=[%lx:%lx] dev=%s\n",
                          alo, ahi, pci_name(dev));
 #endif
 
@@ -172,7 +174,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
        return piar;
 }
 
-static void __pci_addr_cache_insert_device(struct pci_dev *dev)
+static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
 {
        struct device_node *dn;
        struct eeh_dev *edev;
@@ -180,7 +182,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 
        dn = pci_device_to_OF_node(dev);
        if (!dn) {
-               printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev));
+               pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev));
                return;
        }
 
@@ -192,8 +194,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
        }
 
        /* Skip any devices for which EEH is not enabled. */
-       if (!(edev->mode & EEH_MODE_SUPPORTED) ||
-           edev->mode & EEH_MODE_NOCHECK) {
+       if (!edev->pe) {
 #ifdef DEBUG
                pr_info("PCI: skip building address cache for=%s - %s\n",
                        pci_name(dev), dn->full_name);
@@ -212,19 +213,19 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
                        continue;
                if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
                         continue;
-               pci_addr_cache_insert(dev, start, end, flags);
+               eeh_addr_cache_insert(dev, start, end, flags);
        }
 }
 
 /**
- * pci_addr_cache_insert_device - Add a device to the address cache
+ * eeh_addr_cache_insert_dev - Add a device to the address cache
  * @dev: PCI device whose I/O addresses we are interested in.
  *
  * In order to support the fast lookup of devices based on addresses,
  * we maintain a cache of devices that can be quickly searched.
  * This routine adds a device to that cache.
  */
-void pci_addr_cache_insert_device(struct pci_dev *dev)
+void eeh_addr_cache_insert_dev(struct pci_dev *dev)
 {
        unsigned long flags;
 
@@ -233,11 +234,11 @@ void pci_addr_cache_insert_device(struct pci_dev *dev)
                return;
 
        spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-       __pci_addr_cache_insert_device(dev);
+       __eeh_addr_cache_insert_dev(dev);
        spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 }
 
-static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+static inline void __eeh_addr_cache_rmv_dev(struct pci_dev *dev)
 {
        struct rb_node *n;
 
@@ -258,7 +259,7 @@ restart:
 }
 
 /**
- * pci_addr_cache_remove_device - remove pci device from addr cache
+ * eeh_addr_cache_rmv_dev - remove pci device from addr cache
  * @dev: device to remove
  *
  * Remove a device from the addr-cache tree.
@@ -266,17 +267,17 @@ restart:
  * the tree multiple times (once per resource).
  * But so what; device removal doesn't need to be that fast.
  */
-void pci_addr_cache_remove_device(struct pci_dev *dev)
+void eeh_addr_cache_rmv_dev(struct pci_dev *dev)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-       __pci_addr_cache_remove_device(dev);
+       __eeh_addr_cache_rmv_dev(dev);
        spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 }
 
 /**
- * pci_addr_cache_build - Build a cache of I/O addresses
+ * eeh_addr_cache_build - Build a cache of I/O addresses
  *
  * Build a cache of pci i/o addresses.  This cache will be used to
  * find the pci device that corresponds to a given address.
@@ -284,7 +285,7 @@ void pci_addr_cache_remove_device(struct pci_dev *dev)
  * Must be run late in boot process, after the pci controllers
  * have been scanned for devices (after all device resources are known).
  */
-void __init pci_addr_cache_build(void)
+void __init eeh_addr_cache_build(void)
 {
        struct device_node *dn;
        struct eeh_dev *edev;
@@ -293,7 +294,7 @@ void __init pci_addr_cache_build(void)
        spin_lock_init(&pci_io_addr_cache_root.piar_lock);
 
        for_each_pci_dev(dev) {
-               pci_addr_cache_insert_device(dev);
+               eeh_addr_cache_insert_dev(dev);
 
                dn = pci_device_to_OF_node(dev);
                if (!dn)
@@ -312,7 +313,7 @@ void __init pci_addr_cache_build(void)
 
 #ifdef DEBUG
        /* Verify tree built up above, echo back the list of addrs. */
-       pci_addr_cache_print(&pci_io_addr_cache_root);
+       eeh_addr_cache_print(&pci_io_addr_cache_root);
 #endif
 }
 
index c4507d09590029f94726b7b3afaeebba29b276aa..66442341d3a6009882c0039b2049d1f7e3af1800 100644 (file)
@@ -55,7 +55,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
        struct eeh_dev *edev;
 
        /* Allocate EEH device */
-       edev = zalloc_maybe_bootmem(sizeof(*edev), GFP_KERNEL);
+       edev = kzalloc(sizeof(*edev), GFP_KERNEL);
        if (!edev) {
                pr_warning("%s: out of memory\n", __func__);
                return NULL;
@@ -65,6 +65,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
        PCI_DN(dn)->edev = edev;
        edev->dn  = dn;
        edev->phb = phb;
+       INIT_LIST_HEAD(&edev->list);
 
        return NULL;
 }
@@ -80,6 +81,9 @@ void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
 {
        struct device_node *dn = phb->dn;
 
+       /* EEH PE for PHB */
+       eeh_phb_pe_create(phb);
+
        /* EEH device for PHB */
        eeh_dev_init(dn, phb);
 
@@ -93,10 +97,16 @@ void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
  * Scan all the existing PHBs and create EEH devices for their OF
  * nodes and their children OF nodes
  */
-void __init eeh_dev_phb_init(void)
+static int __init eeh_dev_phb_init(void)
 {
        struct pci_controller *phb, *tmp;
 
        list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
                eeh_dev_phb_init_dynamic(phb);
+
+       pr_info("EEH: devices created\n");
+
+       return 0;
 }
+
+core_initcall(eeh_dev_phb_init);
index baf92cd9dfab624c1fa37af234eb9da6f45bacf5..a3fefb61097c76f513c1bf48378120e1c4c74e59 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev)
        return "";
 }
 
+/**
+ * eeh_pcid_get - Get the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is used to retrieve the PCI device driver for
+ * the indicated PCI device. Besides, we will increase the reference
+ * of the PCI device driver to prevent that being unloaded on
+ * the fly. Otherwise, kernel crash would be seen.
+ */
+static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev)
+{
+       if (!pdev || !pdev->driver)
+               return NULL;
+
+       if (!try_module_get(pdev->driver->driver.owner))
+               return NULL;
+
+       return pdev->driver;
+}
+
+/**
+ * eeh_pcid_put - Dereference on the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is called to do dereference on the PCI device
+ * driver of the indicated PCI device.
+ */
+static inline void eeh_pcid_put(struct pci_dev *pdev)
+{
+       if (!pdev || !pdev->driver)
+               return;
+
+       module_put(pdev->driver->driver.owner);
+}
+
 #if 0
 static void print_device_node_tree(struct pci_dn *pdn, int dent)
 {
@@ -93,7 +129,7 @@ static void eeh_disable_irq(struct pci_dev *dev)
        if (!irq_has_action(dev->irq))
                return;
 
-       edev->mode |= EEH_MODE_IRQ_DISABLED;
+       edev->mode |= EEH_DEV_IRQ_DISABLED;
        disable_irq_nosync(dev->irq);
 }
 
@@ -108,36 +144,44 @@ static void eeh_enable_irq(struct pci_dev *dev)
 {
        struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
 
-       if ((edev->mode) & EEH_MODE_IRQ_DISABLED) {
-               edev->mode &= ~EEH_MODE_IRQ_DISABLED;
+       if ((edev->mode) & EEH_DEV_IRQ_DISABLED) {
+               edev->mode &= ~EEH_DEV_IRQ_DISABLED;
                enable_irq(dev->irq);
        }
 }
 
 /**
  * eeh_report_error - Report pci error to each device driver
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  * 
  * Report an EEH error to each device driver, collect up and 
  * merge the device driver responses. Cumulative response 
  * passed back in "userdata".
  */
-static int eeh_report_error(struct pci_dev *dev, void *userdata)
+static void *eeh_report_error(void *data, void *userdata)
 {
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
        enum pci_ers_result rc, *res = userdata;
-       struct pci_driver *driver = dev->driver;
+       struct pci_driver *driver;
 
+       /* We might not have the associated PCI device,
+        * then we should continue for next one.
+        */
+       if (!dev) return NULL;
        dev->error_state = pci_channel_io_frozen;
 
-       if (!driver)
-               return 0;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_disable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->error_detected)
-               return 0;
+           !driver->err_handler->error_detected) {
+               eeh_pcid_put(dev);
+               return NULL;
+       }
 
        rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 
@@ -145,27 +189,34 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata)
        if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
        if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
-       return 0;
+       eeh_pcid_put(dev);
+       return NULL;
 }
 
 /**
  * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * Tells each device driver that IO ports, MMIO and config space I/O
  * are now enabled. Collects up and merges the device driver responses.
  * Cumulative response passed back in "userdata".
  */
-static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
+static void *eeh_report_mmio_enabled(void *data, void *userdata)
 {
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
        enum pci_ers_result rc, *res = userdata;
-       struct pci_driver *driver = dev->driver;
+       struct pci_driver *driver;
 
-       if (!driver ||
-           !driver->err_handler ||
-           !driver->err_handler->mmio_enabled)
-               return 0;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
+
+       if (!driver->err_handler ||
+           !driver->err_handler->mmio_enabled) {
+               eeh_pcid_put(dev);
+               return NULL;
+       }
 
        rc = driver->err_handler->mmio_enabled(dev);
 
@@ -173,12 +224,13 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
        if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
        if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
-       return 0;
+       eeh_pcid_put(dev);
+       return NULL;
 }
 
 /**
  * eeh_report_reset - Tell device that slot has been reset
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This routine must be called while EEH tries to reset particular
@@ -186,21 +238,26 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
  * some actions, usually to save data the driver needs so that the
  * driver can work again while the device is recovered.
  */
-static int eeh_report_reset(struct pci_dev *dev, void *userdata)
+static void *eeh_report_reset(void *data, void *userdata)
 {
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
        enum pci_ers_result rc, *res = userdata;
-       struct pci_driver *driver = dev->driver;
-
-       if (!driver)
-               return 0;
+       struct pci_driver *driver;
 
+       if (!dev) return NULL;
        dev->error_state = pci_channel_io_normal;
 
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
+
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->slot_reset)
-               return 0;
+           !driver->err_handler->slot_reset) {
+               eeh_pcid_put(dev);
+               return NULL;
+       }
 
        rc = driver->err_handler->slot_reset(dev);
        if ((*res == PCI_ERS_RESULT_NONE) ||
@@ -208,109 +265,115 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata)
        if (*res == PCI_ERS_RESULT_DISCONNECT &&
             rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 
-       return 0;
+       eeh_pcid_put(dev);
+       return NULL;
 }
 
 /**
  * eeh_report_resume - Tell device to resume normal operations
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This routine must be called to notify the device driver that it
  * could resume so that the device driver can do some initialization
  * to make the recovered device work again.
  */
-static int eeh_report_resume(struct pci_dev *dev, void *userdata)
+static void *eeh_report_resume(void *data, void *userdata)
 {
-       struct pci_driver *driver = dev->driver;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+       struct pci_driver *driver;
 
+       if (!dev) return NULL;
        dev->error_state = pci_channel_io_normal;
 
-       if (!driver)
-               return 0;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->resume)
-               return 0;
+           !driver->err_handler->resume) {
+               eeh_pcid_put(dev);
+               return NULL;
+       }
 
        driver->err_handler->resume(dev);
 
-       return 0;
+       eeh_pcid_put(dev);
+       return NULL;
 }
 
 /**
  * eeh_report_failure - Tell device driver that device is dead.
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This informs the device driver that the device is permanently
  * dead, and that no further recovery attempts will be made on it.
  */
-static int eeh_report_failure(struct pci_dev *dev, void *userdata)
+static void *eeh_report_failure(void *data, void *userdata)
 {
-       struct pci_driver *driver = dev->driver;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+       struct pci_driver *driver;
 
+       if (!dev) return NULL;
        dev->error_state = pci_channel_io_perm_failure;
 
-       if (!driver)
-               return 0;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_disable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->error_detected)
-               return 0;
+           !driver->err_handler->error_detected) {
+               eeh_pcid_put(dev);
+               return NULL;
+       }
 
        driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 
-       return 0;
+       eeh_pcid_put(dev);
+       return NULL;
 }
 
 /**
  * eeh_reset_device - Perform actual reset of a pci slot
- * @edev: PE associated EEH device
+ * @pe: EEH PE
  * @bus: PCI bus corresponding to the isolcated slot
  *
  * This routine must be called to do reset on the indicated PE.
  * During the reset, udev might be invoked because those affected
  * PCI devices will be removed and then added.
  */
-static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
+static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 {
-       struct device_node *dn;
        int cnt, rc;
 
        /* pcibios will clear the counter; save the value */
-       cnt = edev->freeze_count;
+       cnt = pe->freeze_count;
 
+       /*
+        * We don't remove the corresponding PE instances because
+        * we need the information afterwords. The attached EEH
+        * devices are expected to be attached soon when calling
+        * into pcibios_add_pci_devices().
+        */
        if (bus)
-               pcibios_remove_pci_devices(bus);
+               __pcibios_remove_pci_devices(bus, 0);
 
        /* Reset the pci controller. (Asserts RST#; resets config space).
         * Reconfigure bridges and devices. Don't try to bring the system
         * up if the reset failed for some reason.
         */
-       rc = eeh_reset_pe(edev);
+       rc = eeh_reset_pe(pe);
        if (rc)
                return rc;
 
-       /* Walk over all functions on this device. */
-       dn = eeh_dev_to_of_node(edev);
-       if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-               dn = dn->parent->child;
-
-       while (dn) {
-               struct eeh_dev *pedev = of_node_to_eeh_dev(dn);
-
-               /* On Power4, always true because eeh_pe_config_addr=0 */
-               if (edev->pe_config_addr == pedev->pe_config_addr) {
-                       eeh_ops->configure_bridge(dn);
-                       eeh_restore_bars(pedev);
-               }
-               dn = dn->sibling;
-       }
+       /* Restore PE */
+       eeh_ops->configure_bridge(pe);
+       eeh_pe_restore_bars(pe);
 
        /* Give the system 5 seconds to finish running the user-space
         * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes, 
@@ -322,7 +385,7 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
                ssleep(5);
                pcibios_add_pci_devices(bus);
        }
-       edev->freeze_count = cnt;
+       pe->freeze_count = cnt;
 
        return 0;
 }
@@ -334,7 +397,7 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
 
 /**
  * eeh_handle_event - Reset a PCI device after hard lockup.
- * @event: EEH event
+ * @pe: EEH PE
  *
  * While PHB detects address or data parity errors on particular PCI
  * slot, the associated PE will be frozen. Besides, DMA's occurring
@@ -349,69 +412,24 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
  * drivers (which cause a second set of hotplug events to go out to
  * userspace).
  */
-struct eeh_dev *handle_eeh_events(struct eeh_event *event)
+void eeh_handle_event(struct eeh_pe *pe)
 {
-       struct device_node *frozen_dn;
-       struct eeh_dev *frozen_edev;
        struct pci_bus *frozen_bus;
        int rc = 0;
        enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-       const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;
-
-       frozen_dn = eeh_find_device_pe(eeh_dev_to_of_node(event->edev));
-       if (!frozen_dn) {
-               location = of_get_property(eeh_dev_to_of_node(event->edev), "ibm,loc-code", NULL);
-               location = location ? location : "unknown";
-               printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
-                               "for location=%s pci addr=%s\n",
-                       location, eeh_pci_name(eeh_dev_to_pci_dev(event->edev)));
-               return NULL;
-       }
-
-       frozen_bus = pcibios_find_pci_bus(frozen_dn);
-       location = of_get_property(frozen_dn, "ibm,loc-code", NULL);
-       location = location ? location : "unknown";
-
-       /* There are two different styles for coming up with the PE.
-        * In the old style, it was the highest EEH-capable device
-        * which was always an EADS pci bridge.  In the new style,
-        * there might not be any EADS bridges, and even when there are,
-        * the firmware marks them as "EEH incapable". So another
-        * two-step is needed to find the pci bus..
-        */
-       if (!frozen_bus)
-               frozen_bus = pcibios_find_pci_bus(frozen_dn->parent);
 
+       frozen_bus = eeh_pe_bus_get(pe);
        if (!frozen_bus) {
-               printk(KERN_ERR "EEH: Cannot find PCI bus "
-                       "for location=%s dn=%s\n",
-                       location, frozen_dn->full_name);
-               return NULL;
+               pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
+                       __func__, pe->phb->global_number, pe->addr);
+               return;
        }
 
-       frozen_edev = of_node_to_eeh_dev(frozen_dn);
-       frozen_edev->freeze_count++;
-       pci_str = eeh_pci_name(eeh_dev_to_pci_dev(event->edev));
-       drv_str = eeh_pcid_name(eeh_dev_to_pci_dev(event->edev));
-
-       if (frozen_edev->freeze_count > EEH_MAX_ALLOWED_FREEZES)
+       pe->freeze_count++;
+       if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES)
                goto excess_failures;
-
-       printk(KERN_WARNING
-          "EEH: This PCI device has failed %d times in the last hour:\n",
-               frozen_edev->freeze_count);
-
-       if (frozen_edev->pdev) {
-               bus_pci_str = pci_name(frozen_edev->pdev);
-               bus_drv_str = eeh_pcid_name(frozen_edev->pdev);
-               printk(KERN_WARNING
-                       "EEH: Bus location=%s driver=%s pci addr=%s\n",
-                       location, bus_drv_str, bus_pci_str);
-       }
-
-       printk(KERN_WARNING
-               "EEH: Device location=%s driver=%s pci addr=%s\n",
-               location, drv_str, pci_str);
+       pr_warning("EEH: This PCI device has failed %d times in the last hour\n",
+               pe->freeze_count);
 
        /* Walk the various device drivers attached to this slot through
         * a reset sequence, giving each an opportunity to do what it needs
@@ -419,12 +437,12 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
         * status ... if any child can't handle the reset, then the entire
         * slot is dlpar removed and added.
         */
-       pci_walk_bus(frozen_bus, eeh_report_error, &result);
+       eeh_pe_dev_traverse(pe, eeh_report_error, &result);
 
        /* Get the current PCI slot state. This can take a long time,
         * sometimes over 3 seconds for certain systems.
         */
-       rc = eeh_ops->wait_state(eeh_dev_to_of_node(frozen_edev), MAX_WAIT_FOR_RECOVERY*1000);
+       rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000);
        if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {
                printk(KERN_WARNING "EEH: Permanent failure\n");
                goto hard_fail;
@@ -434,14 +452,14 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
         * don't post the error log until after all dev drivers
         * have been informed.
         */
-       eeh_slot_error_detail(frozen_edev, EEH_LOG_TEMP);
+       eeh_slot_error_detail(pe, EEH_LOG_TEMP);
 
        /* If all device drivers were EEH-unaware, then shut
         * down all of the device drivers, and hope they
         * go down willingly, without panicing the system.
         */
        if (result == PCI_ERS_RESULT_NONE) {
-               rc = eeh_reset_device(frozen_edev, frozen_bus);
+               rc = eeh_reset_device(pe, frozen_bus);
                if (rc) {
                        printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc);
                        goto hard_fail;
@@ -450,7 +468,7 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 
        /* If all devices reported they can proceed, then re-enable MMIO */
        if (result == PCI_ERS_RESULT_CAN_RECOVER) {
-               rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_MMIO);
+               rc = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
                if (rc < 0)
                        goto hard_fail;
@@ -458,13 +476,13 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
                        result = PCI_ERS_RESULT_NEED_RESET;
                } else {
                        result = PCI_ERS_RESULT_NONE;
-                       pci_walk_bus(frozen_bus, eeh_report_mmio_enabled, &result);
+                       eeh_pe_dev_traverse(pe, eeh_report_mmio_enabled, &result);
                }
        }
 
        /* If all devices reported they can proceed, then re-enable DMA */
        if (result == PCI_ERS_RESULT_CAN_RECOVER) {
-               rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_DMA);
+               rc = eeh_pci_enable(pe, EEH_OPT_THAW_DMA);
 
                if (rc < 0)
                        goto hard_fail;
@@ -482,13 +500,13 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 
        /* If any device called out for a reset, then reset the slot */
        if (result == PCI_ERS_RESULT_NEED_RESET) {
-               rc = eeh_reset_device(frozen_edev, NULL);
+               rc = eeh_reset_device(pe, NULL);
                if (rc) {
                        printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc);
                        goto hard_fail;
                }
                result = PCI_ERS_RESULT_NONE;
-               pci_walk_bus(frozen_bus, eeh_report_reset, &result);
+               eeh_pe_dev_traverse(pe, eeh_report_reset, &result);
        }
 
        /* All devices should claim they have recovered by now. */
@@ -499,9 +517,9 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
        }
 
        /* Tell all device drivers that they can resume operations */
-       pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
+       eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
 
-       return frozen_edev;
+       return;
        
 excess_failures:
        /*
@@ -509,30 +527,26 @@ excess_failures:
         * are due to poorly seated PCI cards. Only 10% or so are
         * due to actual, failed cards.
         */
-       printk(KERN_ERR
-          "EEH: PCI device at location=%s driver=%s pci addr=%s\n"
-               "has failed %d times in the last hour "
-               "and has been permanently disabled.\n"
-               "Please try reseating this device or replacing it.\n",
-               location, drv_str, pci_str, frozen_edev->freeze_count);
+       pr_err("EEH: PHB#%d-PE#%x has failed %d times in the\n"
+              "last hour and has been permanently disabled.\n"
+              "Please try reseating or replacing it.\n",
+               pe->phb->global_number, pe->addr,
+               pe->freeze_count);
        goto perm_error;
 
 hard_fail:
-       printk(KERN_ERR
-          "EEH: Unable to recover from failure of PCI device "
-          "at location=%s driver=%s pci addr=%s\n"
-          "Please try reseating this device or replacing it.\n",
-               location, drv_str, pci_str);
+       pr_err("EEH: Unable to recover from failure from PHB#%d-PE#%x.\n"
+              "Please try reseating or replacing it\n",
+               pe->phb->global_number, pe->addr);
 
 perm_error:
-       eeh_slot_error_detail(frozen_edev, EEH_LOG_PERM);
+       eeh_slot_error_detail(pe, EEH_LOG_PERM);
 
        /* Notify all devices that they're about to go down. */
-       pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
+       eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
 
        /* Shut down the device drivers for good. */
-       pcibios_remove_pci_devices(frozen_bus);
-
-       return NULL;
+       if (frozen_bus)
+               pcibios_remove_pci_devices(frozen_bus);
 }
 
index fb506317ebb09141716d0d9bfe068fe7f953221d..51faaac8abe6c401636326deebd59f4d12457b28 100644 (file)
@@ -57,7 +57,7 @@ static int eeh_event_handler(void * dummy)
 {
        unsigned long flags;
        struct eeh_event *event;
-       struct eeh_dev *edev;
+       struct eeh_pe *pe;
 
        set_task_comm(current, "eehd");
 
@@ -76,28 +76,23 @@ static int eeh_event_handler(void * dummy)
 
        /* Serialize processing of EEH events */
        mutex_lock(&eeh_event_mutex);
-       edev = event->edev;
-       eeh_mark_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
-
-       printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-              eeh_pci_name(edev->pdev));
+       pe = event->pe;
+       eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
+       pr_info("EEH: Detected PCI bus error on PHB#%d-PE#%x\n",
+               pe->phb->global_number, pe->addr);
 
        set_current_state(TASK_INTERRUPTIBLE);  /* Don't add to load average */
-       edev = handle_eeh_events(event);
-
-       if (edev) {
-               eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
-               pci_dev_put(edev->pdev);
-       }
+       eeh_handle_event(pe);
+       eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
 
        kfree(event);
        mutex_unlock(&eeh_event_mutex);
 
        /* If there are no new errors after an hour, clear the counter. */
-       if (edev && edev->freeze_count>0) {
+       if (pe && pe->freeze_count > 0) {
                msleep_interruptible(3600*1000);
-               if (edev->freeze_count>0)
-                       edev->freeze_count--;
+               if (pe->freeze_count > 0)
+                       pe->freeze_count--;
 
        }
 
@@ -119,36 +114,23 @@ static void eeh_thread_launcher(struct work_struct *dummy)
 
 /**
  * eeh_send_failure_event - Generate a PCI error event
- * @edev: EEH device
+ * @pe: EEH PE
  *
  * This routine can be called within an interrupt context;
  * the actual event will be delivered in a normal context
  * (from a workqueue).
  */
-int eeh_send_failure_event(struct eeh_dev *edev)
+int eeh_send_failure_event(struct eeh_pe *pe)
 {
        unsigned long flags;
        struct eeh_event *event;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
-       const char *location;
-
-       if (!mem_init_done) {
-               printk(KERN_ERR "EEH: event during early boot not handled\n");
-               location = of_get_property(dn, "ibm,loc-code", NULL);
-               printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
-               printk(KERN_ERR "EEH: PCI location = %s\n", location);
-               return 1;
-       }
-       event = kmalloc(sizeof(*event), GFP_ATOMIC);
-       if (event == NULL) {
-               printk(KERN_ERR "EEH: out of memory, event not handled\n");
-               return 1;
-       }
-
-       if (edev->pdev)
-               pci_dev_get(edev->pdev);
 
-       event->edev = edev;
+       event = kzalloc(sizeof(*event), GFP_ATOMIC);
+       if (!event) {
+               pr_err("EEH: out of memory, event not handled\n");
+               return -ENOMEM;
+       }
+       event->pe = pe;
 
        /* We may or may not be called in an interrupt context */
        spin_lock_irqsave(&eeh_eventlist_lock, flags);
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c
new file mode 100644 (file)
index 0000000..797cd18
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * The file intends to implement PE based on the information from
+ * platforms. Basically, there have 3 types of PEs: PHB/Bus/Device.
+ * All the PEs should be organized as hierarchy tree. The first level
+ * of the tree will be associated to existing PHBs since the particular
+ * PE is only meaningful in one PHB domain.
+ *
+ * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2012.
+ *
+ * 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/export.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+static LIST_HEAD(eeh_phb_pe);
+
+/**
+ * eeh_pe_alloc - Allocate PE
+ * @phb: PCI controller
+ * @type: PE type
+ *
+ * Allocate PE instance dynamically.
+ */
+static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
+{
+       struct eeh_pe *pe;
+
+       /* Allocate PHB PE */
+       pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
+       if (!pe) return NULL;
+
+       /* Initialize PHB PE */
+       pe->type = type;
+       pe->phb = phb;
+       INIT_LIST_HEAD(&pe->child_list);
+       INIT_LIST_HEAD(&pe->child);
+       INIT_LIST_HEAD(&pe->edevs);
+
+       return pe;
+}
+
+/**
+ * eeh_phb_pe_create - Create PHB PE
+ * @phb: PCI controller
+ *
+ * The function should be called while the PHB is detected during
+ * system boot or PCI hotplug in order to create PHB PE.
+ */
+int __devinit eeh_phb_pe_create(struct pci_controller *phb)
+{
+       struct eeh_pe *pe;
+
+       /* Allocate PHB PE */
+       pe = eeh_pe_alloc(phb, EEH_PE_PHB);
+       if (!pe) {
+               pr_err("%s: out of memory!\n", __func__);
+               return -ENOMEM;
+       }
+
+       /* Put it into the list */
+       eeh_lock();
+       list_add_tail(&pe->child, &eeh_phb_pe);
+       eeh_unlock();
+
+       pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
+
+       return 0;
+}
+
+/**
+ * eeh_phb_pe_get - Retrieve PHB PE based on the given PHB
+ * @phb: PCI controller
+ *
+ * The overall PEs form hierarchy tree. The first layer of the
+ * hierarchy tree is composed of PHB PEs. The function is used
+ * to retrieve the corresponding PHB PE according to the given PHB.
+ */
+static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
+{
+       struct eeh_pe *pe;
+
+       list_for_each_entry(pe, &eeh_phb_pe, child) {
+               /*
+                * Actually, we needn't check the type since
+                * the PE for PHB has been determined when that
+                * was created.
+                */
+               if ((pe->type & EEH_PE_PHB) && pe->phb == phb)
+                       return pe;
+       }
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_next - Retrieve the next PE in the tree
+ * @pe: current PE
+ * @root: root PE
+ *
+ * The function is used to retrieve the next PE in the
+ * hierarchy PE tree.
+ */
+static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe,
+                                 struct eeh_pe *root)
+{
+       struct list_head *next = pe->child_list.next;
+
+       if (next == &pe->child_list) {
+               while (1) {
+                       if (pe == root)
+                               return NULL;
+                       next = pe->child.next;
+                       if (next != &pe->parent->child_list)
+                               break;
+                       pe = pe->parent;
+               }
+       }
+
+       return list_entry(next, struct eeh_pe, child);
+}
+
+/**
+ * eeh_pe_traverse - Traverse PEs in the specified PHB
+ * @root: root PE
+ * @fn: callback
+ * @flag: extra parameter to callback
+ *
+ * The function is used to traverse the specified PE and its
+ * child PEs. The traversing is to be terminated once the
+ * callback returns something other than NULL, or no more PEs
+ * to be traversed.
+ */
+static void *eeh_pe_traverse(struct eeh_pe *root,
+                       eeh_traverse_func fn, void *flag)
+{
+       struct eeh_pe *pe;
+       void *ret;
+
+       for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
+               ret = fn(pe, flag);
+               if (ret) return ret;
+       }
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_dev_traverse - Traverse the devices from the PE
+ * @root: EEH PE
+ * @fn: function callback
+ * @flag: extra parameter to callback
+ *
+ * The function is used to traverse the devices of the specified
+ * PE and its child PEs.
+ */
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+               eeh_traverse_func fn, void *flag)
+{
+       struct eeh_pe *pe;
+       struct eeh_dev *edev;
+       void *ret;
+
+       if (!root) {
+               pr_warning("%s: Invalid PE %p\n", __func__, root);
+               return NULL;
+       }
+
+       eeh_lock();
+
+       /* Traverse root PE */
+       for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
+               eeh_pe_for_each_dev(pe, edev) {
+                       ret = fn(edev, flag);
+                       if (ret) {
+                               eeh_unlock();
+                               return ret;
+                       }
+               }
+       }
+
+       eeh_unlock();
+
+       return NULL;
+}
+
+/**
+ * __eeh_pe_get - Check the PE address
+ * @data: EEH PE
+ * @flag: EEH device
+ *
+ * For one particular PE, it can be identified by PE address
+ * or tranditional BDF address. BDF address is composed of
+ * Bus/Device/Function number. The extra data referred by flag
+ * indicates which type of address should be used.
+ */
+static void *__eeh_pe_get(void *data, void *flag)
+{
+       struct eeh_pe *pe = (struct eeh_pe *)data;
+       struct eeh_dev *edev = (struct eeh_dev *)flag;
+
+       /* Unexpected PHB PE */
+       if (pe->type & EEH_PE_PHB)
+               return NULL;
+
+       /* We prefer PE address */
+       if (edev->pe_config_addr &&
+          (edev->pe_config_addr == pe->addr))
+               return pe;
+
+       /* Try BDF address */
+       if (edev->pe_config_addr &&
+          (edev->config_addr == pe->config_addr))
+               return pe;
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_get - Search PE based on the given address
+ * @edev: EEH device
+ *
+ * Search the corresponding PE based on the specified address which
+ * is included in the eeh device. The function is used to check if
+ * the associated PE has been created against the PE address. It's
+ * notable that the PE address has 2 format: traditional PE address
+ * which is composed of PCI bus/device/function number, or unified
+ * PE address.
+ */
+static struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
+{
+       struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
+       struct eeh_pe *pe;
+
+       pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
+
+       return pe;
+}
+
+/**
+ * eeh_pe_get_parent - Retrieve the parent PE
+ * @edev: EEH device
+ *
+ * The whole PEs existing in the system are organized as hierarchy
+ * tree. The function is used to retrieve the parent PE according
+ * to the parent EEH device.
+ */
+static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
+{
+       struct device_node *dn;
+       struct eeh_dev *parent;
+
+       /*
+        * It might have the case for the indirect parent
+        * EEH device already having associated PE, but
+        * the direct parent EEH device doesn't have yet.
+        */
+       dn = edev->dn->parent;
+       while (dn) {
+               /* We're poking out of PCI territory */
+               if (!PCI_DN(dn)) return NULL;
+
+               parent = of_node_to_eeh_dev(dn);
+               /* We're poking out of PCI territory */
+               if (!parent) return NULL;
+
+               if (parent->pe)
+                       return parent->pe;
+
+               dn = dn->parent;
+       }
+
+       return NULL;
+}
+
+/**
+ * eeh_add_to_parent_pe - Add EEH device to parent PE
+ * @edev: EEH device
+ *
+ * Add EEH device to the parent PE. If the parent PE already
+ * exists, the PE type will be changed to EEH_PE_BUS. Otherwise,
+ * we have to create new PE to hold the EEH device and the new
+ * PE will be linked to its parent PE as well.
+ */
+int eeh_add_to_parent_pe(struct eeh_dev *edev)
+{
+       struct eeh_pe *pe, *parent;
+
+       eeh_lock();
+
+       /*
+        * Search the PE has been existing or not according
+        * to the PE address. If that has been existing, the
+        * PE should be composed of PCI bus and its subordinate
+        * components.
+        */
+       pe = eeh_pe_get(edev);
+       if (pe && !(pe->type & EEH_PE_INVALID)) {
+               if (!edev->pe_config_addr) {
+                       eeh_unlock();
+                       pr_err("%s: PE with addr 0x%x already exists\n",
+                               __func__, edev->config_addr);
+                       return -EEXIST;
+               }
+
+               /* Mark the PE as type of PCI bus */
+               pe->type = EEH_PE_BUS;
+               edev->pe = pe;
+
+               /* Put the edev to PE */
+               list_add_tail(&edev->list, &pe->edevs);
+               eeh_unlock();
+               pr_debug("EEH: Add %s to Bus PE#%x\n",
+                       edev->dn->full_name, pe->addr);
+
+               return 0;
+       } else if (pe && (pe->type & EEH_PE_INVALID)) {
+               list_add_tail(&edev->list, &pe->edevs);
+               edev->pe = pe;
+               /*
+                * We're running to here because of PCI hotplug caused by
+                * EEH recovery. We need clear EEH_PE_INVALID until the top.
+                */
+               parent = pe;
+               while (parent) {
+                       if (!(parent->type & EEH_PE_INVALID))
+                               break;
+                       parent->type &= ~EEH_PE_INVALID;
+                       parent = parent->parent;
+               }
+               eeh_unlock();
+               pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
+                       edev->dn->full_name, pe->addr, pe->parent->addr);
+
+               return 0;
+       }
+
+       /* Create a new EEH PE */
+       pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
+       if (!pe) {
+               eeh_unlock();
+               pr_err("%s: out of memory!\n", __func__);
+               return -ENOMEM;
+       }
+       pe->addr        = edev->pe_config_addr;
+       pe->config_addr = edev->config_addr;
+
+       /*
+        * Put the new EEH PE into hierarchy tree. If the parent
+        * can't be found, the newly created PE will be attached
+        * to PHB directly. Otherwise, we have to associate the
+        * PE with its parent.
+        */
+       parent = eeh_pe_get_parent(edev);
+       if (!parent) {
+               parent = eeh_phb_pe_get(edev->phb);
+               if (!parent) {
+                       eeh_unlock();
+                       pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
+                               __func__, edev->phb->global_number);
+                       edev->pe = NULL;
+                       kfree(pe);
+                       return -EEXIST;
+               }
+       }
+       pe->parent = parent;
+
+       /*
+        * Put the newly created PE into the child list and
+        * link the EEH device accordingly.
+        */
+       list_add_tail(&pe->child, &parent->child_list);
+       list_add_tail(&edev->list, &pe->edevs);
+       edev->pe = pe;
+       eeh_unlock();
+       pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
+               edev->dn->full_name, pe->addr, pe->parent->addr);
+
+       return 0;
+}
+
+/**
+ * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
+ * @edev: EEH device
+ * @purge_pe: remove PE or not
+ *
+ * The PE hierarchy tree might be changed when doing PCI hotplug.
+ * Also, the PCI devices or buses could be removed from the system
+ * during EEH recovery. So we have to call the function remove the
+ * corresponding PE accordingly if necessary.
+ */
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
+{
+       struct eeh_pe *pe, *parent, *child;
+       int cnt;
+
+       if (!edev->pe) {
+               pr_warning("%s: No PE found for EEH device %s\n",
+                       __func__, edev->dn->full_name);
+               return -EEXIST;
+       }
+
+       eeh_lock();
+
+       /* Remove the EEH device */
+       pe = edev->pe;
+       edev->pe = NULL;
+       list_del(&edev->list);
+
+       /*
+        * Check if the parent PE includes any EEH devices.
+        * If not, we should delete that. Also, we should
+        * delete the parent PE if it doesn't have associated
+        * child PEs and EEH devices.
+        */
+       while (1) {
+               parent = pe->parent;
+               if (pe->type & EEH_PE_PHB)
+                       break;
+
+               if (purge_pe) {
+                       if (list_empty(&pe->edevs) &&
+                           list_empty(&pe->child_list)) {
+                               list_del(&pe->child);
+                               kfree(pe);
+                       } else {
+                               break;
+                       }
+               } else {
+                       if (list_empty(&pe->edevs)) {
+                               cnt = 0;
+                               list_for_each_entry(child, &pe->child_list, child) {
+                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                               cnt++;
+                                               break;
+                                       }
+                               }
+
+                               if (!cnt)
+                                       pe->type |= EEH_PE_INVALID;
+                               else
+                                       break;
+                       }
+               }
+
+               pe = parent;
+       }
+
+       eeh_unlock();
+
+       return 0;
+}
+
+/**
+ * __eeh_pe_state_mark - Mark the state for the PE
+ * @data: EEH PE
+ * @flag: state
+ *
+ * The function is used to mark the indicated state for the given
+ * PE. Also, the associated PCI devices will be put into IO frozen
+ * state as well.
+ */
+static void *__eeh_pe_state_mark(void *data, void *flag)
+{
+       struct eeh_pe *pe = (struct eeh_pe *)data;
+       int state = *((int *)flag);
+       struct eeh_dev *tmp;
+       struct pci_dev *pdev;
+
+       /*
+        * Mark the PE with the indicated state. Also,
+        * the associated PCI device will be put into
+        * I/O frozen state to avoid I/O accesses from
+        * the PCI device driver.
+        */
+       pe->state |= state;
+       eeh_pe_for_each_dev(pe, tmp) {
+               pdev = eeh_dev_to_pci_dev(tmp);
+               if (pdev)
+                       pdev->error_state = pci_channel_io_frozen;
+       }
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_state_mark - Mark specified state for PE and its associated device
+ * @pe: EEH PE
+ *
+ * EEH error affects the current PE and its child PEs. The function
+ * is used to mark appropriate state for the affected PEs and the
+ * associated devices.
+ */
+void eeh_pe_state_mark(struct eeh_pe *pe, int state)
+{
+       eeh_lock();
+       eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
+       eeh_unlock();
+}
+
+/**
+ * __eeh_pe_state_clear - Clear state for the PE
+ * @data: EEH PE
+ * @flag: state
+ *
+ * The function is used to clear the indicated state from the
+ * given PE. Besides, we also clear the check count of the PE
+ * as well.
+ */
+static void *__eeh_pe_state_clear(void *data, void *flag)
+{
+       struct eeh_pe *pe = (struct eeh_pe *)data;
+       int state = *((int *)flag);
+
+       pe->state &= ~state;
+       pe->check_count = 0;
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_state_clear - Clear state for the PE and its children
+ * @pe: PE
+ * @state: state to be cleared
+ *
+ * When the PE and its children has been recovered from error,
+ * we need clear the error state for that. The function is used
+ * for the purpose.
+ */
+void eeh_pe_state_clear(struct eeh_pe *pe, int state)
+{
+       eeh_lock();
+       eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
+       eeh_unlock();
+}
+
+/**
+ * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
+ * @data: EEH device
+ * @flag: Unused
+ *
+ * Loads the PCI configuration space base address registers,
+ * the expansion ROM base address, the latency timer, and etc.
+ * from the saved values in the device node.
+ */
+static void *eeh_restore_one_device_bars(void *data, void *flag)
+{
+       int i;
+       u32 cmd;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct device_node *dn = eeh_dev_to_of_node(edev);
+
+       for (i = 4; i < 10; i++)
+               eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
+       /* 12 == Expansion ROM Address */
+       eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
+
+#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
+#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
+
+       eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
+               SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+       eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
+               SAVED_BYTE(PCI_LATENCY_TIMER));
+
+       /* max latency, min grant, interrupt pin and line */
+       eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
+
+       /*
+        * Restore PERR & SERR bits, some devices require it,
+        * don't touch the other command bits
+        */
+       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
+       if (edev->config_space[1] & PCI_COMMAND_PARITY)
+               cmd |= PCI_COMMAND_PARITY;
+       else
+               cmd &= ~PCI_COMMAND_PARITY;
+       if (edev->config_space[1] & PCI_COMMAND_SERR)
+               cmd |= PCI_COMMAND_SERR;
+       else
+               cmd &= ~PCI_COMMAND_SERR;
+       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_restore_bars - Restore the PCI config space info
+ * @pe: EEH PE
+ *
+ * This routine performs a recursive walk to the children
+ * of this device as well.
+ */
+void eeh_pe_restore_bars(struct eeh_pe *pe)
+{
+       /*
+        * We needn't take the EEH lock since eeh_pe_dev_traverse()
+        * will take that.
+        */
+       eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
+}
+
+/**
+ * eeh_pe_bus_get - Retrieve PCI bus according to the given PE
+ * @pe: EEH PE
+ *
+ * Retrieve the PCI bus according to the given PE. Basically,
+ * there're 3 types of PEs: PHB/Bus/Device. For PHB PE, the
+ * primary PCI bus will be retrieved. The parent bus will be
+ * returned for BUS PE. However, we don't have associated PCI
+ * bus for DEVICE PE.
+ */
+struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
+{
+       struct pci_bus *bus = NULL;
+       struct eeh_dev *edev;
+       struct pci_dev *pdev;
+
+       eeh_lock();
+
+       if (pe->type & EEH_PE_PHB) {
+               bus = pe->phb->bus;
+       } else if (pe->type & EEH_PE_BUS) {
+               edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
+               pdev = eeh_dev_to_pci_dev(edev);
+               if (pdev)
+                       bus = pdev->bus;
+       }
+
+       eeh_unlock();
+
+       return bus;
+}
index c33360ec4f4f4d9acf4cade2360358c115c4829f..19506f935737d2ee7c27a16d1ecc909cc4b6c518 100644 (file)
@@ -129,27 +129,117 @@ static int pseries_eeh_init(void)
                eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
        }
 
+       /* Set EEH probe mode */
+       eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE);
+
        return 0;
 }
 
+/**
+ * pseries_eeh_of_probe - EEH probe on the given device
+ * @dn: OF node
+ * @flag: Unused
+ *
+ * When EEH module is installed during system boot, all PCI devices
+ * are checked one by one to see if it supports EEH. The function
+ * is introduced for the purpose.
+ */
+static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
+{
+       struct eeh_dev *edev;
+       struct eeh_pe pe;
+       const u32 *class_code, *vendor_id, *device_id;
+       const u32 *regs;
+       int enable = 0;
+       int ret;
+
+       /* Retrieve OF node and eeh device */
+       edev = of_node_to_eeh_dev(dn);
+       if (!of_device_is_available(dn))
+               return NULL;
+
+       /* Retrieve class/vendor/device IDs */
+       class_code = of_get_property(dn, "class-code", NULL);
+       vendor_id  = of_get_property(dn, "vendor-id", NULL);
+       device_id  = of_get_property(dn, "device-id", NULL);
+
+       /* Skip for bad OF node or PCI-ISA bridge */
+       if (!class_code || !vendor_id || !device_id)
+               return NULL;
+       if (dn->type && !strcmp(dn->type, "isa"))
+               return NULL;
+
+       /* Update class code and mode of eeh device */
+       edev->class_code = *class_code;
+       edev->mode = 0;
+
+       /* Retrieve the device address */
+       regs = of_get_property(dn, "reg", NULL);
+       if (!regs) {
+               pr_warning("%s: OF node property %s::reg not found\n",
+                       __func__, dn->full_name);
+               return NULL;
+       }
+
+       /* Initialize the fake PE */
+       memset(&pe, 0, sizeof(struct eeh_pe));
+       pe.phb = edev->phb;
+       pe.config_addr = regs[0];
+
+       /* Enable EEH on the device */
+       ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE);
+       if (!ret) {
+               edev->config_addr = regs[0];
+               /* Retrieve PE address */
+               edev->pe_config_addr = eeh_ops->get_pe_addr(&pe);
+               pe.addr = edev->pe_config_addr;
+
+               /* Some older systems (Power4) allow the ibm,set-eeh-option
+                * call to succeed even on nodes where EEH is not supported.
+                * Verify support explicitly.
+                */
+               ret = eeh_ops->get_state(&pe, NULL);
+               if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
+                       enable = 1;
+
+               if (enable) {
+                       eeh_subsystem_enabled = 1;
+                       eeh_add_to_parent_pe(edev);
+
+                       pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
+                               __func__, dn->full_name, pe.phb->global_number,
+                               pe.addr, pe.config_addr);
+               } else if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
+                          (of_node_to_eeh_dev(dn->parent))->pe) {
+                       /* This device doesn't support EEH, but it may have an
+                        * EEH parent, in which case we mark it as supported.
+                        */
+                       edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
+                       edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr;
+                       eeh_add_to_parent_pe(edev);
+               }
+       }
+
+       /* Save memory bars */
+       eeh_save_bars(edev);
+
+       return NULL;
+}
+
 /**
  * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
- * @dn: device node
+ * @pe: EEH PE
  * @option: operation to be issued
  *
  * The function is used to control the EEH functionality globally.
  * Currently, following options are support according to PAPR:
  * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
  */
-static int pseries_eeh_set_option(struct device_node *dn, int option)
+static int pseries_eeh_set_option(struct eeh_pe *pe, int option)
 {
        int ret = 0;
-       struct eeh_dev *edev;
-       const u32 *reg;
        int config_addr;
 
-       edev = of_node_to_eeh_dev(dn);
-
        /*
         * When we're enabling or disabling EEH functioality on
         * the particular PE, the PE config address is possibly
@@ -159,15 +249,11 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
        switch (option) {
        case EEH_OPT_DISABLE:
        case EEH_OPT_ENABLE:
-               reg = of_get_property(dn, "reg", NULL);
-               config_addr = reg[0];
-               break;
-
        case EEH_OPT_THAW_MMIO:
        case EEH_OPT_THAW_DMA:
-               config_addr = edev->config_addr;
-               if (edev->pe_config_addr)
-                       config_addr = edev->pe_config_addr;
+               config_addr = pe->config_addr;
+               if (pe->addr)
+                       config_addr = pe->addr;
                break;
 
        default:
@@ -177,15 +263,15 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
        }
 
        ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-                       config_addr, BUID_HI(edev->phb->buid),
-                       BUID_LO(edev->phb->buid), option);
+                       config_addr, BUID_HI(pe->phb->buid),
+                       BUID_LO(pe->phb->buid), option);
 
        return ret;
 }
 
 /**
  * pseries_eeh_get_pe_addr - Retrieve PE address
- * @dn: device node
+ * @pe: EEH PE
  *
  * Retrieve the assocated PE address. Actually, there're 2 RTAS
  * function calls dedicated for the purpose. We need implement
@@ -196,14 +282,11 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
  * It's notable that zero'ed return value means invalid PE config
  * address.
  */
-static int pseries_eeh_get_pe_addr(struct device_node *dn)
+static int pseries_eeh_get_pe_addr(struct eeh_pe *pe)
 {
-       struct eeh_dev *edev;
        int ret = 0;
        int rets[3];
 
-       edev = of_node_to_eeh_dev(dn);
-
        if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
                /*
                 * First of all, we need to make sure there has one PE
@@ -211,18 +294,18 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
                 * meaningless.
                 */
                ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
-                               edev->config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid), 1);
+                               pe->config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid), 1);
                if (ret || (rets[0] == 0))
                        return 0;
 
                /* Retrieve the associated PE config address */
                ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
-                               edev->config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid), 0);
+                               pe->config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid), 0);
                if (ret) {
-                       pr_warning("%s: Failed to get PE address for %s\n",
-                               __func__, dn->full_name);
+                       pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+                               __func__, pe->phb->global_number, pe->config_addr);
                        return 0;
                }
 
@@ -231,11 +314,11 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
 
        if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
                ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets,
-                               edev->config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid), 0);
+                               pe->config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid), 0);
                if (ret) {
-                       pr_warning("%s: Failed to get PE address for %s\n",
-                               __func__, dn->full_name);
+                       pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+                               __func__, pe->phb->global_number, pe->config_addr);
                        return 0;
                }
 
@@ -247,7 +330,7 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
 
 /**
  * pseries_eeh_get_state - Retrieve PE state
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @state: return value
  *
  * Retrieve the state of the specified PE. On RTAS compliant
@@ -258,30 +341,28 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
  * RTAS calls for the purpose, we need to try the new one and back
  * to the old one if the new one couldn't work properly.
  */
-static int pseries_eeh_get_state(struct device_node *dn, int *state)
+static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
 {
-       struct eeh_dev *edev;
        int config_addr;
        int ret;
        int rets[4];
        int result;
 
        /* Figure out PE config address if possible */
-       edev = of_node_to_eeh_dev(dn);
-       config_addr = edev->config_addr;
-       if (edev->pe_config_addr)
-               config_addr = edev->pe_config_addr;
+       config_addr = pe->config_addr;
+       if (pe->addr)
+               config_addr = pe->addr;
 
        if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
                ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets,
-                               config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid));
+                               config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid));
        } else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) {
                /* Fake PE unavailable info */
                rets[2] = 0;
                ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
-                               config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid));
+                               config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid));
        } else {
                return EEH_STATE_NOT_SUPPORT;
        }
@@ -333,34 +414,32 @@ static int pseries_eeh_get_state(struct device_node *dn, int *state)
 
 /**
  * pseries_eeh_reset - Reset the specified PE
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @option: reset option
  *
  * Reset the specified PE
  */
-static int pseries_eeh_reset(struct device_node *dn, int option)
+static int pseries_eeh_reset(struct eeh_pe *pe, int option)
 {
-       struct eeh_dev *edev;
        int config_addr;
        int ret;
 
        /* Figure out PE address */
-       edev = of_node_to_eeh_dev(dn);
-       config_addr = edev->config_addr;
-       if (edev->pe_config_addr)
-               config_addr = edev->pe_config_addr;
+       config_addr = pe->config_addr;
+       if (pe->addr)
+               config_addr = pe->addr;
 
        /* Reset PE through RTAS call */
        ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-                       config_addr, BUID_HI(edev->phb->buid),
-                       BUID_LO(edev->phb->buid), option);
+                       config_addr, BUID_HI(pe->phb->buid),
+                       BUID_LO(pe->phb->buid), option);
 
        /* If fundamental-reset not supported, try hot-reset */
        if (option == EEH_RESET_FUNDAMENTAL &&
            ret == -8) {
                ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-                               config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid), EEH_RESET_HOT);
+                               config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid), EEH_RESET_HOT);
        }
 
        return ret;
@@ -368,13 +447,13 @@ static int pseries_eeh_reset(struct device_node *dn, int option)
 
 /**
  * pseries_eeh_wait_state - Wait for PE state
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @max_wait: maximal period in microsecond
  *
  * Wait for the state of associated PE. It might take some time
  * to retrieve the PE's state.
  */
-static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
+static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait)
 {
        int ret;
        int mwait;
@@ -391,7 +470,7 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
 #define EEH_STATE_MAX_WAIT_TIME        (300 * 1000)
 
        while (1) {
-               ret = pseries_eeh_get_state(dn, &mwait);
+               ret = pseries_eeh_get_state(pe, &mwait);
 
                /*
                 * If the PE's state is temporarily unavailable,
@@ -426,7 +505,7 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
 
 /**
  * pseries_eeh_get_log - Retrieve error log
- * @dn: device node
+ * @pe: EEH PE
  * @severity: temporary or permanent error log
  * @drv_log: driver log to be combined with retrieved error log
  * @len: length of driver log
@@ -435,24 +514,22 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
  * Actually, the error will be retrieved through the dedicated
  * RTAS call.
  */
-static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len)
+static int pseries_eeh_get_log(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len)
 {
-       struct eeh_dev *edev;
        int config_addr;
        unsigned long flags;
        int ret;
 
-       edev = of_node_to_eeh_dev(dn);
        spin_lock_irqsave(&slot_errbuf_lock, flags);
        memset(slot_errbuf, 0, eeh_error_buf_size);
 
        /* Figure out the PE address */
-       config_addr = edev->config_addr;
-       if (edev->pe_config_addr)
-               config_addr = edev->pe_config_addr;
+       config_addr = pe->config_addr;
+       if (pe->addr)
+               config_addr = pe->addr;
 
        ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
-                       BUID_HI(edev->phb->buid), BUID_LO(edev->phb->buid),
+                       BUID_HI(pe->phb->buid), BUID_LO(pe->phb->buid),
                        virt_to_phys(drv_log), len,
                        virt_to_phys(slot_errbuf), eeh_error_buf_size,
                        severity);
@@ -465,40 +542,38 @@ static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_l
 
 /**
  * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE
- * @dn: PE associated device node
+ * @pe: EEH PE
  *
  * The function will be called to reconfigure the bridges included
  * in the specified PE so that the mulfunctional PE would be recovered
  * again.
  */
-static int pseries_eeh_configure_bridge(struct device_node *dn)
+static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
 {
-       struct eeh_dev *edev;
        int config_addr;
        int ret;
 
        /* Figure out the PE address */
-       edev = of_node_to_eeh_dev(dn);
-       config_addr = edev->config_addr;
-       if (edev->pe_config_addr)
-               config_addr = edev->pe_config_addr;
+       config_addr = pe->config_addr;
+       if (pe->addr)
+               config_addr = pe->addr;
 
        /* Use new configure-pe function, if supported */
        if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
                ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
-                               config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid));
+                               config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid));
        } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
                ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-                               config_addr, BUID_HI(edev->phb->buid),
-                               BUID_LO(edev->phb->buid));
+                               config_addr, BUID_HI(pe->phb->buid),
+                               BUID_LO(pe->phb->buid));
        } else {
                return -EFAULT;
        }
 
        if (ret)
-               pr_warning("%s: Unable to configure bridge %d for %s\n",
-                       __func__, ret, dn->full_name);
+               pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+                       __func__, pe->phb->global_number, pe->addr, ret);
 
        return ret;
 }
@@ -542,6 +617,8 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size,
 static struct eeh_ops pseries_eeh_ops = {
        .name                   = "pseries",
        .init                   = pseries_eeh_init,
+       .of_probe               = pseries_eeh_of_probe,
+       .dev_probe              = NULL,
        .set_option             = pseries_eeh_set_option,
        .get_pe_addr            = pseries_eeh_get_pe_addr,
        .get_state              = pseries_eeh_get_state,
@@ -559,7 +636,21 @@ static struct eeh_ops pseries_eeh_ops = {
  * EEH initialization on pseries platform. This function should be
  * called before any EEH related functions.
  */
-int __init eeh_pseries_init(void)
+static int __init eeh_pseries_init(void)
 {
-       return eeh_ops_register(&pseries_eeh_ops);
+       int ret = -EINVAL;
+
+       if (!machine_is(pseries))
+               return ret;
+
+       ret = eeh_ops_register(&pseries_eeh_ops);
+       if (!ret)
+               pr_info("EEH: pSeries platform initialized\n");
+       else
+               pr_info("EEH: pSeries platform initialization failure (%d)\n",
+                       ret);
+
+       return ret;
 }
+
+early_initcall(eeh_pseries_init);
index 243b3510d70f7ae2e9e3a801eefd2440dd9366db..d37708360f2e472b68d226df3da5a372ecfd406e 100644 (file)
@@ -53,9 +53,6 @@ static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
 EEH_SHOW_ATTR(eeh_mode,            mode,            "0x%x");
 EEH_SHOW_ATTR(eeh_config_addr,     config_addr,     "0x%x");
 EEH_SHOW_ATTR(eeh_pe_config_addr,  pe_config_addr,  "0x%x");
-EEH_SHOW_ATTR(eeh_check_count,     check_count,     "%d"  );
-EEH_SHOW_ATTR(eeh_freeze_count,    freeze_count,    "%d"  );
-EEH_SHOW_ATTR(eeh_false_positives, false_positives, "%d"  );
 
 void eeh_sysfs_add_device(struct pci_dev *pdev)
 {
@@ -64,9 +61,6 @@ void eeh_sysfs_add_device(struct pci_dev *pdev)
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-       rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
-       rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
-       rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
 
        if (rc)
                printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
@@ -77,8 +71,5 @@ void eeh_sysfs_remove_device(struct pci_dev *pdev)
        device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
        device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
        device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-       device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
-       device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
-       device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
 }
 
index bca220f2873c5cb862d4a9785aef836bf02c4765..6153eea27ce7d39ea51fb4d1f210be2a1934bfdf 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/sched.h>       /* for show_stack */
 #include <linux/string.h>
@@ -41,7 +42,6 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
@@ -99,7 +99,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
 
        while (npages--) {
                /* can't move this out since we might cross MEMBLOCK boundary */
-               rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+               rpn = __pa(uaddr) >> TCE_SHIFT;
                *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
                uaddr += TCE_PAGE_SIZE;
@@ -148,7 +148,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
        int ret = 0;
        long tcenum_start = tcenum, npages_start = npages;
 
-       rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+       rpn = __pa(uaddr) >> TCE_SHIFT;
        proto_tce = TCE_PCI_READ;
        if (direction != DMA_TO_DEVICE)
                proto_tce |= TCE_PCI_WRITE;
@@ -217,7 +217,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                __get_cpu_var(tce_page) = tcep;
        }
 
-       rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+       rpn = __pa(uaddr) >> TCE_SHIFT;
        proto_tce = TCE_PCI_READ;
        if (direction != DMA_TO_DEVICE)
                proto_tce |= TCE_PCI_WRITE;
@@ -237,7 +237,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 
                rc = plpar_tce_put_indirect((u64)tbl->it_index,
                                            (u64)tcenum << 12,
-                                           (u64)virt_to_abs(tcep),
+                                           (u64)__pa(tcep),
                                            limit);
 
                npages -= limit;
@@ -441,7 +441,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
 
                rc = plpar_tce_put_indirect(liobn,
                                            dma_offset,
-                                           (u64)virt_to_abs(tcep),
+                                           (u64)__pa(tcep),
                                            limit);
 
                num_tce -= limit;
index 5f3ef876ded20e0f71da39c963bba0dd19ddb95d..0da39fed355aa25fc17e516cf52d66042ddcc0e4 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/mmu_context.h>
 #include <asm/iommu.h>
 #include <asm/tlbflush.h>
@@ -108,9 +107,9 @@ void vpa_init(int cpu)
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-                             unsigned long va, unsigned long pa,
-                             unsigned long rflags, unsigned long vflags,
-                             int psize, int ssize)
+                                    unsigned long vpn, unsigned long pa,
+                                    unsigned long rflags, unsigned long vflags,
+                                    int psize, int ssize)
 {
        unsigned long lpar_rc;
        unsigned long flags;
@@ -118,11 +117,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long hpte_v, hpte_r;
 
        if (!(vflags & HPTE_V_BOLTED))
-               pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
-                        "rflags=%lx, vflags=%lx, psize=%d)\n",
-                        hpte_group, va, pa, rflags, vflags, psize);
+               pr_devel("hpte_insert(group=%lx, vpn=%016lx, "
+                        "pa=%016lx, rflags=%lx, vflags=%lx, psize=%d)\n",
+                        hpte_group, vpn,  pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED))
@@ -226,22 +225,6 @@ static void pSeries_lpar_hptab_clear(void)
        }
 }
 
-/*
- * This computes the AVPN and B fields of the first dword of a HPTE,
- * for use when we want to match an existing PTE.  The bottom 7 bits
- * of the returned value are zero.
- */
-static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
-                                            int ssize)
-{
-       unsigned long v;
-
-       v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-       v <<= HPTE_V_AVPN_SHIFT;
-       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
-       return v;
-}
-
 /*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
@@ -250,14 +233,14 @@ static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
  */
 static long pSeries_lpar_hpte_updatepp(unsigned long slot,
                                       unsigned long newpp,
-                                      unsigned long va,
+                                      unsigned long vpn,
                                       int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        unsigned long flags = (newpp & 7) | H_AVPN;
        unsigned long want_v;
 
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
 
        pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
                 want_v, slot, flags, psize);
@@ -295,15 +278,15 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
        return dword0;
 }
 
-static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize)
+static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
 {
        unsigned long hash;
        unsigned long i;
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
 
        /* Bolted entries are always in the primary group */
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -323,12 +306,13 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
                                             unsigned long ea,
                                             int psize, int ssize)
 {
-       unsigned long lpar_rc, slot, vsid, va, flags;
+       unsigned long vpn;
+       unsigned long lpar_rc, slot, vsid, flags;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = pSeries_lpar_hpte_find(va, psize, ssize);
+       slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
        BUG_ON(slot == -1);
 
        flags = newpp & 7;
@@ -337,17 +321,17 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
        BUG_ON(lpar_rc != H_SUCCESS);
 }
 
-static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
        unsigned long lpar_rc;
        unsigned long dummy1, dummy2;
 
-       pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-                slot, va, psize, local);
+       pr_devel("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+                slot, vpn, psize, local);
 
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
        lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
        if (lpar_rc == H_NOT_FOUND)
                return;
@@ -358,15 +342,16 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 static void pSeries_lpar_hpte_removebolted(unsigned long ea,
                                           int psize, int ssize)
 {
-       unsigned long slot, vsid, va;
+       unsigned long vpn;
+       unsigned long slot, vsid;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = pSeries_lpar_hpte_find(va, psize, ssize);
+       slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
        BUG_ON(slot == -1);
 
-       pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
+       pSeries_lpar_hpte_invalidate(slot, vpn, psize, ssize, 0);
 }
 
 /* Flag bits for H_BULK_REMOVE */
@@ -382,12 +367,12 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
  */
 static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 {
+       unsigned long vpn;
        unsigned long i, pix, rc;
        unsigned long flags = 0;
        struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
        int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
        unsigned long param[9];
-       unsigned long va;
        unsigned long hash, index, shift, hidx, slot;
        real_pte_t pte;
        int psize, ssize;
@@ -399,21 +384,21 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
        ssize = batch->ssize;
        pix = 0;
        for (i = 0; i < number; i++) {
-               va = batch->vaddr[i];
+               vpn = batch->vpn[i];
                pte = batch->pte[i];
-               pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-                       hash = hpt_hash(va, shift, ssize);
+               pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+                       hash = hpt_hash(vpn, shift, ssize);
                        hidx = __rpte_to_hidx(pte, index);
                        if (hidx & _PTEIDX_SECONDARY)
                                hash = ~hash;
                        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                        slot += hidx & _PTEIDX_GROUP_IX;
                        if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
-                               pSeries_lpar_hpte_invalidate(slot, va, psize,
+                               pSeries_lpar_hpte_invalidate(slot, vpn, psize,
                                                             ssize, local);
                        } else {
                                param[pix] = HBR_REQUEST | HBR_AVPN | slot;
-                               param[pix+1] = hpte_encode_avpn(va, psize,
+                               param[pix+1] = hpte_encode_avpn(vpn, psize,
                                                                ssize);
                                pix += 2;
                                if (pix == 8) {
index 109fdb75578d780a6a1edf162e556be58570f085..d19f4977c83492e1174be5456e1d0ff7ee33ca33 100644 (file)
@@ -210,6 +210,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
 static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 {
        struct device_node *dn;
+       struct eeh_dev *edev;
 
        /* Found our PE and assume 8 at that point. */
 
@@ -217,7 +218,10 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
        if (!dn)
                return NULL;
 
-       dn = eeh_find_device_pe(dn);
+       /* Get the top level device in the PE */
+       edev = of_node_to_eeh_dev(dn);
+       edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+       dn = eeh_dev_to_of_node(edev);
        if (!dn)
                return NULL;
 
@@ -387,12 +391,13 @@ static int check_msix_entries(struct pci_dev *pdev)
        return 0;
 }
 
-static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
 {
        struct pci_dn *pdn;
        int hwirq, virq, i, rc;
        struct msi_desc *entry;
        struct msi_msg msg;
+       int nvec = nvec_in;
 
        pdn = get_pdn(pdev);
        if (!pdn)
@@ -401,11 +406,24 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
                return -EINVAL;
 
+       /*
+        * Firmware currently refuse any non power of two allocation
+        * so we round up if the quota will allow it.
+        */
+       if (type == PCI_CAP_ID_MSIX) {
+               int m = roundup_pow_of_two(nvec);
+               int quota = msi_quota_for_device(pdev, m);
+
+               if (quota >= m)
+                       nvec = m;
+       }
+
        /*
         * Try the new more explicit firmware interface, if that fails fall
         * back to the old interface. The old interface is known to never
         * return MSI-Xs.
         */
+again:
        if (type == PCI_CAP_ID_MSI) {
                rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
 
@@ -417,6 +435,10 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
 
        if (rc != nvec) {
+               if (nvec != nvec_in) {
+                       nvec = nvec_in;
+                       goto again;
+               }
                pr_debug("rtas_msi: rtas_change_msi() failed\n");
                return rc;
        }
index 2c6ded29f73d3d5afbcdef6bd9719d777da0cd12..56b864d777ee518f0cf921c7592c41fdcae8792f 100644 (file)
@@ -73,7 +73,7 @@ void __init pSeries_final_fixup(void)
 {
        pSeries_request_regions();
 
-       pci_addr_cache_build();
+       eeh_addr_cache_build();
 }
 
 /*
index 3ccebc83dc021a23dfdbf66e1cf0f8d80ff59eb1..261a577a3dd2db2d3e651648368ec72ef52628fd 100644 (file)
@@ -65,27 +65,43 @@ pcibios_find_pci_bus(struct device_node *dn)
 EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
- * pcibios_remove_pci_devices - remove all devices under this bus
+ * __pcibios_remove_pci_devices - remove all devices under this bus
+ * @bus: the indicated PCI bus
+ * @purge_pe: destroy the PE on removal of PCI devices
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
+ * By default, the corresponding PE will be destroied during the
+ * normal PCI hotplug path. For PCI hotplug during EEH recovery,
+ * the corresponding PE won't be destroied and deallocated.
  */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
+void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe)
 {
-       struct pci_dev *dev, *tmp;
+       struct pci_dev *dev, *tmp;
        struct pci_bus *child_bus;
 
        /* First go down child busses */
        list_for_each_entry(child_bus, &bus->children, node)
-               pcibios_remove_pci_devices(child_bus);
+               __pcibios_remove_pci_devices(child_bus, purge_pe);
 
        pr_debug("PCI: Removing devices on bus %04x:%02x\n",
-                pci_domain_nr(bus),  bus->number);
+               pci_domain_nr(bus),  bus->number);
        list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
                pr_debug("     * Removing %s...\n", pci_name(dev));
-               eeh_remove_bus_device(dev);
-               pci_stop_and_remove_bus_device(dev);
-       }
+               eeh_remove_bus_device(dev, purge_pe);
+               pci_stop_and_remove_bus_device(dev);
+       }
+}
+
+/**
+ * pcibios_remove_pci_devices - remove all devices under this bus
+ *
+ * Remove all of the PCI devices under this bus both from the
+ * linux pci device tree, and from the powerpc EEH address cache.
+ */
+void pcibios_remove_pci_devices(struct pci_bus *bus)
+{
+       __pcibios_remove_pci_devices(bus, 1);
 }
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
index 51ecac920dd8e4cb74e17a9086cb893ad57dc6d6..e3cb7ae616587c4fa6239683e409fc38fce9328d 100644 (file)
@@ -388,10 +388,8 @@ static void __init pSeries_setup_arch(void)
 
        /* Find and initialize PCI host bridges */
        init_pci_config_tokens();
-       eeh_pseries_init();
        find_and_init_phbs();
        pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
-       eeh_init();
 
        pSeries_nvram_init();
 
@@ -416,16 +414,20 @@ static int __init pSeries_init_panel(void)
 }
 machine_arch_initcall(pseries, pSeries_init_panel);
 
-static int pseries_set_dabr(unsigned long dabr)
+static int pseries_set_dabr(unsigned long dabr, unsigned long dabrx)
 {
        return plpar_hcall_norets(H_SET_DABR, dabr);
 }
 
-static int pseries_set_xdabr(unsigned long dabr)
+static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx)
 {
-       /* We want to catch accesses from kernel and userspace */
-       return plpar_hcall_norets(H_SET_XDABR, dabr,
-                       H_DABRX_KERNEL | H_DABRX_USER);
+       /* Have to set at least one bit in the DABRX according to PAPR */
+       if (dabrx == 0 && dabr == 0)
+               dabrx = DABRX_USER;
+       /* PAPR says we can only set kernel and user bits */
+       dabrx &= DABRX_KERNEL | DABRX_USER;
+
+       return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx);
 }
 
 #define CMO_CHARACTERISTICS_TOKEN 44
@@ -529,10 +531,10 @@ static void __init pSeries_init_early(void)
        if (firmware_has_feature(FW_FEATURE_LPAR))
                hvc_vio_init_early();
 #endif
-       if (firmware_has_feature(FW_FEATURE_DABR))
-               ppc_md.set_dabr = pseries_set_dabr;
-       else if (firmware_has_feature(FW_FEATURE_XDABR))
+       if (firmware_has_feature(FW_FEATURE_XDABR))
                ppc_md.set_dabr = pseries_set_xdabr;
+       else if (firmware_has_feature(FW_FEATURE_DABR))
+               ppc_md.set_dabr = pseries_set_dabr;
 
        pSeries_cmo_feature_init();
        iommu_init_early_pSeries();
index 1bd7ecb246207e8235d6d71dcb4cce3d2d418259..a57600b3a4e3667534c5dc7eb5cd2a188edd8425 100644 (file)
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)  += dcr-low.o
 obj-$(CONFIG_PPC_PMI)          += pmi.o
 obj-$(CONFIG_U3_DART)          += dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)       += mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)          += fsl_soc.o
+obj-$(CONFIG_FSL_SOC)          += fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)          += fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)          += fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
index 4f2680f431b5070fa26aeecacb73edc0345fe453..bd968a43a48b29047fa5f2d9d8cd1fe9ceb66b69 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/cacheflush.h>
 #include <asm/ppc-pci.h>
 
@@ -74,11 +73,16 @@ static int dart_is_u4;
 
 #define DBG(...)
 
+static DEFINE_SPINLOCK(invalidate_lock);
+
 static inline void dart_tlb_invalidate_all(void)
 {
        unsigned long l = 0;
        unsigned int reg, inv_bit;
        unsigned long limit;
+       unsigned long flags;
+
+       spin_lock_irqsave(&invalidate_lock, flags);
 
        DBG("dart: flush\n");
 
@@ -111,12 +115,17 @@ retry:
                        panic("DART: TLB did not flush after waiting a long "
                              "time. Buggy U3 ?");
        }
+
+       spin_unlock_irqrestore(&invalidate_lock, flags);
 }
 
 static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
 {
        unsigned int reg;
        unsigned int l, limit;
+       unsigned long flags;
+
+       spin_lock_irqsave(&invalidate_lock, flags);
 
        reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE |
                (bus_rpn & DART_CNTL_U4_IONE_MASK);
@@ -138,6 +147,8 @@ wait_more:
                        panic("DART: TLB did not flush after waiting a long "
                              "time. Buggy U4 ?");
        }
+
+       spin_unlock_irqrestore(&invalidate_lock, flags);
 }
 
 static void dart_flush(struct iommu_table *tbl)
@@ -167,7 +178,7 @@ static int dart_build(struct iommu_table *tbl, long index,
         */
        l = npages;
        while (l--) {
-               rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
+               rpn = __pa(uaddr) >> DART_PAGE_SHIFT;
 
                *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
 
@@ -244,7 +255,7 @@ static int __init dart_init(struct device_node *dart_node)
                panic("DART: Cannot map registers!");
 
        /* Map in DART table */
-       dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+       dart_vbase = ioremap(__pa(dart_tablebase), dart_tablesize);
 
        /* Fill initial table */
        for (i = 0; i < dart_tablesize/4; i++)
@@ -463,7 +474,7 @@ void __init alloc_dart_table(void)
         * will blow up an entire large page anyway in the kernel mapping
         */
        dart_tablebase = (unsigned long)
-               abs_to_virt(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+               __va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
 
        printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
 }
index 68ac3aacb1919477ed4686f859979d9bc17c7b15..d131c8a1cb15908a955147ae9d4eee3bfa5b3eb4 100644 (file)
@@ -193,6 +193,16 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
        {
                .compatible = "fsl,mpc8548-l2-cache-controller",
        },
+       {       .compatible = "fsl,mpc8544-l2-cache-controller",},
+       {       .compatible = "fsl,mpc8572-l2-cache-controller",},
+       {       .compatible = "fsl,mpc8536-l2-cache-controller",},
+       {       .compatible = "fsl,p1021-l2-cache-controller",},
+       {       .compatible = "fsl,p1012-l2-cache-controller",},
+       {       .compatible = "fsl,p1025-l2-cache-controller",},
+       {       .compatible = "fsl,p1016-l2-cache-controller",},
+       {       .compatible = "fsl,p1024-l2-cache-controller",},
+       {       .compatible = "fsl,p1015-l2-cache-controller",},
+       {       .compatible = "fsl,p1010-l2-cache-controller",},
        {},
 };
 
index b31f19f61031e4a92b80a7b3afb1f6ee903f25a0..097cc9d2585b8341068cbed9699128599dd978ec 100644 (file)
@@ -244,12 +244,6 @@ static int __devinit fsl_ifc_ctrl_probe(struct platform_device *dev)
        /* get the nand machine irq */
        fsl_ifc_ctrl_dev->nand_irq =
                        irq_of_parse_and_map(dev->dev.of_node, 1);
-       if (fsl_ifc_ctrl_dev->nand_irq == NO_IRQ) {
-               dev_err(&dev->dev, "failed to get irq resource "
-                                               "for NAND Machine\n");
-               ret = -ENODEV;
-               goto err;
-       }
 
        fsl_ifc_ctrl_dev->dev = &dev->dev;
 
@@ -267,12 +261,14 @@ static int __devinit fsl_ifc_ctrl_probe(struct platform_device *dev)
                goto err_irq;
        }
 
-       ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq, 0,
-                         "fsl-ifc-nand", fsl_ifc_ctrl_dev);
-       if (ret != 0) {
-               dev_err(&dev->dev, "failed to install irq (%d)\n",
-                       fsl_ifc_ctrl_dev->nand_irq);
-               goto err_nandirq;
+       if (fsl_ifc_ctrl_dev->nand_irq) {
+               ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
+                               0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
+               if (ret != 0) {
+                       dev_err(&dev->dev, "failed to install irq (%d)\n",
+                               fsl_ifc_ctrl_dev->nand_irq);
+                       goto err_nandirq;
+               }
        }
 
        return 0;
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c b/arch/powerpc/sysdev/fsl_mpic_err.c
new file mode 100644 (file)
index 0000000..b83f325
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.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 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE      0x3900
+#define MPIC_ERR_INT_EISR      0x0000
+#define MPIC_ERR_INT_EIMR      0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int err_reg)
+{
+       return in_be32(base + (err_reg >> 2));
+}
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value)
+{
+       out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value);
+}
+
+static void fsl_mpic_mask_err(struct irq_data *d)
+{
+       u32 eimr;
+       struct mpic *mpic = irq_data_get_irq_chip_data(d);
+       unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+       eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+       eimr |= (1 << (31 - src));
+       mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static void fsl_mpic_unmask_err(struct irq_data *d)
+{
+       u32 eimr;
+       struct mpic *mpic = irq_data_get_irq_chip_data(d);
+       unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+       eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+       eimr &= ~(1 << (31 - src));
+       mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static struct irq_chip fsl_mpic_err_chip = {
+       .irq_disable    = fsl_mpic_mask_err,
+       .irq_mask       = fsl_mpic_mask_err,
+       .irq_unmask     = fsl_mpic_unmask_err,
+};
+
+int mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+       int i;
+
+       mpic->err_regs = ioremap(mpic->paddr + MPIC_ERR_INT_BASE, 0x1000);
+       if (!mpic->err_regs) {
+               pr_err("could not map mpic error registers\n");
+               return -ENOMEM;
+       }
+       mpic->hc_err = fsl_mpic_err_chip;
+       mpic->hc_err.name = mpic->name;
+       mpic->flags |= MPIC_FSL_HAS_EIMR;
+       /* allocate interrupt vectors for error interrupts */
+       for (i = MPIC_MAX_ERR - 1; i >= 0; i--)
+               mpic->err_int_vecs[i] = --intvec;
+
+       return 0;
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+       if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+           (hw >= mpic->err_int_vecs[0] &&
+            hw <= mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+               WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+               pr_debug("mpic: mapping as Error Interrupt\n");
+               irq_set_chip_data(virq, mpic);
+               irq_set_chip_and_handler(virq, &mpic->hc_err,
+                                        handle_level_irq);
+               return 1;
+       }
+
+       return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data)
+{
+       struct mpic *mpic = (struct mpic *) data;
+       u32 eisr, eimr;
+       int errint;
+       unsigned int cascade_irq;
+
+       eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+       eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+       if (!(eisr & ~eimr))
+               return IRQ_NONE;
+
+       while (eisr) {
+               errint = __builtin_clz(eisr);
+               cascade_irq = irq_linear_revmap(mpic->irqhost,
+                                mpic->err_int_vecs[errint]);
+               WARN_ON(cascade_irq == NO_IRQ);
+               if (cascade_irq != NO_IRQ) {
+                       generic_handle_irq(cascade_irq);
+               } else {
+                       eimr |=  1 << (31 - errint);
+                       mpic_fsl_err_write(mpic->err_regs, eimr);
+               }
+               eisr &= ~(1 << (31 - errint));
+       }
+
+       return IRQ_HANDLED;
+}
+
+void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+       unsigned int virq;
+       int ret;
+
+       virq = irq_create_mapping(mpic->irqhost, irqnum);
+       if (virq == NO_IRQ) {
+               pr_err("Error interrupt setup failed\n");
+               return;
+       }
+
+       /* Mask all error interrupts */
+       mpic_fsl_err_write(mpic->err_regs, ~0);
+
+       ret = request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+                   "mpic-error-int", mpic);
+       if (ret)
+               pr_err("Failed to register error interrupt handler\n");
+}
index c37f46136321272465327a106383fb440e48fa75..ffb93ae9379b1bb282ca2e99db53049974e81d95 100644 (file)
@@ -38,15 +38,15 @@ static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
 static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev)
 {
-       u8 progif;
+       u8 hdr_type;
 
        /* if we aren't a PCIe don't bother */
        if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
                return;
 
        /* if we aren't in host mode don't bother */
-       pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
-       if (progif & 0x1)
+       pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);
+       if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
                return;
 
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
@@ -143,18 +143,20 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
        pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
                 (u64)rsrc->start, (u64)resource_size(rsrc));
 
-       if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
-               win_idx = 2;
-               start_idx = 0;
-               end_idx = 3;
-       }
-
        pci = ioremap(rsrc->start, resource_size(rsrc));
        if (!pci) {
            dev_err(hose->parent, "Unable to map ATMU registers\n");
            return;
        }
 
+       if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+               if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
+                       win_idx = 2;
+                       start_idx = 0;
+                       end_idx = 3;
+               }
+       }
+
        /* Disable all windows (except powar0 since it's ignored) */
        for(i = 1; i < 5; i++)
                out_be32(&pci->pow[i].powar, 0);
@@ -425,7 +427,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
        struct pci_controller *hose;
        struct resource rsrc;
        const int *bus_range;
-       u8 progif;
+       u8 hdr_type, progif;
 
        if (!of_device_is_available(dev)) {
                pr_warning("%s: disabled\n", dev->full_name);
@@ -457,15 +459,17 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
        setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
                PPC_INDIRECT_TYPE_BIG_ENDIAN);
 
-       early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
-       if ((progif & 1) == 1) {
-               /* unmap cfg_data & cfg_addr separately if not on same page */
-               if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
-                   ((unsigned long)hose->cfg_addr & PAGE_MASK))
-                       iounmap(hose->cfg_data);
-               iounmap(hose->cfg_addr);
-               pcibios_free_controller(hose);
-               return -ENODEV;
+       if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+               /* For PCIE read HEADER_TYPE to identify controler mode */
+               early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
+               if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
+                       goto no_bridge;
+
+       } else {
+               /* For PCI read PROG to identify controller mode */
+               early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
+               if ((progif & 1) == 1)
+                       goto no_bridge;
        }
 
        setup_pci_cmd(hose);
@@ -494,6 +498,15 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
        setup_pci_atmu(hose, &rsrc);
 
        return 0;
+
+no_bridge:
+       /* unmap cfg_data & cfg_addr separately if not on same page */
+       if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
+           ((unsigned long)hose->cfg_addr & PAGE_MASK))
+               iounmap(hose->cfg_data);
+       iounmap(hose->cfg_addr);
+       pcibios_free_controller(hose);
+       return -ENODEV;
 }
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
@@ -818,6 +831,7 @@ static const struct of_device_id pci_ids[] = {
        { .compatible = "fsl,p1010-pcie", },
        { .compatible = "fsl,p1023-pcie", },
        { .compatible = "fsl,p4080-pcie", },
+       { .compatible = "fsl,qoriq-pcie-v2.4", },
        { .compatible = "fsl,qoriq-pcie-v2.3", },
        { .compatible = "fsl,qoriq-pcie-v2.2", },
        {},
@@ -825,57 +839,80 @@ static const struct of_device_id pci_ids[] = {
 
 struct device_node *fsl_pci_primary;
 
-void __devinit fsl_pci_init(void)
+void fsl_pci_assign_primary(void)
 {
-       int ret;
-       struct device_node *node;
-       struct pci_controller *hose;
-       dma_addr_t max = 0xffffffff;
+       struct device_node *np;
 
        /* Callers can specify the primary bus using other means. */
-       if (!fsl_pci_primary) {
-               /* If a PCI host bridge contains an ISA node, it's primary. */
-               node = of_find_node_by_type(NULL, "isa");
-               while ((fsl_pci_primary = of_get_parent(node))) {
-                       of_node_put(node);
-                       node = fsl_pci_primary;
-
-                       if (of_match_node(pci_ids, node))
-                               break;
-               }
+       if (fsl_pci_primary)
+               return;
+
+       /* If a PCI host bridge contains an ISA node, it's primary. */
+       np = of_find_node_by_type(NULL, "isa");
+       while ((fsl_pci_primary = of_get_parent(np))) {
+               of_node_put(np);
+               np = fsl_pci_primary;
+
+               if (of_match_node(pci_ids, np) && of_device_is_available(np))
+                       return;
        }
 
-       node = NULL;
-       for_each_node_by_type(node, "pci") {
-               if (of_match_node(pci_ids, node)) {
-                       /*
-                        * If there's no PCI host bridge with ISA, arbitrarily
-                        * designate one as primary.  This can go away once
-                        * various bugs with primary-less systems are fixed.
-                        */
-                       if (!fsl_pci_primary)
-                               fsl_pci_primary = node;
-
-                       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);
-                       }
+       /*
+        * If there's no PCI host bridge with ISA, arbitrarily
+        * designate one as primary.  This can go away once
+        * various bugs with primary-less systems are fixed.
+        */
+       for_each_matching_node(np, pci_ids) {
+               if (of_device_is_available(np)) {
+                       fsl_pci_primary = np;
+                       of_node_put(np);
+                       return;
                }
        }
+}
 
+static int __devinit fsl_pci_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct device_node *node;
 #ifdef CONFIG_SWIOTLB
-       /*
-        * if we couldn't map all of DRAM via the dma windows
-        * we need SWIOTLB to handle buffers located outside of
-        * dma capable memory region
-        */
-       if (memblock_end_of_DRAM() - 1 > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+       struct pci_controller *hose;
+#endif
+
+       node = pdev->dev.of_node;
+       ret = fsl_add_bridge(node, fsl_pci_primary == node);
+
+#ifdef CONFIG_SWIOTLB
+       if (ret == 0) {
+               hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+
+               /*
+                * if we couldn't map all of DRAM via the dma windows
+                * we need SWIOTLB to handle buffers located outside of
+                * dma capable memory region
+                */
+               if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
+                               hose->dma_window_size)
+                       ppc_swiotlb_enable = 1;
        }
 #endif
+
+       mpc85xx_pci_err_probe(pdev);
+
+       return 0;
+}
+
+static struct platform_driver fsl_pci_driver = {
+       .driver = {
+               .name = "fsl-pci",
+               .of_match_table = pci_ids,
+       },
+       .probe = fsl_pci_probe,
+};
+
+static int __init fsl_pci_init(void)
+{
+       return platform_driver_register(&fsl_pci_driver);
 }
+arch_initcall(fsl_pci_init);
 #endif
index baa0fd18289fa294d4187b853355ce8616fe4b1e..d078537adece3e2d59e59691ef8bf64620d11fcb 100644 (file)
@@ -16,6 +16,7 @@
 
 #define PCIE_LTSSM     0x0404          /* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0  0x16            /* L0 state */
+#define PCIE_IP_REV_2_2                0x02080202 /* PCIE IP block version Rev2.2 */
 #define PIWAR_EN               0x80000000      /* Enable */
 #define PIWAR_PF               0x20000000      /* prefetch */
 #define PIWAR_TGI_LOCAL                0x00f00000      /* target - local memory */
@@ -57,7 +58,9 @@ struct ccsr_pci {
        __be32  pex_pme_mes_disr;       /* 0x.024 - PCIE PME and message disable register */
        __be32  pex_pme_mes_ier;        /* 0x.028 - PCIE PME and message interrupt enable register */
        __be32  pex_pmcr;               /* 0x.02c - PCIE power management command register */
-       u8      res3[3024];
+       u8      res3[3016];
+       __be32  block_rev1;     /* 0x.bf8 - PCIE Block Revision register 1 */
+       __be32  block_rev2;     /* 0x.bfc - PCIE Block Revision register 2 */
 
 /* PCI/PCI Express outbound window 0-4
  * Window 0 is the default window and is the only window enabled upon reset.
@@ -95,10 +98,19 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
 extern struct device_node *fsl_pci_primary;
 
-#ifdef CONFIG_FSL_PCI
-void fsl_pci_init(void);
+#ifdef CONFIG_PCI
+void fsl_pci_assign_primary(void);
 #else
-static inline void fsl_pci_init(void) {}
+static inline void fsl_pci_assign_primary(void) {}
+#endif
+
+#ifdef CONFIG_EDAC_MPC85XX
+int mpc85xx_pci_err_probe(struct platform_device *op);
+#else
+static inline int mpc85xx_pci_err_probe(struct platform_device *op)
+{
+       return -ENOTSUPP;
+}
 #endif
 
 #endif /* __POWERPC_FSL_PCI_H */
index bfc6211e5422ef17b6e0bb0d24b926fa653354d9..9c6e535daad27b676422ea0813f27d322c576452 100644 (file)
@@ -6,7 +6,7 @@
  *  with various broken implementations of this HW.
  *
  *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
- *  Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *  Copyright 2010-2012 Freescale Semiconductor, Inc.
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License.  See the file COPYING in the main directory of this archive
@@ -221,24 +221,24 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
        _mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
 }
 
-static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
+static inline unsigned int mpic_tm_offset(struct mpic *mpic, unsigned int tm)
 {
-       unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
-                             ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
+       return (tm >> 2) * MPIC_TIMER_GROUP_STRIDE +
+              (tm & 3) * MPIC_INFO(TIMER_STRIDE);
+}
 
-       if (tm >= 4)
-               offset += 0x1000 / 4;
+static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
+{
+       unsigned int offset = mpic_tm_offset(mpic, tm) +
+                             MPIC_INFO(TIMER_VECTOR_PRI);
 
        return _mpic_read(mpic->reg_type, &mpic->tmregs, offset);
 }
 
 static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value)
 {
-       unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
-                             ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
-
-       if (tm >= 4)
-               offset += 0x1000 / 4;
+       unsigned int offset = mpic_tm_offset(mpic, tm) +
+                             MPIC_INFO(TIMER_VECTOR_PRI);
 
        _mpic_write(mpic->reg_type, &mpic->tmregs, offset, value);
 }
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
                return 0;
        }
 
+       if (mpic_map_error_int(mpic, virq, hw))
+               return 0;
+
        if (hw >= mpic->num_sources)
                return -EINVAL;
 
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,
                 */
                switch (intspec[2]) {
                case 0:
-               case 1: /* no EISR/EIMR support for now, treat as shared IRQ */
+                       break;
+               case 1:
+                       if (!(mpic->flags & MPIC_FSL_HAS_EIMR))
+                               break;
+
+                       if (intspec[3] >= ARRAY_SIZE(mpic->err_int_vecs))
+                               return -EINVAL;
+
+                       *out_hwirq = mpic->err_int_vecs[intspec[3]];
+
                        break;
                case 2:
                        if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
@@ -1301,6 +1313,42 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
        mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
+       if (mpic->flags & MPIC_FSL) {
+               u32 brr1, version;
+               int ret;
+
+               /*
+                * Yes, Freescale really did put global registers in the
+                * magic per-cpu area -- and they don't even show up in the
+                * non-magic per-cpu copies that this driver normally uses.
+                */
+               mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
+                        MPIC_CPU_THISBASE, 0x1000);
+
+               brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+                               MPIC_FSL_BRR1);
+               version = brr1 & MPIC_FSL_BRR1_VER;
+
+               /* Error interrupt mask register (EIMR) is required for
+                * handling individual device error interrupts. EIMR
+                * was added in MPIC version 4.1.
+                *
+                * Over here we reserve vector number space for error
+                * interrupt vectors. This space is stolen from the
+                * global vector number space, as in case of ipis
+                * and timer interrupts.
+                *
+                * Available vector space = intvec_top - 12, where 12
+                * is the number of vectors which have been consumed by
+                * ipis and timer interrupts.
+                */
+               if (version >= 0x401) {
+                       ret = mpic_setup_error_int(mpic, intvec_top - 12);
+                       if (ret)
+                               return NULL;
+               }
+       }
+
        /* Reset */
 
        /* When using a device-node, reset requests are only honored if the MPIC
@@ -1440,6 +1488,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
 void __init mpic_init(struct mpic *mpic)
 {
        int i, cpu;
+       int num_timers = 4;
 
        BUG_ON(mpic->num_sources == 0);
 
@@ -1448,15 +1497,34 @@ void __init mpic_init(struct mpic *mpic)
        /* Set current processor priority to max */
        mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
 
+       if (mpic->flags & MPIC_FSL) {
+               u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+                                     MPIC_FSL_BRR1);
+               u32 version = brr1 & MPIC_FSL_BRR1_VER;
+
+               /*
+                * Timer group B is present at the latest in MPIC 3.1 (e.g.
+                * mpc8536).  It is not present in MPIC 2.0 (e.g. mpc8544).
+                * I don't know about the status of intermediate versions (or
+                * whether they even exist).
+                */
+               if (version >= 0x0301)
+                       num_timers = 8;
+       }
+
+       /* FSL mpic error interrupt intialization */
+       if (mpic->flags & MPIC_FSL_HAS_EIMR)
+               mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
+
        /* Initialize timers to our reserved vectors and mask them for now */
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < num_timers; i++) {
+               unsigned int offset = mpic_tm_offset(mpic, i);
+
                mpic_write(mpic->tmregs,
-                          i * MPIC_INFO(TIMER_STRIDE) +
-                          MPIC_INFO(TIMER_DESTINATION),
+                          offset + MPIC_INFO(TIMER_DESTINATION),
                           1 << hard_smp_processor_id());
                mpic_write(mpic->tmregs,
-                          i * MPIC_INFO(TIMER_STRIDE) +
-                          MPIC_INFO(TIMER_VECTOR_PRI),
+                          offset + MPIC_INFO(TIMER_VECTOR_PRI),
                           MPIC_VECPRI_MASK |
                           (9 << MPIC_VECPRI_PRIORITY_SHIFT) |
                           (mpic->timer_vecs[0] + i));
index 13f3e8913a932951061743e0884d203e16e73e0f..24bf07a63924e3c28745b6ab3eb264dbf93975bd 100644 (file)
@@ -40,4 +40,26 @@ extern int mpic_set_affinity(struct irq_data *d,
                             const struct cpumask *cpumask, bool force);
 extern void mpic_reset_core(int cpu);
 
+#ifdef CONFIG_FSL_SOC
+extern int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw);
+extern void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum);
+extern int mpic_setup_error_int(struct mpic *mpic, int intvec);
+#else
+static inline int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+       return 0;
+}
+
+
+static inline void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+       return;
+}
+
+static inline int mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+       return -1;
+}
+#endif
+
 #endif /* _POWERPC_SYSDEV_MPIC_H */
index 9b49c65ee7a42f6f9d0b8dc436628c34bafb262b..3a56a639a92e88962a0b7c1274e9d8330d6e218e 100644 (file)
@@ -60,6 +60,8 @@ static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long xmon_taken = 1;
 static int xmon_owner;
 static int xmon_gate;
+#else
+#define xmon_owner 0
 #endif /* CONFIG_SMP */
 
 static unsigned long in_xmon __read_mostly = 0;
@@ -202,7 +204,13 @@ Commands:\n\
   di   dump instructions\n\
   df   dump float values\n\
   dd   dump double values\n\
-  dl    dump the kernel log buffer\n\
+  dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC64
+  "\
+  dp[#]        dump paca for current cpu, or cpu #\n\
+  dpa  dump paca for all possible cpus\n"
+#endif
+  "\
   dr   dump stream of raw bytes\n\
   e    print exception information\n\
   f    flush cache\n\
@@ -740,7 +748,7 @@ static void insert_bpts(void)
 static void insert_cpu_bpts(void)
 {
        if (dabr.enabled)
-               set_dabr(dabr.address | (dabr.enabled & 7));
+               set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL);
        if (iabr && cpu_has_feature(CPU_FTR_IABR))
                mtspr(SPRN_IABR, iabr->address
                         | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -768,7 +776,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-       set_dabr(0);
+       set_dabr(0, 0);
        if (cpu_has_feature(CPU_FTR_IABR))
                mtspr(SPRN_IABR, 0);
 }
@@ -2009,6 +2017,95 @@ static void xmon_rawdump (unsigned long adrs, long ndump)
        printf("\n");
 }
 
+#ifdef CONFIG_PPC64
+static void dump_one_paca(int cpu)
+{
+       struct paca_struct *p;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       p = &paca[cpu];
+
+       printf("paca for cpu 0x%x @ %p:\n", cpu, p);
+
+       printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
+
+#define DUMP(paca, name, format) \
+       printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
+               offsetof(struct paca_struct, name));
+
+       DUMP(p, lock_token, "x");
+       DUMP(p, paca_index, "x");
+       DUMP(p, kernel_toc, "lx");
+       DUMP(p, kernelbase, "lx");
+       DUMP(p, kernel_msr, "lx");
+#ifdef CONFIG_PPC_STD_MMU_64
+       DUMP(p, stab_real, "lx");
+       DUMP(p, stab_addr, "lx");
+#endif
+       DUMP(p, emergency_sp, "p");
+       DUMP(p, data_offset, "lx");
+       DUMP(p, hw_cpu_id, "x");
+       DUMP(p, cpu_start, "x");
+       DUMP(p, kexec_state, "x");
+       DUMP(p, __current, "p");
+       DUMP(p, kstack, "lx");
+       DUMP(p, stab_rr, "lx");
+       DUMP(p, saved_r1, "lx");
+       DUMP(p, trap_save, "x");
+       DUMP(p, soft_enabled, "x");
+       DUMP(p, irq_happened, "x");
+       DUMP(p, io_sync, "x");
+       DUMP(p, irq_work_pending, "x");
+       DUMP(p, nap_state_lost, "x");
+
+#undef DUMP
+
+       catch_memory_errors = 0;
+       sync();
+}
+
+static void dump_all_pacas(void)
+{
+       int cpu;
+
+       if (num_possible_cpus() == 0) {
+               printf("No possible cpus, use 'dp #' to dump individual cpus\n");
+               return;
+       }
+
+       for_each_possible_cpu(cpu)
+               dump_one_paca(cpu);
+}
+
+static void dump_pacas(void)
+{
+       unsigned long num;
+       int c;
+
+       c = inchar();
+       if (c == 'a') {
+               dump_all_pacas();
+               return;
+       }
+
+       termch = c;     /* Put c back, it wasn't 'a' */
+
+       if (scanhex(&num))
+               dump_one_paca(num);
+       else
+               dump_one_paca(xmon_owner);
+}
+#endif
+
 #define isxdigit(c)    (('0' <= (c) && (c) <= '9') \
                         || ('a' <= (c) && (c) <= 'f') \
                         || ('A' <= (c) && (c) <= 'F'))
@@ -2018,6 +2115,14 @@ dump(void)
        int c;
 
        c = inchar();
+
+#ifdef CONFIG_PPC64
+       if (c == 'p') {
+               dump_pacas();
+               return;
+       }
+#endif
+
        if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
                termch = c;
        scanhex((void *)&adrs);
index f9acddd9ace399e66a3d787129dc41f63c6d60af..c8af429991d98748ec8dbc635d461885ab32eee7 100644 (file)
@@ -656,7 +656,6 @@ config S390_GUEST
        depends on 64BIT && EXPERIMENTAL
        select VIRTUALIZATION
        select VIRTIO
-       select VIRTIO_RING
        select VIRTIO_CONSOLE
        help
          Enabling this option adds support for virtio based paravirtual device
index 234f1d859cea07c4f0cd31be401448fc8fe0870e..a34a9d612fc0f2d4ecc9a4bfbcef2794fba7de41 100644 (file)
@@ -65,6 +65,7 @@ typedef s64           compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64            compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -144,6 +145,79 @@ typedef u32                compat_old_sigset_t;    /* at least 32 bits */
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+       int     si_signo;
+       int     si_errno;
+       int     si_code;
+
+       union {
+               int _pad[128/sizeof(int) - 3];
+
+               /* kill() */
+               struct {
+                       pid_t   _pid;   /* sender's pid */
+                       uid_t   _uid;   /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;            /* timer id */
+                       int _overrun;                   /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       pid_t                   _pid;   /* sender's pid */
+                       uid_t                   _uid;   /* sender's uid */
+                       compat_sigval_t         _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       pid_t                   _pid;   /* which child */
+                       uid_t                   _uid;   /* sender's uid */
+                       int                     _status;/* exit code */
+                       compat_clock_t          _utime;
+                       compat_clock_t          _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       __u32   _addr;  /* faulting insn/memory ref. - pointer */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int     _band;  /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int     _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid         _sifields._kill._pid
+#define si_uid         _sifields._kill._uid
+#define si_status      _sifields._sigchld._status
+#define si_utime       _sifields._sigchld._utime
+#define si_stime       _sifields._sigchld._stime
+#define si_value       _sifields._rt._sigval
+#define si_int         _sifields._rt._sigval.sival_int
+#define si_ptr         _sifields._rt._sigval.sival_ptr
+#define si_addr                _sifields._sigfault._addr
+#define si_band                _sifields._sigpoll._band
+#define si_fd          _sifields._sigpoll._fd
+#define si_tid         _sifields._timer._tid
+#define si_overrun     _sifields._timer._overrun
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -153,7 +227,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index 9635d759c2b9fbb107e39f326ff7b638bc353c36..90887bd98cf0b384ce91d2f1bc1ce7187e51498f 100644 (file)
@@ -23,74 +23,6 @@ struct old_sigaction32 {
        __u32                   sa_flags;
        __u32                   sa_restorer;    /* Another 32 bit pointer */
 };
-typedef struct compat_siginfo {
-       int     si_signo;
-       int     si_errno;
-       int     si_code;
-
-       union {
-               int _pad[((128/sizeof(int)) - 3)];
-
-               /* kill() */
-               struct {
-                       pid_t   _pid;   /* sender's pid */
-                       uid_t   _uid;   /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;            /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;        /* same as below */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       pid_t                   _pid;   /* sender's pid */
-                       uid_t                   _uid;   /* sender's uid */
-                       compat_sigval_t         _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       pid_t                   _pid;   /* which child */
-                       uid_t                   _uid;   /* sender's uid */
-                       int                     _status;/* exit code */
-                       compat_clock_t          _utime;
-                       compat_clock_t          _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       __u32   _addr;  /* faulting insn/memory ref. - pointer */
-               } _sigfault;
-                          
-               /* SIGPOLL */
-               struct {
-                       int     _band;  /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int     _fd;
-               } _sigpoll;
-       } _sifields;
-} compat_siginfo_t;
-
-/*
- * How these fields are to be accessed.
- */
-#define si_pid         _sifields._kill._pid
-#define si_uid         _sifields._kill._uid
-#define si_status      _sifields._sigchld._status
-#define si_utime       _sifields._sigchld._utime
-#define si_stime       _sifields._sigchld._stime
-#define si_value       _sifields._rt._sigval
-#define si_int         _sifields._rt._sigval.sival_int
-#define si_ptr         _sifields._rt._sigval.sival_ptr
-#define si_addr                _sifields._sigfault._addr
-#define si_band                _sifields._sigpoll._band
-#define si_fd          _sifields._sigpoll._fd    
-#define si_tid         _sifields._timer._tid
-#define si_overrun     _sifields._timer._overrun
 
 /* asm/sigcontext.h */
 typedef union
index ba0f412920befb05cdd0a26c6a707e2b91289954..461c23747491a85372b9e34f26ed4c61971767a0 100644 (file)
@@ -5,6 +5,7 @@ config SCORE
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
+       select GENERIC_ATOMIC64
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select ARCH_DISCARD_MEMBLOCK
index f478ce94181fb349324bf836e9fe5a01abfaa13d..5d566c7a0af26c5cf65f7b5d37fc57c0f6f93e8a 100644 (file)
@@ -54,7 +54,7 @@ typedef elf_fpreg_t   elf_fpregset_t;
 
 #define SET_PERSONALITY(ex)                                    \
 do {                                                           \
-       set_personality(PER_LINUX);                             \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
 } while (0)
 
 struct task_struct;
index 4aa957364d4dc7865b8e8a662be2443c15c5f83c..a862384e9c16d80defe1b478bb40cd2c1e877f25 100644 (file)
@@ -1,6 +1,3 @@
-#if !defined(_ASM_SCORE_UNISTD_H) || defined(__SYSCALL)
-#define _ASM_SCORE_UNISTD_H
-
 #define __ARCH_HAVE_MMU
 
 #define __ARCH_WANT_SYSCALL_NO_AT
@@ -9,5 +6,3 @@
 #define __ARCH_WANT_SYSCALL_DEPRECATED
 
 #include <asm-generic/unistd.h>
-
-#endif /* _ASM_SCORE_UNISTD_H */
index e478bf9a7e9181cd2e929535aaf0c3680e71a17b..21e8679740667c8d1a2e314252f7f35cad143159 100644 (file)
@@ -112,6 +112,7 @@ score_execve(struct pt_regs *regs)
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
  */
+asmlinkage
 int kernel_execve(const char *filename,
                  const char *const argv[],
                  const char *const envp[])
index f38112be67d29555eb76042c57598e34c2b2e8a4..37924afa8d8a26781a2e8ebf4952144b141f9295 100644 (file)
@@ -183,7 +183,8 @@ do {                                                                        \
 } while (0)
 #endif
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 #ifdef CONFIG_VSYSCALL
 /* vDSO has arch_setup_additional_pages */
index 0cf60a62881435559ddec1d1c930ba2d71298a5c..73a23f4617a37c5a5270d5bc50d9689af45d8f89 100644 (file)
@@ -134,7 +134,7 @@ __BUILD_MEMORY_STRING(__raw_, q, u64)
  * load/store instructions. sh_io_port_base is the virtual address to
  * which all ports are being mapped.
  */
-extern const unsigned long sh_io_port_base;
+extern unsigned long sh_io_port_base;
 
 static inline void __set_io_port_base(unsigned long pbase)
 {
index e3ad6103e7c181ba955b2c9967a41a8a61659eb7..cca14ba84a379fea07bb74ddaabb02bb062cd649 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
-const unsigned long sh_io_port_base __read_mostly = -1;
+unsigned long sh_io_port_base __read_mostly = -1;
 EXPORT_SYMBOL(sh_io_port_base);
 
 void __iomem *__ioport_map(unsigned long addr, unsigned int size)
index b8be20d42a0a8b89ab9d6ac261b445b64cbb8d1d..cef99fbc0a214b80721029fd826d1733f066868e 100644 (file)
@@ -36,6 +36,7 @@ typedef s64           compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64            compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -147,6 +148,65 @@ typedef u32                compat_old_sigset_t;
 
 typedef u32            compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32  (128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               int _pad[SI_PAD_SIZE32];
+
+               /* kill() */
+               struct {
+                       compat_pid_t _pid;              /* sender's pid */
+                       unsigned int _uid;              /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;            /* timer id */
+                       int _overrun;                   /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;              /* sender's pid */
+                       unsigned int _uid;              /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       compat_pid_t _pid;              /* which child */
+                       unsigned int _uid;              /* sender's uid */
+                       int _status;                    /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+               struct {
+                       u32 _addr; /* faulting insn/memory ref. */
+                       int _trapno;
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -156,7 +216,6 @@ typedef u32         compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index 2d4d755cba9ebcc67d8420cb927f66a98e00de74..ac74a2c98e6dde55417db847f9f103b2e8771457 100644 (file)
@@ -128,6 +128,7 @@ typedef struct {
 
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif /* !(__ASMSPARC_ELF_H) */
index 215900fce21b0f4bfd637a83585a9540e30c4662..dbc182c438b494052d2f2aa51a9b001199472f10 100644 (file)
@@ -3,7 +3,6 @@
 
 #if defined(__sparc__) && defined(__arch64__)
 
-#define SI_PAD_SIZE32  ((SI_MAX_SIZE/sizeof(int)) - 3)
 #define __ARCH_SI_PREAMBLE_SIZE        (4 * sizeof(int))
 #define __ARCH_SI_BAND_T int
 
index a53e0a5fd3a3d944a5eb42391e2862c92a23c044..53e48f721ce3e0ceb122ac42550178e74886ad0e 100644 (file)
@@ -54,58 +54,6 @@ struct signal_frame32 {
        /* __siginfo_rwin_t * */u32 rwin_save;
 } __attribute__((aligned(8)));
 
-typedef struct compat_siginfo{
-       int si_signo;
-       int si_errno;
-       int si_code;
-
-       union {
-               int _pad[SI_PAD_SIZE32];
-
-               /* kill() */
-               struct {
-                       compat_pid_t _pid;              /* sender's pid */
-                       unsigned int _uid;              /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;                    /* timer id */
-                       int _overrun;                   /* overrun count */
-                       compat_sigval_t _sigval;                /* same as below */
-                       int _sys_private;               /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       compat_pid_t _pid;              /* sender's pid */
-                       unsigned int _uid;              /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       compat_pid_t _pid;              /* which child */
-                       unsigned int _uid;              /* sender's uid */
-                       int _status;                    /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-               struct {
-                       u32 _addr; /* faulting insn/memory ref. */
-                       int _trapno;
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-       } _sifields;
-}compat_siginfo_t;
-
 struct rt_signal_frame32 {
        struct sparc_stackf32   ss;
        compat_siginfo_t        info;
index 6e74450ff0a110afc32901e273d74a77c80f8ca4..3063e6fc8daaa0dd3dd982a857889ffec74f451e 100644 (file)
@@ -110,6 +110,68 @@ struct compat_flock64 {
 
 typedef u32               compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+#define COMPAT_SI_PAD_SIZE     (128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               int _pad[COMPAT_SI_PAD_SIZE];
+
+               /* kill() */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;    /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+                       int _overrun_incr;      /* amount to add to overrun */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       unsigned int _pid;      /* which child */
+                       unsigned int _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       unsigned int _addr;     /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+                       int _trapno;    /* TRAP # which caused the signal */
+#endif
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
index d16d006d660e20307783eb63695c1faf5b46af46..f8ccf08f6934704924f6081476d61d85e28b181f 100644 (file)
@@ -156,12 +156,12 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #undef SET_PERSONALITY
 #define SET_PERSONALITY(ex) \
 do { \
-       current->personality = PER_LINUX; \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
        current_thread_info()->status &= ~TS_COMPAT; \
 } while (0)
 #define COMPAT_SET_PERSONALITY(ex) \
 do { \
-       current->personality = PER_LINUX_32BIT; \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
        current_thread_info()->status |= TS_COMPAT; \
 } while (0)
 
index a017246ca0cec75db546c5523830e36668fe206f..0e1f3e66e492d01090313d634cef49c52da2e302 100644 (file)
@@ -12,9 +12,6 @@
  *   more details.
  */
 
-#if !defined(_ASM_TILE_UNISTD_H) || defined(__SYSCALL)
-#define _ASM_TILE_UNISTD_H
-
 #if !defined(__LP64__) || defined(__SYSCALL_COMPAT)
 /* Use the flavor of this syscall that matches the 32-bit API better. */
 #define __ARCH_WANT_SYNC_FILE_RANGE2
@@ -43,5 +40,3 @@ __SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr)
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #endif
-
-#endif /* _ASM_TILE_UNISTD_H */
index 474571b8408584d37743678ce02b2ca77c3c9938..7bc0859a9f5ea688779266c10b967ad9f9a554ed 100644 (file)
@@ -55,63 +55,6 @@ struct compat_ucontext {
        sigset_t          uc_sigmask;   /* mask last for extensibility */
 };
 
-#define COMPAT_SI_PAD_SIZE     ((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int))
-
-struct compat_siginfo {
-       int si_signo;
-       int si_errno;
-       int si_code;
-
-       union {
-               int _pad[COMPAT_SI_PAD_SIZE];
-
-               /* kill() */
-               struct {
-                       unsigned int _pid;      /* sender's pid */
-                       unsigned int _uid;      /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;    /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;        /* same as below */
-                       int _sys_private;       /* not to be passed to user */
-                       int _overrun_incr;      /* amount to add to overrun */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       unsigned int _pid;      /* sender's pid */
-                       unsigned int _uid;      /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       unsigned int _pid;      /* which child */
-                       unsigned int _uid;      /* sender's uid */
-                       int _status;            /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       unsigned int _addr;     /* faulting insn/memory ref. */
-#ifdef __ARCH_SI_TRAPNO
-                       int _trapno;    /* TRAP # which caused the signal */
-#endif
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-       } _sifields;
-};
-
 struct compat_rt_sigframe {
        unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
        struct compat_siginfo info;
index b0a47433341e4164988c8332ff85b1560eb11252..1e638e75a6b70a342f00ed5565a4541f1f57533d 100644 (file)
@@ -6,6 +6,7 @@ config UNICORE32
        select HAVE_DMA_ATTRS
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
+       select GENERIC_ATOMIC64
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
        select ARCH_HAVE_CUSTOM_GPIO_H
index 9b24280199618b9e3efba651b4f5073dc1b5ea75..2abcf61c615dd82bfe10114357d663a8482dff10 100644 (file)
@@ -9,10 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#if !defined(__UNICORE_UNISTD_H__) || defined(__SYSCALL)
-#define __UNICORE_UNISTD_H__
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
-
-#endif /* __UNICORE_UNISTD_H__ */
index f34261296ffb71bc9f62f57ecf069508fe40d9d6..3388034222390150c0ee27674a012e6b3a47095b 100644 (file)
@@ -409,7 +409,7 @@ extern struct apic *apic;
  * to enforce the order with in them.
  */
 #define apic_driver(sym)                                       \
-       static struct apic *__apicdrivers_##sym __used          \
+       static const struct apic *__apicdrivers_##sym __used            \
        __aligned(sizeof(struct apic *))                        \
        __section(.apicdrivers) = { &sym }
 
index fedf32b73e65d8e288fc1bd4ed209212bd2c5163..59c6c401f79f16d9b98533275d66d437cbaeff0c 100644 (file)
@@ -41,6 +41,7 @@ typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32            compat_uint_t;
 typedef u32            compat_ulong_t;
 typedef u64 __attribute__((aligned(4))) compat_u64;
+typedef u32            compat_uptr_t;
 
 struct compat_timespec {
        compat_time_t   tv_sec;
@@ -124,6 +125,78 @@ typedef u32                compat_old_sigset_t;    /* at least 32 bits */
 
 typedef u32               compat_sigset_word;
 
+typedef union compat_sigval {
+       compat_int_t    sival_int;
+       compat_uptr_t   sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+       int si_signo;
+       int si_errno;
+       int si_code;
+
+       union {
+               int _pad[128/sizeof(int) - 3];
+
+               /* kill() */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+               } _kill;
+
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;    /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+                       int _sys_private;       /* not to be passed to user */
+                       int _overrun_incr;      /* amount to add to overrun */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       unsigned int _pid;      /* sender's pid */
+                       unsigned int _uid;      /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
+               /* SIGCHLD */
+               struct {
+                       unsigned int _pid;      /* which child */
+                       unsigned int _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_clock_t _utime;
+                       compat_clock_t _stime;
+               } _sigchld;
+
+               /* SIGCHLD (x32 version) */
+               struct {
+                       unsigned int _pid;      /* which child */
+                       unsigned int _uid;      /* sender's uid */
+                       int _status;            /* exit code */
+                       compat_s64 _utime;
+                       compat_s64 _stime;
+               } _sigchld_x32;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       unsigned int _addr;     /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+
+               struct {
+                       unsigned int _call_addr; /* calling insn */
+                       int _syscall;   /* triggering system call number */
+                       unsigned int _arch;     /* AUDIT_ARCH_* of syscall */
+               } _sigsys;
+       } _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX       0x7fffffff
 #define COMPAT_LOFF_T_MAX      0x7fffffffffffffffL
 
@@ -209,7 +282,6 @@ typedef struct user_regs_struct32 compat_elf_gregset_t;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef        u32             compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
index b04cbdb138cd74017c5a38973a668413ea6671e0..e6232773ce4925dc790a2b6b41152393f80b84a1 100644 (file)
@@ -86,73 +86,6 @@ struct stat64 {
        unsigned long long      st_ino;
 } __attribute__((packed));
 
-typedef struct compat_siginfo {
-       int si_signo;
-       int si_errno;
-       int si_code;
-
-       union {
-               int _pad[((128 / sizeof(int)) - 3)];
-
-               /* kill() */
-               struct {
-                       unsigned int _pid;      /* sender's pid */
-                       unsigned int _uid;      /* sender's uid */
-               } _kill;
-
-               /* POSIX.1b timers */
-               struct {
-                       compat_timer_t _tid;    /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;        /* same as below */
-                       int _sys_private;       /* not to be passed to user */
-                       int _overrun_incr;      /* amount to add to overrun */
-               } _timer;
-
-               /* POSIX.1b signals */
-               struct {
-                       unsigned int _pid;      /* sender's pid */
-                       unsigned int _uid;      /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
-               /* SIGCHLD */
-               struct {
-                       unsigned int _pid;      /* which child */
-                       unsigned int _uid;      /* sender's uid */
-                       int _status;            /* exit code */
-                       compat_clock_t _utime;
-                       compat_clock_t _stime;
-               } _sigchld;
-
-               /* SIGCHLD (x32 version) */
-               struct {
-                       unsigned int _pid;      /* which child */
-                       unsigned int _uid;      /* sender's uid */
-                       int _status;            /* exit code */
-                       compat_s64 _utime;
-                       compat_s64 _stime;
-               } _sigchld_x32;
-
-               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-               struct {
-                       unsigned int _addr;     /* faulting insn/memory ref. */
-               } _sigfault;
-
-               /* SIGPOLL */
-               struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                       int _fd;
-               } _sigpoll;
-
-               struct {
-                       unsigned int _call_addr; /* calling insn */
-                       int _syscall;   /* triggering system call number */
-                       unsigned int _arch;     /* AUDIT_ARCH_* of syscall */
-               } _sigsys;
-       } _sifields;
-} compat_siginfo_t;
-
 #define IA32_STACK_TOP IA32_PAGE_OFFSET
 
 #ifdef __KERNEL__
index 1707cfa928fbff64b74a85a2de28c345308353fc..6d2f75a82a14bca62162f38cde9fff8e6404bec9 100644 (file)
@@ -51,6 +51,7 @@
  * with Xen so that on ARM we can have one ABI that works for 32 and 64
  * bit guests. */
 typedef unsigned long xen_pfn_t;
+typedef unsigned long xen_ulong_t;
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
index bc552cff257834bee7a8c1078112ea46380892d4..a65829ac2b9a1b4cb9517f94318bc106291061ad 100644 (file)
@@ -30,7 +30,7 @@
 
 static int numachip_system __read_mostly;
 
-static struct apic apic_numachip __read_mostly;
+static const struct apic apic_numachip __read_mostly;
 
 static unsigned int get_apic_id(unsigned long x)
 {
@@ -199,7 +199,7 @@ static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 0;
 }
 
-static struct apic apic_numachip __refconst = {
+static const struct apic apic_numachip __refconst = {
 
        .name                           = "NumaConnect system",
        .probe                          = numachip_probe,
index af6db6ec5b2a20db3d13861bdb97b878f8371f1e..4929c1be0ac0077f7c279fe296ece8e425684c9a 100644 (file)
@@ -225,7 +225,7 @@ static struct platform_device rtc_device = {
 static __init int add_rtc_cmos(void)
 {
 #ifdef CONFIG_PNP
-       static const char *ids[] __initconst =
+       static const char * const  const ids[] __initconst =
            { "PNP0b00", "PNP0b01", "PNP0b02", };
        struct pnp_dev *dev;
        struct pnp_id *id;
index 6e121a2a49e1b672fc8c191ae8c7ee40733076d0..7872a3330fb51ed1576e3c40d78820cb73915b50 100644 (file)
@@ -4,7 +4,6 @@ config LGUEST_GUEST
        depends on X86_32
        select VIRTUALIZATION
        select VIRTIO
-       select VIRTIO_RING
        select VIRTIO_CONSOLE
        help
          Lguest is a tiny in-kernel hypervisor.  Selecting this will
index 2d932c351f91fec22daa30d1a1aabe20a772a2bb..bf788d34530df5fbb93e60bb64023d80f7bbedf3 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/memblock.h>
 
 #include <xen/xen.h>
+#include <xen/events.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
 #include <xen/interface/physdev.h>
index 1573376579714ec3b9a195a898090dba7ac20087..01a4dc015ae1e37206469df5ea45b3437da19cad 100644 (file)
@@ -5,6 +5,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/vcpu.h>
+#include <xen/events.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
index bb5a8105ea8604e6fdb0b2f720b5e0403ceaf100..a95b41744ad0bafdcde069cb965cabb67ab0f61b 100644 (file)
@@ -35,7 +35,6 @@ void xen_set_pat(u64);
 
 char * __init xen_memory_setup(void);
 void __init xen_arch_setup(void);
-void __init xen_init_IRQ(void);
 void xen_enable_sysenter(void);
 void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
index 6e65eadaae14c60c1972b3fe96c5bbae0c2a38bb..5293312bc6a4c55d842519ef6c16cede7e5e197b 100644 (file)
@@ -189,7 +189,8 @@ typedef struct {
 #endif
 } elf_xtregs_t;
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 struct task_struct;
 
index 2059ee460b0c61cf48614283db428ff5675f5904..81e44f7b0ab6669b4e88bc28cac5402f2856452f 100644 (file)
@@ -1567,7 +1567,7 @@ tx_complete++;
 /*--------------------------------- entries ---------------------------------*/
 
 
-static const char *media_name[] __devinitdata = {
+static char * const media_name[] __devinitconst = {
     "MMF", "SMF", "MMF", "03?", /*  0- 3 */
     "UTP", "05?", "06?", "07?", /*  4- 7 */
     "TAXI","09?", "10?", "11?", /*  8-11 */
index db195abad69889e4d499bde162ff5e818601f3b2..d2ed7f18d1acfa6303b67999b0b39a93e575f49b 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "47"
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
+#define VERSION "50"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -10,9 +10,6 @@
 #define AOE_PARTITIONS (16)
 #endif
 
-#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
-#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
-#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
 #define WHITESPACE " \t\v\f\n"
 
 enum {
@@ -75,72 +72,67 @@ enum {
        DEVFL_UP = 1,   /* device is installed in system and ready for AoE->ATA commands */
        DEVFL_TKILL = (1<<1),   /* flag for timer to know when to kill self */
        DEVFL_EXT = (1<<2),     /* device accepts lba48 commands */
-       DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */
-       DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */
-       DEVFL_KICKME = (1<<5),  /* slow polling network card catch */
-       DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
-
-       BUFFL_FAIL = 1,
+       DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */
+       DEVFL_KICKME = (1<<4),  /* slow polling network card catch */
+       DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */
 };
 
 enum {
        DEFAULTBCNT = 2 * 512,  /* 2 sectors */
-       NPERSHELF = 16,         /* number of slots per shelf address */
-       FREETAG = -1,
        MIN_BUFS = 16,
        NTARGETS = 8,
        NAOEIFS = 8,
-       NSKBPOOLMAX = 128,
+       NSKBPOOLMAX = 256,
+       NFACTIVE = 61,
 
        TIMERTICK = HZ / 10,
        MINTIMER = HZ >> 2,
        MAXTIMER = HZ << 1,
-       HELPWAIT = 20,
 };
 
 struct buf {
-       struct list_head bufs;
-       ulong stime;    /* for disk stats */
-       ulong flags;
        ulong nframesout;
        ulong resid;
        ulong bv_resid;
-       ulong bv_off;
        sector_t sector;
        struct bio *bio;
        struct bio_vec *bv;
+       struct request *rq;
 };
 
 struct frame {
-       int tag;
+       struct list_head head;
+       u32 tag;
        ulong waited;
+       struct aoetgt *t;               /* parent target I belong to */
+       sector_t lba;
+       struct sk_buff *skb;            /* command skb freed on module exit */
+       struct sk_buff *r_skb;          /* response skb for async processing */
        struct buf *buf;
-       char *bufaddr;
+       struct bio_vec *bv;
        ulong bcnt;
-       sector_t lba;
-       struct sk_buff *skb;
+       ulong bv_off;
 };
 
 struct aoeif {
        struct net_device *nd;
-       unsigned char lost;
-       unsigned char lostjumbo;
-       ushort maxbcnt;
+       ulong lost;
+       int bcnt;
 };
 
 struct aoetgt {
        unsigned char addr[6];
        ushort nframes;
-       struct frame *frames;
+       struct aoedev *d;                       /* parent device I belong to */
+       struct list_head ffree;                 /* list of free frames */
        struct aoeif ifs[NAOEIFS];
        struct aoeif *ifp;      /* current aoeif in use */
        ushort nout;
        ushort maxout;
-       u16 lasttag;            /* last tag sent */
-       u16 useme;
+       ulong falloc;
        ulong lastwadj;         /* last window adjustment */
+       int minbcnt;
        int wpkts, rpkts;
-       int dataref;
 };
 
 struct aoedev {
@@ -153,6 +145,9 @@ struct aoedev {
        u16 rttavg;             /* round trip average of requests/responses */
        u16 mintimer;
        u16 fw_ver;             /* version of blade's firmware */
+       u16 lasttag;            /* last tag sent */
+       u16 useme;
+       ulong ref;
        struct work_struct work;/* disk create work struct */
        struct gendisk *gd;
        struct request_queue *blkq;
@@ -160,16 +155,31 @@ struct aoedev {
        sector_t ssize;
        struct timer_list timer;
        spinlock_t lock;
-       struct sk_buff_head sendq;
        struct sk_buff_head skbpool;
        mempool_t *bufpool;     /* for deadlock-free Buf allocation */
-       struct list_head bufq;  /* queue of bios to work on */
-       struct buf *inprocess;  /* the one we're currently working on */
+       struct {                /* pointers to work in progress */
+               struct buf *buf;
+               struct bio *nxbio;
+               struct request *rq;
+       } ip;
+       ulong maxbcnt;
+       struct list_head factive[NFACTIVE];     /* hash of active frames */
        struct aoetgt *targets[NTARGETS];
        struct aoetgt **tgt;    /* target in use when working */
-       struct aoetgt **htgt;   /* target needing rexmit assistance */
+       struct aoetgt *htgt;    /* target needing rexmit assistance */
+       ulong ntargets;
+       ulong kicked;
 };
 
+/* kthread tracking */
+struct ktstate {
+       struct completion rendez;
+       struct task_struct *task;
+       wait_queue_head_t *waitq;
+       int (*fn) (void);
+       char *name;
+       spinlock_t *lock;
+};
 
 int aoeblk_init(void);
 void aoeblk_exit(void);
@@ -182,22 +192,29 @@ void aoechr_error(char *);
 
 void aoecmd_work(struct aoedev *d);
 void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
-void aoecmd_ata_rsp(struct sk_buff *);
+struct sk_buff *aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
 void aoecmd_sleepwork(struct work_struct *);
 void aoecmd_cleanslate(struct aoedev *);
+void aoecmd_exit(void);
+int aoecmd_init(void);
 struct sk_buff *aoecmd_ata_id(struct aoedev *);
+void aoe_freetframe(struct frame *);
+void aoe_flush_iocq(void);
+void aoe_end_request(struct aoedev *, struct request *, int);
+int aoe_ktstart(struct ktstate *k);
+void aoe_ktstop(struct ktstate *k);
 
 int aoedev_init(void);
 void aoedev_exit(void);
-struct aoedev *aoedev_by_aoeaddr(int maj, int min);
-struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
+struct aoedev *aoedev_by_aoeaddr(ulong maj, int min, int do_alloc);
 void aoedev_downdev(struct aoedev *d);
 int aoedev_flush(const char __user *str, size_t size);
+void aoe_failbuf(struct aoedev *, struct buf *);
+void aoedev_put(struct aoedev *);
 
 int aoenet_init(void);
 void aoenet_exit(void);
 void aoenet_xmit(struct sk_buff_head *);
 int is_aoe_netif(struct net_device *ifp);
 int set_aoe_iflist(const char __user *str, size_t size);
-
index 321de7b6c44228e5b7c5cfc0a410be19a54759fe..00dfc5008ad4bddd8a8efa036eb1bbbc8cc8ec23 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoeblk.c
  * block device routines
@@ -161,68 +161,22 @@ aoeblk_release(struct gendisk *disk, fmode_t mode)
 }
 
 static void
-aoeblk_make_request(struct request_queue *q, struct bio *bio)
+aoeblk_request(struct request_queue *q)
 {
-       struct sk_buff_head queue;
        struct aoedev *d;
-       struct buf *buf;
-       ulong flags;
-
-       blk_queue_bounce(q, &bio);
-
-       if (bio == NULL) {
-               printk(KERN_ERR "aoe: bio is NULL\n");
-               BUG();
-               return;
-       }
-       d = bio->bi_bdev->bd_disk->private_data;
-       if (d == NULL) {
-               printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
-               BUG();
-               bio_endio(bio, -ENXIO);
-               return;
-       } else if (bio->bi_io_vec == NULL) {
-               printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
-               BUG();
-               bio_endio(bio, -ENXIO);
-               return;
-       }
-       buf = mempool_alloc(d->bufpool, GFP_NOIO);
-       if (buf == NULL) {
-               printk(KERN_INFO "aoe: buf allocation failure\n");
-               bio_endio(bio, -ENOMEM);
-               return;
-       }
-       memset(buf, 0, sizeof(*buf));
-       INIT_LIST_HEAD(&buf->bufs);
-       buf->stime = jiffies;
-       buf->bio = bio;
-       buf->resid = bio->bi_size;
-       buf->sector = bio->bi_sector;
-       buf->bv = &bio->bi_io_vec[bio->bi_idx];
-       buf->bv_resid = buf->bv->bv_len;
-       WARN_ON(buf->bv_resid == 0);
-       buf->bv_off = buf->bv->bv_offset;
-
-       spin_lock_irqsave(&d->lock, flags);
+       struct request *rq;
 
+       d = q->queuedata;
        if ((d->flags & DEVFL_UP) == 0) {
                pr_info_ratelimited("aoe: device %ld.%d is not up\n",
                        d->aoemajor, d->aoeminor);
-               spin_unlock_irqrestore(&d->lock, flags);
-               mempool_free(buf, d->bufpool);
-               bio_endio(bio, -ENXIO);
+               while ((rq = blk_peek_request(q))) {
+                       blk_start_request(rq);
+                       aoe_end_request(d, rq, 1);
+               }
                return;
        }
-
-       list_add_tail(&buf->bufs, &d->bufq);
-
        aoecmd_work(d);
-       __skb_queue_head_init(&queue);
-       skb_queue_splice_init(&d->sendq, &queue);
-
-       spin_unlock_irqrestore(&d->lock, flags);
-       aoenet_xmit(&queue);
 }
 
 static int
@@ -254,41 +208,54 @@ aoeblk_gdalloc(void *vp)
 {
        struct aoedev *d = vp;
        struct gendisk *gd;
+       mempool_t *mp;
+       struct request_queue *q;
+       enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
        ulong flags;
 
        gd = alloc_disk(AOE_PARTITIONS);
        if (gd == NULL) {
-               printk(KERN_ERR
-                       "aoe: cannot allocate disk structure for %ld.%d\n",
+               pr_err("aoe: cannot allocate disk structure for %ld.%d\n",
                        d->aoemajor, d->aoeminor);
                goto err;
        }
 
-       d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache);
-       if (d->bufpool == NULL) {
+       mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab,
+               buf_pool_cache);
+       if (mp == NULL) {
                printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n",
                        d->aoemajor, d->aoeminor);
                goto err_disk;
        }
+       q = blk_init_queue(aoeblk_request, &d->lock);
+       if (q == NULL) {
+               pr_err("aoe: cannot allocate block queue for %ld.%d\n",
+                       d->aoemajor, d->aoeminor);
+               mempool_destroy(mp);
+               goto err_disk;
+       }
 
        d->blkq = blk_alloc_queue(GFP_KERNEL);
        if (!d->blkq)
                goto err_mempool;
-       blk_queue_make_request(d->blkq, aoeblk_make_request);
        d->blkq->backing_dev_info.name = "aoe";
        if (bdi_init(&d->blkq->backing_dev_info))
                goto err_blkq;
        spin_lock_irqsave(&d->lock, flags);
+       blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS);
+       q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
+       d->bufpool = mp;
+       d->blkq = gd->queue = q;
+       q->queuedata = d;
+       d->gd = gd;
        gd->major = AOE_MAJOR;
-       gd->first_minor = d->sysminor * AOE_PARTITIONS;
+       gd->first_minor = d->sysminor;
        gd->fops = &aoe_bdops;
        gd->private_data = d;
        set_capacity(gd, d->ssize);
        snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
                d->aoemajor, d->aoeminor);
 
-       gd->queue = d->blkq;
-       d->gd = gd;
        d->flags &= ~DEVFL_GDALLOC;
        d->flags |= DEVFL_UP;
 
index e86d2062a1641f36ff2bc0200d286f433e56fb27..ed57a890c6431ce882c84486481967c2103f1724 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoechr.c
  * AoE character device driver
@@ -86,34 +86,34 @@ revalidate(const char __user *str, size_t size)
        if (copy_from_user(buf, str, size))
                return -EFAULT;
 
-       /* should be e%d.%d format */
        n = sscanf(buf, "e%d.%d", &major, &minor);
        if (n != 2) {
-               printk(KERN_ERR "aoe: invalid device specification\n");
+               pr_err("aoe: invalid device specification %s\n", buf);
                return -EINVAL;
        }
-       d = aoedev_by_aoeaddr(major, minor);
+       d = aoedev_by_aoeaddr(major, minor, 0);
        if (!d)
                return -EINVAL;
        spin_lock_irqsave(&d->lock, flags);
        aoecmd_cleanslate(d);
+       aoecmd_cfg(major, minor);
 loop:
        skb = aoecmd_ata_id(d);
        spin_unlock_irqrestore(&d->lock, flags);
        /* try again if we are able to sleep a bit,
         * otherwise give up this revalidation
         */
-       if (!skb && !msleep_interruptible(200)) {
+       if (!skb && !msleep_interruptible(250)) {
                spin_lock_irqsave(&d->lock, flags);
                goto loop;
        }
+       aoedev_put(d);
        if (skb) {
                struct sk_buff_head queue;
                __skb_queue_head_init(&queue);
                __skb_queue_tail(&queue, skb);
                aoenet_xmit(&queue);
        }
-       aoecmd_cfg(major, minor);
        return 0;
 }
 
@@ -174,6 +174,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
                break;
        case MINOR_FLUSH:
                ret = aoedev_flush(buf, cnt);
+               break;
        }
        if (ret == 0)
                ret = cnt;
index 887f68f6d79a9e615beba7525cb9d0e671917c4e..3804a0af3ef192c441643eee425d06f747b86d97 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoecmd.c
  * Filesystem request handling methods
 #include <linux/netdevice.h>
 #include <linux/genhd.h>
 #include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
 #include <net/net_namespace.h>
 #include <asm/unaligned.h>
+#include <linux/uio.h>
 #include "aoe.h"
 
+#define MAXIOC (8192)  /* default meant to avoid most soft lockups */
+
+static void ktcomplete(struct frame *, struct sk_buff *);
+
+static struct buf *nextbuf(struct aoedev *);
+
 static int aoe_deadsecs = 60 * 3;
 module_param(aoe_deadsecs, int, 0644);
 MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
@@ -25,6 +34,15 @@ module_param(aoe_maxout, int, 0644);
 MODULE_PARM_DESC(aoe_maxout,
        "Only aoe_maxout outstanding packets for every MAC on eX.Y.");
 
+static wait_queue_head_t ktiowq;
+static struct ktstate kts;
+
+/* io completion queue */
+static struct {
+       struct list_head head;
+       spinlock_t lock;
+} iocq;
+
 static struct sk_buff *
 new_skb(ulong len)
 {
@@ -41,15 +59,21 @@ new_skb(ulong len)
 }
 
 static struct frame *
-getframe(struct aoetgt *t, int tag)
+getframe(struct aoedev *d, u32 tag)
 {
-       struct frame *f, *e;
+       struct frame *f;
+       struct list_head *head, *pos, *nx;
+       u32 n;
 
-       f = t->frames;
-       e = f + t->nframes;
-       for (; f<e; f++)
-               if (f->tag == tag)
+       n = tag % NFACTIVE;
+       head = &d->factive[n];
+       list_for_each_safe(pos, nx, head) {
+               f = list_entry(pos, struct frame, head);
+               if (f->tag == tag) {
+                       list_del(pos);
                        return f;
+               }
+       }
        return NULL;
 }
 
@@ -59,18 +83,18 @@ getframe(struct aoetgt *t, int tag)
  * This driver reserves tag -1 to mean "unused frame."
  */
 static int
-newtag(struct aoetgt *t)
+newtag(struct aoedev *d)
 {
        register ulong n;
 
        n = jiffies & 0xffff;
-       return n |= (++t->lasttag & 0x7fff) << 16;
+       return n |= (++d->lasttag & 0x7fff) << 16;
 }
 
-static int
+static u32
 aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h)
 {
-       u32 host_tag = newtag(t);
+       u32 host_tag = newtag(d);
 
        memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
        memcpy(h->dst, t->addr, sizeof h->dst);
@@ -95,16 +119,18 @@ put_lba(struct aoe_atahdr *ah, sector_t lba)
        ah->lba5 = lba >>= 8;
 }
 
-static void
+static struct aoeif *
 ifrotate(struct aoetgt *t)
 {
-       t->ifp++;
-       if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL)
-               t->ifp = t->ifs;
-       if (t->ifp->nd == NULL) {
-               printk(KERN_INFO "aoe: no interface to rotate to\n");
-               BUG();
-       }
+       struct aoeif *ifp;
+
+       ifp = t->ifp;
+       ifp++;
+       if (ifp >= &t->ifs[NAOEIFS] || ifp->nd == NULL)
+               ifp = t->ifs;
+       if (ifp->nd == NULL)
+               return NULL;
+       return t->ifp = ifp;
 }
 
 static void
@@ -129,78 +155,128 @@ skb_pool_get(struct aoedev *d)
        return NULL;
 }
 
-/* freeframe is where we do our load balancing so it's a little hairy. */
+void
+aoe_freetframe(struct frame *f)
+{
+       struct aoetgt *t;
+
+       t = f->t;
+       f->buf = NULL;
+       f->bv = NULL;
+       f->r_skb = NULL;
+       list_add(&f->head, &t->ffree);
+}
+
 static struct frame *
-freeframe(struct aoedev *d)
+newtframe(struct aoedev *d, struct aoetgt *t)
 {
-       struct frame *f, *e, *rf;
-       struct aoetgt **t;
+       struct frame *f;
        struct sk_buff *skb;
+       struct list_head *pos;
+
+       if (list_empty(&t->ffree)) {
+               if (t->falloc >= NSKBPOOLMAX*2)
+                       return NULL;
+               f = kcalloc(1, sizeof(*f), GFP_ATOMIC);
+               if (f == NULL)
+                       return NULL;
+               t->falloc++;
+               f->t = t;
+       } else {
+               pos = t->ffree.next;
+               list_del(pos);
+               f = list_entry(pos, struct frame, head);
+       }
+
+       skb = f->skb;
+       if (skb == NULL) {
+               f->skb = skb = new_skb(ETH_ZLEN);
+               if (!skb) {
+bail:                  aoe_freetframe(f);
+                       return NULL;
+               }
+       }
+
+       if (atomic_read(&skb_shinfo(skb)->dataref) != 1) {
+               skb = skb_pool_get(d);
+               if (skb == NULL)
+                       goto bail;
+               skb_pool_put(d, f->skb);
+               f->skb = skb;
+       }
+
+       skb->truesize -= skb->data_len;
+       skb_shinfo(skb)->nr_frags = skb->data_len = 0;
+       skb_trim(skb, 0);
+       return f;
+}
+
+static struct frame *
+newframe(struct aoedev *d)
+{
+       struct frame *f;
+       struct aoetgt *t, **tt;
+       int totout = 0;
 
        if (d->targets[0] == NULL) {    /* shouldn't happen, but I'm paranoid */
                printk(KERN_ERR "aoe: NULL TARGETS!\n");
                return NULL;
        }
-       t = d->tgt;
-       t++;
-       if (t >= &d->targets[NTARGETS] || !*t)
-               t = d->targets;
+       tt = d->tgt;    /* last used target */
        for (;;) {
-               if ((*t)->nout < (*t)->maxout
+               tt++;
+               if (tt >= &d->targets[NTARGETS] || !*tt)
+                       tt = d->targets;
+               t = *tt;
+               totout += t->nout;
+               if (t->nout < t->maxout
                && t != d->htgt
-               && (*t)->ifp->nd) {
-                       rf = NULL;
-                       f = (*t)->frames;
-                       e = f + (*t)->nframes;
-                       for (; f < e; f++) {
-                               if (f->tag != FREETAG)
-                                       continue;
-                               skb = f->skb;
-                               if (!skb
-                               && !(f->skb = skb = new_skb(ETH_ZLEN)))
-                                       continue;
-                               if (atomic_read(&skb_shinfo(skb)->dataref)
-                                       != 1) {
-                                       if (!rf)
-                                               rf = f;
-                                       continue;
-                               }
-gotone:                                skb_shinfo(skb)->nr_frags = skb->data_len = 0;
-                               skb_trim(skb, 0);
-                               d->tgt = t;
-                               ifrotate(*t);
+               && t->ifp->nd) {
+                       f = newtframe(d, t);
+                       if (f) {
+                               ifrotate(t);
+                               d->tgt = tt;
                                return f;
                        }
-                       /* Work can be done, but the network layer is
-                          holding our precious packets.  Try to grab
-                          one from the pool. */
-                       f = rf;
-                       if (f == NULL) {        /* more paranoia */
-                               printk(KERN_ERR
-                                       "aoe: freeframe: %s.\n",
-                                       "unexpected null rf");
-                               d->flags |= DEVFL_KICKME;
-                               return NULL;
-                       }
-                       skb = skb_pool_get(d);
-                       if (skb) {
-                               skb_pool_put(d, f->skb);
-                               f->skb = skb;
-                               goto gotone;
-                       }
-                       (*t)->dataref++;
-                       if ((*t)->nout == 0)
-                               d->flags |= DEVFL_KICKME;
                }
-               if (t == d->tgt)        /* we've looped and found nada */
+               if (tt == d->tgt)       /* we've looped and found nada */
                        break;
-               t++;
-               if (t >= &d->targets[NTARGETS] || !*t)
-                       t = d->targets;
+       }
+       if (totout == 0) {
+               d->kicked++;
+               d->flags |= DEVFL_KICKME;
        }
        return NULL;
 }
 
+static void
+skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt)
+{
+       int frag = 0;
+       ulong fcnt;
+loop:
+       fcnt = bv->bv_len - (off - bv->bv_offset);
+       if (fcnt > cnt)
+               fcnt = cnt;
+       skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt);
+       cnt -= fcnt;
+       if (cnt <= 0)
+               return;
+       bv++;
+       off = bv->bv_offset;
+       goto loop;
+}
+
+static void
+fhash(struct frame *f)
+{
+       struct aoedev *d = f->t->d;
+       u32 n;
+
+       n = f->tag % NFACTIVE;
+       list_add_tail(&f->head, &d->factive[n]);
+}
+
 static int
 aoecmd_ata_rw(struct aoedev *d)
 {
@@ -208,26 +284,47 @@ aoecmd_ata_rw(struct aoedev *d)
        struct aoe_hdr *h;
        struct aoe_atahdr *ah;
        struct buf *buf;
-       struct bio_vec *bv;
        struct aoetgt *t;
        struct sk_buff *skb;
-       ulong bcnt;
+       struct sk_buff_head queue;
+       ulong bcnt, fbcnt;
        char writebit, extbit;
 
        writebit = 0x10;
        extbit = 0x4;
 
-       f = freeframe(d);
+       buf = nextbuf(d);
+       if (buf == NULL)
+               return 0;
+       f = newframe(d);
        if (f == NULL)
                return 0;
        t = *d->tgt;
-       buf = d->inprocess;
-       bv = buf->bv;
-       bcnt = t->ifp->maxbcnt;
+       bcnt = d->maxbcnt;
        if (bcnt == 0)
                bcnt = DEFAULTBCNT;
-       if (bcnt > buf->bv_resid)
-               bcnt = buf->bv_resid;
+       if (bcnt > buf->resid)
+               bcnt = buf->resid;
+       fbcnt = bcnt;
+       f->bv = buf->bv;
+       f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid);
+       do {
+               if (fbcnt < buf->bv_resid) {
+                       buf->bv_resid -= fbcnt;
+                       buf->resid -= fbcnt;
+                       break;
+               }
+               fbcnt -= buf->bv_resid;
+               buf->resid -= buf->bv_resid;
+               if (buf->resid == 0) {
+                       d->ip.buf = NULL;
+                       break;
+               }
+               buf->bv++;
+               buf->bv_resid = buf->bv->bv_len;
+               WARN_ON(buf->bv_resid == 0);
+       } while (fbcnt);
+
        /* initialize the headers & frame */
        skb = f->skb;
        h = (struct aoe_hdr *) skb_mac_header(skb);
@@ -235,10 +332,10 @@ aoecmd_ata_rw(struct aoedev *d)
        skb_put(skb, sizeof *h + sizeof *ah);
        memset(h, 0, skb->len);
        f->tag = aoehdr_atainit(d, t, h);
+       fhash(f);
        t->nout++;
        f->waited = 0;
        f->buf = buf;
-       f->bufaddr = page_address(bv->bv_page) + buf->bv_off;
        f->bcnt = bcnt;
        f->lba = buf->sector;
 
@@ -253,10 +350,11 @@ aoecmd_ata_rw(struct aoedev *d)
                ah->lba3 |= 0xe0;       /* LBA bit + obsolete 0xa0 */
        }
        if (bio_data_dir(buf->bio) == WRITE) {
-               skb_fill_page_desc(skb, 0, bv->bv_page, buf->bv_off, bcnt);
+               skb_fillup(skb, f->bv, f->bv_off, bcnt);
                ah->aflags |= AOEAFL_WRITE;
                skb->len += bcnt;
                skb->data_len = bcnt;
+               skb->truesize += bcnt;
                t->wpkts++;
        } else {
                t->rpkts++;
@@ -267,23 +365,15 @@ aoecmd_ata_rw(struct aoedev *d)
 
        /* mark all tracking fields and load out */
        buf->nframesout += 1;
-       buf->bv_off += bcnt;
-       buf->bv_resid -= bcnt;
-       buf->resid -= bcnt;
        buf->sector += bcnt >> 9;
-       if (buf->resid == 0) {
-               d->inprocess = NULL;
-       } else if (buf->bv_resid == 0) {
-               buf->bv = ++bv;
-               buf->bv_resid = bv->bv_len;
-               WARN_ON(buf->bv_resid == 0);
-               buf->bv_off = bv->bv_offset;
-       }
 
        skb->dev = t->ifp->nd;
        skb = skb_clone(skb, GFP_ATOMIC);
-       if (skb)
-               __skb_queue_tail(&d->sendq, skb);
+       if (skb) {
+               __skb_queue_head_init(&queue);
+               __skb_queue_tail(&queue, skb);
+               aoenet_xmit(&queue);
+       }
        return 1;
 }
 
@@ -330,17 +420,25 @@ cont:
 }
 
 static void
-resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
+resend(struct aoedev *d, struct frame *f)
 {
        struct sk_buff *skb;
+       struct sk_buff_head queue;
        struct aoe_hdr *h;
        struct aoe_atahdr *ah;
+       struct aoetgt *t;
        char buf[128];
        u32 n;
 
-       ifrotate(t);
-       n = newtag(t);
+       t = f->t;
+       n = newtag(d);
        skb = f->skb;
+       if (ifrotate(t) == NULL) {
+               /* probably can't happen, but set it up to fail anyway */
+               pr_info("aoe: resend: no interfaces to rotate to.\n");
+               ktcomplete(f, NULL);
+               return;
+       }
        h = (struct aoe_hdr *) skb_mac_header(skb);
        ah = (struct aoe_atahdr *) (h+1);
 
@@ -351,39 +449,22 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
        aoechr_error(buf);
 
        f->tag = n;
+       fhash(f);
        h->tag = cpu_to_be32(n);
        memcpy(h->dst, t->addr, sizeof h->dst);
        memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
 
-       switch (ah->cmdstat) {
-       default:
-               break;
-       case ATA_CMD_PIO_READ:
-       case ATA_CMD_PIO_READ_EXT:
-       case ATA_CMD_PIO_WRITE:
-       case ATA_CMD_PIO_WRITE_EXT:
-               put_lba(ah, f->lba);
-
-               n = f->bcnt;
-               if (n > DEFAULTBCNT)
-                       n = DEFAULTBCNT;
-               ah->scnt = n >> 9;
-               if (ah->aflags & AOEAFL_WRITE) {
-                       skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
-                               offset_in_page(f->bufaddr), n);
-                       skb->len = sizeof *h + sizeof *ah + n;
-                       skb->data_len = n;
-               }
-       }
        skb->dev = t->ifp->nd;
        skb = skb_clone(skb, GFP_ATOMIC);
        if (skb == NULL)
                return;
-       __skb_queue_tail(&d->sendq, skb);
+       __skb_queue_head_init(&queue);
+       __skb_queue_tail(&queue, skb);
+       aoenet_xmit(&queue);
 }
 
 static int
-tsince(int tag)
+tsince(u32 tag)
 {
        int n;
 
@@ -407,58 +488,65 @@ getif(struct aoetgt *t, struct net_device *nd)
        return NULL;
 }
 
-static struct aoeif *
-addif(struct aoetgt *t, struct net_device *nd)
-{
-       struct aoeif *p;
-
-       p = getif(t, NULL);
-       if (!p)
-               return NULL;
-       p->nd = nd;
-       p->maxbcnt = DEFAULTBCNT;
-       p->lost = 0;
-       p->lostjumbo = 0;
-       return p;
-}
-
 static void
 ejectif(struct aoetgt *t, struct aoeif *ifp)
 {
        struct aoeif *e;
+       struct net_device *nd;
        ulong n;
 
+       nd = ifp->nd;
        e = t->ifs + NAOEIFS - 1;
        n = (e - ifp) * sizeof *ifp;
        memmove(ifp, ifp+1, n);
        e->nd = NULL;
+       dev_put(nd);
 }
 
 static int
 sthtith(struct aoedev *d)
 {
-       struct frame *f, *e, *nf;
+       struct frame *f, *nf;
+       struct list_head *nx, *pos, *head;
        struct sk_buff *skb;
-       struct aoetgt *ht = *d->htgt;
-
-       f = ht->frames;
-       e = f + ht->nframes;
-       for (; f < e; f++) {
-               if (f->tag == FREETAG)
-                       continue;
-               nf = freeframe(d);
-               if (!nf)
-                       return 0;
-               skb = nf->skb;
-               *nf = *f;
-               f->skb = skb;
-               f->tag = FREETAG;
-               nf->waited = 0;
-               ht->nout--;
-               (*d->tgt)->nout++;
-               resend(d, *d->tgt, nf);
+       struct aoetgt *ht = d->htgt;
+       int i;
+
+       for (i = 0; i < NFACTIVE; i++) {
+               head = &d->factive[i];
+               list_for_each_safe(pos, nx, head) {
+                       f = list_entry(pos, struct frame, head);
+                       if (f->t != ht)
+                               continue;
+
+                       nf = newframe(d);
+                       if (!nf)
+                               return 0;
+
+                       /* remove frame from active list */
+                       list_del(pos);
+
+                       /* reassign all pertinent bits to new outbound frame */
+                       skb = nf->skb;
+                       nf->skb = f->skb;
+                       nf->buf = f->buf;
+                       nf->bcnt = f->bcnt;
+                       nf->lba = f->lba;
+                       nf->bv = f->bv;
+                       nf->bv_off = f->bv_off;
+                       nf->waited = 0;
+                       f->skb = skb;
+                       aoe_freetframe(f);
+                       ht->nout--;
+                       nf->t->nout++;
+                       resend(d, nf);
+               }
        }
-       /* he's clean, he's useless.  take away his interfaces */
+       /* We've cleaned up the outstanding so take away his
+        * interfaces so he won't be used.  We should remove him from
+        * the target array here, but cleaning up a target is
+        * involved.  PUNT!
+        */
        memset(ht->ifs, 0, sizeof ht->ifs);
        d->htgt = NULL;
        return 1;
@@ -477,13 +565,15 @@ ata_scnt(unsigned char *packet) {
 static void
 rexmit_timer(ulong vp)
 {
-       struct sk_buff_head queue;
        struct aoedev *d;
        struct aoetgt *t, **tt, **te;
        struct aoeif *ifp;
-       struct frame *f, *e;
+       struct frame *f;
+       struct list_head *head, *pos, *nx;
+       LIST_HEAD(flist);
        register long timeout;
        ulong flags, n;
+       int i;
 
        d = (struct aoedev *) vp;
 
@@ -497,58 +587,22 @@ rexmit_timer(ulong vp)
                spin_unlock_irqrestore(&d->lock, flags);
                return;
        }
-       tt = d->targets;
-       te = tt + NTARGETS;
-       for (; tt < te && *tt; tt++) {
-               t = *tt;
-               f = t->frames;
-               e = f + t->nframes;
-               for (; f < e; f++) {
-                       if (f->tag == FREETAG
-                       || tsince(f->tag) < timeout)
-                               continue;
-                       n = f->waited += timeout;
-                       n /= HZ;
-                       if (n > aoe_deadsecs) {
-                               /* waited too long.  device failure. */
-                               aoedev_downdev(d);
-                               break;
-                       }
-
-                       if (n > HELPWAIT /* see if another target can help */
-                       && (tt != d->targets || d->targets[1]))
-                               d->htgt = tt;
-
-                       if (t->nout == t->maxout) {
-                               if (t->maxout > 1)
-                                       t->maxout--;
-                               t->lastwadj = jiffies;
-                       }
-
-                       ifp = getif(t, f->skb->dev);
-                       if (ifp && ++ifp->lost > (t->nframes << 1)
-                       && (ifp != t->ifs || t->ifs[1].nd)) {
-                               ejectif(t, ifp);
-                               ifp = NULL;
-                       }
 
-                       if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512
-                       && ifp && ++ifp->lostjumbo > (t->nframes << 1)
-                       && ifp->maxbcnt != DEFAULTBCNT) {
-                               printk(KERN_INFO
-                                       "aoe: e%ld.%d: "
-                                       "too many lost jumbo on "
-                                       "%s:%pm - "
-                                       "falling back to %d frames.\n",
-                                       d->aoemajor, d->aoeminor,
-                                       ifp->nd->name, t->addr,
-                                       DEFAULTBCNT);
-                               ifp->maxbcnt = 0;
-                       }
-                       resend(d, t, f);
+       /* collect all frames to rexmit into flist */
+       for (i = 0; i < NFACTIVE; i++) {
+               head = &d->factive[i];
+               list_for_each_safe(pos, nx, head) {
+                       f = list_entry(pos, struct frame, head);
+                       if (tsince(f->tag) < timeout)
+                               break;  /* end of expired frames */
+                       /* move to flist for later processing */
+                       list_move_tail(pos, &flist);
                }
-
-               /* window check */
+       }
+       /* window check */
+       tt = d->targets;
+       te = tt + d->ntargets;
+       for (; tt < te && (t = *tt); tt++) {
                if (t->nout == t->maxout
                && t->maxout < t->nframes
                && (jiffies - t->lastwadj)/HZ > 10) {
@@ -557,45 +611,173 @@ rexmit_timer(ulong vp)
                }
        }
 
-       if (!skb_queue_empty(&d->sendq)) {
+       if (!list_empty(&flist)) {      /* retransmissions necessary */
                n = d->rttavg <<= 1;
                if (n > MAXTIMER)
                        d->rttavg = MAXTIMER;
        }
 
-       if (d->flags & DEVFL_KICKME || d->htgt) {
-               d->flags &= ~DEVFL_KICKME;
-               aoecmd_work(d);
+       /* process expired frames */
+       while (!list_empty(&flist)) {
+               pos = flist.next;
+               f = list_entry(pos, struct frame, head);
+               n = f->waited += timeout;
+               n /= HZ;
+               if (n > aoe_deadsecs) {
+                       /* Waited too long.  Device failure.
+                        * Hang all frames on first hash bucket for downdev
+                        * to clean up.
+                        */
+                       list_splice(&flist, &d->factive[0]);
+                       aoedev_downdev(d);
+                       break;
+               }
+               list_del(pos);
+
+               t = f->t;
+               if (n > aoe_deadsecs/2)
+                       d->htgt = t; /* see if another target can help */
+
+               if (t->nout == t->maxout) {
+                       if (t->maxout > 1)
+                               t->maxout--;
+                       t->lastwadj = jiffies;
+               }
+
+               ifp = getif(t, f->skb->dev);
+               if (ifp && ++ifp->lost > (t->nframes << 1)
+               && (ifp != t->ifs || t->ifs[1].nd)) {
+                       ejectif(t, ifp);
+                       ifp = NULL;
+               }
+               resend(d, f);
        }
 
-       __skb_queue_head_init(&queue);
-       skb_queue_splice_init(&d->sendq, &queue);
+       if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) {
+               d->flags &= ~DEVFL_KICKME;
+               d->blkq->request_fn(d->blkq);
+       }
 
        d->timer.expires = jiffies + TIMERTICK;
        add_timer(&d->timer);
 
        spin_unlock_irqrestore(&d->lock, flags);
+}
 
-       aoenet_xmit(&queue);
+static unsigned long
+rqbiocnt(struct request *r)
+{
+       struct bio *bio;
+       unsigned long n = 0;
+
+       __rq_for_each_bio(bio, r)
+               n++;
+       return n;
+}
+
+/* This can be removed if we are certain that no users of the block
+ * layer will ever use zero-count pages in bios.  Otherwise we have to
+ * protect against the put_page sometimes done by the network layer.
+ *
+ * See http://oss.sgi.com/archives/xfs/2007-01/msg00594.html for
+ * discussion.
+ *
+ * We cannot use get_page in the workaround, because it insists on a
+ * positive page count as a precondition.  So we use _count directly.
+ */
+static void
+bio_pageinc(struct bio *bio)
+{
+       struct bio_vec *bv;
+       struct page *page;
+       int i;
+
+       bio_for_each_segment(bv, bio, i) {
+               page = bv->bv_page;
+               /* Non-zero page count for non-head members of
+                * compound pages is no longer allowed by the kernel,
+                * but this has never been seen here.
+                */
+               if (unlikely(PageCompound(page)))
+                       if (compound_trans_head(page) != page) {
+                               pr_crit("page tail used for block I/O\n");
+                               BUG();
+                       }
+               atomic_inc(&page->_count);
+       }
+}
+
+static void
+bio_pagedec(struct bio *bio)
+{
+       struct bio_vec *bv;
+       int i;
+
+       bio_for_each_segment(bv, bio, i)
+               atomic_dec(&bv->bv_page->_count);
+}
+
+static void
+bufinit(struct buf *buf, struct request *rq, struct bio *bio)
+{
+       struct bio_vec *bv;
+
+       memset(buf, 0, sizeof(*buf));
+       buf->rq = rq;
+       buf->bio = bio;
+       buf->resid = bio->bi_size;
+       buf->sector = bio->bi_sector;
+       bio_pageinc(bio);
+       buf->bv = bv = &bio->bi_io_vec[bio->bi_idx];
+       buf->bv_resid = bv->bv_len;
+       WARN_ON(buf->bv_resid == 0);
+}
+
+static struct buf *
+nextbuf(struct aoedev *d)
+{
+       struct request *rq;
+       struct request_queue *q;
+       struct buf *buf;
+       struct bio *bio;
+
+       q = d->blkq;
+       if (q == NULL)
+               return NULL;    /* initializing */
+       if (d->ip.buf)
+               return d->ip.buf;
+       rq = d->ip.rq;
+       if (rq == NULL) {
+               rq = blk_peek_request(q);
+               if (rq == NULL)
+                       return NULL;
+               blk_start_request(rq);
+               d->ip.rq = rq;
+               d->ip.nxbio = rq->bio;
+               rq->special = (void *) rqbiocnt(rq);
+       }
+       buf = mempool_alloc(d->bufpool, GFP_ATOMIC);
+       if (buf == NULL) {
+               pr_err("aoe: nextbuf: unable to mempool_alloc!\n");
+               return NULL;
+       }
+       bio = d->ip.nxbio;
+       bufinit(buf, rq, bio);
+       bio = bio->bi_next;
+       d->ip.nxbio = bio;
+       if (bio == NULL)
+               d->ip.rq = NULL;
+       return d->ip.buf = buf;
 }
 
 /* enters with d->lock held */
 void
 aoecmd_work(struct aoedev *d)
 {
-       struct buf *buf;
-loop:
        if (d->htgt && !sthtith(d))
                return;
-       if (d->inprocess == NULL) {
-               if (list_empty(&d->bufq))
-                       return;
-               buf = container_of(d->bufq.next, struct buf, bufs);
-               list_del(d->bufq.next);
-               d->inprocess = buf;
-       }
-       if (aoecmd_ata_rw(d))
-               goto loop;
+       while (aoecmd_ata_rw(d))
+               ;
 }
 
 /* this function performs work that has been deferred until sleeping is OK
@@ -604,28 +786,25 @@ void
 aoecmd_sleepwork(struct work_struct *work)
 {
        struct aoedev *d = container_of(work, struct aoedev, work);
+       struct block_device *bd;
+       u64 ssize;
 
        if (d->flags & DEVFL_GDALLOC)
                aoeblk_gdalloc(d);
 
        if (d->flags & DEVFL_NEWSIZE) {
-               struct block_device *bd;
-               unsigned long flags;
-               u64 ssize;
-
                ssize = get_capacity(d->gd);
                bd = bdget_disk(d->gd, 0);
-
                if (bd) {
                        mutex_lock(&bd->bd_inode->i_mutex);
                        i_size_write(bd->bd_inode, (loff_t)ssize<<9);
                        mutex_unlock(&bd->bd_inode->i_mutex);
                        bdput(bd);
                }
-               spin_lock_irqsave(&d->lock, flags);
+               spin_lock_irq(&d->lock);
                d->flags |= DEVFL_UP;
                d->flags &= ~DEVFL_NEWSIZE;
-               spin_unlock_irqrestore(&d->lock, flags);
+               spin_unlock_irq(&d->lock);
        }
 }
 
@@ -718,163 +897,299 @@ gettgt(struct aoedev *d, char *addr)
        return NULL;
 }
 
-static inline void
-diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector)
+static void
+bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt)
+{
+       ulong fcnt;
+       char *p;
+       int soff = 0;
+loop:
+       fcnt = bv->bv_len - (off - bv->bv_offset);
+       if (fcnt > cnt)
+               fcnt = cnt;
+       p = page_address(bv->bv_page) + off;
+       skb_copy_bits(skb, soff, p, fcnt);
+       soff += fcnt;
+       cnt -= fcnt;
+       if (cnt <= 0)
+               return;
+       bv++;
+       off = bv->bv_offset;
+       goto loop;
+}
+
+void
+aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
+{
+       struct bio *bio;
+       int bok;
+       struct request_queue *q;
+
+       q = d->blkq;
+       if (rq == d->ip.rq)
+               d->ip.rq = NULL;
+       do {
+               bio = rq->bio;
+               bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags);
+       } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size));
+
+       /* cf. http://lkml.org/lkml/2006/10/31/28 */
+       if (!fastfail)
+               q->request_fn(q);
+}
+
+static void
+aoe_end_buf(struct aoedev *d, struct buf *buf)
+{
+       struct request *rq;
+       unsigned long n;
+
+       if (buf == d->ip.buf)
+               d->ip.buf = NULL;
+       rq = buf->rq;
+       bio_pagedec(buf->bio);
+       mempool_free(buf, d->bufpool);
+       n = (unsigned long) rq->special;
+       rq->special = (void *) --n;
+       if (n == 0)
+               aoe_end_request(d, rq, 0);
+}
+
+static void
+ktiocomplete(struct frame *f)
 {
-       unsigned long n_sect = bio->bi_size >> 9;
-       const int rw = bio_data_dir(bio);
-       struct hd_struct *part;
-       int cpu;
+       struct aoe_hdr *hin, *hout;
+       struct aoe_atahdr *ahin, *ahout;
+       struct buf *buf;
+       struct sk_buff *skb;
+       struct aoetgt *t;
+       struct aoeif *ifp;
+       struct aoedev *d;
+       long n;
+
+       if (f == NULL)
+               return;
+
+       t = f->t;
+       d = t->d;
+
+       hout = (struct aoe_hdr *) skb_mac_header(f->skb);
+       ahout = (struct aoe_atahdr *) (hout+1);
+       buf = f->buf;
+       skb = f->r_skb;
+       if (skb == NULL)
+               goto noskb;     /* just fail the buf. */
+
+       hin = (struct aoe_hdr *) skb->data;
+       skb_pull(skb, sizeof(*hin));
+       ahin = (struct aoe_atahdr *) skb->data;
+       skb_pull(skb, sizeof(*ahin));
+       if (ahin->cmdstat & 0xa9) {     /* these bits cleared on success */
+               pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
+                       ahout->cmdstat, ahin->cmdstat,
+                       d->aoemajor, d->aoeminor);
+noskb: if (buf)
+                       clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+               goto badrsp;
+       }
 
-       cpu = part_stat_lock();
-       part = disk_map_sector_rcu(disk, sector);
+       n = ahout->scnt << 9;
+       switch (ahout->cmdstat) {
+       case ATA_CMD_PIO_READ:
+       case ATA_CMD_PIO_READ_EXT:
+               if (skb->len < n) {
+                       pr_err("aoe: runt data size in read.  skb->len=%d need=%ld\n",
+                               skb->len, n);
+                       clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+                       break;
+               }
+               bvcpy(f->bv, f->bv_off, skb, n);
+       case ATA_CMD_PIO_WRITE:
+       case ATA_CMD_PIO_WRITE_EXT:
+               spin_lock_irq(&d->lock);
+               ifp = getif(t, skb->dev);
+               if (ifp)
+                       ifp->lost = 0;
+               if (d->htgt == t) /* I'll help myself, thank you. */
+                       d->htgt = NULL;
+               spin_unlock_irq(&d->lock);
+               break;
+       case ATA_CMD_ID_ATA:
+               if (skb->len < 512) {
+                       pr_info("aoe: runt data size in ataid.  skb->len=%d\n",
+                               skb->len);
+                       break;
+               }
+               if (skb_linearize(skb))
+                       break;
+               spin_lock_irq(&d->lock);
+               ataid_complete(d, t, skb->data);
+               spin_unlock_irq(&d->lock);
+               break;
+       default:
+               pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n",
+                       ahout->cmdstat,
+                       be16_to_cpu(get_unaligned(&hin->major)),
+                       hin->minor);
+       }
+badrsp:
+       spin_lock_irq(&d->lock);
+
+       aoe_freetframe(f);
+
+       if (buf && --buf->nframesout == 0 && buf->resid == 0)
+               aoe_end_buf(d, buf);
+
+       aoecmd_work(d);
+
+       spin_unlock_irq(&d->lock);
+       aoedev_put(d);
+       dev_kfree_skb(skb);
+}
+
+/* Enters with iocq.lock held.
+ * Returns true iff responses needing processing remain.
+ */
+static int
+ktio(void)
+{
+       struct frame *f;
+       struct list_head *pos;
+       int i;
 
-       part_stat_inc(cpu, part, ios[rw]);
-       part_stat_add(cpu, part, ticks[rw], duration);
-       part_stat_add(cpu, part, sectors[rw], n_sect);
-       part_stat_add(cpu, part, io_ticks, duration);
+       for (i = 0; ; ++i) {
+               if (i == MAXIOC)
+                       return 1;
+               if (list_empty(&iocq.head))
+                       return 0;
+               pos = iocq.head.next;
+               list_del(pos);
+               spin_unlock_irq(&iocq.lock);
+               f = list_entry(pos, struct frame, head);
+               ktiocomplete(f);
+               spin_lock_irq(&iocq.lock);
+       }
+}
 
-       part_stat_unlock();
+static int
+kthread(void *vp)
+{
+       struct ktstate *k;
+       DECLARE_WAITQUEUE(wait, current);
+       int more;
+
+       k = vp;
+       current->flags |= PF_NOFREEZE;
+       set_user_nice(current, -10);
+       complete(&k->rendez);   /* tell spawner we're running */
+       do {
+               spin_lock_irq(k->lock);
+               more = k->fn();
+               if (!more) {
+                       add_wait_queue(k->waitq, &wait);
+                       __set_current_state(TASK_INTERRUPTIBLE);
+               }
+               spin_unlock_irq(k->lock);
+               if (!more) {
+                       schedule();
+                       remove_wait_queue(k->waitq, &wait);
+               } else
+                       cond_resched();
+       } while (!kthread_should_stop());
+       complete(&k->rendez);   /* tell spawner we're stopping */
+       return 0;
 }
 
 void
+aoe_ktstop(struct ktstate *k)
+{
+       kthread_stop(k->task);
+       wait_for_completion(&k->rendez);
+}
+
+int
+aoe_ktstart(struct ktstate *k)
+{
+       struct task_struct *task;
+
+       init_completion(&k->rendez);
+       task = kthread_run(kthread, k, k->name);
+       if (task == NULL || IS_ERR(task))
+               return -ENOMEM;
+       k->task = task;
+       wait_for_completion(&k->rendez); /* allow kthread to start */
+       init_completion(&k->rendez);    /* for waiting for exit later */
+       return 0;
+}
+
+/* pass it off to kthreads for processing */
+static void
+ktcomplete(struct frame *f, struct sk_buff *skb)
+{
+       ulong flags;
+
+       f->r_skb = skb;
+       spin_lock_irqsave(&iocq.lock, flags);
+       list_add_tail(&f->head, &iocq.head);
+       spin_unlock_irqrestore(&iocq.lock, flags);
+       wake_up(&ktiowq);
+}
+
+struct sk_buff *
 aoecmd_ata_rsp(struct sk_buff *skb)
 {
-       struct sk_buff_head queue;
        struct aoedev *d;
-       struct aoe_hdr *hin, *hout;
-       struct aoe_atahdr *ahin, *ahout;
+       struct aoe_hdr *h;
        struct frame *f;
-       struct buf *buf;
        struct aoetgt *t;
-       struct aoeif *ifp;
-       register long n;
+       u32 n;
        ulong flags;
        char ebuf[128];
        u16 aoemajor;
 
-       hin = (struct aoe_hdr *) skb_mac_header(skb);
-       aoemajor = get_unaligned_be16(&hin->major);
-       d = aoedev_by_aoeaddr(aoemajor, hin->minor);
+       h = (struct aoe_hdr *) skb->data;
+       aoemajor = be16_to_cpu(get_unaligned(&h->major));
+       d = aoedev_by_aoeaddr(aoemajor, h->minor, 0);
        if (d == NULL) {
                snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
                        "for unknown device %d.%d\n",
-                        aoemajor, hin->minor);
+                       aoemajor, h->minor);
                aoechr_error(ebuf);
-               return;
+               return skb;
        }
 
        spin_lock_irqsave(&d->lock, flags);
 
-       n = get_unaligned_be32(&hin->tag);
-       t = gettgt(d, hin->src);
-       if (t == NULL) {
-               printk(KERN_INFO "aoe: can't find target e%ld.%d:%pm\n",
-                       d->aoemajor, d->aoeminor, hin->src);
-               spin_unlock_irqrestore(&d->lock, flags);
-               return;
-       }
-       f = getframe(t, n);
+       n = be32_to_cpu(get_unaligned(&h->tag));
+       f = getframe(d, n);
        if (f == NULL) {
                calc_rttavg(d, -tsince(n));
                spin_unlock_irqrestore(&d->lock, flags);
+               aoedev_put(d);
                snprintf(ebuf, sizeof ebuf,
                        "%15s e%d.%d    tag=%08x@%08lx\n",
                        "unexpected rsp",
-                       get_unaligned_be16(&hin->major),
-                       hin->minor,
-                       get_unaligned_be32(&hin->tag),
+                       get_unaligned_be16(&h->major),
+                       h->minor,
+                       get_unaligned_be32(&h->tag),
                        jiffies);
                aoechr_error(ebuf);
-               return;
+               return skb;
        }
-
+       t = f->t;
        calc_rttavg(d, tsince(f->tag));
-
-       ahin = (struct aoe_atahdr *) (hin+1);
-       hout = (struct aoe_hdr *) skb_mac_header(f->skb);
-       ahout = (struct aoe_atahdr *) (hout+1);
-       buf = f->buf;
-
-       if (ahin->cmdstat & 0xa9) {     /* these bits cleared on success */
-               printk(KERN_ERR
-                       "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
-                       ahout->cmdstat, ahin->cmdstat,
-                       d->aoemajor, d->aoeminor);
-               if (buf)
-                       buf->flags |= BUFFL_FAIL;
-       } else {
-               if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */
-                       d->htgt = NULL;
-               n = ahout->scnt << 9;
-               switch (ahout->cmdstat) {
-               case ATA_CMD_PIO_READ:
-               case ATA_CMD_PIO_READ_EXT:
-                       if (skb->len - sizeof *hin - sizeof *ahin < n) {
-                               printk(KERN_ERR
-                                       "aoe: %s.  skb->len=%d need=%ld\n",
-                                       "runt data size in read", skb->len, n);
-                               /* fail frame f?  just returning will rexmit. */
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-                       memcpy(f->bufaddr, ahin+1, n);
-               case ATA_CMD_PIO_WRITE:
-               case ATA_CMD_PIO_WRITE_EXT:
-                       ifp = getif(t, skb->dev);
-                       if (ifp) {
-                               ifp->lost = 0;
-                               if (n > DEFAULTBCNT)
-                                       ifp->lostjumbo = 0;
-                       }
-                       if (f->bcnt -= n) {
-                               f->lba += n >> 9;
-                               f->bufaddr += n;
-                               resend(d, t, f);
-                               goto xmit;
-                       }
-                       break;
-               case ATA_CMD_ID_ATA:
-                       if (skb->len - sizeof *hin - sizeof *ahin < 512) {
-                               printk(KERN_INFO
-                                       "aoe: runt data size in ataid.  skb->len=%d\n",
-                                       skb->len);
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-                       ataid_complete(d, t, (char *) (ahin+1));
-                       break;
-               default:
-                       printk(KERN_INFO
-                               "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
-                               ahout->cmdstat,
-                               get_unaligned_be16(&hin->major),
-                               hin->minor);
-               }
-       }
-
-       if (buf && --buf->nframesout == 0 && buf->resid == 0) {
-               diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector);
-               if (buf->flags & BUFFL_FAIL)
-                       bio_endio(buf->bio, -EIO);
-               else {
-                       bio_flush_dcache_pages(buf->bio);
-                       bio_endio(buf->bio, 0);
-               }
-               mempool_free(buf, d->bufpool);
-       }
-
-       f->buf = NULL;
-       f->tag = FREETAG;
        t->nout--;
-
        aoecmd_work(d);
-xmit:
-       __skb_queue_head_init(&queue);
-       skb_queue_splice_init(&d->sendq, &queue);
 
        spin_unlock_irqrestore(&d->lock, flags);
-       aoenet_xmit(&queue);
+
+       ktcomplete(f, skb);
+
+       /*
+        * Note here that we do not perform an aoedev_put, as we are
+        * leaving this reference for the ktio to release.
+        */
+       return NULL;
 }
 
 void
@@ -896,7 +1211,7 @@ aoecmd_ata_id(struct aoedev *d)
        struct sk_buff *skb;
        struct aoetgt *t;
 
-       f = freeframe(d);
+       f = newframe(d);
        if (f == NULL)
                return NULL;
 
@@ -909,6 +1224,7 @@ aoecmd_ata_id(struct aoedev *d)
        skb_put(skb, sizeof *h + sizeof *ah);
        memset(h, 0, skb->len);
        f->tag = aoehdr_atainit(d, t, h);
+       fhash(f);
        t->nout++;
        f->waited = 0;
 
@@ -929,7 +1245,6 @@ static struct aoetgt *
 addtgt(struct aoedev *d, char *addr, ulong nframes)
 {
        struct aoetgt *t, **tt, **te;
-       struct frame *f, *e;
 
        tt = d->targets;
        te = tt + NTARGETS;
@@ -941,26 +1256,73 @@ addtgt(struct aoedev *d, char *addr, ulong nframes)
                        "aoe: device addtgt failure; too many targets\n");
                return NULL;
        }
-       t = kcalloc(1, sizeof *t, GFP_ATOMIC);
-       f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
-       if (!t || !f) {
-               kfree(f);
-               kfree(t);
+       t = kzalloc(sizeof(*t), GFP_ATOMIC);
+       if (!t) {
                printk(KERN_INFO "aoe: cannot allocate memory to add target\n");
                return NULL;
        }
 
+       d->ntargets++;
        t->nframes = nframes;
-       t->frames = f;
-       e = f + nframes;
-       for (; f < e; f++)
-               f->tag = FREETAG;
+       t->d = d;
        memcpy(t->addr, addr, sizeof t->addr);
        t->ifp = t->ifs;
        t->maxout = t->nframes;
+       INIT_LIST_HEAD(&t->ffree);
        return *tt = t;
 }
 
+static void
+setdbcnt(struct aoedev *d)
+{
+       struct aoetgt **t, **e;
+       int bcnt = 0;
+
+       t = d->targets;
+       e = t + NTARGETS;
+       for (; t < e && *t; t++)
+               if (bcnt == 0 || bcnt > (*t)->minbcnt)
+                       bcnt = (*t)->minbcnt;
+       if (bcnt != d->maxbcnt) {
+               d->maxbcnt = bcnt;
+               pr_info("aoe: e%ld.%d: setting %d byte data frames\n",
+                       d->aoemajor, d->aoeminor, bcnt);
+       }
+}
+
+static void
+setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt)
+{
+       struct aoedev *d;
+       struct aoeif *p, *e;
+       int minbcnt;
+
+       d = t->d;
+       minbcnt = bcnt;
+       p = t->ifs;
+       e = p + NAOEIFS;
+       for (; p < e; p++) {
+               if (p->nd == NULL)
+                       break;          /* end of the valid interfaces */
+               if (p->nd == nd) {
+                       p->bcnt = bcnt; /* we're updating */
+                       nd = NULL;
+               } else if (minbcnt > p->bcnt)
+                       minbcnt = p->bcnt; /* find the min interface */
+       }
+       if (nd) {
+               if (p == e) {
+                       pr_err("aoe: device setifbcnt failure; too many interfaces.\n");
+                       return;
+               }
+               dev_hold(nd);
+               p->nd = nd;
+               p->bcnt = bcnt;
+       }
+       t->minbcnt = minbcnt;
+       setdbcnt(d);
+}
+
 void
 aoecmd_cfg_rsp(struct sk_buff *skb)
 {
@@ -968,11 +1330,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
        struct aoe_hdr *h;
        struct aoe_cfghdr *ch;
        struct aoetgt *t;
-       struct aoeif *ifp;
-       ulong flags, sysminor, aoemajor;
+       ulong flags, aoemajor;
        struct sk_buff *sl;
+       struct sk_buff_head queue;
        u16 n;
 
+       sl = NULL;
        h = (struct aoe_hdr *) skb_mac_header(skb);
        ch = (struct aoe_cfghdr *) (h+1);
 
@@ -986,10 +1349,13 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
                        "Check shelf dip switches.\n");
                return;
        }
-
-       sysminor = SYSMINOR(aoemajor, h->minor);
-       if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {
-               printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n",
+       if (aoemajor == 0xffff) {
+               pr_info("aoe: e%ld.%d: broadcast shelf number invalid\n",
+                       aoemajor, (int) h->minor);
+               return;
+       }
+       if (h->minor == 0xff) {
+               pr_info("aoe: e%ld.%d: broadcast slot number invalid\n",
                        aoemajor, (int) h->minor);
                return;
        }
@@ -998,9 +1364,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
        if (n > aoe_maxout)     /* keep it reasonable */
                n = aoe_maxout;
 
-       d = aoedev_by_sysminor_m(sysminor);
+       d = aoedev_by_aoeaddr(aoemajor, h->minor, 1);
        if (d == NULL) {
-               printk(KERN_INFO "aoe: device sysminor_m failure\n");
+               pr_info("aoe: device allocation failure\n");
                return;
        }
 
@@ -1009,52 +1375,26 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
        t = gettgt(d, h->src);
        if (!t) {
                t = addtgt(d, h->src, n);
-               if (!t) {
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return;
-               }
-       }
-       ifp = getif(t, skb->dev);
-       if (!ifp) {
-               ifp = addif(t, skb->dev);
-               if (!ifp) {
-                       printk(KERN_INFO
-                               "aoe: device addif failure; "
-                               "too many interfaces?\n");
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return;
-               }
-       }
-       if (ifp->maxbcnt) {
-               n = ifp->nd->mtu;
-               n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
-               n /= 512;
-               if (n > ch->scnt)
-                       n = ch->scnt;
-               n = n ? n * 512 : DEFAULTBCNT;
-               if (n != ifp->maxbcnt) {
-                       printk(KERN_INFO
-                               "aoe: e%ld.%d: setting %d%s%s:%pm\n",
-                               d->aoemajor, d->aoeminor, n,
-                               " byte data frames on ", ifp->nd->name,
-                               t->addr);
-                       ifp->maxbcnt = n;
-               }
+               if (!t)
+                       goto bail;
        }
+       n = skb->dev->mtu;
+       n -= sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
+       n /= 512;
+       if (n > ch->scnt)
+               n = ch->scnt;
+       n = n ? n * 512 : DEFAULTBCNT;
+       setifbcnt(t, skb->dev, n);
 
        /* don't change users' perspective */
-       if (d->nopen) {
-               spin_unlock_irqrestore(&d->lock, flags);
-               return;
+       if (d->nopen == 0) {
+               d->fw_ver = be16_to_cpu(ch->fwver);
+               sl = aoecmd_ata_id(d);
        }
-       d->fw_ver = be16_to_cpu(ch->fwver);
-
-       sl = aoecmd_ata_id(d);
-
+bail:
        spin_unlock_irqrestore(&d->lock, flags);
-
+       aoedev_put(d);
        if (sl) {
-               struct sk_buff_head queue;
                __skb_queue_head_init(&queue);
                __skb_queue_tail(&queue, sl);
                aoenet_xmit(&queue);
@@ -1065,20 +1405,74 @@ void
 aoecmd_cleanslate(struct aoedev *d)
 {
        struct aoetgt **t, **te;
-       struct aoeif *p, *e;
 
        d->mintimer = MINTIMER;
+       d->maxbcnt = 0;
 
        t = d->targets;
        te = t + NTARGETS;
-       for (; t < te && *t; t++) {
+       for (; t < te && *t; t++)
                (*t)->maxout = (*t)->nframes;
-               p = (*t)->ifs;
-               e = p + NAOEIFS;
-               for (; p < e; p++) {
-                       p->lostjumbo = 0;
-                       p->lost = 0;
-                       p->maxbcnt = DEFAULTBCNT;
+}
+
+void
+aoe_failbuf(struct aoedev *d, struct buf *buf)
+{
+       if (buf == NULL)
+               return;
+       buf->resid = 0;
+       clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+       if (buf->nframesout == 0)
+               aoe_end_buf(d, buf);
+}
+
+void
+aoe_flush_iocq(void)
+{
+       struct frame *f;
+       struct aoedev *d;
+       LIST_HEAD(flist);
+       struct list_head *pos;
+       struct sk_buff *skb;
+       ulong flags;
+
+       spin_lock_irqsave(&iocq.lock, flags);
+       list_splice_init(&iocq.head, &flist);
+       spin_unlock_irqrestore(&iocq.lock, flags);
+       while (!list_empty(&flist)) {
+               pos = flist.next;
+               list_del(pos);
+               f = list_entry(pos, struct frame, head);
+               d = f->t->d;
+               skb = f->r_skb;
+               spin_lock_irqsave(&d->lock, flags);
+               if (f->buf) {
+                       f->buf->nframesout--;
+                       aoe_failbuf(d, f->buf);
                }
+               aoe_freetframe(f);
+               spin_unlock_irqrestore(&d->lock, flags);
+               dev_kfree_skb(skb);
+               aoedev_put(d);
        }
 }
+
+int __init
+aoecmd_init(void)
+{
+       INIT_LIST_HEAD(&iocq.head);
+       spin_lock_init(&iocq.lock);
+       init_waitqueue_head(&ktiowq);
+       kts.name = "aoe_ktio";
+       kts.fn = ktio;
+       kts.waitq = &ktiowq;
+       kts.lock = &iocq.lock;
+       return aoe_ktstart(&kts);
+}
+
+void
+aoecmd_exit(void)
+{
+       aoe_ktstop(&kts);
+       aoe_flush_iocq();
+}
index 6b5110a474582fb296e7abbb0076c99a466d7fc8..90e5b537f94bf3875afe7f73404a626a9994c37a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoedev.c
  * AoE device utility functions; maintains device list.
@@ -9,6 +9,9 @@
 #include <linux/netdevice.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/bitmap.h>
+#include <linux/kdev_t.h>
+#include <linux/moduleparam.h>
 #include "aoe.h"
 
 static void dummy_timer(ulong);
@@ -16,23 +19,121 @@ static void aoedev_freedev(struct aoedev *);
 static void freetgt(struct aoedev *d, struct aoetgt *t);
 static void skbpoolfree(struct aoedev *d);
 
+static int aoe_dyndevs = 1;
+module_param(aoe_dyndevs, int, 0644);
+MODULE_PARM_DESC(aoe_dyndevs, "Use dynamic minor numbers for devices.");
+
 static struct aoedev *devlist;
 static DEFINE_SPINLOCK(devlist_lock);
 
-struct aoedev *
-aoedev_by_aoeaddr(int maj, int min)
+/* Because some systems will have one, many, or no
+ *   - partitions,
+ *   - slots per shelf,
+ *   - or shelves,
+ * we need some flexibility in the way the minor numbers
+ * are allocated.  So they are dynamic.
+ */
+#define N_DEVS ((1U<<MINORBITS)/AOE_PARTITIONS)
+
+static DEFINE_SPINLOCK(used_minors_lock);
+static DECLARE_BITMAP(used_minors, N_DEVS);
+
+static int
+minor_get_dyn(ulong *sysminor)
 {
-       struct aoedev *d;
        ulong flags;
+       ulong n;
+       int error = 0;
+
+       spin_lock_irqsave(&used_minors_lock, flags);
+       n = find_first_zero_bit(used_minors, N_DEVS);
+       if (n < N_DEVS)
+               set_bit(n, used_minors);
+       else
+               error = -1;
+       spin_unlock_irqrestore(&used_minors_lock, flags);
+
+       *sysminor = n * AOE_PARTITIONS;
+       return error;
+}
 
-       spin_lock_irqsave(&devlist_lock, flags);
+static int
+minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin)
+{
+       ulong flags;
+       ulong n;
+       int error = 0;
+       enum {
+               /* for backwards compatibility when !aoe_dyndevs,
+                * a static number of supported slots per shelf */
+               NPERSHELF = 16,
+       };
+
+       n = aoemaj * NPERSHELF + aoemin;
+       if (aoemin >= NPERSHELF || n >= N_DEVS) {
+               pr_err("aoe: %s with e%ld.%d\n",
+                       "cannot use static minor device numbers",
+                       aoemaj, aoemin);
+               error = -1;
+       } else {
+               spin_lock_irqsave(&used_minors_lock, flags);
+               if (test_bit(n, used_minors)) {
+                       pr_err("aoe: %s %lu\n",
+                               "existing device already has static minor number",
+                               n);
+                       error = -1;
+               } else
+                       set_bit(n, used_minors);
+               spin_unlock_irqrestore(&used_minors_lock, flags);
+       }
 
-       for (d=devlist; d; d=d->next)
-               if (d->aoemajor == maj && d->aoeminor == min)
-                       break;
+       *sysminor = n;
+       return error;
+}
+
+static int
+minor_get(ulong *sysminor, ulong aoemaj, int aoemin)
+{
+       if (aoe_dyndevs)
+               return minor_get_dyn(sysminor);
+       else
+               return minor_get_static(sysminor, aoemaj, aoemin);
+}
+
+static void
+minor_free(ulong minor)
+{
+       ulong flags;
+
+       minor /= AOE_PARTITIONS;
+       BUG_ON(minor >= N_DEVS);
+
+       spin_lock_irqsave(&used_minors_lock, flags);
+       BUG_ON(!test_bit(minor, used_minors));
+       clear_bit(minor, used_minors);
+       spin_unlock_irqrestore(&used_minors_lock, flags);
+}
+
+/*
+ * Users who grab a pointer to the device with aoedev_by_aoeaddr
+ * automatically get a reference count and must be responsible
+ * for performing a aoedev_put.  With the addition of async
+ * kthread processing I'm no longer confident that we can
+ * guarantee consistency in the face of device flushes.
+ *
+ * For the time being, we only bother to add extra references for
+ * frames sitting on the iocq.  When the kthreads finish processing
+ * these frames, they will aoedev_put the device.
+ */
+
+void
+aoedev_put(struct aoedev *d)
+{
+       ulong flags;
 
+       spin_lock_irqsave(&devlist_lock, flags);
+       d->ref--;
        spin_unlock_irqrestore(&devlist_lock, flags);
-       return d;
 }
 
 static void
@@ -47,54 +148,74 @@ dummy_timer(ulong vp)
        add_timer(&d->timer);
 }
 
+static void
+aoe_failip(struct aoedev *d)
+{
+       struct request *rq;
+       struct bio *bio;
+       unsigned long n;
+
+       aoe_failbuf(d, d->ip.buf);
+
+       rq = d->ip.rq;
+       if (rq == NULL)
+               return;
+       while ((bio = d->ip.nxbio)) {
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
+               d->ip.nxbio = bio->bi_next;
+               n = (unsigned long) rq->special;
+               rq->special = (void *) --n;
+       }
+       if ((unsigned long) rq->special == 0)
+               aoe_end_request(d, rq, 0);
+}
+
 void
 aoedev_downdev(struct aoedev *d)
 {
-       struct aoetgt **t, **te;
-       struct frame *f, *e;
-       struct buf *buf;
-       struct bio *bio;
+       struct aoetgt *t, **tt, **te;
+       struct frame *f;
+       struct list_head *head, *pos, *nx;
+       struct request *rq;
+       int i;
 
-       t = d->targets;
-       te = t + NTARGETS;
-       for (; t < te && *t; t++) {
-               f = (*t)->frames;
-               e = f + (*t)->nframes;
-               for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) {
-                       if (f->tag == FREETAG || f->buf == NULL)
-                               continue;
-                       buf = f->buf;
-                       bio = buf->bio;
-                       if (--buf->nframesout == 0
-                       && buf != d->inprocess) {
-                               mempool_free(buf, d->bufpool);
-                               bio_endio(bio, -EIO);
+       d->flags &= ~DEVFL_UP;
+
+       /* clean out active buffers */
+       for (i = 0; i < NFACTIVE; i++) {
+               head = &d->factive[i];
+               list_for_each_safe(pos, nx, head) {
+                       f = list_entry(pos, struct frame, head);
+                       list_del(pos);
+                       if (f->buf) {
+                               f->buf->nframesout--;
+                               aoe_failbuf(d, f->buf);
                        }
+                       aoe_freetframe(f);
                }
-               (*t)->maxout = (*t)->nframes;
-               (*t)->nout = 0;
        }
-       buf = d->inprocess;
-       if (buf) {
-               bio = buf->bio;
-               mempool_free(buf, d->bufpool);
-               bio_endio(bio, -EIO);
+       /* reset window dressings */
+       tt = d->targets;
+       te = tt + NTARGETS;
+       for (; tt < te && (t = *tt); tt++) {
+               t->maxout = t->nframes;
+               t->nout = 0;
        }
-       d->inprocess = NULL;
+
+       /* clean out the in-process request (if any) */
+       aoe_failip(d);
        d->htgt = NULL;
 
-       while (!list_empty(&d->bufq)) {
-               buf = container_of(d->bufq.next, struct buf, bufs);
-               list_del(d->bufq.next);
-               bio = buf->bio;
-               mempool_free(buf, d->bufpool);
-               bio_endio(bio, -EIO);
+       /* fast fail all pending I/O */
+       if (d->blkq) {
+               while ((rq = blk_peek_request(d->blkq))) {
+                       blk_start_request(rq);
+                       aoe_end_request(d, rq, 1);
+               }
        }
 
        if (d->gd)
                set_capacity(d->gd, 0);
-
-       d->flags &= ~DEVFL_UP;
 }
 
 static void
@@ -107,6 +228,7 @@ aoedev_freedev(struct aoedev *d)
                aoedisk_rm_sysfs(d);
                del_gendisk(d->gd);
                put_disk(d->gd);
+               blk_cleanup_queue(d->blkq);
        }
        t = d->targets;
        e = t + NTARGETS;
@@ -115,7 +237,7 @@ aoedev_freedev(struct aoedev *d)
        if (d->bufpool)
                mempool_destroy(d->bufpool);
        skbpoolfree(d);
-       blk_cleanup_queue(d->blkq);
+       minor_free(d->sysminor);
        kfree(d);
 }
 
@@ -142,7 +264,8 @@ aoedev_flush(const char __user *str, size_t cnt)
                spin_lock(&d->lock);
                if ((!all && (d->flags & DEVFL_UP))
                || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
-               || d->nopen) {
+               || d->nopen
+               || d->ref) {
                        spin_unlock(&d->lock);
                        dd = &d->next;
                        continue;
@@ -163,12 +286,15 @@ aoedev_flush(const char __user *str, size_t cnt)
        return 0;
 }
 
-/* I'm not really sure that this is a realistic problem, but if the
-network driver goes gonzo let's just leak memory after complaining. */
+/* This has been confirmed to occur once with Tms=3*1000 due to the
+ * driver changing link and not processing its transmit ring.  The
+ * problem is hard enough to solve by returning an error that I'm
+ * still punting on "solving" this.
+ */
 static void
 skbfree(struct sk_buff *skb)
 {
-       enum { Sms = 100, Tms = 3*1000};
+       enum { Sms = 250, Tms = 30 * 1000};
        int i = Tms / Sms;
 
        if (skb == NULL)
@@ -182,6 +308,7 @@ skbfree(struct sk_buff *skb)
                        "cannot free skb -- memory leaked.");
                return;
        }
+       skb->truesize -= skb->data_len;
        skb_shinfo(skb)->nr_frags = skb->data_len = 0;
        skb_trim(skb, 0);
        dev_kfree_skb(skb);
@@ -198,26 +325,29 @@ skbpoolfree(struct aoedev *d)
        __skb_queue_head_init(&d->skbpool);
 }
 
-/* find it or malloc it */
+/* find it or allocate it */
 struct aoedev *
-aoedev_by_sysminor_m(ulong sysminor)
+aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
 {
        struct aoedev *d;
+       int i;
        ulong flags;
+       ulong sysminor;
 
        spin_lock_irqsave(&devlist_lock, flags);
 
        for (d=devlist; d; d=d->next)
-               if (d->sysminor == sysminor)
+               if (d->aoemajor == maj && d->aoeminor == min) {
+                       d->ref++;
                        break;
-       if (d)
+               }
+       if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0)
                goto out;
        d = kcalloc(1, sizeof *d, GFP_ATOMIC);
        if (!d)
                goto out;
        INIT_WORK(&d->work, aoecmd_sleepwork);
        spin_lock_init(&d->lock);
-       skb_queue_head_init(&d->sendq);
        skb_queue_head_init(&d->skbpool);
        init_timer(&d->timer);
        d->timer.data = (ulong) d;
@@ -226,10 +356,12 @@ aoedev_by_sysminor_m(ulong sysminor)
        add_timer(&d->timer);
        d->bufpool = NULL;      /* defer to aoeblk_gdalloc */
        d->tgt = d->targets;
-       INIT_LIST_HEAD(&d->bufq);
+       d->ref = 1;
+       for (i = 0; i < NFACTIVE; i++)
+               INIT_LIST_HEAD(&d->factive[i]);
        d->sysminor = sysminor;
-       d->aoemajor = AOEMAJOR(sysminor);
-       d->aoeminor = AOEMINOR(sysminor);
+       d->aoemajor = maj;
+       d->aoeminor = min;
        d->mintimer = MINTIMER;
        d->next = devlist;
        devlist = d;
@@ -241,13 +373,23 @@ aoedev_by_sysminor_m(ulong sysminor)
 static void
 freetgt(struct aoedev *d, struct aoetgt *t)
 {
-       struct frame *f, *e;
+       struct frame *f;
+       struct list_head *pos, *nx, *head;
+       struct aoeif *ifp;
 
-       f = t->frames;
-       e = f + t->nframes;
-       for (; f < e; f++)
+       for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS]; ++ifp) {
+               if (!ifp->nd)
+                       break;
+               dev_put(ifp->nd);
+       }
+
+       head = &t->ffree;
+       list_for_each_safe(pos, nx, head) {
+               list_del(pos);
+               f = list_entry(pos, struct frame, head);
                skbfree(f->skb);
-       kfree(t->frames);
+               kfree(f);
+       }
        kfree(t);
 }
 
@@ -257,6 +399,7 @@ aoedev_exit(void)
        struct aoedev *d;
        ulong flags;
 
+       aoe_flush_iocq();
        while ((d = devlist)) {
                devlist = d->next;
 
index 7f83ad90e76fd9f4e971ec4d00826eea2e1cffe7..04793c2c701b7b0bf707a576a5a9e1a01bccc376 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoemain.c
  * Module initialization routines, discover timer
@@ -61,6 +61,7 @@ aoe_exit(void)
 
        aoenet_exit();
        unregister_blkdev(AOE_MAJOR, DEVICE_NAME);
+       aoecmd_exit();
        aoechr_exit();
        aoedev_exit();
        aoeblk_exit();          /* free cache after de-allocating bufs */
@@ -83,17 +84,20 @@ aoe_init(void)
        ret = aoenet_init();
        if (ret)
                goto net_fail;
+       ret = aoecmd_init();
+       if (ret)
+               goto cmd_fail;
        ret = register_blkdev(AOE_MAJOR, DEVICE_NAME);
        if (ret < 0) {
                printk(KERN_ERR "aoe: can't register major\n");
                goto blkreg_fail;
        }
-
        printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION);
        discover_timer(TINIT);
        return 0;
-
  blkreg_fail:
+       aoecmd_exit();
+ cmd_fail:
        aoenet_exit();
  net_fail:
        aoeblk_exit();
index 4d3bc0d49df59394ea550a74c05c4ad0c84c436b..162c6471275c6792454871732e1d4d21cefa04ac 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoenet.c
  * Ethernet portion of AoE driver
@@ -33,6 +33,9 @@ static char aoe_iflist[IFLISTSZ];
 module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600);
 MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\"");
 
+static wait_queue_head_t txwq;
+static struct ktstate kts;
+
 #ifndef MODULE
 static int __init aoe_iflist_setup(char *str)
 {
@@ -44,6 +47,23 @@ static int __init aoe_iflist_setup(char *str)
 __setup("aoe_iflist=", aoe_iflist_setup);
 #endif
 
+static spinlock_t txlock;
+static struct sk_buff_head skbtxq;
+
+/* enters with txlock held */
+static int
+tx(void)
+{
+       struct sk_buff *skb;
+
+       while ((skb = skb_dequeue(&skbtxq))) {
+               spin_unlock_irq(&txlock);
+               dev_queue_xmit(skb);
+               spin_lock_irq(&txlock);
+       }
+       return 0;
+}
+
 int
 is_aoe_netif(struct net_device *ifp)
 {
@@ -88,10 +108,14 @@ void
 aoenet_xmit(struct sk_buff_head *queue)
 {
        struct sk_buff *skb, *tmp;
+       ulong flags;
 
        skb_queue_walk_safe(queue, skb, tmp) {
                __skb_unlink(skb, queue);
-               dev_queue_xmit(skb);
+               spin_lock_irqsave(&txlock, flags);
+               skb_queue_tail(&skbtxq, skb);
+               spin_unlock_irqrestore(&txlock, flags);
+               wake_up(&txwq);
        }
 }
 
@@ -102,7 +126,9 @@ static int
 aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
 {
        struct aoe_hdr *h;
+       struct aoe_atahdr *ah;
        u32 n;
+       int sn;
 
        if (dev_net(ifp) != &init_net)
                goto exit;
@@ -110,13 +136,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
        skb = skb_share_check(skb, GFP_ATOMIC);
        if (skb == NULL)
                return 0;
-       if (skb_linearize(skb))
-               goto exit;
        if (!is_aoe_netif(ifp))
                goto exit;
        skb_push(skb, ETH_HLEN);        /* (1) */
-
-       h = (struct aoe_hdr *) skb_mac_header(skb);
+       sn = sizeof(*h) + sizeof(*ah);
+       if (skb->len >= sn) {
+               sn -= skb_headlen(skb);
+               if (sn > 0 && !__pskb_pull_tail(skb, sn))
+                       goto exit;
+       }
+       h = (struct aoe_hdr *) skb->data;
        n = get_unaligned_be32(&h->tag);
        if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
                goto exit;
@@ -137,7 +166,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
 
        switch (h->cmd) {
        case AOECMD_ATA:
-               aoecmd_ata_rsp(skb);
+               /* ata_rsp may keep skb for later processing or give it back */
+               skb = aoecmd_ata_rsp(skb);
                break;
        case AOECMD_CFG:
                aoecmd_cfg_rsp(skb);
@@ -145,8 +175,12 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
        default:
                if (h->cmd >= AOECMD_VEND_MIN)
                        break;  /* don't complain about vendor commands */
-               printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
+               pr_info("aoe: unknown AoE command type 0x%02x\n", h->cmd);
+               break;
        }
+
+       if (!skb)
+               return 0;
 exit:
        dev_kfree_skb(skb);
        return 0;
@@ -160,6 +194,15 @@ static struct packet_type aoe_pt __read_mostly = {
 int __init
 aoenet_init(void)
 {
+       skb_queue_head_init(&skbtxq);
+       init_waitqueue_head(&txwq);
+       spin_lock_init(&txlock);
+       kts.lock = &txlock;
+       kts.fn = tx;
+       kts.waitq = &txwq;
+       kts.name = "aoe_tx";
+       if (aoe_ktstart(&kts))
+               return -EAGAIN;
        dev_add_pack(&aoe_pt);
        return 0;
 }
@@ -167,6 +210,8 @@ aoenet_init(void)
 void
 aoenet_exit(void)
 {
+       aoe_ktstop(&kts);
+       skb_queue_purge(&skbtxq);
        dev_remove_pack(&aoe_pt);
 }
 
index 0c03411c59eb8cba0f744e72aed93342dc9cace8..043ddcca4abf936d576a03c1a9e7241e5d59d2eb 100644 (file)
@@ -78,6 +78,8 @@ static const char *ioctl_cmd_to_ascii(int cmd)
        case NBD_SET_SOCK: return "set-sock";
        case NBD_SET_BLKSIZE: return "set-blksize";
        case NBD_SET_SIZE: return "set-size";
+       case NBD_SET_TIMEOUT: return "set-timeout";
+       case NBD_SET_FLAGS: return "set-flags";
        case NBD_DO_IT: return "do-it";
        case NBD_CLEAR_SOCK: return "clear-sock";
        case NBD_CLEAR_QUE: return "clear-que";
@@ -96,6 +98,7 @@ static const char *nbdcmd_to_ascii(int cmd)
        case  NBD_CMD_READ: return "read";
        case NBD_CMD_WRITE: return "write";
        case  NBD_CMD_DISC: return "disconnect";
+       case  NBD_CMD_TRIM: return "trim/discard";
        }
        return "invalid";
 }
@@ -467,8 +470,12 @@ static void nbd_handle_req(struct nbd_device *nbd, struct request *req)
 
        nbd_cmd(req) = NBD_CMD_READ;
        if (rq_data_dir(req) == WRITE) {
-               nbd_cmd(req) = NBD_CMD_WRITE;
-               if (nbd->flags & NBD_READ_ONLY) {
+               if ((req->cmd_flags & REQ_DISCARD)) {
+                       WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM));
+                       nbd_cmd(req) = NBD_CMD_TRIM;
+               } else
+                       nbd_cmd(req) = NBD_CMD_WRITE;
+               if (nbd->flags & NBD_FLAG_READ_ONLY) {
                        dev_err(disk_to_dev(nbd->disk),
                                "Write on read-only\n");
                        goto error_out;
@@ -651,6 +658,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                nbd->xmit_timeout = arg * HZ;
                return 0;
 
+       case NBD_SET_FLAGS:
+               nbd->flags = arg;
+               return 0;
+
        case NBD_SET_SIZE_BLOCKS:
                nbd->bytesize = ((u64) arg) * nbd->blksize;
                bdev->bd_inode->i_size = nbd->bytesize;
@@ -670,6 +681,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 
                mutex_unlock(&nbd->tx_lock);
 
+               if (nbd->flags & NBD_FLAG_SEND_TRIM)
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+                               nbd->disk->queue);
+
                thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name);
                if (IS_ERR(thread)) {
                        mutex_lock(&nbd->tx_lock);
@@ -687,6 +702,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                nbd->file = NULL;
                nbd_clear_que(nbd);
                dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
+               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
                if (file)
                        fput(file);
                nbd->bytesize = 0;
@@ -805,6 +821,9 @@ static int __init nbd_init(void)
                 * Tell the block layer that we are not a rotational device
                 */
                queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
+               disk->queue->limits.discard_granularity = 512;
+               disk->queue->limits.max_discard_sectors = UINT_MAX;
+               disk->queue->limits.discard_zeroes_data = 0;
        }
 
        if (register_blkdev(NBD_MAJOR, "nbd")) {
index c0bbeb4707542ac2370b0337de5f3e4a3037d619..0bdde8fba3970d81010736f3a1b4bf5f9fb53a07 100644 (file)
@@ -14,6 +14,9 @@
 
 #define PART_BITS 4
 
+static bool use_bio;
+module_param(use_bio, bool, S_IRUGO);
+
 static int major;
 static DEFINE_IDA(vd_index_ida);
 
@@ -23,6 +26,7 @@ struct virtio_blk
 {
        struct virtio_device *vdev;
        struct virtqueue *vq;
+       wait_queue_head_t queue_wait;
 
        /* The disk structure for the kernel. */
        struct gendisk *disk;
@@ -51,53 +55,244 @@ struct virtio_blk
 struct virtblk_req
 {
        struct request *req;
+       struct bio *bio;
        struct virtio_blk_outhdr out_hdr;
        struct virtio_scsi_inhdr in_hdr;
+       struct work_struct work;
+       struct virtio_blk *vblk;
+       int flags;
        u8 status;
+       struct scatterlist sg[];
+};
+
+enum {
+       VBLK_IS_FLUSH           = 1,
+       VBLK_REQ_FLUSH          = 2,
+       VBLK_REQ_DATA           = 4,
+       VBLK_REQ_FUA            = 8,
 };
 
-static void blk_done(struct virtqueue *vq)
+static inline int virtblk_result(struct virtblk_req *vbr)
+{
+       switch (vbr->status) {
+       case VIRTIO_BLK_S_OK:
+               return 0;
+       case VIRTIO_BLK_S_UNSUPP:
+               return -ENOTTY;
+       default:
+               return -EIO;
+       }
+}
+
+static inline struct virtblk_req *virtblk_alloc_req(struct virtio_blk *vblk,
+                                                   gfp_t gfp_mask)
 {
-       struct virtio_blk *vblk = vq->vdev->priv;
        struct virtblk_req *vbr;
-       unsigned int len;
-       unsigned long flags;
 
-       spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
-       while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
-               int error;
+       vbr = mempool_alloc(vblk->pool, gfp_mask);
+       if (!vbr)
+               return NULL;
 
-               switch (vbr->status) {
-               case VIRTIO_BLK_S_OK:
-                       error = 0;
-                       break;
-               case VIRTIO_BLK_S_UNSUPP:
-                       error = -ENOTTY;
-                       break;
-               default:
-                       error = -EIO;
+       vbr->vblk = vblk;
+       if (use_bio)
+               sg_init_table(vbr->sg, vblk->sg_elems);
+
+       return vbr;
+}
+
+static void virtblk_add_buf_wait(struct virtio_blk *vblk,
+                                struct virtblk_req *vbr,
+                                unsigned long out,
+                                unsigned long in)
+{
+       DEFINE_WAIT(wait);
+
+       for (;;) {
+               prepare_to_wait_exclusive(&vblk->queue_wait, &wait,
+                                         TASK_UNINTERRUPTIBLE);
+
+               spin_lock_irq(vblk->disk->queue->queue_lock);
+               if (virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
+                                     GFP_ATOMIC) < 0) {
+                       spin_unlock_irq(vblk->disk->queue->queue_lock);
+                       io_schedule();
+               } else {
+                       virtqueue_kick(vblk->vq);
+                       spin_unlock_irq(vblk->disk->queue->queue_lock);
                        break;
                }
 
-               switch (vbr->req->cmd_type) {
-               case REQ_TYPE_BLOCK_PC:
-                       vbr->req->resid_len = vbr->in_hdr.residual;
-                       vbr->req->sense_len = vbr->in_hdr.sense_len;
-                       vbr->req->errors = vbr->in_hdr.errors;
-                       break;
-               case REQ_TYPE_SPECIAL:
-                       vbr->req->errors = (error != 0);
-                       break;
-               default:
-                       break;
+       }
+
+       finish_wait(&vblk->queue_wait, &wait);
+}
+
+static inline void virtblk_add_req(struct virtblk_req *vbr,
+                                  unsigned int out, unsigned int in)
+{
+       struct virtio_blk *vblk = vbr->vblk;
+
+       spin_lock_irq(vblk->disk->queue->queue_lock);
+       if (unlikely(virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
+                                       GFP_ATOMIC) < 0)) {
+               spin_unlock_irq(vblk->disk->queue->queue_lock);
+               virtblk_add_buf_wait(vblk, vbr, out, in);
+               return;
+       }
+       virtqueue_kick(vblk->vq);
+       spin_unlock_irq(vblk->disk->queue->queue_lock);
+}
+
+static int virtblk_bio_send_flush(struct virtblk_req *vbr)
+{
+       unsigned int out = 0, in = 0;
+
+       vbr->flags |= VBLK_IS_FLUSH;
+       vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
+       vbr->out_hdr.sector = 0;
+       vbr->out_hdr.ioprio = 0;
+       sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
+       sg_set_buf(&vbr->sg[out + in++], &vbr->status, sizeof(vbr->status));
+
+       virtblk_add_req(vbr, out, in);
+
+       return 0;
+}
+
+static int virtblk_bio_send_data(struct virtblk_req *vbr)
+{
+       struct virtio_blk *vblk = vbr->vblk;
+       unsigned int num, out = 0, in = 0;
+       struct bio *bio = vbr->bio;
+
+       vbr->flags &= ~VBLK_IS_FLUSH;
+       vbr->out_hdr.type = 0;
+       vbr->out_hdr.sector = bio->bi_sector;
+       vbr->out_hdr.ioprio = bio_prio(bio);
+
+       sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
+
+       num = blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg + out);
+
+       sg_set_buf(&vbr->sg[num + out + in++], &vbr->status,
+                  sizeof(vbr->status));
+
+       if (num) {
+               if (bio->bi_rw & REQ_WRITE) {
+                       vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+                       out += num;
+               } else {
+                       vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+                       in += num;
                }
+       }
+
+       virtblk_add_req(vbr, out, in);
+
+       return 0;
+}
+
+static void virtblk_bio_send_data_work(struct work_struct *work)
+{
+       struct virtblk_req *vbr;
+
+       vbr = container_of(work, struct virtblk_req, work);
+
+       virtblk_bio_send_data(vbr);
+}
+
+static void virtblk_bio_send_flush_work(struct work_struct *work)
+{
+       struct virtblk_req *vbr;
+
+       vbr = container_of(work, struct virtblk_req, work);
+
+       virtblk_bio_send_flush(vbr);
+}
+
+static inline void virtblk_request_done(struct virtblk_req *vbr)
+{
+       struct virtio_blk *vblk = vbr->vblk;
+       struct request *req = vbr->req;
+       int error = virtblk_result(vbr);
+
+       if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
+               req->resid_len = vbr->in_hdr.residual;
+               req->sense_len = vbr->in_hdr.sense_len;
+               req->errors = vbr->in_hdr.errors;
+       } else if (req->cmd_type == REQ_TYPE_SPECIAL) {
+               req->errors = (error != 0);
+       }
+
+       __blk_end_request_all(req, error);
+       mempool_free(vbr, vblk->pool);
+}
+
+static inline void virtblk_bio_flush_done(struct virtblk_req *vbr)
+{
+       struct virtio_blk *vblk = vbr->vblk;
+
+       if (vbr->flags & VBLK_REQ_DATA) {
+               /* Send out the actual write data */
+               INIT_WORK(&vbr->work, virtblk_bio_send_data_work);
+               queue_work(virtblk_wq, &vbr->work);
+       } else {
+               bio_endio(vbr->bio, virtblk_result(vbr));
+               mempool_free(vbr, vblk->pool);
+       }
+}
+
+static inline void virtblk_bio_data_done(struct virtblk_req *vbr)
+{
+       struct virtio_blk *vblk = vbr->vblk;
 
-               __blk_end_request_all(vbr->req, error);
+       if (unlikely(vbr->flags & VBLK_REQ_FUA)) {
+               /* Send out a flush before end the bio */
+               vbr->flags &= ~VBLK_REQ_DATA;
+               INIT_WORK(&vbr->work, virtblk_bio_send_flush_work);
+               queue_work(virtblk_wq, &vbr->work);
+       } else {
+               bio_endio(vbr->bio, virtblk_result(vbr));
                mempool_free(vbr, vblk->pool);
        }
+}
+
+static inline void virtblk_bio_done(struct virtblk_req *vbr)
+{
+       if (unlikely(vbr->flags & VBLK_IS_FLUSH))
+               virtblk_bio_flush_done(vbr);
+       else
+               virtblk_bio_data_done(vbr);
+}
+
+static void virtblk_done(struct virtqueue *vq)
+{
+       struct virtio_blk *vblk = vq->vdev->priv;
+       bool bio_done = false, req_done = false;
+       struct virtblk_req *vbr;
+       unsigned long flags;
+       unsigned int len;
+
+       spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
+       do {
+               virtqueue_disable_cb(vq);
+               while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
+                       if (vbr->bio) {
+                               virtblk_bio_done(vbr);
+                               bio_done = true;
+                       } else {
+                               virtblk_request_done(vbr);
+                               req_done = true;
+                       }
+               }
+       } while (!virtqueue_enable_cb(vq));
        /* In case queue is stopped waiting for more buffers. */
-       blk_start_queue(vblk->disk->queue);
+       if (req_done)
+               blk_start_queue(vblk->disk->queue);
        spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
+
+       if (bio_done)
+               wake_up(&vblk->queue_wait);
 }
 
 static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
@@ -106,13 +301,13 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
        unsigned long num, out = 0, in = 0;
        struct virtblk_req *vbr;
 
-       vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
+       vbr = virtblk_alloc_req(vblk, GFP_ATOMIC);
        if (!vbr)
                /* When another request finishes we'll try again. */
                return false;
 
        vbr->req = req;
-
+       vbr->bio = NULL;
        if (req->cmd_flags & REQ_FLUSH) {
                vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
                vbr->out_hdr.sector = 0;
@@ -172,7 +367,8 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
                }
        }
 
-       if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr, GFP_ATOMIC)<0) {
+       if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr,
+                             GFP_ATOMIC) < 0) {
                mempool_free(vbr, vblk->pool);
                return false;
        }
@@ -180,7 +376,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
        return true;
 }
 
-static void do_virtblk_request(struct request_queue *q)
+static void virtblk_request(struct request_queue *q)
 {
        struct virtio_blk *vblk = q->queuedata;
        struct request *req;
@@ -203,6 +399,34 @@ static void do_virtblk_request(struct request_queue *q)
                virtqueue_kick(vblk->vq);
 }
 
+static void virtblk_make_request(struct request_queue *q, struct bio *bio)
+{
+       struct virtio_blk *vblk = q->queuedata;
+       struct virtblk_req *vbr;
+
+       BUG_ON(bio->bi_phys_segments + 2 > vblk->sg_elems);
+
+       vbr = virtblk_alloc_req(vblk, GFP_NOIO);
+       if (!vbr) {
+               bio_endio(bio, -ENOMEM);
+               return;
+       }
+
+       vbr->bio = bio;
+       vbr->flags = 0;
+       if (bio->bi_rw & REQ_FLUSH)
+               vbr->flags |= VBLK_REQ_FLUSH;
+       if (bio->bi_rw & REQ_FUA)
+               vbr->flags |= VBLK_REQ_FUA;
+       if (bio->bi_size)
+               vbr->flags |= VBLK_REQ_DATA;
+
+       if (unlikely(vbr->flags & VBLK_REQ_FLUSH))
+               virtblk_bio_send_flush(vbr);
+       else
+               virtblk_bio_send_data(vbr);
+}
+
 /* return id (s/n) string for *disk to *id_str
  */
 static int virtblk_get_id(struct gendisk *disk, char *id_str)
@@ -360,7 +584,7 @@ static int init_vq(struct virtio_blk *vblk)
        int err = 0;
 
        /* We expect one virtqueue, for output. */
-       vblk->vq = virtio_find_single_vq(vblk->vdev, blk_done, "requests");
+       vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
        if (IS_ERR(vblk->vq))
                err = PTR_ERR(vblk->vq);
 
@@ -477,6 +701,8 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        struct virtio_blk *vblk;
        struct request_queue *q;
        int err, index;
+       int pool_size;
+
        u64 cap;
        u32 v, blk_size, sg_elems, opt_io_size;
        u16 min_io_size;
@@ -506,10 +732,12 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
                goto out_free_index;
        }
 
+       init_waitqueue_head(&vblk->queue_wait);
        vblk->vdev = vdev;
        vblk->sg_elems = sg_elems;
        sg_init_table(vblk->sg, vblk->sg_elems);
        mutex_init(&vblk->config_lock);
+
        INIT_WORK(&vblk->config_work, virtblk_config_changed_work);
        vblk->config_enable = true;
 
@@ -517,7 +745,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        if (err)
                goto out_free_vblk;
 
-       vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct virtblk_req));
+       pool_size = sizeof(struct virtblk_req);
+       if (use_bio)
+               pool_size += sizeof(struct scatterlist) * sg_elems;
+       vblk->pool = mempool_create_kmalloc_pool(1, pool_size);
        if (!vblk->pool) {
                err = -ENOMEM;
                goto out_free_vq;
@@ -530,12 +761,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
                goto out_mempool;
        }
 
-       q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL);
+       q = vblk->disk->queue = blk_init_queue(virtblk_request, NULL);
        if (!q) {
                err = -ENOMEM;
                goto out_put_disk;
        }
 
+       if (use_bio)
+               blk_queue_make_request(q, virtblk_make_request);
        q->queuedata = vblk;
 
        virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
@@ -620,7 +853,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        if (!err && opt_io_size)
                blk_queue_io_opt(q, blk_size * opt_io_size);
 
-
        add_disk(vblk->disk);
        err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
        if (err)
index c6decb901e5e16f4ba09ccef7db33675aeecb189..280a13846e6cb06e1f774dd927598c1f3bfa5a8c 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <xen/events.h>
 #include <xen/page.h>
+#include <xen/xen.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 #include "common.h"
index 4fbdceb6f773d7e45189a22347668c34a0b52c63..a5effd813abddbcdb6a0603148caa822b7dd36f6 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/random.h>
-#include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/hw_random.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/io.h>
 
 #define RNG_SYSSTATUS          0x44            /* System status
                                                        [0] = RESETDONE */
 
-static void __iomem *rng_base;
-static struct clk *rng_ick;
-static struct platform_device *rng_dev;
+/**
+ * struct omap_rng_private_data - RNG IP block-specific data
+ * @base: virtual address of the beginning of the RNG IP block registers
+ * @mem_res: struct resource * for the IP block registers physical memory
+ */
+struct omap_rng_private_data {
+       void __iomem *base;
+       struct resource *mem_res;
+};
 
-static inline u32 omap_rng_read_reg(int reg)
+static inline u32 omap_rng_read_reg(struct omap_rng_private_data *priv, int reg)
 {
-       return __raw_readl(rng_base + reg);
+       return __raw_readl(priv->base + reg);
 }
 
-static inline void omap_rng_write_reg(int reg, u32 val)
+static inline void omap_rng_write_reg(struct omap_rng_private_data *priv,
+                                     int reg, u32 val)
 {
-       __raw_writel(val, rng_base + reg);
+       __raw_writel(val, priv->base + reg);
 }
 
 static int omap_rng_data_present(struct hwrng *rng, int wait)
 {
+       struct omap_rng_private_data *priv;
        int data, i;
 
+       priv = (struct omap_rng_private_data *)rng->priv;
+
        for (i = 0; i < 20; i++) {
-               data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+               data = omap_rng_read_reg(priv, RNG_STAT_REG) ? 0 : 1;
                if (data || !wait)
                        break;
                /* RNG produces data fast enough (2+ MBit/sec, even
@@ -80,9 +91,13 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
 
 static int omap_rng_data_read(struct hwrng *rng, u32 *data)
 {
-       *data = omap_rng_read_reg(RNG_OUT_REG);
+       struct omap_rng_private_data *priv;
+
+       priv = (struct omap_rng_private_data *)rng->priv;
+
+       *data = omap_rng_read_reg(priv, RNG_OUT_REG);
 
-       return 4;
+       return sizeof(u32);
 }
 
 static struct hwrng omap_rng_ops = {
@@ -93,69 +108,68 @@ static struct hwrng omap_rng_ops = {
 
 static int __devinit omap_rng_probe(struct platform_device *pdev)
 {
-       struct resource *res;
+       struct omap_rng_private_data *priv;
        int ret;
 
-       /*
-        * A bit ugly, and it will never actually happen but there can
-        * be only one RNG and this catches any bork
-        */
-       if (rng_dev)
-               return -EBUSY;
-
-       if (cpu_is_omap24xx()) {
-               rng_ick = clk_get(&pdev->dev, "ick");
-               if (IS_ERR(rng_ick)) {
-                       dev_err(&pdev->dev, "Could not get rng_ick\n");
-                       ret = PTR_ERR(rng_ick);
-                       return ret;
-               } else
-                       clk_enable(rng_ick);
-       }
+       priv = kzalloc(sizeof(struct omap_rng_private_data), GFP_KERNEL);
+       if (!priv) {
+               dev_err(&pdev->dev, "could not allocate memory\n");
+               return -ENOMEM;
+       };
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       omap_rng_ops.priv = (unsigned long)priv;
+       dev_set_drvdata(&pdev->dev, priv);
 
-       rng_base = devm_request_and_ioremap(&pdev->dev, res);
-       if (!rng_base) {
+       priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!priv->mem_res) {
+               ret = -ENOENT;
+               goto err_ioremap;
+       }
+
+       priv->base = devm_request_and_ioremap(&pdev->dev, priv->mem_res);
+       if (!priv->base) {
                ret = -ENOMEM;
                goto err_ioremap;
        }
-       dev_set_drvdata(&pdev->dev, res);
+       dev_set_drvdata(&pdev->dev, priv);
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        ret = hwrng_register(&omap_rng_ops);
        if (ret)
                goto err_register;
 
        dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
-               omap_rng_read_reg(RNG_REV_REG));
-       omap_rng_write_reg(RNG_MASK_REG, 0x1);
+                omap_rng_read_reg(priv, RNG_REV_REG));
 
-       rng_dev = pdev;
+       omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
 
        return 0;
 
 err_register:
-       rng_base = NULL;
+       priv->base = NULL;
+       pm_runtime_disable(&pdev->dev);
 err_ioremap:
-       if (cpu_is_omap24xx()) {
-               clk_disable(rng_ick);
-               clk_put(rng_ick);
-       }
+       kfree(priv);
+
        return ret;
 }
 
 static int __exit omap_rng_remove(struct platform_device *pdev)
 {
+       struct omap_rng_private_data *priv = dev_get_drvdata(&pdev->dev);
+
        hwrng_unregister(&omap_rng_ops);
 
-       omap_rng_write_reg(RNG_MASK_REG, 0x0);
+       omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
 
-       if (cpu_is_omap24xx()) {
-               clk_disable(rng_ick);
-               clk_put(rng_ick);
-       }
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+
+       release_mem_region(priv->mem_res->start, resource_size(priv->mem_res));
 
-       rng_base = NULL;
+       kfree(priv);
 
        return 0;
 }
@@ -164,13 +178,21 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
 
 static int omap_rng_suspend(struct device *dev)
 {
-       omap_rng_write_reg(RNG_MASK_REG, 0x0);
+       struct omap_rng_private_data *priv = dev_get_drvdata(dev);
+
+       omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
+       pm_runtime_put_sync(dev);
+
        return 0;
 }
 
 static int omap_rng_resume(struct device *dev)
 {
-       omap_rng_write_reg(RNG_MASK_REG, 0x1);
+       struct omap_rng_private_data *priv = dev_get_drvdata(dev);
+
+       pm_runtime_get_sync(dev);
+       omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
+
        return 0;
 }
 
@@ -198,9 +220,6 @@ static struct platform_driver omap_rng_driver = {
 
 static int __init omap_rng_init(void)
 {
-       if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
-               return -ENODEV;
-
        return platform_driver_register(&omap_rng_driver);
 }
 
index 47ff7e470d87dc15cd0f8ba558b00c1e45e5ecbc..0c7d340b9ab9b69aa6b977d97afe2587743f2e61 100644 (file)
@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
        return 0;
 }
 
-static const struct cx_device_id __devinitdata mbcs_id_table[] = {
+static const struct cx_device_id __devinitconst mbcs_id_table[] = {
        {
         .part_num = MBCS_PART_NUM,
         .mfg_num = MBCS_MFG_NUM,
index 060a672ebb7bf3189bd8a7b0e872c1b437347635..8ab9c3d4bf134c23bda43adafc688485a1c9e764 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/err.h>
 #include <linux/freezer.h>
 #include <linux/fs.h>
+#include <linux/splice.h>
+#include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/poll.h>
@@ -474,26 +476,53 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
        return 0;
 }
 
+struct buffer_token {
+       union {
+               void *buf;
+               struct scatterlist *sg;
+       } u;
+       /* If sgpages == 0 then buf is used, else sg is used */
+       unsigned int sgpages;
+};
+
+static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
+{
+       int i;
+       struct page *page;
+
+       for (i = 0; i < nrpages; i++) {
+               page = sg_page(&sg[i]);
+               if (!page)
+                       break;
+               put_page(page);
+       }
+       kfree(sg);
+}
+
 /* Callers must take the port->outvq_lock */
 static void reclaim_consumed_buffers(struct port *port)
 {
-       void *buf;
+       struct buffer_token *tok;
        unsigned int len;
 
        if (!port->portdev) {
                /* Device has been unplugged.  vqs are already gone. */
                return;
        }
-       while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-               kfree(buf);
+       while ((tok = virtqueue_get_buf(port->out_vq, &len))) {
+               if (tok->sgpages)
+                       reclaim_sg_pages(tok->u.sg, tok->sgpages);
+               else
+                       kfree(tok->u.buf);
+               kfree(tok);
                port->outvq_full = false;
        }
 }
 
-static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
-                       bool nonblock)
+static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
+                             int nents, size_t in_count,
+                             struct buffer_token *tok, bool nonblock)
 {
-       struct scatterlist sg[1];
        struct virtqueue *out_vq;
        ssize_t ret;
        unsigned long flags;
@@ -505,8 +534,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
 
        reclaim_consumed_buffers(port);
 
-       sg_init_one(sg, in_buf, in_count);
-       ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf, GFP_ATOMIC);
+       ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
 
        /* Tell Host to go! */
        virtqueue_kick(out_vq);
@@ -544,6 +572,37 @@ done:
        return in_count;
 }
 
+static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
+                       bool nonblock)
+{
+       struct scatterlist sg[1];
+       struct buffer_token *tok;
+
+       tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
+       if (!tok)
+               return -ENOMEM;
+       tok->sgpages = 0;
+       tok->u.buf = in_buf;
+
+       sg_init_one(sg, in_buf, in_count);
+
+       return __send_to_port(port, sg, 1, in_count, tok, nonblock);
+}
+
+static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents,
+                         size_t in_count, bool nonblock)
+{
+       struct buffer_token *tok;
+
+       tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
+       if (!tok)
+               return -ENOMEM;
+       tok->sgpages = nents;
+       tok->u.sg = sg;
+
+       return __send_to_port(port, sg, nents, in_count, tok, nonblock);
+}
+
 /*
  * Give out the data that's requested from the buffer that we have
  * queued up.
@@ -665,6 +724,26 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
        return fill_readbuf(port, ubuf, count, true);
 }
 
+static int wait_port_writable(struct port *port, bool nonblock)
+{
+       int ret;
+
+       if (will_write_block(port)) {
+               if (nonblock)
+                       return -EAGAIN;
+
+               ret = wait_event_freezable(port->waitqueue,
+                                          !will_write_block(port));
+               if (ret < 0)
+                       return ret;
+       }
+       /* Port got hot-unplugged. */
+       if (!port->guest_connected)
+               return -ENODEV;
+
+       return 0;
+}
+
 static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
                               size_t count, loff_t *offp)
 {
@@ -681,18 +760,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
 
        nonblock = filp->f_flags & O_NONBLOCK;
 
-       if (will_write_block(port)) {
-               if (nonblock)
-                       return -EAGAIN;
-
-               ret = wait_event_freezable(port->waitqueue,
-                                          !will_write_block(port));
-               if (ret < 0)
-                       return ret;
-       }
-       /* Port got hot-unplugged. */
-       if (!port->guest_connected)
-               return -ENODEV;
+       ret = wait_port_writable(port, nonblock);
+       if (ret < 0)
+               return ret;
 
        count = min((size_t)(32 * 1024), count);
 
@@ -725,6 +795,93 @@ out:
        return ret;
 }
 
+struct sg_list {
+       unsigned int n;
+       unsigned int size;
+       size_t len;
+       struct scatterlist *sg;
+};
+
+static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+                       struct splice_desc *sd)
+{
+       struct sg_list *sgl = sd->u.data;
+       unsigned int offset, len;
+
+       if (sgl->n == sgl->size)
+               return 0;
+
+       /* Try lock this page */
+       if (buf->ops->steal(pipe, buf) == 0) {
+               /* Get reference and unlock page for moving */
+               get_page(buf->page);
+               unlock_page(buf->page);
+
+               len = min(buf->len, sd->len);
+               sg_set_page(&(sgl->sg[sgl->n]), buf->page, len, buf->offset);
+       } else {
+               /* Failback to copying a page */
+               struct page *page = alloc_page(GFP_KERNEL);
+               char *src = buf->ops->map(pipe, buf, 1);
+               char *dst;
+
+               if (!page)
+                       return -ENOMEM;
+               dst = kmap(page);
+
+               offset = sd->pos & ~PAGE_MASK;
+
+               len = sd->len;
+               if (len + offset > PAGE_SIZE)
+                       len = PAGE_SIZE - offset;
+
+               memcpy(dst + offset, src + buf->offset, len);
+
+               kunmap(page);
+               buf->ops->unmap(pipe, buf, src);
+
+               sg_set_page(&(sgl->sg[sgl->n]), page, len, offset);
+       }
+       sgl->n++;
+       sgl->len += len;
+
+       return len;
+}
+
+/* Faster zero-copy write by splicing */
+static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
+                                     struct file *filp, loff_t *ppos,
+                                     size_t len, unsigned int flags)
+{
+       struct port *port = filp->private_data;
+       struct sg_list sgl;
+       ssize_t ret;
+       struct splice_desc sd = {
+               .total_len = len,
+               .flags = flags,
+               .pos = *ppos,
+               .u.data = &sgl,
+       };
+
+       ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
+       if (ret < 0)
+               return ret;
+
+       sgl.n = 0;
+       sgl.len = 0;
+       sgl.size = pipe->nrbufs;
+       sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL);
+       if (unlikely(!sgl.sg))
+               return -ENOMEM;
+
+       sg_init_table(sgl.sg, sgl.size);
+       ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
+       if (likely(ret > 0))
+               ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
+
+       return ret;
+}
+
 static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
 {
        struct port *port;
@@ -856,6 +1013,7 @@ static const struct file_operations port_fops = {
        .open  = port_fops_open,
        .read  = port_fops_read,
        .write = port_fops_write,
+       .splice_write = port_fops_splice_write,
        .poll  = port_fops_poll,
        .release = port_fops_release,
        .fasync = port_fops_fasync,
index 21c1a87032b76b3efce5f0d8bf4a5d3051ddeed8..24ccae453e7940c8e74c60c245072eb7754354cc 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/clk.h>
 #include <crypto/internal/hash.h>
 #include <crypto/sha.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
 
 #include "mv_cesa.h"
 
@@ -1062,7 +1065,10 @@ static int mv_probe(struct platform_device *pdev)
                goto err_unmap_reg;
        }
 
-       irq = platform_get_irq(pdev, 0);
+       if (pdev->dev.of_node)
+               irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+       else
+               irq = platform_get_irq(pdev, 0);
        if (irq < 0 || irq == NO_IRQ) {
                ret = irq;
                goto err_unmap_sram;
@@ -1170,12 +1176,19 @@ static int mv_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id mv_cesa_of_match_table[] = {
+       { .compatible = "marvell,orion-crypto", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mv_cesa_of_match_table);
+
 static struct platform_driver marvell_crypto = {
        .probe          = mv_probe,
-       .remove         = mv_remove,
+       .remove         = __devexit_p(mv_remove),
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "mv_crypto",
+               .of_match_table = of_match_ptr(mv_cesa_of_match_table),
        },
 };
 MODULE_ALIAS("platform:mv_crypto");
index d7f179cc2e984ae17d3888db194b309edfa2bb21..638110efae9bede0b58e2f4f2b2315e73d07402d 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/device.h>
 #include <linux/of.h>
 #include <asm/pSeries_reconfig.h>
-#include <asm/abs_addr.h>
 #include <asm/hvcall.h>
 #include <asm/vio.h>
 
@@ -104,10 +103,10 @@ struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
        /* determine the start and end for this address range - slightly
         * different if this is in VMALLOC_REGION */
        if (is_vmalloc_addr(start_addr))
-               sg_addr = phys_to_abs(page_to_phys(vmalloc_to_page(start_addr)))
+               sg_addr = page_to_phys(vmalloc_to_page(start_addr))
                          + offset_in_page(sg_addr);
        else
-               sg_addr = virt_to_abs(sg_addr);
+               sg_addr = __pa(sg_addr);
 
        end_addr = sg_addr + len;
 
@@ -265,17 +264,17 @@ void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
        nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
 
        nx_ctx->op.flags = function;
-       nx_ctx->op.csbcpb = virt_to_abs(nx_ctx->csbcpb);
-       nx_ctx->op.in = virt_to_abs(nx_ctx->in_sg);
-       nx_ctx->op.out = virt_to_abs(nx_ctx->out_sg);
+       nx_ctx->op.csbcpb = __pa(nx_ctx->csbcpb);
+       nx_ctx->op.in = __pa(nx_ctx->in_sg);
+       nx_ctx->op.out = __pa(nx_ctx->out_sg);
 
        if (nx_ctx->csbcpb_aead) {
                nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
 
                nx_ctx->op_aead.flags = function;
-               nx_ctx->op_aead.csbcpb = virt_to_abs(nx_ctx->csbcpb_aead);
-               nx_ctx->op_aead.in = virt_to_abs(nx_ctx->in_sg);
-               nx_ctx->op_aead.out = virt_to_abs(nx_ctx->out_sg);
+               nx_ctx->op_aead.csbcpb = __pa(nx_ctx->csbcpb_aead);
+               nx_ctx->op_aead.in = __pa(nx_ctx->in_sg);
+               nx_ctx->op_aead.out = __pa(nx_ctx->out_sg);
        }
 }
 
index 3491654cdf7b84fdcd2253f71542b3a53dcefdb9..a815d44c70a41b802c771dea337bf2e5348592a8 100644 (file)
@@ -582,7 +582,7 @@ void dmaengine_get(void)
                                list_del_rcu(&device->global_node);
                                break;
                        } else if (err)
-                               pr_err("%s: failed to get %s: (%d)\n",
+                               pr_debug("%s: failed to get %s: (%d)\n",
                                       __func__, dma_chan_name(chan), err);
                }
        }
index a1e791ec25d38514b7c47ae27bd2cab0198ded68..4fe66fa183ec964acc27781ed8f8b90eaaaa41eb 100644 (file)
@@ -212,7 +212,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
        struct edac_pci_ctl_info *pci;
        struct mpc85xx_pci_pdata *pdata;
@@ -226,6 +226,16 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
        if (!pci)
                return -ENOMEM;
 
+       /* make sure error reporting method is sane */
+       switch (edac_op_state) {
+       case EDAC_OPSTATE_POLL:
+       case EDAC_OPSTATE_INT:
+               break;
+       default:
+               edac_op_state = EDAC_OPSTATE_INT;
+               break;
+       }
+
        pdata = pci->pvt_info;
        pdata->name = "mpc85xx_pci_err";
        pdata->irq = NO_IRQ;
@@ -315,6 +325,7 @@ err:
        devres_release_group(&op->dev, mpc85xx_pci_err_probe);
        return res;
 }
+EXPORT_SYMBOL(mpc85xx_pci_err_probe);
 
 static int mpc85xx_pci_err_remove(struct platform_device *op)
 {
@@ -338,27 +349,6 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
-       {
-        .compatible = "fsl,mpc8540-pcix",
-        },
-       {
-        .compatible = "fsl,mpc8540-pci",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
-
-static struct platform_driver mpc85xx_pci_err_driver = {
-       .probe = mpc85xx_pci_err_probe,
-       .remove = __devexit_p(mpc85xx_pci_err_remove),
-       .driver = {
-               .name = "mpc85xx_pci_err",
-               .owner = THIS_MODULE,
-               .of_match_table = mpc85xx_pci_err_of_match,
-       },
-};
-
 #endif                         /* CONFIG_PCI */
 
 /**************************** L2 Err device ***************************/
@@ -1210,12 +1200,6 @@ static int __init mpc85xx_mc_init(void)
        if (res)
                printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
-#ifdef CONFIG_PCI
-       res = platform_driver_register(&mpc85xx_pci_err_driver);
-       if (res)
-               printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
-#endif
-
 #ifdef CONFIG_FSL_SOC_BOOKE
        pvr = mfspr(SPRN_PVR);
 
@@ -1251,9 +1235,6 @@ static void __exit mpc85xx_mc_exit(void)
            (PVR_VER(pvr) == PVR_VER_E500V2)) {
                on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
        }
-#endif
-#ifdef CONFIG_PCI
-       platform_driver_unregister(&mpc85xx_pci_err_driver);
 #endif
        platform_driver_unregister(&mpc85xx_l2_err_driver);
        platform_driver_unregister(&mpc85xx_mc_err_driver);
index 8382dc832929a4044bbb61ec3c4423a738a5a8df..d055cee36942d5e7aea8535b5f8d77b4ab34fe09 100644 (file)
@@ -150,6 +150,12 @@ config GPIO_MSM_V2
          Qualcomm MSM chips.  Most of the pins on the MSM can be
          selected for GPIO, and are controlled by this driver.
 
+config GPIO_MVEBU
+       def_bool y
+       depends on ARCH_MVEBU
+       select GPIO_GENERIC
+       select GENERIC_IRQ_CHIP
+
 config GPIO_MXC
        def_bool y
        depends on ARCH_MXC
@@ -409,6 +415,13 @@ config GPIO_TWL4030
          Say yes here to access the GPIO signals of various multi-function
          power management chips from Texas Instruments.
 
+config GPIO_TWL6040
+       tristate "TWL6040 GPO"
+       depends on TWL6040_CORE
+       help
+         Say yes here to access the GPO signals of twl6040
+         audio chip from Texas Instruments.
+
 config GPIO_WM831X
        tristate "WM831x GPIOs"
        depends on MFD_WM831X
index 0ffaa8423e87c07d9d83d9408edc0da804939c40..9aeed67073261f94702d8a873542bfff78ab2261 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_GPIO_MPC8XXX)    += gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)                += gpio-msic.o
 obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
 obj-$(CONFIG_ARCH_OMAP)                += gpio-omap.o
@@ -68,6 +69,7 @@ obj-$(CONFIG_GPIO_TPS6586X)   += gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
+obj-$(CONFIG_GPIO_TWL6040)     += gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VR41XX)      += gpio-vr41xx.o
 obj-$(CONFIG_GPIO_VT8500)      += gpio-vt8500.o
index aba97abda77cff7856a41aef420aa5735aacb4e3..7d9d7cb35f2861ffeb0ba4f83b575a1cedb00add 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 b7c06517403dab8acc257570f6bdb83d6036aa94..d4d61796669675696ce30711796773b4f7d1fa36 100644 (file)
@@ -49,6 +49,10 @@ static const u8 ichx_regs[3][3] = {
        {0x0c, 0x38, 0x48},     /* LVL[1-3] offsets */
 };
 
+static const u8 ichx_reglen[3] = {
+       0x30, 0x10, 0x10,
+};
+
 #define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
 #define ICHX_READ(reg, base_res)       inl((reg) + (base_res)->start)
 
@@ -75,6 +79,7 @@ static struct {
        struct resource *pm_base;       /* Power Mangagment IO base */
        struct ichx_desc *desc; /* Pointer to chipset-specific description */
        u32 orig_gpio_ctrl;     /* Orig CTRL value, used to restore on exit */
+       u8 use_gpio;            /* Which GPIO groups are usable */
 } ichx_priv;
 
 static int modparam_gpiobase = -1;     /* dynamic */
@@ -123,8 +128,16 @@ static int ichx_read_bit(int reg, unsigned nr)
        return data & (1 << bit) ? 1 : 0;
 }
 
+static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
+{
+       return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO;
+}
+
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
+       if (!ichx_gpio_check_available(gpio, nr))
+               return -ENXIO;
+
        /*
         * Try setting pin as an input and verify it worked since many pins
         * are output-only.
@@ -138,6 +151,9 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
                                        int val)
 {
+       if (!ichx_gpio_check_available(gpio, nr))
+               return -ENXIO;
+
        /* Set GPIO output value. */
        ichx_write_bit(GPIO_LVL, nr, val, 0);
 
@@ -153,6 +169,9 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 
 static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
 {
+       if (!ichx_gpio_check_available(chip, nr))
+               return -ENXIO;
+
        return ichx_read_bit(GPIO_LVL, nr);
 }
 
@@ -161,6 +180,9 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
        unsigned long flags;
        u32 data;
 
+       if (!ichx_gpio_check_available(chip, nr))
+               return -ENXIO;
+
        /*
         * GPI 0 - 15 need to be read from the power management registers on
         * a ICH6/3100 bridge.
@@ -291,6 +313,46 @@ static struct ichx_desc intel5_desc = {
        .ngpio = 76,
 };
 
+static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+                                               const char *name, u8 use_gpio)
+{
+       int i;
+
+       if (!res_base || !res_base->start || !res_base->end)
+               return -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+               if (!(use_gpio & (1 << i)))
+                       continue;
+               if (!request_region(res_base->start + ichx_regs[0][i],
+                                   ichx_reglen[i], name))
+                       goto request_err;
+       }
+       return 0;
+
+request_err:
+       /* Clean up: release already requested regions, if any */
+       for (i--; i >= 0; i--) {
+               if (!(use_gpio & (1 << i)))
+                       continue;
+               release_region(res_base->start + ichx_regs[0][i],
+                              ichx_reglen[i]);
+       }
+       return -EBUSY;
+}
+
+static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+               if (!(use_gpio & (1 << i)))
+                       continue;
+               release_region(res_base->start + ichx_regs[0][i],
+                              ichx_reglen[i]);
+       }
+}
+
 static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 {
        struct resource *res_base, *res_pm;
@@ -329,12 +391,11 @@ static int __devinit ichx_gpio_probe(struct platform_device *pdev)
        }
 
        res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
-       if (!res_base || !res_base->start || !res_base->end)
-               return -ENODEV;
-
-       if (!request_region(res_base->start, resource_size(res_base),
-                               pdev->name))
-               return -EBUSY;
+       ichx_priv.use_gpio = ich_info->use_gpio;
+       err = ichx_gpio_request_regions(res_base, pdev->name,
+                                       ichx_priv.use_gpio);
+       if (err)
+               return err;
 
        ichx_priv.gpio_base = res_base;
 
@@ -374,8 +435,7 @@ init:
        return 0;
 
 add_err:
-       release_region(ichx_priv.gpio_base->start,
-                       resource_size(ichx_priv.gpio_base));
+       ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
        if (ichx_priv.pm_base)
                release_region(ichx_priv.pm_base->start,
                                resource_size(ichx_priv.pm_base));
@@ -393,8 +453,7 @@ static int __devexit ichx_gpio_remove(struct platform_device *pdev)
                return err;
        }
 
-       release_region(ichx_priv.gpio_base->start,
-                               resource_size(ichx_priv.gpio_base));
+       ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
        if (ichx_priv.pm_base)
                release_region(ichx_priv.pm_base->start,
                                resource_size(ichx_priv.pm_base));
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
new file mode 100644 (file)
index 0000000..902af43
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * GPIO driver for Marvell SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver is a fairly straightforward GPIO driver for the
+ * complete family of Marvell EBU SoC platforms (Orion, Dove,
+ * Kirkwood, Discovery, Armada 370/XP). The only complexity of this
+ * driver is the different register layout that exists between the
+ * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP
+ * platforms (MV78200 from the Discovery family and the Armada
+ * XP). Therefore, this driver handles three variants of the GPIO
+ * block:
+ * - the basic variant, called "orion-gpio", with the simplest
+ *   register set. Used on Orion, Dove, Kirkwoord, Armada 370 and
+ *   non-SMP Discovery systems
+ * - the mv78200 variant for MV78200 Discovery systems. This variant
+ *   turns the edge mask and level mask registers into CPU0 edge
+ *   mask/level mask registers, and adds CPU1 edge mask/level mask
+ *   registers.
+ * - the armadaxp variant for Armada XP systems. This variant keeps
+ *   the normal cause/edge mask/level mask registers when the global
+ *   interrupts are used, but adds per-CPU cause/edge mask/level mask
+ *   registers n a separate memory area for the per-CPU GPIO
+ *   interrupts.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF           0x0000
+#define GPIO_IO_CONF_OFF       0x0004
+#define GPIO_BLINK_EN_OFF      0x0008
+#define GPIO_IN_POL_OFF                0x000c
+#define GPIO_DATA_IN_OFF       0x0010
+#define GPIO_EDGE_CAUSE_OFF    0x0014
+#define GPIO_EDGE_MASK_OFF     0x0018
+#define GPIO_LEVEL_MASK_OFF    0x001c
+
+/* The MV78200 has per-CPU registers for edge mask and level mask */
+#define GPIO_EDGE_MASK_MV78200_OFF(cpu)   ((cpu) ? 0x30 : 0x18)
+#define GPIO_LEVEL_MASK_MV78200_OFF(cpu)  ((cpu) ? 0x34 : 0x1C)
+
+/* The Armada XP has per-CPU registers for interrupt cause, interrupt
+ * mask and interrupt level mask. Those are relative to the
+ * percpu_membase. */
+#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
+#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)  (0x10 + (cpu) * 0x4)
+#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
+
+#define MVEBU_GPIO_SOC_VARIANT_ORION    0x1
+#define MVEBU_GPIO_SOC_VARIANT_MV78200  0x2
+#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
+
+#define MVEBU_MAX_GPIO_PER_BANK         32
+
+struct mvebu_gpio_chip {
+       struct gpio_chip   chip;
+       spinlock_t         lock;
+       void __iomem      *membase;
+       void __iomem      *percpu_membase;
+       unsigned int       irqbase;
+       struct irq_domain *domain;
+       int                soc_variant;
+};
+
+/*
+ * Functions returning addresses of individual registers for a given
+ * GPIO controller.
+ */
+static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_OUT_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_IO_CONF_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_IN_POL_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_DATA_IN_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
+{
+       int cpu;
+
+       switch(mvchip->soc_variant) {
+       case MVEBU_GPIO_SOC_VARIANT_ORION:
+       case MVEBU_GPIO_SOC_VARIANT_MV78200:
+               return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
+       case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+               cpu = smp_processor_id();
+               return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
+       default:
+               BUG();
+       }
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
+{
+       int cpu;
+
+       switch(mvchip->soc_variant) {
+       case MVEBU_GPIO_SOC_VARIANT_ORION:
+               return mvchip->membase + GPIO_EDGE_MASK_OFF;
+       case MVEBU_GPIO_SOC_VARIANT_MV78200:
+               cpu = smp_processor_id();
+               return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
+       case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+               cpu = smp_processor_id();
+               return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
+       default:
+               BUG();
+       }
+}
+
+static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
+{
+       int cpu;
+
+       switch(mvchip->soc_variant) {
+       case MVEBU_GPIO_SOC_VARIANT_ORION:
+               return mvchip->membase + GPIO_LEVEL_MASK_OFF;
+       case MVEBU_GPIO_SOC_VARIANT_MV78200:
+               cpu = smp_processor_id();
+               return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
+       case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+               cpu = smp_processor_id();
+               return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
+       default:
+               BUG();
+       }
+}
+
+/*
+ * Functions implementing the gpio_chip methods
+ */
+
+int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+       return pinctrl_request_gpio(chip->base + pin);
+}
+
+void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+{
+       pinctrl_free_gpio(chip->base + pin);
+}
+
+static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       u32 u;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+       if (value)
+               u |= 1 << pin;
+       else
+               u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_out(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
+static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       u32 u;
+
+       if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
+               u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
+                       readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+       } else {
+               u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+       }
+
+       return (u >> pin) & 1;
+}
+
+static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       int ret;
+       u32 u;
+
+       /* Check with the pinctrl driver whether this pin is usable as
+        * an input GPIO */
+       ret = pinctrl_gpio_direction_input(chip->base + pin);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+       u |= 1 << pin;
+       writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+
+       return 0;
+}
+
+static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+                                      int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       int ret;
+       u32 u;
+
+       /* Check with the pinctrl driver whether this pin is usable as
+        * an output GPIO */
+       ret = pinctrl_gpio_direction_output(chip->base + pin);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+       u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+
+       return 0;
+}
+
+static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       return irq_create_mapping(mvchip->domain, pin);
+}
+
+/*
+ * Functions implementing the irq_chip methods
+ */
+static void mvebu_gpio_irq_ack(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       u32 mask = ~(1 << (d->irq - gc->irq_base));
+
+       irq_gc_lock(gc);
+       writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
+       irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache &= ~mask;
+       writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+       irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache |= mask;
+       writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+       irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_mask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache &= ~mask;
+       writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+       irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       u32 mask = 1 << (d->irq - gc->irq_base);
+
+       irq_gc_lock(gc);
+       gc->mask_cache |= mask;
+       writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+       irq_gc_unlock(gc);
+}
+
+/*****************************************************************************
+ * MVEBU GPIO IRQ
+ *
+ * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
+ * value of the line or the opposite value.
+ *
+ * Level IRQ handlers: DATA_IN is used directly as cause register.
+ *                     Interrupt are masked by LEVEL_MASK registers.
+ * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
+ *                     Interrupt are masked by EDGE_MASK registers.
+ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+ *                     the polarity to catch the next line transaction.
+ *                     This is a race condition that might not perfectly
+ *                     work on some use cases.
+ *
+ * Every eight GPIO lines are grouped (OR'ed) before going up to main
+ * cause register.
+ *
+ *                    EDGE  cause    mask
+ *        data-in   /--------| |-----| |----\
+ *     -----| |-----                         ---- to main cause reg
+ *           X      \----------------| |----/
+ *        polarity    LEVEL          mask
+ *
+ ****************************************************************************/
+
+static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+       struct mvebu_gpio_chip *mvchip = gc->private;
+       int pin;
+       u32 u;
+
+       pin = d->hwirq;
+
+       u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
+       if (!u) {
+               return -EINVAL;
+       }
+
+       type &= IRQ_TYPE_SENSE_MASK;
+       if (type == IRQ_TYPE_NONE)
+               return -EINVAL;
+
+       /* Check if we need to change chip and handler */
+       if (!(ct->type & type))
+               if (irq_setup_alt_chip(d, type))
+                       return -EINVAL;
+
+       /*
+        * Configure interrupt polarity.
+        */
+       switch(type) {
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_LEVEL_HIGH:
+               u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+               u &= ~(1 << pin);
+               writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_LEVEL_LOW:
+               u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+               u |= 1 << pin;
+               writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+       case IRQ_TYPE_EDGE_BOTH: {
+               u32 v;
+
+               v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^
+                       readl_relaxed(mvebu_gpioreg_data_in(mvchip));
+
+               /*
+                * set initial polarity based on current input level
+                */
+               u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+               if (v & (1 << pin))
+                       u |= 1 << pin;          /* falling */
+               else
+                       u &= ~(1 << pin);       /* rising */
+               writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+       }
+       }
+       return 0;
+}
+
+static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
+       u32 cause, type;
+       int i;
+
+       if (mvchip == NULL)
+               return;
+
+       cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
+               readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
+       cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
+               readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
+
+       for (i = 0; i < mvchip->chip.ngpio; i++) {
+               int irq;
+
+               irq = mvchip->irqbase + i;
+
+               if (!(cause & (1 << i)))
+                       continue;
+
+               type = irqd_get_trigger_type(irq_get_irq_data(irq));
+               if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+                       /* Swap polarity (race with GPIO line) */
+                       u32 polarity;
+
+                       polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+                       polarity ^= 1 << i;
+                       writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
+               }
+               generic_handle_irq(irq);
+       }
+}
+
+static struct platform_device_id mvebu_gpio_ids[] = {
+       {
+               .name = "orion-gpio",
+       }, {
+               .name = "mv78200-gpio",
+       }, {
+               .name = "armadaxp-gpio",
+       }, {
+               /* sentinel */
+       },
+};
+MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
+
+static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+       {
+               .compatible = "marvell,orion-gpio",
+               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+       },
+       {
+               .compatible = "marvell,mv78200-gpio",
+               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
+       },
+       {
+               .compatible = "marvell,armadaxp-gpio",
+               .data       = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
+       },
+       {
+               /* sentinel */
+       },
+};
+MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
+
+static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+{
+       struct mvebu_gpio_chip *mvchip;
+       const struct of_device_id *match;
+       struct device_node *np = pdev->dev.of_node;
+       struct resource *res;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+       unsigned int ngpios;
+       int soc_variant;
+       int i, cpu, id;
+
+       match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
+       if (match)
+               soc_variant = (int) match->data;
+       else
+               soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (! res) {
+               dev_err(&pdev->dev, "Cannot get memory resource\n");
+               return -ENODEV;
+       }
+
+       mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
+       if (! mvchip){
+               dev_err(&pdev->dev, "Cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
+               dev_err(&pdev->dev, "Missing ngpios OF property\n");
+               return -ENODEV;
+       }
+
+       id = of_alias_get_id(pdev->dev.of_node, "gpio");
+       if (id < 0) {
+               dev_err(&pdev->dev, "Couldn't get OF id\n");
+               return id;
+       }
+
+       mvchip->soc_variant = soc_variant;
+       mvchip->chip.label = dev_name(&pdev->dev);
+       mvchip->chip.dev = &pdev->dev;
+       mvchip->chip.request = mvebu_gpio_request;
+       mvchip->chip.direction_input = mvebu_gpio_direction_input;
+       mvchip->chip.get = mvebu_gpio_get;
+       mvchip->chip.direction_output = mvebu_gpio_direction_output;
+       mvchip->chip.set = mvebu_gpio_set;
+       mvchip->chip.to_irq = mvebu_gpio_to_irq;
+       mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
+       mvchip->chip.ngpio = ngpios;
+       mvchip->chip.can_sleep = 0;
+#ifdef CONFIG_OF
+       mvchip->chip.of_node = np;
+#endif
+
+       spin_lock_init(&mvchip->lock);
+       mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
+       if (! mvchip->membase) {
+               dev_err(&pdev->dev, "Cannot ioremap\n");
+               kfree(mvchip->chip.label);
+               return -ENOMEM;
+       }
+
+       /* The Armada XP has a second range of registers for the
+        * per-CPU registers */
+       if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (! res) {
+                       dev_err(&pdev->dev, "Cannot get memory resource\n");
+                       kfree(mvchip->chip.label);
+                       return -ENODEV;
+               }
+
+               mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
+               if (! mvchip->percpu_membase) {
+                       dev_err(&pdev->dev, "Cannot ioremap\n");
+                       kfree(mvchip->chip.label);
+                       return -ENOMEM;
+               }
+       }
+
+       /*
+        * Mask and clear GPIO interrupts.
+        */
+       switch(soc_variant) {
+       case MVEBU_GPIO_SOC_VARIANT_ORION:
+               writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+               writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+               writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+               break;
+       case MVEBU_GPIO_SOC_VARIANT_MV78200:
+               writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+               for (cpu = 0; cpu < 2; cpu++) {
+                       writel_relaxed(0, mvchip->membase +
+                                      GPIO_EDGE_MASK_MV78200_OFF(cpu));
+                       writel_relaxed(0, mvchip->membase +
+                                      GPIO_LEVEL_MASK_MV78200_OFF(cpu));
+               }
+               break;
+       case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+               writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+               writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+               writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+               for (cpu = 0; cpu < 4; cpu++) {
+                       writel_relaxed(0, mvchip->percpu_membase +
+                                      GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu));
+                       writel_relaxed(0, mvchip->percpu_membase +
+                                      GPIO_EDGE_MASK_ARMADAXP_OFF(cpu));
+                       writel_relaxed(0, mvchip->percpu_membase +
+                                      GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu));
+               }
+               break;
+       default:
+               BUG();
+       }
+
+       gpiochip_add(&mvchip->chip);
+
+       /* Some gpio controllers do not provide irq support */
+       if (!of_irq_count(np))
+               return 0;
+
+       /* Setup the interrupt handlers. Each chip can have up to 4
+        * interrupt handlers, with each handler dealing with 8 GPIO
+        * pins. */
+       for (i = 0; i < 4; i++) {
+               int irq;
+               irq = platform_get_irq(pdev, i);
+               if (irq < 0)
+                       continue;
+               irq_set_handler_data(irq, mvchip);
+               irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
+       }
+
+       mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
+       if (mvchip->irqbase < 0) {
+               dev_err(&pdev->dev, "no irqs\n");
+               kfree(mvchip->chip.label);
+               return -ENOMEM;
+       }
+
+       gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
+                                   mvchip->membase, handle_level_irq);
+       if (! gc) {
+               dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
+               kfree(mvchip->chip.label);
+               return -ENOMEM;
+       }
+
+       gc->private = mvchip;
+       ct = &gc->chip_types[0];
+       ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+       ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
+       ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
+       ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+       ct->chip.name = mvchip->chip.label;
+
+       ct = &gc->chip_types[1];
+       ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+       ct->chip.irq_ack = mvebu_gpio_irq_ack;
+       ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
+       ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
+       ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+       ct->handler = handle_edge_irq;
+       ct->chip.name = mvchip->chip.label;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+
+       /* Setup irq domain on top of the generic chip. */
+       mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
+                                              mvchip->irqbase, 0,
+                                              &irq_domain_simple_ops,
+                                              mvchip);
+       if (!mvchip->domain) {
+               dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
+                       mvchip->chip.label);
+               irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
+                                       IRQ_LEVEL | IRQ_NOPROBE);
+               kfree(gc);
+               kfree(mvchip->chip.label);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static struct platform_driver mvebu_gpio_driver = {
+       .driver         = {
+               .name           = "mvebu-gpio",
+               .owner          = THIS_MODULE,
+               .of_match_table = mvebu_gpio_of_match,
+       },
+       .probe          = mvebu_gpio_probe,
+       .id_table       = mvebu_gpio_ids,
+};
+
+static int __init mvebu_gpio_init(void)
+{
+       return platform_driver_register(&mvebu_gpio_driver);
+}
+postcore_initcall(mvebu_gpio_init);
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
new file mode 100644 (file)
index 0000000..dd58e8b
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Access to GPOs on TWL6040 chip
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Authors:
+ *     Sergio Aguirre <saaguirre@ti.com>
+ *     Peter Ujfalusi <peter.ujfalusi@ti.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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <linux/mfd/twl6040.h>
+
+static struct gpio_chip twl6040gpo_chip;
+
+static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+       int ret = 0;
+
+       ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+       if (ret < 0)
+               return ret;
+
+       return (ret >> offset) & 1;
+}
+
+static int twl6040gpo_direction_out(struct gpio_chip *chip, unsigned offset,
+                                   int value)
+{
+       /* This only drives GPOs, and can't change direction */
+       return 0;
+}
+
+static void twl6040gpo_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+       int ret;
+       u8 gpoctl;
+
+       ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+       if (ret < 0)
+               return;
+
+       if (value)
+               gpoctl = ret | (1 << offset);
+       else
+               gpoctl = ret & ~(1 << offset);
+
+       twl6040_reg_write(twl6040, TWL6040_REG_GPOCTL, gpoctl);
+}
+
+static struct gpio_chip twl6040gpo_chip = {
+       .label                  = "twl6040",
+       .owner                  = THIS_MODULE,
+       .get                    = twl6040gpo_get,
+       .direction_output       = twl6040gpo_direction_out,
+       .set                    = twl6040gpo_set,
+       .can_sleep              = 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+{
+       struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
+       struct device *twl6040_core_dev = pdev->dev.parent;
+       struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
+       int ret;
+
+       if (pdata)
+               twl6040gpo_chip.base = pdata->gpio_base;
+       else
+               twl6040gpo_chip.base = -1;
+
+       if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
+               twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */
+       else
+               twl6040gpo_chip.ngpio = 1; /* twl6041 have 1 GPO */
+
+       twl6040gpo_chip.dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+       twl6040gpo_chip.of_node = twl6040_core_dev->of_node;
+#endif
+
+       ret = gpiochip_add(&twl6040gpo_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
+               twl6040gpo_chip.ngpio = 0;
+       }
+
+       return ret;
+}
+
+static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+{
+       return gpiochip_remove(&twl6040gpo_chip);
+}
+
+/* Note:  this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl6040-gpo");
+
+static struct platform_driver gpo_twl6040_driver = {
+       .driver = {
+               .name   = "twl6040-gpo",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = gpo_twl6040_probe,
+       .remove         = gpo_twl6040_remove,
+};
+
+module_platform_driver(gpo_twl6040_driver);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPO interface for TWL6040");
+MODULE_LICENSE("GPL");
index 2f4b01bda87c16bfc7bfb70a48f2c686f27be26c..36509ae32083d2b3e48ec894768c504e1179577c 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/hwmon.h>
 #include <linux/gpio.h>
 #include <linux/gpio-fan.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 struct gpio_fan_data {
        struct platform_device  *pdev;
@@ -400,14 +402,131 @@ static ssize_t show_name(struct device *dev,
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
+
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_fan_get_of_pdata(struct device *dev,
+                           struct gpio_fan_platform_data *pdata)
+{
+       struct device_node *node;
+       struct gpio_fan_speed *speed;
+       unsigned *ctrl;
+       unsigned i;
+       u32 u;
+       struct property *prop;
+       const __be32 *p;
+
+       node = dev->of_node;
+
+       /* Fill GPIO pin array */
+       pdata->num_ctrl = of_gpio_count(node);
+       if (!pdata->num_ctrl) {
+               dev_err(dev, "gpios DT property empty / missing");
+               return -ENODEV;
+       }
+       ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned),
+                               GFP_KERNEL);
+       if (!ctrl)
+               return -ENOMEM;
+       for (i = 0; i < pdata->num_ctrl; i++) {
+               int val;
+
+               val = of_get_gpio(node, i);
+               if (val < 0)
+                       return val;
+               ctrl[i] = val;
+       }
+       pdata->ctrl = ctrl;
+
+       /* Get number of RPM/ctrl_val pairs in speed map */
+       prop = of_find_property(node, "gpio-fan,speed-map", &i);
+       if (!prop) {
+               dev_err(dev, "gpio-fan,speed-map DT property missing");
+               return -ENODEV;
+       }
+       i = i / sizeof(u32);
+       if (i == 0 || i & 1) {
+               dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");
+               return -ENODEV;
+       }
+       pdata->num_speed = i / 2;
+
+       /*
+        * Populate speed map
+        * Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
+        * this needs splitting into pairs to create gpio_fan_speed structs
+        */
+       speed = devm_kzalloc(dev,
+                       pdata->num_speed * sizeof(struct gpio_fan_speed),
+                       GFP_KERNEL);
+       if (!speed)
+               return -ENOMEM;
+       p = NULL;
+       for (i = 0; i < pdata->num_speed; i++) {
+               p = of_prop_next_u32(prop, p, &u);
+               if (!p)
+                       return -ENODEV;
+               speed[i].rpm = u;
+               p = of_prop_next_u32(prop, p, &u);
+               if (!p)
+                       return -ENODEV;
+               speed[i].ctrl_val = u;
+       }
+       pdata->speed = speed;
+
+       /* Alarm GPIO if one exists */
+       if (of_gpio_named_count(node, "alarm-gpios")) {
+               struct gpio_fan_alarm *alarm;
+               int val;
+               enum of_gpio_flags flags;
+
+               alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
+                                       GFP_KERNEL);
+               if (!alarm)
+                       return -ENOMEM;
+
+               val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
+               if (val < 0)
+                       return val;
+               alarm->gpio = val;
+               alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+               pdata->alarm = alarm;
+       }
+
+       return 0;
+}
+
+static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+       { .compatible = "gpio-fan", },
+       {},
+};
+#endif /* CONFIG_OF_GPIO */
+
 static int __devinit gpio_fan_probe(struct platform_device *pdev)
 {
        int err;
        struct gpio_fan_data *fan_data;
        struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
 
+#ifdef CONFIG_OF_GPIO
+       if (!pdata) {
+               pdata = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct gpio_fan_platform_data),
+                                       GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+
+               err = gpio_fan_get_of_pdata(&pdev->dev, pdata);
+               if (err)
+                       return err;
+       }
+#else /* CONFIG_OF_GPIO */
        if (!pdata)
                return -EINVAL;
+#endif /* CONFIG_OF_GPIO */
 
        fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
                                GFP_KERNEL);
@@ -511,6 +630,7 @@ static struct platform_driver gpio_fan_driver = {
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
+               .of_match_table = of_match_ptr(of_gpio_fan_match),
        },
 };
 
index 2091ae8f539a5e78ee59338cd29876109b22883d..2421d95130d48ac526ac0203be47b614c4254617 100644 (file)
@@ -982,7 +982,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap)
 
        if (adap->nr == -1) /* -1 means dynamically assign bus id */
                return i2c_add_adapter(adap);
-       if (adap->nr & ~MAX_ID_MASK)
+       if (adap->nr & ~MAX_IDR_MASK)
                return -EINVAL;
 
 retry:
index 57d00caefc86c2762b1c5eeee5c3bd8e9a408b76..01451940393b9b95dd9a228cdb1283884c781aa3 100644 (file)
@@ -181,7 +181,7 @@ static const struct ide_port_ops atp86x_port_ops = {
        .cable_detect           = atp86x_cable_detect,
 };
 
-static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+static const struct ide_port_info aec62xx_chipsets[] __devinitconst = {
        {       /* 0: AEC6210 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_aec62xx,
index d3be99fb4154fdc1f55198d46b3d1f6611c1dd12..8f3570ee64c356ed48438cd31ac438a6a87dc126 100644 (file)
 
 /* port addresses for auto-detection */
 #define ALI_NUM_PORTS 4
-static const int ports[ALI_NUM_PORTS] __initdata =
+static const int ports[ALI_NUM_PORTS] __initconst =
        { 0x074, 0x0f4, 0x034, 0x0e4 };
 
 /* register initialization data */
 typedef struct { u8 reg, data; } RegInitializer;
 
-static const RegInitializer initData[] __initdata = {
+static const RegInitializer initData[] __initconst = {
        {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
        {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
        {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
index 2c8016ad0e269edf7887d13fc775ce4f9ebd1927..911a27ca356b71b406d4ff0eae80e7d4d5b51abf 100644 (file)
@@ -512,7 +512,7 @@ static const struct ide_dma_ops ali_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info ali15x3_chipset __devinitdata = {
+static const struct ide_port_info ali15x3_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_ali15x3,
        .init_hwif      = init_hwif_ali15x3,
index 3747b2561f099f7af257edb2b1fbebdbfb979f25..56fc99557ba28dfc24d8d5e0e06054fa8605553a 100644 (file)
@@ -223,7 +223,7 @@ static const struct ide_port_ops amd_port_ops = {
                .udma_mask      = udma,                                 \
        }
 
-static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
+static const struct ide_port_info amd74xx_chipsets[] __devinitconst = {
        /* 0: AMD7401 */        DECLARE_AMD_DEV(0x00, ATA_UDMA2),
        /* 1: AMD7409 */        DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
        /* 2: AMD7411/7441 */   DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
index 15f0ead89f5cfac911e92a2a0df3279ec8088486..cb43480b1bd5eb34f0a345eb57e1502618e09dbb 100644 (file)
@@ -139,7 +139,7 @@ static const struct ide_port_ops atiixp_port_ops = {
        .cable_detect           = atiixp_cable_detect,
 };
 
-static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+static const struct ide_port_info atiixp_pci_info[] __devinitconst = {
        {       /* 0: IXP200/300/400/700 */
                .name           = DRV_NAME,
                .enablebits     = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
index 14717304b3888fc5ce45eb2771629dc39368bd64..70f0a2754c13eb38b92010b55db25505716f92a5 100644 (file)
@@ -685,7 +685,7 @@ static int pci_conf2(void)
        return 0;
 }
 
-static const struct ide_port_info cmd640_port_info __initdata = {
+static const struct ide_port_info cmd640_port_info __initconst = {
        .chipset                = ide_cmd640,
        .host_flags             = IDE_HFLAG_SERIALIZE |
                                  IDE_HFLAG_NO_DMA |
index 5f80312e636b25f05bd3732760d3536c24425242..d1fc43802f5d21c9427aa1bc80cf6fc47d9302ef 100644 (file)
@@ -327,7 +327,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+static const struct ide_port_info cmd64x_chipsets[] __devinitconst = {
        {       /* 0: CMD643 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
index 2c1e5f7cd261f79e82f947ae0cf7baaa3fc0505e..14447621e60b7072dc3cb0d5845c81d98ed6a611 100644 (file)
@@ -94,7 +94,7 @@ static const struct ide_port_ops cs5520_port_ops = {
        .set_dma_mode           = cs5520_set_dma_mode,
 };
 
-static const struct ide_port_info cyrix_chipset __devinitdata = {
+static const struct ide_port_info cyrix_chipset __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
        .port_ops       = &cs5520_port_ops,
index 4dc4eb92b076f62218c14f7b966f2040fce6625b..49b40ad59d1a71e5ad6e96b15a8c0e1c028e6636 100644 (file)
@@ -245,7 +245,7 @@ static const struct ide_port_ops cs5530_port_ops = {
        .udma_filter            = cs5530_udma_filter,
 };
 
-static const struct ide_port_info cs5530_chipset __devinitdata = {
+static const struct ide_port_info cs5530_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
index 5059fafadf29d469568f2106766117d30069f294..18d4c852602bfa042926d21d03dce3e231bc33eb 100644 (file)
@@ -170,7 +170,7 @@ static const struct ide_port_ops cs5535_port_ops = {
        .cable_detect           = cs5535_cable_detect,
 };
 
-static const struct ide_port_info cs5535_chipset __devinitdata = {
+static const struct ide_port_info cs5535_chipset __devinitconst = {
        .name           = DRV_NAME,
        .port_ops       = &cs5535_port_ops,
        .host_flags     = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
index 847553fd8b963beca810aadb548d2f4f96db666e..3ffb49dab574e80929e764fd50b4a3e5f8c72fe5 100644 (file)
@@ -163,7 +163,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
        .set_dma_mode           = cy82c693_set_dma_mode,
 };
 
-static const struct ide_port_info cy82c693_chipset __devinitdata = {
+static const struct ide_port_info cy82c693_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_iops      = init_iops_cy82c693,
        .port_ops       = &cy82c693_port_ops,
index 46af4743b3e68db2a7d099d2cec82ae3e95eb411..8722df329cbeb30d4500c17f53435c00c4e83d13 100644 (file)
@@ -91,7 +91,7 @@ static const struct ide_port_ops dtc2278_port_ops = {
        .set_pio_mode           = dtc2278_set_pio_mode,
 };
 
-static const struct ide_port_info dtc2278_port_info __initdata = {
+static const struct ide_port_info dtc2278_port_info __initconst = {
        .name                   = DRV_NAME,
        .chipset                = ide_dtc2278,
        .port_ops               = &dtc2278_port_ops,
index 58c51cddc1002500b67d5799d70a55f21fab74bb..4aec3b87ff91aec9b1e575c9c69af1b485a60914 100644 (file)
@@ -443,7 +443,7 @@ static struct hpt_timings hpt37x_timings = {
        }
 };
 
-static const struct hpt_info hpt36x __devinitdata = {
+static const struct hpt_info hpt36x __devinitconst = {
        .chip_name      = "HPT36x",
        .chip_type      = HPT36x,
        .udma_mask      = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
@@ -451,7 +451,7 @@ static const struct hpt_info hpt36x __devinitdata = {
        .timings        = &hpt36x_timings
 };
 
-static const struct hpt_info hpt370 __devinitdata = {
+static const struct hpt_info hpt370 __devinitconst = {
        .chip_name      = "HPT370",
        .chip_type      = HPT370,
        .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -459,7 +459,7 @@ static const struct hpt_info hpt370 __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt370a __devinitdata = {
+static const struct hpt_info hpt370a __devinitconst = {
        .chip_name      = "HPT370A",
        .chip_type      = HPT370A,
        .udma_mask      = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -467,7 +467,7 @@ static const struct hpt_info hpt370a __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt374 __devinitdata = {
+static const struct hpt_info hpt374 __devinitconst = {
        .chip_name      = "HPT374",
        .chip_type      = HPT374,
        .udma_mask      = ATA_UDMA5,
@@ -475,7 +475,7 @@ static const struct hpt_info hpt374 __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372 __devinitdata = {
+static const struct hpt_info hpt372 __devinitconst = {
        .chip_name      = "HPT372",
        .chip_type      = HPT372,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -483,7 +483,7 @@ static const struct hpt_info hpt372 __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372a __devinitdata = {
+static const struct hpt_info hpt372a __devinitconst = {
        .chip_name      = "HPT372A",
        .chip_type      = HPT372A,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -491,7 +491,7 @@ static const struct hpt_info hpt372a __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt302 __devinitdata = {
+static const struct hpt_info hpt302 __devinitconst = {
        .chip_name      = "HPT302",
        .chip_type      = HPT302,
        .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -499,7 +499,7 @@ static const struct hpt_info hpt302 __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt371 __devinitdata = {
+static const struct hpt_info hpt371 __devinitconst = {
        .chip_name      = "HPT371",
        .chip_type      = HPT371,
        .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -507,7 +507,7 @@ static const struct hpt_info hpt371 __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt372n __devinitdata = {
+static const struct hpt_info hpt372n __devinitconst = {
        .chip_name      = "HPT372N",
        .chip_type      = HPT372N,
        .udma_mask      = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -515,7 +515,7 @@ static const struct hpt_info hpt372n __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt302n __devinitdata = {
+static const struct hpt_info hpt302n __devinitconst = {
        .chip_name      = "HPT302N",
        .chip_type      = HPT302N,
        .udma_mask      = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -523,7 +523,7 @@ static const struct hpt_info hpt302n __devinitdata = {
        .timings        = &hpt37x_timings
 };
 
-static const struct hpt_info hpt371n __devinitdata = {
+static const struct hpt_info hpt371n __devinitconst = {
        .chip_name      = "HPT371N",
        .chip_type      = HPT371N,
        .udma_mask      = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -1361,7 +1361,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+static const struct ide_port_info hpt366_chipsets[] __devinitconst = {
        {       /* 0: HPT36x */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_hpt366,
index 986f2513eab435e06e2597977624fd9d8a2550ce..1e0fd3aa962ddcaec7164064e1e2c60c9506036b 100644 (file)
@@ -341,7 +341,7 @@ static const struct ide_port_ops ht6560b_port_ops = {
        .set_pio_mode           = ht6560b_set_pio_mode,
 };
 
-static const struct ide_port_info ht6560b_port_info __initdata = {
+static const struct ide_port_info ht6560b_port_info __initconst = {
        .name                   = DRV_NAME,
        .chipset                = ide_ht6560b,
        .tp_ops                 = &ht6560b_tp_ops,
index bcb507b0cfd4c22f4b9b988ac9c789f3e27dc3cf..e640d0ac3af63cad4730fc370fa58bc7e5a7ac1f 100644 (file)
@@ -451,7 +451,7 @@ err_free:
        return ret;
 }
 
-static const struct ide_port_info icside_v6_port_info __initdata = {
+static const struct ide_port_info icside_v6_port_info __initconst = {
        .init_dma               = icside_dma_off_init,
        .port_ops               = &icside_v6_no_dma_port_ops,
        .host_flags             = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
index 7f56b738d7621f8a37377afc2f93e7236f387996..dab5b670bfbff335b02346044f1380d262b569f5 100644 (file)
@@ -53,7 +53,7 @@ static const struct ide_port_ops netcell_port_ops = {
                .udma_mask      = ATA_UDMA6, \
        }
 
-static const struct ide_port_info generic_chipsets[] __devinitdata = {
+static const struct ide_port_info generic_chipsets[] __devinitconst = {
        /*  0: Unknown */
        DECLARE_GENERIC_PCI_DEV(0),
 
index 560e66d07659b46f8ccbc2fef17dccf26f963f96..d5dd180c4b85766649ada84c63f2d67f93cdac2e 100644 (file)
@@ -115,7 +115,7 @@ static const struct ide_port_ops it8172_port_ops = {
        .set_dma_mode   = it8172_set_dma_mode,
 };
 
-static const struct ide_port_info it8172_port_info __devinitdata = {
+static const struct ide_port_info it8172_port_info __devinitconst = {
        .name           = DRV_NAME,
        .port_ops       = &it8172_port_ops,
        .enablebits     = { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} },
index 46816ba26416d30ebe650ead5e99bd96532f558f..1847aeb5450aa7d698bc1308832f0562a1202997 100644 (file)
@@ -156,7 +156,7 @@ static const struct ide_port_ops it8213_port_ops = {
        .cable_detect           = it8213_cable_detect,
 };
 
-static const struct ide_port_info it8213_chipset __devinitdata = {
+static const struct ide_port_info it8213_chipset __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = { {0x41, 0x80, 0x80} },
        .port_ops       = &it8213_port_ops,
index 2e3169f2acda26b50e16ac56232dd5e8b5e8ca24..c5611dbca34241dfe2f68078c3693f44a1dd4338 100644 (file)
@@ -630,7 +630,7 @@ static const struct ide_port_ops it821x_port_ops = {
        .cable_detect           = it821x_cable_detect,
 };
 
-static const struct ide_port_info it821x_chipset __devinitdata = {
+static const struct ide_port_info it821x_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_it821x,
        .init_hwif      = init_hwif_it821x,
index 74c2c4a6d909703b6c9cf7a605967f60cfda0149..efddd7d9f92d9b5f983bd41f4d6eac2f564eac2a 100644 (file)
@@ -102,7 +102,7 @@ static const struct ide_port_ops jmicron_port_ops = {
        .cable_detect           = jmicron_cable_detect,
 };
 
-static const struct ide_port_info jmicron_chipset __devinitdata = {
+static const struct ide_port_info jmicron_chipset __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
        .port_ops       = &jmicron_port_ops,
index 95327a2c2422a5c7e86c3bbe9d93a26d38547de7..73f78d872d551cf5be82b690672daddc7be97cb8 100644 (file)
@@ -293,7 +293,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
        .dma_sff_read_status    = superio_dma_sff_read_status,
 };
 
-static const struct ide_port_info ns87415_chipset __devinitdata = {
+static const struct ide_port_info ns87415_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_ns87415,
        .tp_ops         = &ns87415_tp_ops,
index 1a53a4c375ed4fdf998ac4be336dc1d79e2b82a3..39edc66cb96cfb52b613fc481de36270b584223c 100644 (file)
@@ -131,7 +131,7 @@ static const struct ide_port_ops opti621_port_ops = {
        .set_pio_mode           = opti621_set_pio_mode,
 };
 
-static const struct ide_port_info opti621_chipset __devinitdata = {
+static const struct ide_port_info opti621_chipset __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
        .port_ops       = &opti621_port_ops,
index 9546fe2a93f7f5560175d590af1203e25b8821ea..2e5ceb62fb3b38d461f2c61fa6c534e47ade22c6 100644 (file)
@@ -465,7 +465,7 @@ static const struct ide_port_ops pdcnew_port_ops = {
                .udma_mask      = udma, \
        }
 
-static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
+static const struct ide_port_info pdcnew_chipsets[] __devinitconst = {
        /* 0: PDC202{68,70} */          DECLARE_PDCNEW_DEV(ATA_UDMA5),
        /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6),
 };
index 3a35ec6193d25241312cdd03595a53cdf2999a49..5634510968128f499bf136959619a444328d0e2a 100644 (file)
@@ -270,7 +270,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
                .max_sectors    = sectors, \
        }
 
-static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
+static const struct ide_port_info pdc202xx_chipsets[] __devinitconst = {
        {       /* 0: PDC20246 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_pdc202xx,
index 1892e81fb00f615b80c3dfaa8f10a643037a5eb6..fe0fd60cfc09040e3e47e9dadd8e455ba610f421 100644 (file)
@@ -344,7 +344,7 @@ static const struct ide_port_ops ich_port_ops = {
                .udma_mask      = udma, \
        }
 
-static const struct ide_port_info piix_pci_info[] __devinitdata = {
+static const struct ide_port_info piix_pci_info[] __devinitconst = {
        /* 0: MPIIX */
        {       /*
                 * MPIIX actually has only a single IDE channel mapped to
index e03f4f19c1d61af084012a8714b5067f4d1a6c41..a6fb6a894c7bfb5c4b45bcd109f01b706b643f2a 100644 (file)
@@ -335,7 +335,7 @@ static const struct ide_port_ops qd6580_port_ops = {
        .set_pio_mode           = qd6580_set_pio_mode,
 };
 
-static const struct ide_port_info qd65xx_port_info __initdata = {
+static const struct ide_port_info qd65xx_port_info __initconst = {
        .name                   = DRV_NAME,
        .tp_ops                 = &qd65xx_tp_ops,
        .chipset                = ide_qd65xx,
index a6414a884eb120f07018b5b8a2b9887d8275d191..c04173e9fc38264326536088bd7c28aeb64adeff 100644 (file)
@@ -38,7 +38,7 @@ static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
        }
 }
 
-static const struct ide_port_info rz1000_chipset __devinitdata = {
+static const struct ide_port_info rz1000_chipset __devinitconst = {
        .name           = DRV_NAME,
        .host_flags     = IDE_HFLAG_NO_DMA,
 };
index 356b9b504ffd421c4088316694f7392e34b5ed42..d4758ebe77da66586f2ff16c2b06ab3d25cd5fae 100644 (file)
@@ -291,7 +291,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sc1200_chipset __devinitdata = {
+static const struct ide_port_info sc1200_chipset __devinitconst = {
        .name           = DRV_NAME,
        .port_ops       = &sc1200_port_ops,
        .dma_ops        = &sc1200_dma_ops,
index b7f5b0c4310c2e18558f222b217b1ed9a4f3e0b4..9701038100216e03d77c113b34354c193573edb4 100644 (file)
@@ -811,7 +811,7 @@ static const struct ide_dma_ops scc_dma_ops = {
        .dma_sff_read_status    = scc_dma_sff_read_status,
 };
 
-static const struct ide_port_info scc_chipset __devinitdata = {
+static const struct ide_port_info scc_chipset __devinitconst = {
        .name           = "sccIDE",
        .init_iops      = init_iops_scc,
        .init_dma       = scc_init_dma,
index 35fb8dabb55dc4e4cf5e32217095ea819b1c4f9f..24d72ef23df7cd550270a78e2ff04a74c37464ab 100644 (file)
@@ -337,7 +337,7 @@ static const struct ide_port_ops svwks_port_ops = {
        .cable_detect           = svwks_cable_detect,
 };
 
-static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+static const struct ide_port_info serverworks_chipsets[] __devinitconst = {
        {       /* 0: OSB4 */
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_svwks,
index ddeda444a27aebdcfda34a20bb04742d288656d2..46f7e30d379038bcd47575952f02f5a61996a1f4 100644 (file)
@@ -719,7 +719,7 @@ static const struct ide_dma_ops sil_dma_ops = {
                .udma_mask      = ATA_UDMA6,            \
        }
 
-static const struct ide_port_info siimage_chipsets[] __devinitdata = {
+static const struct ide_port_info siimage_chipsets[] __devinitconst = {
        /* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
        /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
 };
index 4a00225677584ac8ff0a19577b83592ea8593f2a..09e61b4c5e94f5331413ae52f56ff8a93983ed85 100644 (file)
@@ -563,7 +563,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
        .cable_detect           = sis_cable_detect,
 };
 
-static const struct ide_port_info sis5513_chipset __devinitdata = {
+static const struct ide_port_info sis5513_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_sis5513,
        .enablebits     = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
index f21dc2ad768274bc03d1cbe88b487ad0fc87d3e8..d051cd224bdbe363a2b43fcc3d1c87e0bc4105ba 100644 (file)
@@ -299,7 +299,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sl82c105_chipset __devinitdata = {
+static const struct ide_port_info sl82c105_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_sl82c105,
        .enablebits     = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
index 864ffe0e26d9eb0342e139bce4e468d25d36d3a7..863a5e9283ca189895f53e3f233a0b75af0777d3 100644 (file)
@@ -132,7 +132,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
        .cable_detect           = slc90e66_cable_detect,
 };
 
-static const struct ide_port_info slc90e66_chipset __devinitdata = {
+static const struct ide_port_info slc90e66_chipset __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
        .port_ops       = &slc90e66_port_ops,
index 4799d5c384e7ee8711342d32c4b58af52a13b8f5..17946785ebf672c3e615b8761cb31da533e28b4e 100644 (file)
@@ -192,7 +192,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
        .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info tc86c001_chipset __devinitdata = {
+static const struct ide_port_info tc86c001_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_tc86c001,
        .port_ops       = &tc86c001_port_ops,
index 281c91426345946279412880bc804d01d287ec4c..55ce1b80efcbd861161595c2d10f55439129eb0b 100644 (file)
@@ -92,7 +92,7 @@ static const struct ide_port_ops triflex_port_ops = {
        .set_dma_mode           = triflex_set_mode,
 };
 
-static const struct ide_port_info triflex_device __devinitdata = {
+static const struct ide_port_info triflex_device __devinitconst = {
        .name           = DRV_NAME,
        .enablebits     = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
        .port_ops       = &triflex_port_ops,
index 4b42ca091534093a52cefdd5398ba8a6a0726cb6..e494a98a43a9ba2cebd5111c5839073e8130e39b 100644 (file)
@@ -324,7 +324,7 @@ static struct ide_dma_ops trm290_dma_ops = {
        .dma_check              = trm290_dma_check,
 };
 
-static const struct ide_port_info trm290_chipset __devinitdata = {
+static const struct ide_port_info trm290_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_hwif      = init_hwif_trm290,
        .tp_ops         = &trm290_tp_ops,
index 7002765b593ce052b8f72acf7e0dda5ddf1261df..91d49dd957ef634f02a6c9657afe236524d3a936 100644 (file)
@@ -117,7 +117,7 @@ static const struct ide_port_ops tx4938ide_port_ops = {
        .set_pio_mode           = tx4938ide_set_pio_mode,
 };
 
-static const struct ide_port_info tx4938ide_port_info __initdata = {
+static const struct ide_port_info tx4938ide_port_info __initconst = {
        .port_ops               = &tx4938ide_port_ops,
 #ifdef __BIG_ENDIAN
        .tp_ops                 = &tx4938ide_tp_ops,
index 71c231954972d304f6e402995ae963b56c20763b..c0ab800b7bb34f228cc6488a966cfad588c1f765 100644 (file)
@@ -522,7 +522,7 @@ static const struct ide_dma_ops tx4939ide_dma_ops = {
        .dma_sff_read_status    = tx4939ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info tx4939ide_port_info __initdata = {
+static const struct ide_port_info tx4939ide_port_info __initconst = {
        .init_hwif              = tx4939ide_init_hwif,
        .init_dma               = tx4939ide_init_dma,
        .port_ops               = &tx4939ide_port_ops,
index 5cfb7812066961281a37710dca2f033c80b4d733..3aa0fea0f3d9c779048f1c07ab9422646eb8068d 100644 (file)
@@ -128,7 +128,7 @@ static const struct ide_port_ops umc8672_port_ops = {
        .set_pio_mode           = umc_set_pio_mode,
 };
 
-static const struct ide_port_info umc8672_port_info __initdata = {
+static const struct ide_port_info umc8672_port_info __initconst = {
        .name                   = DRV_NAME,
        .chipset                = ide_umc8672,
        .port_ops               = &umc8672_port_ops,
index f46f49cfcc28a25aed707d0d57a69e87b93409b5..eb7767864d10530ce2a72485823fb615ca1436d9 100644 (file)
@@ -403,7 +403,7 @@ static const struct ide_port_ops via_port_ops = {
        .cable_detect           = via82cxxx_cable_detect,
 };
 
-static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+static const struct ide_port_info via82cxxx_chipset __devinitconst = {
        .name           = DRV_NAME,
        .init_chipset   = init_chipset_via82cxxx,
        .enablebits     = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
index d67999f6e34a147a6f99cdcd162fba4ebfdbb82d..394fea2ba1bc2018cac2f047ee7f0802823b0222 100644 (file)
@@ -390,7 +390,7 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
                ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
                                        next_id, &id);
                if (!ret)
-                       next_id = ((unsigned) id + 1) & MAX_ID_MASK;
+                       next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
                spin_unlock_irqrestore(&cm.lock, flags);
        } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
 
index 26b37603dcf11b63a7ae396d93533fed8a2a09cd..1983adc192432936e67b3ab128627596604b6f2d 100644 (file)
@@ -2648,8 +2648,8 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
        req.responder_resources = conn_param->responder_resources;
        req.initiator_depth = conn_param->initiator_depth;
        req.flow_control = conn_param->flow_control;
-       req.retry_count = conn_param->retry_count;
-       req.rnr_retry_count = conn_param->rnr_retry_count;
+       req.retry_count = min_t(u8, 7, conn_param->retry_count);
+       req.rnr_retry_count = min_t(u8, 7, conn_param->rnr_retry_count);
        req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
        req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
        req.max_cm_retries = CMA_MAX_CM_RETRIES;
@@ -2770,7 +2770,7 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
        rep.initiator_depth = conn_param->initiator_depth;
        rep.failover_accepted = 0;
        rep.flow_control = conn_param->flow_control;
-       rep.rnr_retry_count = conn_param->rnr_retry_count;
+       rep.rnr_retry_count = min_t(u8, 7, conn_param->rnr_retry_count);
        rep.srq = id_priv->srq ? 1 : 0;
 
        ret = ib_send_cm_rep(id_priv->cm_id.ib, &rep);
index d9b0ebcb67d7371946f8a644d26066e3a175df28..8f5290147e8a8d1fbeb5399f230a900c6e023c97 100644 (file)
@@ -220,7 +220,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
                        cq = ERR_PTR(-EAGAIN);
                        goto create_cq_exit4;
                }
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
 
                h_ret = hipz_h_register_rpage_cq(adapter_handle,
                                                 my_cq->ipz_cq_handle,
index 818d721fc4489186fee9d7c6b1fa7e79835f412a..90da6747d3954507ff6bf1149509d85eb58f0484 100644 (file)
@@ -101,7 +101,7 @@ int ehca_create_eq(struct ehca_shca *shca,
                if (!vpage)
                        goto create_eq_exit2;
 
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
                h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
                                                 eq->ipz_eq_handle,
                                                 &eq->pf,
index b781b2cb062409a2f97a4a045c2c67b7e6641a71..87844869dcc2f76f8a07d9b6397d02a16bfbeeae 100644 (file)
@@ -1136,7 +1136,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
                }
 
                if (rnum > 1) {
-                       rpage = virt_to_abs(kpage);
+                       rpage = __pa(kpage);
                        if (!rpage) {
                                ehca_err(&shca->ib_device, "kpage=%p i=%x",
                                         kpage, i);
@@ -1231,7 +1231,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
                         pginfo->num_kpages, pginfo->num_hwpages, kpage);
                goto ehca_rereg_mr_rereg1_exit1;
        }
-       rpage = virt_to_abs(kpage);
+       rpage = __pa(kpage);
        if (!rpage) {
                ehca_err(&shca->ib_device, "kpage=%p", kpage);
                ret = -EFAULT;
@@ -1525,7 +1525,7 @@ static inline void *ehca_calc_sectbase(int top, int dir, int idx)
        unsigned long ret = idx;
        ret |= dir << EHCA_DIR_INDEX_SHIFT;
        ret |= top << EHCA_TOP_INDEX_SHIFT;
-       return abs_to_virt(ret << SECTION_SIZE_BITS);
+       return __va(ret << SECTION_SIZE_BITS);
 }
 
 #define ehca_bmap_valid(entry) \
@@ -1537,7 +1537,7 @@ static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
 {
        u64 h_ret = 0;
        unsigned long page = 0;
-       u64 rpage = virt_to_abs(kpage);
+       u64 rpage = __pa(kpage);
        int page_count;
 
        void *sectbase = ehca_calc_sectbase(top, dir, idx);
@@ -1553,7 +1553,7 @@ static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
                for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
                     rnum++) {
                        void *pg = sectbase + ((page++) * pginfo->hwpage_size);
-                       kpage[rnum] = virt_to_abs(pg);
+                       kpage[rnum] = __pa(pg);
                }
 
                h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
@@ -1870,9 +1870,8 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
                for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
                        pgaddr = page_to_pfn(sg_page(&chunk->page_list[i]))
                                << PAGE_SHIFT ;
-                       *kpage = phys_to_abs(pgaddr +
-                                            (pginfo->next_hwpage *
-                                             pginfo->hwpage_size));
+                       *kpage = pgaddr + (pginfo->next_hwpage *
+                                          pginfo->hwpage_size);
                        if ( !(*kpage) ) {
                                ehca_gen_err("pgaddr=%llx "
                                             "chunk->page_list[i]=%llx "
@@ -1927,7 +1926,7 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
                u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
                if (ehca_debug_level >= 3)
                        ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
-                                    *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+                                    *(u64 *)__va(pgaddr));
                if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
                        ehca_gen_err("uncontiguous page found pgaddr=%llx "
                                     "prev_pgaddr=%llx page_list_i=%x",
@@ -1962,7 +1961,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
                        if (nr_kpages == kpages_per_hwpage) {
                                pgaddr = ( page_to_pfn(sg_page(&chunk->page_list[i]))
                                           << PAGE_SHIFT );
-                               *kpage = phys_to_abs(pgaddr);
+                               *kpage = pgaddr;
                                if ( !(*kpage) ) {
                                        ehca_gen_err("pgaddr=%llx i=%x",
                                                     pgaddr, i);
@@ -1990,13 +1989,11 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
                                                 (pginfo->hwpage_size - 1)) >>
                                                PAGE_SHIFT;
                                        nr_kpages -= pginfo->kpage_cnt;
-                                       *kpage = phys_to_abs(
-                                               pgaddr &
-                                               ~(pginfo->hwpage_size - 1));
+                                       *kpage = pgaddr &
+                                                ~(pginfo->hwpage_size - 1);
                                }
                                if (ehca_debug_level >= 3) {
-                                       u64 val = *(u64 *)abs_to_virt(
-                                               phys_to_abs(pgaddr));
+                                       u64 val = *(u64 *)__va(pgaddr);
                                        ehca_gen_dbg("kpage=%llx chunk_page=%llx "
                                                     "value=%016llx",
                                                     *kpage, pgaddr, val);
@@ -2084,9 +2081,8 @@ static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
                                             pginfo->num_hwpages, i);
                                return -EFAULT;
                        }
-                       *kpage = phys_to_abs(
-                               (pbuf->addr & ~(pginfo->hwpage_size - 1)) +
-                               (pginfo->next_hwpage * pginfo->hwpage_size));
+                       *kpage = (pbuf->addr & ~(pginfo->hwpage_size - 1)) +
+                                (pginfo->next_hwpage * pginfo->hwpage_size);
                        if ( !(*kpage) && pbuf->addr ) {
                                ehca_gen_err("pbuf->addr=%llx pbuf->size=%llx "
                                             "next_hwpage=%llx", pbuf->addr,
@@ -2124,8 +2120,8 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
        /* loop over desired page_list entries */
        fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
        for (i = 0; i < number; i++) {
-               *kpage = phys_to_abs((*fmrlist & ~(pginfo->hwpage_size - 1)) +
-                                    pginfo->next_hwpage * pginfo->hwpage_size);
+               *kpage = (*fmrlist & ~(pginfo->hwpage_size - 1)) +
+                          pginfo->next_hwpage * pginfo->hwpage_size;
                if ( !(*kpage) ) {
                        ehca_gen_err("*fmrlist=%llx fmrlist=%p "
                                     "next_listelem=%llx next_hwpage=%llx",
@@ -2152,8 +2148,7 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
                        u64 prev = *kpage;
                        /* check if adrs are contiguous */
                        for (j = 1; j < cnt_per_hwpage; j++) {
-                               u64 p = phys_to_abs(fmrlist[j] &
-                                                   ~(pginfo->hwpage_size - 1));
+                               u64 p = fmrlist[j] & ~(pginfo->hwpage_size - 1);
                                if (prev + pginfo->u.fmr.fmr_pgsize != p) {
                                        ehca_gen_err("uncontiguous fmr pages "
                                                     "found prev=%llx p=%llx "
@@ -2388,8 +2383,8 @@ static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
                memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
        }
 
-       start_section = phys_to_abs(pfn * PAGE_SIZE) / EHCA_SECTSIZE;
-       end_section = phys_to_abs((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
+       start_section = (pfn * PAGE_SIZE) / EHCA_SECTSIZE;
+       end_section = ((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
        for (i = start_section; i < end_section; i++) {
                int ret;
                top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
@@ -2508,7 +2503,7 @@ static u64 ehca_map_vaddr(void *caddr)
        if (!ehca_bmap)
                return EHCA_INVAL_ADDR;
 
-       abs_addr = virt_to_abs(caddr);
+       abs_addr = __pa(caddr);
        top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
        if (!ehca_bmap_valid(ehca_bmap->top[top]))
                return EHCA_INVAL_ADDR;
index 964f85520798b81605cf65ea516ef5465e7dc8ad..149393915ae5aa700891ed8422e36fd57b15a16e 100644 (file)
@@ -321,7 +321,7 @@ static inline int init_qp_queue(struct ehca_shca *shca,
                        ret = -EINVAL;
                        goto init_qp_queue1;
                }
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
 
                h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
                                                 my_qp->ipz_qp_handle,
@@ -1094,7 +1094,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
        ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",
                 qp_num, bad_send_wqe_p);
        /* convert wqe pointer to vadr */
-       bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);
+       bad_send_wqe_v = __va((u64)bad_send_wqe_p);
        if (ehca_debug_level >= 2)
                ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
        squeue = &my_qp->ipz_squeue;
@@ -1138,7 +1138,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
        /* convert real to abs address */
        wqe_p = wqe_p & (~(1UL << 63));
 
-       wqe_v = abs_to_virt(wqe_p);
+       wqe_v = __va(wqe_p);
 
        if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
                ehca_gen_err("Invalid offset for calculating left cqes "
index fd05f48f6b0b649305014e22967e41bf4dcafefb..47f94984353de9afac694d51806696d5c6d3d7c8 100644 (file)
@@ -135,7 +135,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
                                     mad_hdr->attr_mod);
                }
                for (j = 0; j < send_wr->num_sge; j++) {
-                       u8 *data = (u8 *)abs_to_virt(sge->addr);
+                       u8 *data = __va(sge->addr);
                        ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
                                     "lkey=%x",
                                     idx, j, data, sge->length, sge->lkey);
index 54c0d23bad9294c97f55402bb2910ef209d951b8..d280b12aae6499860a7913ab3f8e2406bd65bc12 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/device.h>
 
 #include <linux/atomic.h>
-#include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index e6f9cdd94c7a9e0bc5114024974eb47de59e1e6e..2d41d04fd959421df86e7348ea277e8e3a01f521 100644 (file)
@@ -396,7 +396,7 @@ u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
                      struct hipz_query_port *query_port_response_block)
 {
        u64 ret;
-       u64 r_cb = virt_to_abs(query_port_response_block);
+       u64 r_cb = __pa(query_port_response_block);
 
        if (r_cb & (EHCA_PAGESIZE-1)) {
                ehca_gen_err("response block not page aligned");
@@ -438,7 +438,7 @@ u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
                     struct hipz_query_hca *query_hca_rblock)
 {
-       u64 r_cb = virt_to_abs(query_hca_rblock);
+       u64 r_cb = __pa(query_hca_rblock);
 
        if (r_cb & (EHCA_PAGESIZE-1)) {
                ehca_gen_err("response_block=%p not page aligned",
@@ -577,7 +577,7 @@ u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
                                adapter_handle.handle, /* r4 */
                                qp_handle.handle,      /* r5 */
                                update_mask,           /* r6 */
-                               virt_to_abs(mqpcb),    /* r7 */
+                               __pa(mqpcb),           /* r7 */
                                0, 0, 0, 0, 0);
 
        if (ret == H_NOT_ENOUGH_RESOURCES)
@@ -595,7 +595,7 @@ u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
        return ehca_plpar_hcall_norets(H_QUERY_QP,
                                       adapter_handle.handle, /* r4 */
                                       qp_handle.handle,      /* r5 */
-                                      virt_to_abs(qqpcb),    /* r6 */
+                                      __pa(qqpcb),           /* r6 */
                                       0, 0, 0, 0);
 }
 
@@ -787,7 +787,7 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
                if (count > 1) {
                        u64 *kpage;
                        int i;
-                       kpage = (u64 *)abs_to_virt(logical_address_of_page);
+                       kpage = __va(logical_address_of_page);
                        for (i = 0; i < count; i++)
                                ehca_gen_dbg("kpage[%d]=%p",
                                             i, (void *)kpage[i]);
@@ -944,7 +944,7 @@ u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
                      void *rblock,
                      unsigned long *byte_count)
 {
-       u64 r_cb = virt_to_abs(rblock);
+       u64 r_cb = __pa(rblock);
 
        if (r_cb & (EHCA_PAGESIZE-1)) {
                ehca_gen_err("rblock not page aligned.");
index 1898d6e7cce5374b48d811c7cf00e041c20d0b05..62c71fadb4d97d10a29f0e05452b63f888fb0814 100644 (file)
@@ -81,7 +81,7 @@ int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset)
 {
        int i;
        for (i = 0; i < queue->queue_length / queue->pagesize; i++) {
-               u64 page = (u64)virt_to_abs(queue->queue_pages[i]);
+               u64 page = __pa(queue->queue_pages[i]);
                if (addr >= page && addr < page + queue->pagesize) {
                        *q_offset = addr - page + i * queue->pagesize;
                        return 0;
index e25e4dafb8a8dd26e7dfc37fe8c655753aa5ddac..80079e5a2e30f47da6e781d6d5932cab519571d4 100644 (file)
@@ -225,7 +225,7 @@ id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id)
                ret = idr_get_new_above(&sriov->pv_id_table, ent,
                                        next_id, &id);
                if (!ret) {
-                       next_id = ((unsigned) id + 1) & MAX_ID_MASK;
+                       next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
                        ent->pv_cm_id = (u32)id;
                        sl_id_map_add(ibdev, ent);
                }
index 7140199f562ead43fb9062d0c89a1faa2568dc04..748db2d3e465b9aa0b472bab32e9dbd22ca33ec4 100644 (file)
@@ -79,11 +79,6 @@ int disable_mpa_crc = 0;
 module_param(disable_mpa_crc, int, 0644);
 MODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC");
 
-unsigned int send_first = 0;
-module_param(send_first, int, 0644);
-MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
-
-
 unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
 module_param(nes_drv_opt, int, 0644);
 MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
index 0da62b904d00f3f51407522d6e4ae03eafbbf879..5cac29e6bc1c73b50dc5fdb113cf5d377a64fbb8 100644 (file)
@@ -57,7 +57,7 @@
 #define QUEUE_DISCONNECTS
 
 #define DRV_NAME    "iw_nes"
-#define DRV_VERSION "1.5.0.0"
+#define DRV_VERSION "1.5.0.1"
 #define PFX         DRV_NAME ": "
 
 /*
@@ -172,7 +172,6 @@ extern int interrupt_mod_interval;
 extern int nes_if_count;
 extern int mpa_version;
 extern int disable_mpa_crc;
-extern unsigned int send_first;
 extern unsigned int nes_drv_opt;
 extern unsigned int nes_debug_level;
 extern unsigned int wqm_quanta;
index 1dadcf388c0278b1d2e8597e1baa1c5d833ef106..cd0ecb215cca01c5be942da3bf4c07bcc3895c5f 100644 (file)
@@ -3006,6 +3006,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                                        switch (nesqp->hw_iwarp_state) {
                                                case NES_AEQE_IWARP_STATE_CLOSING:
                                                        next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
+                                                       break;
                                                case NES_AEQE_IWARP_STATE_TERMINATE:
                                                        next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
                                                        break;
@@ -3068,18 +3069,9 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                }
 
                nesqp->ibqp_state = attr->qp_state;
-               if (((nesqp->iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) ==
-                               (u32)NES_CQP_QP_IWARP_STATE_RTS) &&
-                               ((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) >
-                               (u32)NES_CQP_QP_IWARP_STATE_RTS)) {
-                       nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
-                       nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
-                                       nesqp->iwarp_state);
-               } else {
-                       nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
-                       nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
-                                       nesqp->iwarp_state);
-               }
+               nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
+               nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
+                               nesqp->iwarp_state);
        }
 
        if (attr_mask & IB_QP_ACCESS_FLAGS) {
index 196eb52f003519c15cafdf97dd0a08703e33111b..07ca6fd5546b100ae45a86034fae8696d149b2bb 100644 (file)
@@ -535,14 +535,14 @@ void ipoib_drain_cq(struct net_device *dev);
 void ipoib_set_ethtool_ops(struct net_device *dev);
 int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca);
 
-#ifdef CONFIG_INFINIBAND_IPOIB_CM
-
 #define IPOIB_FLAGS_RC         0x80
 #define IPOIB_FLAGS_UC         0x40
 
 /* We don't support UC connections at the moment */
 #define IPOIB_CM_SUPPORTED(ha)   (ha[0] & (IPOIB_FLAGS_RC))
 
+#ifdef CONFIG_INFINIBAND_IPOIB_CM
+
 extern int ipoib_max_conn_qp;
 
 static inline int ipoib_cm_admin_enabled(struct net_device *dev)
index 175581cf478c2188c101dbb14a264b4e35c14c1b..72ae63f0072d45fd931377e4a6f354b271c4b261 100644 (file)
@@ -1448,37 +1448,6 @@ static ssize_t show_mode(struct device *d, struct device_attribute *attr,
                return sprintf(buf, "datagram\n");
 }
 
-int ipoib_set_mode(struct net_device *dev, const char *buf)
-{
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
-
-       /* flush paths if we switch modes so that connections are restarted */
-       if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
-               set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
-               ipoib_warn(priv, "enabling connected mode "
-                          "will cause multicast packet drops\n");
-               netdev_update_features(dev);
-               rtnl_unlock();
-               priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
-
-               ipoib_flush_paths(dev);
-               rtnl_lock();
-               return 0;
-       }
-
-       if (!strcmp(buf, "datagram\n")) {
-               clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
-               netdev_update_features(dev);
-               dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
-               rtnl_unlock();
-               ipoib_flush_paths(dev);
-               rtnl_lock();
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
 static ssize_t set_mode(struct device *d, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
index d576c7aad89d491bf53f0a79e8b133f23531f0eb..6fdc9e78da0d454030496a3f5c048b993672aed6 100644 (file)
@@ -215,6 +215,37 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+int ipoib_set_mode(struct net_device *dev, const char *buf)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       /* flush paths if we switch modes so that connections are restarted */
+       if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) {
+               set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+               ipoib_warn(priv, "enabling connected mode "
+                          "will cause multicast packet drops\n");
+               netdev_update_features(dev);
+               rtnl_unlock();
+               priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
+
+               ipoib_flush_paths(dev);
+               rtnl_lock();
+               return 0;
+       }
+
+       if (!strcmp(buf, "datagram\n")) {
+               clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
+               netdev_update_features(dev);
+               dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
+               rtnl_unlock();
+               ipoib_flush_paths(dev);
+               rtnl_lock();
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static struct ipoib_path *__path_find(struct net_device *dev, void *gid)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
index 296be431a0e93b773b5618efd0b07d018d187b3b..ef7d3be46c316b20361fa1e406c1cae38177e366 100644 (file)
@@ -177,6 +177,7 @@ struct iser_data_buf {
 
 /* fwd declarations */
 struct iser_device;
+struct iser_cq_desc;
 struct iscsi_iser_conn;
 struct iscsi_iser_task;
 struct iscsi_endpoint;
@@ -226,16 +227,21 @@ struct iser_rx_desc {
        char                         pad[ISER_RX_PAD_SIZE];
 } __attribute__((packed));
 
+#define ISER_MAX_CQ 4
+
 struct iser_device {
        struct ib_device             *ib_device;
        struct ib_pd                 *pd;
-       struct ib_cq                 *rx_cq;
-       struct ib_cq                 *tx_cq;
+       struct ib_cq                 *rx_cq[ISER_MAX_CQ];
+       struct ib_cq                 *tx_cq[ISER_MAX_CQ];
        struct ib_mr                 *mr;
-       struct tasklet_struct        cq_tasklet;
+       struct tasklet_struct        cq_tasklet[ISER_MAX_CQ];
        struct ib_event_handler      event_handler;
        struct list_head             ig_list; /* entry in ig devices list */
        int                          refcount;
+       int                          cq_active_qps[ISER_MAX_CQ];
+       int                          cqs_used;
+       struct iser_cq_desc          *cq_desc;
 };
 
 struct iser_conn {
@@ -287,6 +293,11 @@ struct iser_page_vec {
        int data_size;
 };
 
+struct iser_cq_desc {
+       struct iser_device           *device;
+       int                          cq_index;
+};
+
 struct iser_global {
        struct mutex      device_list_mutex;/*                   */
        struct list_head  device_list;       /* all iSER devices */
index 2dddabd8fcf9882fe93f59f9dcbf5faaf862f016..95a49affee44cbaa8223da2943722eac43d09300 100644 (file)
@@ -70,32 +70,50 @@ static void iser_event_handler(struct ib_event_handler *handler,
  */
 static int iser_create_device_ib_res(struct iser_device *device)
 {
+       int i, j;
+       struct iser_cq_desc *cq_desc;
+
+       device->cqs_used = min(ISER_MAX_CQ, device->ib_device->num_comp_vectors);
+       iser_err("using %d CQs, device %s supports %d vectors\n", device->cqs_used,
+                device->ib_device->name, device->ib_device->num_comp_vectors);
+
+       device->cq_desc = kmalloc(sizeof(struct iser_cq_desc) * device->cqs_used,
+                                 GFP_KERNEL);
+       if (device->cq_desc == NULL)
+               goto cq_desc_err;
+       cq_desc = device->cq_desc;
+
        device->pd = ib_alloc_pd(device->ib_device);
        if (IS_ERR(device->pd))
                goto pd_err;
 
-       device->rx_cq = ib_create_cq(device->ib_device,
-                                 iser_cq_callback,
-                                 iser_cq_event_callback,
-                                 (void *)device,
-                                 ISER_MAX_RX_CQ_LEN, 0);
-       if (IS_ERR(device->rx_cq))
-               goto rx_cq_err;
+       for (i = 0; i < device->cqs_used; i++) {
+               cq_desc[i].device   = device;
+               cq_desc[i].cq_index = i;
+
+               device->rx_cq[i] = ib_create_cq(device->ib_device,
+                                         iser_cq_callback,
+                                         iser_cq_event_callback,
+                                         (void *)&cq_desc[i],
+                                         ISER_MAX_RX_CQ_LEN, i);
+               if (IS_ERR(device->rx_cq[i]))
+                       goto cq_err;
 
-       device->tx_cq = ib_create_cq(device->ib_device,
-                                 NULL, iser_cq_event_callback,
-                                 (void *)device,
-                                 ISER_MAX_TX_CQ_LEN, 0);
+               device->tx_cq[i] = ib_create_cq(device->ib_device,
+                                         NULL, iser_cq_event_callback,
+                                         (void *)&cq_desc[i],
+                                         ISER_MAX_TX_CQ_LEN, i);
 
-       if (IS_ERR(device->tx_cq))
-               goto tx_cq_err;
+               if (IS_ERR(device->tx_cq[i]))
+                       goto cq_err;
 
-       if (ib_req_notify_cq(device->rx_cq, IB_CQ_NEXT_COMP))
-               goto cq_arm_err;
+               if (ib_req_notify_cq(device->rx_cq[i], IB_CQ_NEXT_COMP))
+                       goto cq_err;
 
-       tasklet_init(&device->cq_tasklet,
-                    iser_cq_tasklet_fn,
-                    (unsigned long)device);
+               tasklet_init(&device->cq_tasklet[i],
+                            iser_cq_tasklet_fn,
+                       (unsigned long)&cq_desc[i]);
+       }
 
        device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE |
                                   IB_ACCESS_REMOTE_WRITE |
@@ -113,14 +131,19 @@ static int iser_create_device_ib_res(struct iser_device *device)
 handler_err:
        ib_dereg_mr(device->mr);
 dma_mr_err:
-       tasklet_kill(&device->cq_tasklet);
-cq_arm_err:
-       ib_destroy_cq(device->tx_cq);
-tx_cq_err:
-       ib_destroy_cq(device->rx_cq);
-rx_cq_err:
+       for (j = 0; j < device->cqs_used; j++)
+               tasklet_kill(&device->cq_tasklet[j]);
+cq_err:
+       for (j = 0; j < i; j++) {
+               if (device->tx_cq[j])
+                       ib_destroy_cq(device->tx_cq[j]);
+               if (device->rx_cq[j])
+                       ib_destroy_cq(device->rx_cq[j]);
+       }
        ib_dealloc_pd(device->pd);
 pd_err:
+       kfree(device->cq_desc);
+cq_desc_err:
        iser_err("failed to allocate an IB resource\n");
        return -1;
 }
@@ -131,18 +154,24 @@ pd_err:
  */
 static void iser_free_device_ib_res(struct iser_device *device)
 {
+       int i;
        BUG_ON(device->mr == NULL);
 
-       tasklet_kill(&device->cq_tasklet);
+       for (i = 0; i < device->cqs_used; i++) {
+               tasklet_kill(&device->cq_tasklet[i]);
+               (void)ib_destroy_cq(device->tx_cq[i]);
+               (void)ib_destroy_cq(device->rx_cq[i]);
+               device->tx_cq[i] = NULL;
+               device->rx_cq[i] = NULL;
+       }
+
        (void)ib_unregister_event_handler(&device->event_handler);
        (void)ib_dereg_mr(device->mr);
-       (void)ib_destroy_cq(device->tx_cq);
-       (void)ib_destroy_cq(device->rx_cq);
        (void)ib_dealloc_pd(device->pd);
 
+       kfree(device->cq_desc);
+
        device->mr = NULL;
-       device->tx_cq = NULL;
-       device->rx_cq = NULL;
        device->pd = NULL;
 }
 
@@ -157,6 +186,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
        struct ib_qp_init_attr  init_attr;
        int                     req_err, resp_err, ret = -ENOMEM;
        struct ib_fmr_pool_param params;
+       int index, min_index = 0;
 
        BUG_ON(ib_conn->device == NULL);
 
@@ -220,10 +250,20 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
 
        memset(&init_attr, 0, sizeof init_attr);
 
+       mutex_lock(&ig.connlist_mutex);
+       /* select the CQ with the minimal number of usages */
+       for (index = 0; index < device->cqs_used; index++)
+               if (device->cq_active_qps[index] <
+                   device->cq_active_qps[min_index])
+                       min_index = index;
+       device->cq_active_qps[min_index]++;
+       mutex_unlock(&ig.connlist_mutex);
+       iser_err("cq index %d used for ib_conn %p\n", min_index, ib_conn);
+
        init_attr.event_handler = iser_qp_event_callback;
        init_attr.qp_context    = (void *)ib_conn;
-       init_attr.send_cq       = device->tx_cq;
-       init_attr.recv_cq       = device->rx_cq;
+       init_attr.send_cq       = device->tx_cq[min_index];
+       init_attr.recv_cq       = device->rx_cq[min_index];
        init_attr.cap.max_send_wr  = ISER_QP_MAX_REQ_DTOS;
        init_attr.cap.max_recv_wr  = ISER_QP_MAX_RECV_DTOS;
        init_attr.cap.max_send_sge = 2;
@@ -252,6 +292,7 @@ out_err:
  */
 static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
 {
+       int cq_index;
        BUG_ON(ib_conn == NULL);
 
        iser_err("freeing conn %p cma_id %p fmr pool %p qp %p\n",
@@ -262,9 +303,12 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
        if (ib_conn->fmr_pool != NULL)
                ib_destroy_fmr_pool(ib_conn->fmr_pool);
 
-       if (ib_conn->qp != NULL)
-               rdma_destroy_qp(ib_conn->cma_id);
+       if (ib_conn->qp != NULL) {
+               cq_index = ((struct iser_cq_desc *)ib_conn->qp->recv_cq->cq_context)->cq_index;
+               ib_conn->device->cq_active_qps[cq_index]--;
 
+               rdma_destroy_qp(ib_conn->cma_id);
+       }
        /* if cma handler context, the caller acts s.t the cma destroy the id */
        if (ib_conn->cma_id != NULL && can_destroy_id)
                rdma_destroy_id(ib_conn->cma_id);
@@ -791,9 +835,9 @@ static void iser_handle_comp_error(struct iser_tx_desc *desc,
        }
 }
 
-static int iser_drain_tx_cq(struct iser_device  *device)
+static int iser_drain_tx_cq(struct iser_device  *device, int cq_index)
 {
-       struct ib_cq  *cq = device->tx_cq;
+       struct ib_cq  *cq = device->tx_cq[cq_index];
        struct ib_wc  wc;
        struct iser_tx_desc *tx_desc;
        struct iser_conn *ib_conn;
@@ -822,8 +866,10 @@ static int iser_drain_tx_cq(struct iser_device  *device)
 
 static void iser_cq_tasklet_fn(unsigned long data)
 {
-        struct iser_device  *device = (struct iser_device *)data;
-        struct ib_cq        *cq = device->rx_cq;
+       struct iser_cq_desc *cq_desc = (struct iser_cq_desc *)data;
+       struct iser_device  *device = cq_desc->device;
+       int cq_index = cq_desc->cq_index;
+       struct ib_cq         *cq = device->rx_cq[cq_index];
         struct ib_wc        wc;
         struct iser_rx_desc *desc;
         unsigned long       xfer_len;
@@ -851,19 +897,21 @@ static void iser_cq_tasklet_fn(unsigned long data)
                }
                completed_rx++;
                if (!(completed_rx & 63))
-                       completed_tx += iser_drain_tx_cq(device);
+                       completed_tx += iser_drain_tx_cq(device, cq_index);
        }
        /* #warning "it is assumed here that arming CQ only once its empty" *
         * " would not cause interrupts to be missed"                       */
        ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
 
-       completed_tx += iser_drain_tx_cq(device);
+       completed_tx += iser_drain_tx_cq(device, cq_index);
        iser_dbg("got %d rx %d tx completions\n", completed_rx, completed_tx);
 }
 
 static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
 {
-       struct iser_device  *device = (struct iser_device *)cq_context;
+       struct iser_cq_desc *cq_desc = (struct iser_cq_desc *)cq_context;
+       struct iser_device  *device = cq_desc->device;
+       int cq_index = cq_desc->cq_index;
 
-       tasklet_schedule(&device->cq_tasklet);
+       tasklet_schedule(&device->cq_tasklet[cq_index]);
 }
index fc0ed9b43424c705796f16bf43939b5f340e7bf4..2194a3c7236addb20583026c3eb9c4075e6a57ea 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/twl4030-audio.h>
@@ -194,13 +195,26 @@ static int twl4030_vibra_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
                         twl4030_vibra_suspend, twl4030_vibra_resume);
 
+static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
+                             struct device_node *node)
+{
+       if (pdata && pdata->coexist)
+               return true;
+
+       if (of_find_node_by_name(node, "codec"))
+               return true;
+
+       return false;
+}
+
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
        struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+       struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
        struct vibra_info *info;
        int ret;
 
-       if (!pdata) {
+       if (!pdata && !twl4030_core_node) {
                dev_dbg(&pdev->dev, "platform_data not available\n");
                return -EINVAL;
        }
@@ -210,7 +224,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        info->dev = &pdev->dev;
-       info->coexist = pdata->coexist;
+       info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
        INIT_WORK(&info->play_work, vibra_play_work);
 
        info->input_dev = input_allocate_device();
index 05f30b73c3c385efc2906185877ecee28e30bc9f..326218dbd6e64e72e28cecfd7ad5c878a1def9aa 100644 (file)
@@ -10,6 +10,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
@@ -113,14 +114,69 @@ static void pm860x_touch_close(struct input_dev *dev)
        pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
 }
 
+#ifdef CONFIG_OF
+static int __devinit pm860x_touch_dt_init(struct platform_device *pdev,
+                                         struct pm860x_chip *chip,
+                                         int *res_x)
+{
+       struct device_node *np = pdev->dev.parent->of_node;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+                                : chip->companion;
+       int data, n, ret;
+       if (!np)
+               return -ENODEV;
+       np = of_find_node_by_name(np, "touch");
+       if (!np) {
+               dev_err(&pdev->dev, "Can't find touch node\n");
+               return -EINVAL;
+       }
+       /* set GPADC MISC1 register */
+       data = 0;
+       if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n))
+               data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK;
+       if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n))
+               data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
+       if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n))
+               data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK;
+       if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n))
+               data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK;
+       if (data) {
+               ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+               if (ret < 0)
+                       return -EINVAL;
+       }
+       /* set tsi prebias time */
+       if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
+               ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+               if (ret < 0)
+                       return -EINVAL;
+       }
+       /* set prebias & prechg time of pen detect */
+       data = 0;
+       if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n))
+               data |= n & PM8607_PD_PREBIAS_MASK;
+       if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n))
+               data |= n & PM8607_PD_PRECHG_MASK;
+       if (data) {
+               ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+               if (ret < 0)
+                       return -EINVAL;
+       }
+       of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
+       return 0;
+}
+#else
+#define pm860x_touch_dt_init(x, y, z)  (-1)
+#endif
+
 static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm860x_platform_data *pm860x_pdata =             \
-                               pdev->dev.parent->platform_data;
-       struct pm860x_touch_pdata *pdata = NULL;
+       struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
        struct pm860x_touch *touch;
-       int irq, ret;
+       struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+                                : chip->companion;
+       int irq, ret, res_x = 0, data = 0;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -128,16 +184,55 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       if (!pm860x_pdata) {
-               dev_err(&pdev->dev, "platform data is missing\n");
-               return -EINVAL;
-       }
-
-       pdata = pm860x_pdata->touch;
-       if (!pdata) {
-               dev_err(&pdev->dev, "touchscreen data is missing\n");
-               return -EINVAL;
+       if (pm860x_touch_dt_init(pdev, chip, &res_x)) {
+               if (pdata) {
+                       /* set GPADC MISC1 register */
+                       data = 0;
+                       data |= (pdata->gpadc_prebias << 1)
+                               & PM8607_GPADC_PREBIAS_MASK;
+                       data |= (pdata->slot_cycle << 3)
+                               & PM8607_GPADC_SLOT_CYCLE_MASK;
+                       data |= (pdata->off_scale << 5)
+                               & PM8607_GPADC_OFF_SCALE_MASK;
+                       data |= (pdata->sw_cal << 7)
+                               & PM8607_GPADC_SW_CAL_MASK;
+                       if (data) {
+                               ret = pm860x_reg_write(i2c,
+                                       PM8607_GPADC_MISC1, data);
+                               if (ret < 0)
+                                       return -EINVAL;
+                       }
+                       /* set tsi prebias time */
+                       if (pdata->tsi_prebias) {
+                               data = pdata->tsi_prebias;
+                               ret = pm860x_reg_write(i2c,
+                                       PM8607_TSI_PREBIAS, data);
+                               if (ret < 0)
+                                       return -EINVAL;
+                       }
+                       /* set prebias & prechg time of pen detect */
+                       data = 0;
+                       data |= pdata->pen_prebias
+                               & PM8607_PD_PREBIAS_MASK;
+                       data |= (pdata->pen_prechg << 5)
+                               & PM8607_PD_PRECHG_MASK;
+                       if (data) {
+                               ret = pm860x_reg_write(i2c,
+                                       PM8607_PD_PREBIAS, data);
+                               if (ret < 0)
+                                       return -EINVAL;
+                       }
+                       res_x = pdata->res_x;
+               } else {
+                       dev_err(&pdev->dev, "failed to get platform data\n");
+                       return -EINVAL;
+               }
        }
+       /* enable GPADC */
+       ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN,
+                             PM8607_GPADC_EN);
+       if (ret)
+               return ret;
 
        touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
        if (touch == NULL)
@@ -158,9 +253,9 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
        touch->idev->open = pm860x_touch_open;
        touch->idev->close = pm860x_touch_close;
        touch->chip = chip;
-       touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
-       touch->irq = irq + chip->irq_base;
-       touch->res_x = pdata->res_x;
+       touch->i2c = i2c;
+       touch->irq = irq;
+       touch->res_x = res_x;
        input_set_drvdata(touch->idev, touch);
 
        ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
index 61897cfeeda6ed76bbd012a385a7a7c5a0656f4a..b7e8cc0957fcb65328fe300fffccfe3fc937a96b 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/module.h>
 
-#define LED_PWM_SHIFT          (3)
 #define LED_PWM_MASK           (0x1F)
 #define LED_CURRENT_MASK       (0x07 << 5)
 
-#define LED_BLINK_ON_MASK      (0x07)
 #define LED_BLINK_MASK         (0x7F)
 
-#define LED_BLINK_ON(x)                ((x & 0x7) * 66 + 66)
-#define LED_BLINK_ON_MIN       LED_BLINK_ON(0)
-#define LED_BLINK_ON_MAX       LED_BLINK_ON(0x7)
 #define LED_ON_CONTINUOUS      (0x0F << 3)
-#define LED_TO_ON(x)           ((x - 66) / 66)
 
 #define LED1_BLINK_EN          (1 << 1)
 #define LED2_BLINK_EN          (1 << 2)
@@ -49,85 +44,25 @@ struct pm860x_led {
        unsigned char brightness;
        unsigned char current_brightness;
 
-       int blink_data;
-       int blink_time;
-       int blink_on;
-       int blink_off;
+       int reg_control;
+       int reg_blink;
+       int blink_mask;
 };
 
-/* return offset of color register */
-static inline int __led_off(int port)
-{
-       int ret = -EINVAL;
-
-       switch (port) {
-       case PM8606_LED1_RED:
-       case PM8606_LED1_GREEN:
-       case PM8606_LED1_BLUE:
-               ret = port - PM8606_LED1_RED + PM8606_RGB1B;
-               break;
-       case PM8606_LED2_RED:
-       case PM8606_LED2_GREEN:
-       case PM8606_LED2_BLUE:
-               ret = port - PM8606_LED2_RED + PM8606_RGB2B;
-               break;
-       }
-       return ret;
-}
-
-/* return offset of blink register */
-static inline int __blink_off(int port)
-{
-       int ret = -EINVAL;
-
-       switch (port) {
-       case PM8606_LED1_RED:
-       case PM8606_LED1_GREEN:
-       case PM8606_LED1_BLUE:
-               ret = PM8606_RGB1A;
-               break;
-       case PM8606_LED2_RED:
-       case PM8606_LED2_GREEN:
-       case PM8606_LED2_BLUE:
-               ret = PM8606_RGB2A;
-               break;
-       }
-       return ret;
-}
-
-static inline int __blink_ctl_mask(int port)
-{
-       int ret = -EINVAL;
-
-       switch (port) {
-       case PM8606_LED1_RED:
-       case PM8606_LED1_GREEN:
-       case PM8606_LED1_BLUE:
-               ret = LED1_BLINK_EN;
-               break;
-       case PM8606_LED2_RED:
-       case PM8606_LED2_GREEN:
-       case PM8606_LED2_BLUE:
-               ret = LED2_BLINK_EN;
-               break;
-       }
-       return ret;
-}
-
 static int led_power_set(struct pm860x_chip *chip, int port, int on)
 {
        int ret = -EINVAL;
 
        switch (port) {
-       case PM8606_LED1_RED:
-       case PM8606_LED1_GREEN:
-       case PM8606_LED1_BLUE:
+       case 0:
+       case 1:
+       case 2:
                ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
                        pm8606_osc_disable(chip, RGB1_ENABLE);
                break;
-       case PM8606_LED2_RED:
-       case PM8606_LED2_GREEN:
-       case PM8606_LED2_BLUE:
+       case 3:
+       case 4:
+       case 5:
                ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
                        pm8606_osc_disable(chip, RGB2_ENABLE);
                break;
@@ -141,7 +76,7 @@ static void pm860x_led_work(struct work_struct *work)
        struct pm860x_led *led;
        struct pm860x_chip *chip;
        unsigned char buf[3];
-       int mask, ret;
+       int ret;
 
        led = container_of(work, struct pm860x_led, work);
        chip = led->chip;
@@ -149,34 +84,34 @@ static void pm860x_led_work(struct work_struct *work)
        if ((led->current_brightness == 0) && led->brightness) {
                led_power_set(chip, led->port, 1);
                if (led->iset) {
-                       pm860x_set_bits(led->i2c, __led_off(led->port),
+                       pm860x_set_bits(led->i2c, led->reg_control,
                                        LED_CURRENT_MASK, led->iset);
                }
-               pm860x_set_bits(led->i2c, __blink_off(led->port),
+               pm860x_set_bits(led->i2c, led->reg_blink,
                                LED_BLINK_MASK, LED_ON_CONTINUOUS);
-               mask = __blink_ctl_mask(led->port);
-               pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
+               pm860x_set_bits(led->i2c, PM8606_WLED3B, led->blink_mask,
+                               led->blink_mask);
        }
-       pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
+       pm860x_set_bits(led->i2c, led->reg_control, LED_PWM_MASK,
                        led->brightness);
 
        if (led->brightness == 0) {
-               pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
+               pm860x_bulk_read(led->i2c, led->reg_control, 3, buf);
                ret = buf[0] & LED_PWM_MASK;
                ret |= buf[1] & LED_PWM_MASK;
                ret |= buf[2] & LED_PWM_MASK;
                if (ret == 0) {
                        /* unset current since no led is lighting */
-                       pm860x_set_bits(led->i2c, __led_off(led->port),
+                       pm860x_set_bits(led->i2c, led->reg_control,
                                        LED_CURRENT_MASK, 0);
-                       mask = __blink_ctl_mask(led->port);
-                       pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+                       pm860x_set_bits(led->i2c, PM8606_WLED3B,
+                                       led->blink_mask, 0);
                        led_power_set(chip, led->port, 0);
                }
        }
        led->current_brightness = led->brightness;
        dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
-               __led_off(led->port), led->brightness);
+               led->reg_control, led->brightness);
        mutex_unlock(&led->lock);
 }
 
@@ -189,39 +124,92 @@ static void pm860x_led_set(struct led_classdev *cdev,
        schedule_work(&data->work);
 }
 
+#ifdef CONFIG_OF
+static int pm860x_led_dt_init(struct platform_device *pdev,
+                             struct pm860x_led *data)
+{
+       struct device_node *nproot = pdev->dev.parent->of_node, *np;
+       int iset = 0;
+       if (!nproot)
+               return -ENODEV;
+       nproot = of_find_node_by_name(nproot, "leds");
+       if (!nproot) {
+               dev_err(&pdev->dev, "failed to find leds node\n");
+               return -ENODEV;
+       }
+       for_each_child_of_node(nproot, np) {
+               if (!of_node_cmp(np->name, data->name)) {
+                       of_property_read_u32(np, "marvell,88pm860x-iset",
+                                            &iset);
+                       data->iset = PM8606_LED_CURRENT(iset);
+                       break;
+               }
+       }
+       return 0;
+}
+#else
+#define pm860x_led_dt_init(x, y)       (-1)
+#endif
+
 static int pm860x_led_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm860x_led_pdata *pdata;
+       struct pm860x_led_pdata *pdata = pdev->dev.platform_data;
        struct pm860x_led *data;
        struct resource *res;
-       int ret;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource!\n");
-               return -EINVAL;
-       }
-
-       pdata = pdev->dev.platform_data;
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "No platform data!\n");
-               return -EINVAL;
-       }
+       int ret = 0;
 
        data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL);
        if (data == NULL)
                return -ENOMEM;
-       strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
+       res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control");
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for control\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_control = res->start;
+       res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink");
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for blink\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_blink = res->start;
+       memset(data->name, 0, MFD_NAME_SIZE);
+       switch (pdev->id) {
+       case 0:
+               data->blink_mask = LED1_BLINK_EN;
+               sprintf(data->name, "led0-red");
+               break;
+       case 1:
+               data->blink_mask = LED1_BLINK_EN;
+               sprintf(data->name, "led0-green");
+               break;
+       case 2:
+               data->blink_mask = LED1_BLINK_EN;
+               sprintf(data->name, "led0-blue");
+               break;
+       case 3:
+               data->blink_mask = LED2_BLINK_EN;
+               sprintf(data->name, "led1-red");
+               break;
+       case 4:
+               data->blink_mask = LED2_BLINK_EN;
+               sprintf(data->name, "led1-green");
+               break;
+       case 5:
+               data->blink_mask = LED2_BLINK_EN;
+               sprintf(data->name, "led1-blue");
+               break;
+       }
        dev_set_drvdata(&pdev->dev, data);
        data->chip = chip;
        data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
-       data->iset = pdata->iset;
-       data->port = pdata->flags;
-       if (data->port < 0) {
-               dev_err(&pdev->dev, "check device failed\n");
-               return -EINVAL;
-       }
+       data->port = pdev->id;
+       if (pm860x_led_dt_init(pdev, data))
+               if (pdata)
+                       data->iset = pdata->iset;
 
        data->current_brightness = 0;
        data->cdev.name = data->name;
@@ -236,6 +224,9 @@ static int pm860x_led_probe(struct platform_device *pdev)
        }
        pm860x_led_set(&data->cdev, 0);
        return 0;
+out:
+       devm_kfree(&pdev->dev, data);
+       return ret;
 }
 
 static int pm860x_led_remove(struct platform_device *pdev)
index 9e8388efd88e2cffeb4c11fc8c432d2a5a7eb371..fc92ccbd71dc22472c9c6fcea4fb54e5079fa19e 100644 (file)
@@ -263,6 +263,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
        struct virtqueue *vq;
        int err;
 
+       if (!name)
+               return NULL;
+
        /* We must have this many virtqueues. */
        if (index >= ldev->desc->num_vq)
                return ERR_PTR(-ENOENT);
@@ -296,7 +299,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
         * to 'true': the host just a(nother) SMP CPU, so we only need inter-cpu
         * barriers.
         */
-       vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, vdev,
+       vq = vring_new_virtqueue(index, lvq->config.num, LGUEST_VRING_ALIGN, vdev,
                                 true, lvq->pages, lg_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
index 20e5c2cda430e9f0a8ffbab8fbd1fc7e2f8dbf8b..ef87310b7662415b4fca8f18c212d85090790ee1 100644 (file)
@@ -748,7 +748,7 @@ static void __devexit macio_pci_remove(struct pci_dev* pdev)
  * MacIO is matched against any Apple ID, it's probe() function
  * will then decide wether it applies or not
  */
-static const struct pci_device_id __devinitdata pci_ids [] = { {
+static const struct pci_device_id __devinitconst pci_ids[] = { {
        .vendor         = PCI_VENDOR_ID_APPLE,
        .device         = PCI_ANY_ID,
        .subvendor      = PCI_ANY_ID,
index 54ac7ffacb40c9dc6352af3045c836f0162e7b73..7d5a6b40b31cf973a99e7f7232ab52bcd0bddf90 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/pmac_feature.h>
 #include <asm/smu.h>
 #include <asm/sections.h>
-#include <asm/abs_addr.h>
 #include <asm/uaccess.h>
 
 #define VERSION "0.7"
@@ -502,7 +501,7 @@ int __init smu_init (void)
         * 32 bits value safely
         */
        smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
-       smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
+       smu->cmd_buf = __va(smu_cmdbuf_abs);
 
        smu->db_node = of_find_node_by_name(NULL, "smu-doorbell");
        if (smu->db_node == NULL) {
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 87%
rename from drivers/media/dvb/frontends/af9033.c
rename to drivers/media/dvb-frontends/af9033.c
index a38998286260043f9fdc9fa294c3bab8ccdd7306..8162d939c4b2d460a2d12111b256e6600dc19f6f 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;
 }
@@ -407,8 +412,8 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
        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;
        }
@@ -467,7 +473,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
                else
                        if_frequency *= -1;
 
-               freq_cw = af9033_div(if_frequency, adc_freq, 23ul);
+               freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul);
 
                if (spec_inv == -1)
                        freq_cw *= -1;
@@ -522,7 +528,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 +540,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 +655,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 +701,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 +755,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 +777,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 +821,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 +859,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 +868,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 +882,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 +894,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 +909,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 98%
rename from drivers/media/video/m5mols/m5mols.h
rename to drivers/media/i2c/m5mols/m5mols.h
index bb589917b65b26b743744ed1c78234060238fb2d..86c815be348cbe9214de2f87d1915b01a2452555 100644 (file)
@@ -155,8 +155,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 +172,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 +183,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 +215,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 +231,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 +327,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 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 95%
rename from drivers/media/video/m5mols/m5mols_core.c
rename to drivers/media/i2c/m5mols/m5mols_core.c
index ac7d28b6ddf25e44347cf1a931755c27e2bdd5ac..2f490ef26c388e2b868369dd189299430288efa3 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,7 +595,8 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                info->res_type = type;
        }
 
-       return 0;
+       mutex_unlock(&info->lock);
+       return ret;
 }
 
 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
@@ -661,20 +668,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 +785,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 +811,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 +845,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 +935,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 +949,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 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 98%
rename from drivers/media/video/mt9p031.c
rename to drivers/media/i2c/mt9p031.c
index 3be537ef22d2f4138067ca9d09d48ffe65fb7cda..2c0f4077c4916215da4cff1580b79fbce27c4fe6 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;
 
similarity index 88%
rename from drivers/media/video/mt9v032.c
rename to drivers/media/i2c/mt9v032.c
index 4ba4884c016eccfec828ecbc67134f6949c5e634..e2177405dad2eb65de2bbc635727dca3f86099d1 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,20 @@ 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;
 };
 
 static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
@@ -187,13 +198,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 +342,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 +387,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 +429,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 +486,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;
@@ -469,6 +507,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
        struct mt9v032 *mt9v032 =
                        container_of(ctrl->handler, struct mt9v032, ctrls);
        struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+       u32 freq;
        u16 data;
 
        switch (ctrl->id) {
@@ -487,6 +526,24 @@ 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) {
                case 0:
@@ -598,6 +655,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 +722,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 +739,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, ARRAY_SIZE(mt9v032_ctrls) + 8);
 
        v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
                          V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -695,6 +755,34 @@ 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->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);
@@ -717,6 +805,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 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 99%
rename from drivers/media/video/tvp514x.c
rename to drivers/media/i2c/tvp514x.c
index cd615c1d6011feaa31405336e13ce07dc0348a2f..1f3943bb87d531bdc16337feb7f6a36c2e232fbb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/tvp514x.c
+ * drivers/media/i2c/tvp514x.c
  *
  * TI TVP5146/47 decoder driver
  *
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 2ce7179a386464ff8932e498a1766919e845ca9a..b68918c97f66868baaa1ece4da01ad286f391747 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 75c890907920b487bd38e424332344942d92d707..039133d692e34e0f839c1496ce13cb6b869b67d8 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 bcbf7faf1bab34bcf2974d40e7204e921b223929..2c925f77cf2aa4baeb8288efba0b660448747cb8 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 0a497be97af88f52a1a12c7e243cab1cead961b7..96a13ed197d0856389a1bd9f7cbde4ca895dfbd8 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 98%
rename from drivers/media/video/davinci/vpbe_display.c
rename to drivers/media/platform/davinci/vpbe_display.c
index 6fe7034bea7c427e9da4503ea42b4b83991bb1ec..239f37bfa313b40903d8ac4d54192747165cd87d 100644 (file)
@@ -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;
@@ -1376,10 +1376,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 +1397,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 +1436,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 +1479,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 +1514,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);
@@ -1620,11 +1632,8 @@ 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) {
similarity index 99%
rename from drivers/media/video/davinci/vpfe_capture.c
rename to drivers/media/platform/davinci/vpfe_capture.c
index 49a845fb804a006fb0951a4426d543f31ac986d0..48052cbffc2ba36d123faba417116a980706f894 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,7 +1666,7 @@ 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);
        int ret = 0;
@@ -1748,8 +1748,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 +1830,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 95%
rename from drivers/media/video/davinci/vpif_capture.c
rename to drivers/media/platform/davinci/vpif_capture.c
index 266025e5d81d424b90ceedd4a1de6fe9c1d016e8..0bafecac4923bce09cef1850ebb3660a62401609 100644 (file)
@@ -339,6 +339,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 +351,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 +551,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 +821,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 +842,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;
 }
 
 /**
@@ -895,6 +905,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 +926,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 +947,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 +977,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;
@@ -1368,8 +1385,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)) {
@@ -1703,108 +1719,37 @@ 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;
 
        return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                       video, enum_dv_presets, preset);
+                               video, enum_dv_timings, timings);
 }
 
 /**
- * vpif_query_dv_presets() - QUERY_DV_PRESET handler
+ * vpif_query_dv_timings() - QUERY_DV_TIMINGS handler
  * @file: file ptr
  * @priv: file handle
- * @preset: input preset
+ * @timings: input timings
  */
-static int vpif_query_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;
 
        return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                      video, query_dv_preset, 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];
-       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);
-
-       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;
+                               video, query_dv_timings, timings);
 }
 
 /**
@@ -1821,7 +1766,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) {
@@ -1857,7 +1802,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 +1845,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 +1862,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;
 }
@@ -2024,10 +1966,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,
@@ -2208,10 +2148,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                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);
similarity index 98%
rename from drivers/media/video/davinci/vpif_capture.h
rename to drivers/media/platform/davinci/vpif_capture.h
index 3511510f43ee32098732e0f480f1067579404a69..d24efc17e4c876537933aeff8e7a95f6aded1e28 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,8 +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;
+       struct v4l2_dv_timings dv_timings;
        /* This is to track the last input that is passed to application */
        u32 input_idx;
 };
similarity index 94%
rename from drivers/media/video/davinci/vpif_display.c
rename to drivers/media/platform/davinci/vpif_display.c
index e129c98921ad493b0b8ea90562d2878325218fc5..a5b88689abad1d9055c45f6624190d68734dbf30 100644 (file)
@@ -302,6 +302,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_CHANNEL2_VIDEO == ch->channel_id) {
                channel2_intr_assert();
                channel2_intr_enable(1);
@@ -318,7 +319,6 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                if (vpif_config_data->ch3_clip_en)
                        channel3_clipping_enable(1);
        }
-       channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
 
        return 0;
 }
@@ -499,12 +499,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 +517,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 +689,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 +708,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 +726,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 +737,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 +758,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 +773,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 +808,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;
@@ -1039,9 +1049,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;
@@ -1271,87 +1279,23 @@ 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);
+                       video, enum_dv_timings, timings);
 }
 
-/**
- * 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);
-
-       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 +1310,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) {
@@ -1402,7 +1346,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 +1390,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 +1407,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;
 }
@@ -1572,9 +1512,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,
@@ -1729,6 +1667,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);
@@ -1789,10 +1728,6 @@ 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;
 
                /* register video device */
similarity index 98%
rename from drivers/media/video/davinci/vpif_display.h
rename to drivers/media/platform/davinci/vpif_display.h
index 8967ffb4405846ec6ffa0213eb747a19448af232..f628ebcf36747110c78c86f4b904d76a5fca2ff8 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,8 +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;
+       struct v4l2_dv_timings dv_timings;
        u32 output_id;                  /* Current output id */
 };
 
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..897250b886474c0c950e23b0279e9f5e22343329 100644 (file)
@@ -860,7 +860,7 @@ 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;
@@ -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 409da0f8e5cfdb92fa0347bd3b4a6f4cee56cfa3..66ac21d466afa29a6975fb0cabf61b1e69b8b356 100644 (file)
@@ -1292,7 +1292,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;
@@ -1745,7 +1745,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;
@@ -1952,6 +1952,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 8d7283bbd431af44a9d7ff4e564e264ac54b8a1a..70f45c381318929f4b80b70025fb368305a0b788 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 43e61fe5df50f9b07150c1dcd2442f8607afe882..99640d8c1db0a51d9e2fa2d9a6e64f23f2f1b2ee 100644 (file)
@@ -254,13 +254,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 :
@@ -270,9 +275,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);
 }
 
 /*
@@ -289,7 +295,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;
 
@@ -298,12 +304,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;
 
@@ -325,9 +331,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);
 }
 
@@ -1283,7 +1286,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)
@@ -1443,7 +1448,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;
 
@@ -1462,10 +1467,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)
@@ -1475,6 +1479,11 @@ out:
        return __isp;
 }
 
+struct isp_device *omap3isp_get(struct isp_device *isp)
+{
+       return __omap3isp_get(isp, true);
+}
+
 /*
  * omap3isp_put - Release the ISP
  *
@@ -1490,8 +1499,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.
                 */
@@ -1975,7 +1986,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;
@@ -2093,8 +2104,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)
@@ -2160,7 +2173,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 97%
rename from drivers/media/video/s5p-fimc/fimc-capture.c
rename to drivers/media/platform/s5p-fimc/fimc-capture.c
index 8e413dd3c0b098a5811f87add3113efc5bd2844e..dded988152206e779c3f49844d5ade4a09f14663 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;
 }
@@ -264,7 +265,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 +290,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 +306,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);
@@ -371,7 +373,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 +424,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 +475,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 +505,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 +539,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);
        }
 
@@ -1587,13 +1590,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 +1607,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 +1657,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 +1666,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 +1689,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 99%
rename from drivers/media/video/s5p-fimc/fimc-core.h
rename to drivers/media/platform/s5p-fimc/fimc-core.h
index 808ccc621846fee63d2c4aa762e4a81e63f4490e..cd716ba6015f6e5c441c84a4fe34627f1121ee47 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>
@@ -287,7 +287,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 +320,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 +440,7 @@ struct fimc_dev {
        unsigned long                   state;
        struct vb2_alloc_ctx            *alloc_ctx;
        struct fimc_pipeline            pipeline;
+       const struct fimc_pipeline_ops  *pipeline_ops;
 };
 
 /**
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 95%
rename from drivers/media/video/s5p-fimc/fimc-m2m.c
rename to drivers/media/platform/s5p-fimc/fimc-m2m.c
index c587011d80eff668c8e1347d099e91d1fb33d427..6b71d953fd15b1a533f90a39d0eb0b9ed112b17c 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,7 +551,7 @@ 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 *cr)
 {
        struct fimc_ctx *ctx = fh_to_ctx(fh);
        struct fimc_dev *fimc = ctx->fimc_dev;
@@ -577,7 +577,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
                                        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;
                }
        }
@@ -620,7 +620,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 +631,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 +659,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 +782,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 +821,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 +831,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 99%
rename from drivers/media/video/s5p-fimc/fimc-reg.c
rename to drivers/media/platform/s5p-fimc/fimc-reg.c
index 0e3eb9ce4f981857a805e80fed82629fd4c88100..783408fd7d566b53b165e5bd896ee8aaef38c4ea 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;
@@ -684,7 +684,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
                        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 +701,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);
similarity index 82%
rename from drivers/media/video/s5p-fimc/mipi-csis.c
rename to drivers/media/platform/s5p-fimc/mipi-csis.c
index 5e898432883a28a848ea206be03453ad051d8fed..e92236ac5cfe86e5787f0f95bc057a920d3d4255 100644 (file)
@@ -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,10 +60,38 @@ 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
@@ -93,6 +121,29 @@ 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_state - the driver's internal state data structure
  * @lock: mutex serializing the subdev and power management operations,
@@ -101,11 +152,14 @@ 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
+ * @events: MIPI-CSIS event (error) counters
  */
 struct csis_state {
        struct mutex lock;
@@ -119,6 +173,9 @@ struct csis_state {
        u32 flags;
        const struct csis_pix_format *csis_fmt;
        struct v4l2_mbus_framefmt format;
+
+       struct spinlock slock;
+       struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
 };
 
 /**
@@ -292,17 +349,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 +363,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 +413,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 +430,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 +529,14 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        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 +556,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 = {
@@ -479,12 +578,29 @@ 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;
-
-       /* Just clear the interrupt pending bits. */
-       val = s5pcsis_read(state, S5PCSIS_INTSRC);
-       s5pcsis_write(state, S5PCSIS_INTSRC, val);
+       unsigned long flags;
+       u32 status;
+
+       status = s5pcsis_read(state, S5PCSIS_INTSRC);
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       /* 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 +617,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 +695,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..1e3b9dd014c094655d7e5b6719c60d06c48d49a8 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,
@@ -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 98%
rename from drivers/media/video/s5p-jpeg/jpeg-core.c
rename to drivers/media/platform/s5p-jpeg/jpeg-core.c
index 813b801238d1f72e910ab8eea63feeb586b477bb..394775ae5774f4d21d98719c3afae2343b658466 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;
@@ -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) {
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/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 f7831e73f077d8da7282ac847cdec076c0499709..f7297ae76b4888f8a8aafc3b52e09f4b0066fd3d 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(&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 94%
rename from drivers/media/video/v4l2-ctrls.c
rename to drivers/media/v4l2-core/v4l2-ctrls.c
index b6a2ee71e5c300cead8a4d77cb4e627c687a476e..631cdc0e0bdaab5524b0f9a6eff5bc8208791a2b 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;
@@ -733,6 +750,16 @@ const char *v4l2_ctrl_get_name(u32 id)
        case V4L2_CID_LINK_FREQ:                return "Link Frequency";
        case V4L2_CID_PIXEL_RATE:               return "Pixel Rate";
 
+       /* 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 +859,9 @@ 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:
                *type = V4L2_CTRL_TYPE_MENU;
                break;
        case V4L2_CID_LINK_FREQ:
@@ -853,6 +883,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 +900,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 +968,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 +1213,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)
@@ -1671,7 +1687,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 +1708,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 +1720,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 +2274,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 +2296,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 +2307,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 +2326,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 +2563,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 +2592,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 +2607,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 +2616,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 +2631,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 +2722,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..9d3e46c446ad7cf502ca49fe6dcaa1d85ec09277 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),
@@ -2191,6 +2206,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 98%
rename from drivers/media/video/videobuf2-core.c
rename to drivers/media/v4l2-core/videobuf2-core.c
index 268c7dd4f8231ebc2f3ca033bfea4bbc689f07f7..e6a26b433e87ffe74728a5e3b93ca353d6e1d83d 100644 (file)
@@ -1738,14 +1738,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 +2273,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 +2295,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 +2320,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 +2335,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 +2347,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 b73f033b2c602fadce09dd97d0c7623581962e12..8fa86edf70d46ae77d7e47589b6641a3e411ba58 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/regulator/machine.h>
+#include <linux/power/charger-manager.h>
 
 #define INT_STATUS_NUM                 3
 
-static struct resource bk_resources[] __devinitdata = {
-       {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
-       {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
-       {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
-};
-
-static struct resource led_resources[] __devinitdata = {
-       {PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
-       {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
-       {PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
-       {PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,},
-       {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
-       {PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
-};
-
-static struct resource regulator_resources[] __devinitdata = {
-       {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
-       {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
-       {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
-       {PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,},
-       {PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,},
-       {PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,},
-       {PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,},
-       {PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,},
-       {PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,},
-       {PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,},
-       {PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,},
-       {PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,},
-       {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
-       {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
-       {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
-       {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
-       {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
-       {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
+static struct resource bk0_resources[] __devinitdata = {
+       {2, 2, "duty cycle", IORESOURCE_REG, },
+       {3, 3, "always on",  IORESOURCE_REG, },
+       {3, 3, "current",    IORESOURCE_REG, },
+};
+static struct resource bk1_resources[] __devinitdata = {
+       {4, 4, "duty cycle", IORESOURCE_REG, },
+       {5, 5, "always on",  IORESOURCE_REG, },
+       {5, 5, "current",    IORESOURCE_REG, },
+};
+static struct resource bk2_resources[] __devinitdata = {
+       {6, 6, "duty cycle", IORESOURCE_REG, },
+       {7, 7, "always on",  IORESOURCE_REG, },
+       {5, 5, "current",    IORESOURCE_REG, },
+};
+
+static struct resource led0_resources[] __devinitdata = {
+       /* RGB1 Red LED */
+       {0xd, 0xd, "control", IORESOURCE_REG, },
+       {0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led1_resources[] __devinitdata = {
+       /* RGB1 Green LED */
+       {0xe, 0xe, "control", IORESOURCE_REG, },
+       {0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led2_resources[] __devinitdata = {
+       /* RGB1 Blue LED */
+       {0xf, 0xf, "control", IORESOURCE_REG, },
+       {0xc, 0xc, "blink",   IORESOURCE_REG, },
+};
+static struct resource led3_resources[] __devinitdata = {
+       /* RGB2 Red LED */
+       {0x9, 0x9, "control", IORESOURCE_REG, },
+       {0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+static struct resource led4_resources[] __devinitdata = {
+       /* RGB2 Green LED */
+       {0xa, 0xa, "control", IORESOURCE_REG, },
+       {0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+static struct resource led5_resources[] __devinitdata = {
+       /* RGB2 Blue LED */
+       {0xb, 0xb, "control", IORESOURCE_REG, },
+       {0x8, 0x8, "blink",   IORESOURCE_REG, },
+};
+
+static struct resource buck1_resources[] __devinitdata = {
+       {0x24, 0x24, "buck set", IORESOURCE_REG, },
+};
+static struct resource buck2_resources[] __devinitdata = {
+       {0x25, 0x25, "buck set", IORESOURCE_REG, },
+};
+static struct resource buck3_resources[] __devinitdata = {
+       {0x26, 0x26, "buck set", IORESOURCE_REG, },
+};
+static struct resource ldo1_resources[] __devinitdata = {
+       {0x10, 0x10, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo2_resources[] __devinitdata = {
+       {0x11, 0x11, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo3_resources[] __devinitdata = {
+       {0x12, 0x12, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo4_resources[] __devinitdata = {
+       {0x13, 0x13, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo5_resources[] __devinitdata = {
+       {0x14, 0x14, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo6_resources[] __devinitdata = {
+       {0x15, 0x15, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo7_resources[] __devinitdata = {
+       {0x16, 0x16, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo8_resources[] __devinitdata = {
+       {0x17, 0x17, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo9_resources[] __devinitdata = {
+       {0x18, 0x18, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo10_resources[] __devinitdata = {
+       {0x19, 0x19, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo12_resources[] __devinitdata = {
+       {0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo_vibrator_resources[] __devinitdata = {
+       {0x28, 0x28, "ldo set", IORESOURCE_REG, },
+};
+static struct resource ldo14_resources[] __devinitdata = {
+       {0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
 };
 
 static struct resource touch_resources[] __devinitdata = {
@@ -84,54 +151,152 @@ static struct resource battery_resources[] __devinitdata = {
 static struct resource charger_resources[] __devinitdata = {
        {PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
        {PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
-       {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout",    IORESOURCE_IRQ,},
+       {PM8607_IRQ_CHG_FAIL,  PM8607_IRQ_CHG_FAIL,  "charging timeout",    IORESOURCE_IRQ,},
+       {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",      IORESOURCE_IRQ,},
        {PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature", IORESOURCE_IRQ,},
        {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
        {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
 
-static struct resource preg_resources[] __devinitdata = {
-       {PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_IO,},
-};
-
 static struct resource rtc_resources[] __devinitdata = {
        {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell bk_devs[] = {
-       {"88pm860x-backlight", 0,},
-       {"88pm860x-backlight", 1,},
-       {"88pm860x-backlight", 2,},
-};
-
-static struct mfd_cell led_devs[] = {
-       {"88pm860x-led", 0,},
-       {"88pm860x-led", 1,},
-       {"88pm860x-led", 2,},
-       {"88pm860x-led", 3,},
-       {"88pm860x-led", 4,},
-       {"88pm860x-led", 5,},
-};
-
-static struct mfd_cell regulator_devs[] = {
-       {"88pm860x-regulator", 0,},
-       {"88pm860x-regulator", 1,},
-       {"88pm860x-regulator", 2,},
-       {"88pm860x-regulator", 3,},
-       {"88pm860x-regulator", 4,},
-       {"88pm860x-regulator", 5,},
-       {"88pm860x-regulator", 6,},
-       {"88pm860x-regulator", 7,},
-       {"88pm860x-regulator", 8,},
-       {"88pm860x-regulator", 9,},
-       {"88pm860x-regulator", 10,},
-       {"88pm860x-regulator", 11,},
-       {"88pm860x-regulator", 12,},
-       {"88pm860x-regulator", 13,},
-       {"88pm860x-regulator", 14,},
-       {"88pm860x-regulator", 15,},
-       {"88pm860x-regulator", 16,},
-       {"88pm860x-regulator", 17,},
+static struct mfd_cell bk_devs[] __devinitdata = {
+       {
+               .name = "88pm860x-backlight",
+               .id = 0,
+               .num_resources = ARRAY_SIZE(bk0_resources),
+               .resources = bk0_resources,
+       }, {
+               .name = "88pm860x-backlight",
+               .id = 1,
+               .num_resources = ARRAY_SIZE(bk1_resources),
+               .resources = bk1_resources,
+       }, {
+               .name = "88pm860x-backlight",
+               .id = 2,
+               .num_resources = ARRAY_SIZE(bk2_resources),
+               .resources = bk2_resources,
+       },
+};
+
+static struct mfd_cell led_devs[] __devinitdata = {
+       {
+               .name = "88pm860x-led",
+               .id = 0,
+               .num_resources = ARRAY_SIZE(led0_resources),
+               .resources = led0_resources,
+       }, {
+               .name = "88pm860x-led",
+               .id = 1,
+               .num_resources = ARRAY_SIZE(led1_resources),
+               .resources = led1_resources,
+       }, {
+               .name = "88pm860x-led",
+               .id = 2,
+               .num_resources = ARRAY_SIZE(led2_resources),
+               .resources = led2_resources,
+       }, {
+               .name = "88pm860x-led",
+               .id = 3,
+               .num_resources = ARRAY_SIZE(led3_resources),
+               .resources = led3_resources,
+       }, {
+               .name = "88pm860x-led",
+               .id = 4,
+               .num_resources = ARRAY_SIZE(led4_resources),
+               .resources = led4_resources,
+       }, {
+               .name = "88pm860x-led",
+               .id = 5,
+               .num_resources = ARRAY_SIZE(led5_resources),
+               .resources = led5_resources,
+       },
+};
+
+static struct mfd_cell reg_devs[] __devinitdata = {
+       {
+               .name = "88pm860x-regulator",
+               .id = 0,
+               .num_resources = ARRAY_SIZE(buck1_resources),
+               .resources = buck1_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 1,
+               .num_resources = ARRAY_SIZE(buck2_resources),
+               .resources = buck2_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 2,
+               .num_resources = ARRAY_SIZE(buck3_resources),
+               .resources = buck3_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 3,
+               .num_resources = ARRAY_SIZE(ldo1_resources),
+               .resources = ldo1_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 4,
+               .num_resources = ARRAY_SIZE(ldo2_resources),
+               .resources = ldo2_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 5,
+               .num_resources = ARRAY_SIZE(ldo3_resources),
+               .resources = ldo3_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 6,
+               .num_resources = ARRAY_SIZE(ldo4_resources),
+               .resources = ldo4_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 7,
+               .num_resources = ARRAY_SIZE(ldo5_resources),
+               .resources = ldo5_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 8,
+               .num_resources = ARRAY_SIZE(ldo6_resources),
+               .resources = ldo6_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 9,
+               .num_resources = ARRAY_SIZE(ldo7_resources),
+               .resources = ldo7_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 10,
+               .num_resources = ARRAY_SIZE(ldo8_resources),
+               .resources = ldo8_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 11,
+               .num_resources = ARRAY_SIZE(ldo9_resources),
+               .resources = ldo9_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 12,
+               .num_resources = ARRAY_SIZE(ldo10_resources),
+               .resources = ldo10_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 13,
+               .num_resources = ARRAY_SIZE(ldo12_resources),
+               .resources = ldo12_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 14,
+               .num_resources = ARRAY_SIZE(ldo_vibrator_resources),
+               .resources = ldo_vibrator_resources,
+       }, {
+               .name = "88pm860x-regulator",
+               .id = 15,
+               .num_resources = ARRAY_SIZE(ldo14_resources),
+               .resources = ldo14_resources,
+       },
 };
 
 static struct mfd_cell touch_devs[] = {
@@ -155,10 +320,15 @@ static struct regulator_init_data preg_init_data = {
        .consumer_supplies      = &preg_supply[0],
 };
 
+static struct charger_regulator chg_desc_regulator_data[] = {
+       { .regulator_name = "preg", },
+};
+
 static struct mfd_cell power_devs[] = {
        {"88pm860x-battery", -1,},
        {"88pm860x-charger", -1,},
        {"88pm860x-preg",    -1,},
+       {"charger-manager", -1,},
 };
 
 static struct mfd_cell rtc_devs[] = {
@@ -360,15 +530,12 @@ static void pm860x_irq_sync_unlock(struct irq_data *data)
 
 static void pm860x_irq_enable(struct irq_data *data)
 {
-       struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
-       pm860x_irqs[data->irq - chip->irq_base].enable
-               = pm860x_irqs[data->irq - chip->irq_base].offs;
+       pm860x_irqs[data->hwirq].enable = pm860x_irqs[data->hwirq].offs;
 }
 
 static void pm860x_irq_disable(struct irq_data *data)
 {
-       struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
-       pm860x_irqs[data->irq - chip->irq_base].enable = 0;
+       pm860x_irqs[data->hwirq].enable = 0;
 }
 
 static struct irq_chip pm860x_irq_chip = {
@@ -379,53 +546,25 @@ static struct irq_chip pm860x_irq_chip = {
        .irq_disable    = pm860x_irq_disable,
 };
 
-static int __devinit device_gpadc_init(struct pm860x_chip *chip,
-                                      struct pm860x_platform_data *pdata)
+static int pm860x_irq_domain_map(struct irq_domain *d, unsigned int virq,
+                                irq_hw_number_t hw)
 {
-       struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
-                               : chip->companion;
-       int data;
-       int ret;
-
-       /* initialize GPADC without activating it */
-
-       if (!pdata || !pdata->touch)
-               return -EINVAL;
-
-       /* set GPADC MISC1 register */
-       data = 0;
-       data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
-       data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
-       data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
-       data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
-       if (data) {
-               ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
-               if (ret < 0)
-                       goto out;
-       }
-       /* set tsi prebias time */
-       if (pdata->touch->tsi_prebias) {
-               data = pdata->touch->tsi_prebias;
-               ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
-               if (ret < 0)
-                       goto out;
-       }
-       /* set prebias & prechg time of pen detect */
-       data = 0;
-       data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
-       data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
-       if (data) {
-               ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
-               if (ret < 0)
-                       goto out;
-       }
-
-       ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
-                             PM8607_GPADC_EN, PM8607_GPADC_EN);
-out:
-       return ret;
+       irq_set_chip_data(virq, d->host_data);
+       irq_set_chip_and_handler(virq, &pm860x_irq_chip, handle_edge_irq);
+       irq_set_nested_thread(virq, 1);
+#ifdef CONFIG_ARM
+       set_irq_flags(virq, IRQF_VALID);
+#else
+       irq_set_noprobe(virq);
+#endif
+       return 0;
 }
 
+static struct irq_domain_ops pm860x_irq_domain_ops = {
+       .map    = pm860x_irq_domain_map,
+       .xlate  = irq_domain_xlate_onetwocell,
+};
+
 static int __devinit device_irq_init(struct pm860x_chip *chip,
                                     struct pm860x_platform_data *pdata)
 {
@@ -433,13 +572,9 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
                                : chip->companion;
        unsigned char status_buf[INT_STATUS_NUM];
        unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-       int i, data, mask, ret = -EINVAL;
-       int __irq;
-
-       if (!pdata || !pdata->irq_base) {
-               dev_warn(chip->dev, "No interrupt support on IRQ base\n");
-               return -EINVAL;
-       }
+       int data, mask, ret = -EINVAL;
+       int nr_irqs, irq_base = -1;
+       struct device_node *node = i2c->dev.of_node;
 
        mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
                | PM8607_B0_MISC1_INT_MASK;
@@ -479,26 +614,24 @@ static int __devinit device_irq_init(struct pm860x_chip *chip,
                goto out;
 
        mutex_init(&chip->irq_lock);
-       chip->irq_base = pdata->irq_base;
+
+       if (pdata && pdata->irq_base)
+               irq_base = pdata->irq_base;
+       nr_irqs = ARRAY_SIZE(pm860x_irqs);
+       chip->irq_base = irq_alloc_descs(irq_base, 0, nr_irqs, 0);
+       if (chip->irq_base < 0) {
+               dev_err(&i2c->dev, "Failed to allocate interrupts, ret:%d\n",
+                       chip->irq_base);
+               ret = -EBUSY;
+               goto out;
+       }
+       irq_domain_add_legacy(node, nr_irqs, chip->irq_base, 0,
+                             &pm860x_irq_domain_ops, chip);
        chip->core_irq = i2c->irq;
        if (!chip->core_irq)
                goto out;
 
-       /* register IRQ by genirq */
-       for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
-               __irq = i + chip->irq_base;
-               irq_set_chip_data(__irq, chip);
-               irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
-                                        handle_edge_irq);
-               irq_set_nested_thread(__irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(__irq, IRQF_VALID);
-#else
-               irq_set_noprobe(__irq);
-#endif
-       }
-
-       ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
+       ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
                                   "88pm860x", chip);
        if (ret) {
                dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
@@ -615,108 +748,122 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
 static void __devinit device_bk_init(struct pm860x_chip *chip,
                                     struct pm860x_platform_data *pdata)
 {
-       int ret;
-       int i, j, id;
-
-       if ((pdata == NULL) || (pdata->backlight == NULL))
-               return;
-
-       if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
-               pdata->num_backlights = ARRAY_SIZE(bk_devs);
-
-       for (i = 0; i < pdata->num_backlights; i++) {
-               bk_devs[i].platform_data = &pdata->backlight[i];
-               bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata);
-
-               for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
-                       id = bk_resources[j].start;
-                       if (pdata->backlight[i].flags != id)
-                               continue;
-
-                       bk_devs[i].num_resources = 1;
-                       bk_devs[i].resources = &bk_resources[j];
-                       ret = mfd_add_devices(chip->dev, 0,
-                                             &bk_devs[i], 1,
-                                             &bk_resources[j], 0, NULL);
-                       if (ret < 0) {
-                               dev_err(chip->dev, "Failed to add "
-                                       "backlight subdev\n");
-                               return;
-                       }
+       int ret, i;
+
+       if (pdata && pdata->backlight) {
+               if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
+                       pdata->num_backlights = ARRAY_SIZE(bk_devs);
+               for (i = 0; i < pdata->num_backlights; i++) {
+                       bk_devs[i].platform_data = &pdata->backlight[i];
+                       bk_devs[i].pdata_size =
+                               sizeof(struct pm860x_backlight_pdata);
                }
        }
+       ret = mfd_add_devices(chip->dev, 0, bk_devs,
+                             ARRAY_SIZE(bk_devs), NULL, 0, NULL);
+       if (ret < 0)
+               dev_err(chip->dev, "Failed to add backlight subdev\n");
 }
 
 static void __devinit device_led_init(struct pm860x_chip *chip,
                                      struct pm860x_platform_data *pdata)
 {
-       int ret;
-       int i, j, id;
-
-       if ((pdata == NULL) || (pdata->led == NULL))
-               return;
-
-       if (pdata->num_leds > ARRAY_SIZE(led_devs))
-               pdata->num_leds = ARRAY_SIZE(led_devs);
-
-       for (i = 0; i < pdata->num_leds; i++) {
-               led_devs[i].platform_data = &pdata->led[i];
-               led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
-
-               for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
-                       id = led_resources[j].start;
-                       if (pdata->led[i].flags != id)
-                               continue;
-
-                       led_devs[i].num_resources = 1;
-                       led_devs[i].resources = &led_resources[j],
-                       ret = mfd_add_devices(chip->dev, 0,
-                                             &led_devs[i], 1,
-                                             &led_resources[j], 0, NULL);
-                       if (ret < 0) {
-                               dev_err(chip->dev, "Failed to add "
-                                       "led subdev\n");
-                               return;
-                       }
+       int ret, i;
+
+       if (pdata && pdata->led) {
+               if (pdata->num_leds > ARRAY_SIZE(led_devs))
+                       pdata->num_leds = ARRAY_SIZE(led_devs);
+               for (i = 0; i < pdata->num_leds; i++) {
+                       led_devs[i].platform_data = &pdata->led[i];
+                       led_devs[i].pdata_size =
+                               sizeof(struct pm860x_led_pdata);
                }
        }
+       ret = mfd_add_devices(chip->dev, 0, led_devs,
+                             ARRAY_SIZE(led_devs), NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to add led subdev\n");
+               return;
+       }
 }
 
 static void __devinit device_regulator_init(struct pm860x_chip *chip,
                                            struct pm860x_platform_data *pdata)
 {
-       struct regulator_init_data *initdata;
        int ret;
-       int i, seq;
 
-       if ((pdata == NULL) || (pdata->regulator == NULL))
+       if (pdata == NULL)
+               return;
+       if (pdata->buck1) {
+               reg_devs[0].platform_data = pdata->buck1;
+               reg_devs[0].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->buck2) {
+               reg_devs[1].platform_data = pdata->buck2;
+               reg_devs[1].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->buck3) {
+               reg_devs[2].platform_data = pdata->buck3;
+               reg_devs[2].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo1) {
+               reg_devs[3].platform_data = pdata->ldo1;
+               reg_devs[3].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo2) {
+               reg_devs[4].platform_data = pdata->ldo2;
+               reg_devs[4].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo3) {
+               reg_devs[5].platform_data = pdata->ldo3;
+               reg_devs[5].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo4) {
+               reg_devs[6].platform_data = pdata->ldo4;
+               reg_devs[6].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo5) {
+               reg_devs[7].platform_data = pdata->ldo5;
+               reg_devs[7].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo6) {
+               reg_devs[8].platform_data = pdata->ldo6;
+               reg_devs[8].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo7) {
+               reg_devs[9].platform_data = pdata->ldo7;
+               reg_devs[9].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo8) {
+               reg_devs[10].platform_data = pdata->ldo8;
+               reg_devs[10].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo9) {
+               reg_devs[11].platform_data = pdata->ldo9;
+               reg_devs[11].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo10) {
+               reg_devs[12].platform_data = pdata->ldo10;
+               reg_devs[12].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo12) {
+               reg_devs[13].platform_data = pdata->ldo12;
+               reg_devs[13].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo_vibrator) {
+               reg_devs[14].platform_data = pdata->ldo_vibrator;
+               reg_devs[14].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo14) {
+               reg_devs[15].platform_data = pdata->ldo14;
+               reg_devs[15].pdata_size = sizeof(struct regulator_init_data);
+       }
+       ret = mfd_add_devices(chip->dev, 0, reg_devs,
+                             ARRAY_SIZE(reg_devs), NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to add regulator subdev\n");
                return;
-
-       if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
-               pdata->num_regulators = ARRAY_SIZE(regulator_devs);
-
-       for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
-               initdata = &pdata->regulator[i];
-               seq = *(unsigned int *)initdata->driver_data;
-               if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
-                       dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
-                               seq, initdata->constraints.name);
-                       goto out;
-               }
-               regulator_devs[i].platform_data = &pdata->regulator[i];
-               regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
-               regulator_devs[i].num_resources = 1;
-               regulator_devs[i].resources = &regulator_resources[seq];
-
-               ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
-                                     &regulator_resources[seq], 0, NULL);
-               if (ret < 0) {
-                       dev_err(chip->dev, "Failed to add regulator subdev\n");
-                       goto out;
-               }
        }
-out:
-       return;
 }
 
 static void __devinit device_rtc_init(struct pm860x_chip *chip,
@@ -785,12 +932,23 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
 
        power_devs[2].platform_data = &preg_init_data;
        power_devs[2].pdata_size = sizeof(struct regulator_init_data);
-       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, NULL);
+                             NULL, chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add preg subdev\n");
+
+       if (pdata->chg_desc) {
+               pdata->chg_desc->charger_regulators =
+                       &chg_desc_regulator_data[0];
+               pdata->chg_desc->num_charger_regulators =
+                       ARRAY_SIZE(chg_desc_regulator_data),
+               power_devs[3].platform_data = pdata->chg_desc;
+               power_devs[3].pdata_size = sizeof(*pdata->chg_desc);
+               ret = mfd_add_devices(chip->dev, 0, &power_devs[3], 1,
+                                     NULL, chip->irq_base, NULL);
+               if (ret < 0)
+                       dev_err(chip->dev, "Failed to add chg-manager subdev\n");
+       }
 }
 
 static void __devinit device_onkey_init(struct pm860x_chip *chip,
@@ -868,10 +1026,6 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
                goto out;
        }
 
-       ret = device_gpadc_init(chip, pdata);
-       if (ret < 0)
-               goto out;
-
        ret = device_irq_init(chip, pdata);
        if (ret < 0)
                goto out;
@@ -895,8 +1049,8 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
        device_led_init(chip, pdata);
 }
 
-int __devinit pm860x_device_init(struct pm860x_chip *chip,
-                      struct pm860x_platform_data *pdata)
+static int __devinit pm860x_device_init(struct pm860x_chip *chip,
+                                       struct pm860x_platform_data *pdata)
 {
        chip->core_irq = 0;
 
@@ -923,12 +1077,207 @@ int __devinit pm860x_device_init(struct pm860x_chip *chip,
        return 0;
 }
 
-void __devexit pm860x_device_exit(struct pm860x_chip *chip)
+static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
 {
        device_irq_exit(chip);
        mfd_remove_devices(chip->dev);
 }
 
+static int verify_addr(struct i2c_client *i2c)
+{
+       unsigned short addr_8607[] = {0x30, 0x34};
+       unsigned short addr_8606[] = {0x10, 0x11};
+       int size, i;
+
+       if (i2c == NULL)
+               return 0;
+       size = ARRAY_SIZE(addr_8606);
+       for (i = 0; i < size; i++) {
+               if (i2c->addr == *(addr_8606 + i))
+                       return CHIP_PM8606;
+       }
+       size = ARRAY_SIZE(addr_8607);
+       for (i = 0; i < size; i++) {
+               if (i2c->addr == *(addr_8607 + i))
+                       return CHIP_PM8607;
+       }
+       return 0;
+}
+
+static struct regmap_config pm860x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int __devinit pm860x_dt_init(struct device_node *np,
+                                   struct device *dev,
+                                   struct pm860x_platform_data *pdata)
+{
+       int ret;
+
+       if (of_get_property(np, "marvell,88pm860x-irq-read-clr", NULL))
+               pdata->irq_mode = 1;
+       ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
+                                  &pdata->companion_addr);
+       if (ret) {
+               dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
+                       "property\n");
+               pdata->companion_addr = 0;
+       }
+       return 0;
+}
+
+static int __devinit pm860x_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct pm860x_platform_data *pdata = client->dev.platform_data;
+       struct device_node *node = client->dev.of_node;
+       struct pm860x_chip *chip;
+       int ret;
+
+       if (node && !pdata) {
+               /* parse DT to get platform data */
+               pdata = devm_kzalloc(&client->dev,
+                                    sizeof(struct pm860x_platform_data),
+                                    GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+               ret = pm860x_dt_init(node, &client->dev, pdata);
+               if (ret)
+                       goto err;
+       } else if (!pdata) {
+               pr_info("No platform data in %s!\n", __func__);
+               return -EINVAL;
+       }
+
+       chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
+       if (chip == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       chip->id = verify_addr(client);
+       chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
+       if (IS_ERR(chip->regmap)) {
+               ret = PTR_ERR(chip->regmap);
+               dev_err(&client->dev, "Failed to allocate register map: %d\n",
+                               ret);
+               kfree(chip);
+               return ret;
+       }
+       chip->client = client;
+       i2c_set_clientdata(client, chip);
+       chip->dev = &client->dev;
+       dev_set_drvdata(chip->dev, chip);
+
+       /*
+        * Both client and companion client shares same platform driver.
+        * Driver distinguishes them by pdata->companion_addr.
+        * pdata->companion_addr is only assigned if companion chip exists.
+        * At the same time, the companion_addr shouldn't equal to client
+        * address.
+        */
+       if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
+               chip->companion_addr = pdata->companion_addr;
+               chip->companion = i2c_new_dummy(chip->client->adapter,
+                                               chip->companion_addr);
+               chip->regmap_companion = regmap_init_i2c(chip->companion,
+                                                       &pm860x_regmap_config);
+               if (IS_ERR(chip->regmap_companion)) {
+                       ret = PTR_ERR(chip->regmap_companion);
+                       dev_err(&chip->companion->dev,
+                               "Failed to allocate register map: %d\n", ret);
+                       return ret;
+               }
+               i2c_set_clientdata(chip->companion, chip);
+       }
+
+       pm860x_device_init(chip, pdata);
+       return 0;
+err:
+       if (node)
+               devm_kfree(&client->dev, pdata);
+       return ret;
+}
+
+static int __devexit pm860x_remove(struct i2c_client *client)
+{
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       pm860x_device_exit(chip);
+       if (chip->companion) {
+               regmap_exit(chip->regmap_companion);
+               i2c_unregister_device(chip->companion);
+       }
+       regmap_exit(chip->regmap);
+       kfree(chip);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               enable_irq_wake(chip->core_irq);
+       return 0;
+}
+
+static int pm860x_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+       if (device_may_wakeup(dev) && chip->wakeup_flag)
+               disable_irq_wake(chip->core_irq);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
+
+static const struct i2c_device_id pm860x_id_table[] = {
+       { "88PM860x", 0 },
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
+
+static const struct of_device_id pm860x_dt_ids[] = {
+       { .compatible = "marvell,88pm860x", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, pm860x_dt_ids);
+
+static struct i2c_driver pm860x_driver = {
+       .driver = {
+               .name   = "88PM860x",
+               .owner  = THIS_MODULE,
+               .pm     = &pm860x_pm_ops,
+               .of_match_table = of_match_ptr(pm860x_dt_ids),
+       },
+       .probe          = pm860x_probe,
+       .remove         = __devexit_p(pm860x_remove),
+       .id_table       = pm860x_id_table,
+};
+
+static int __init pm860x_i2c_init(void)
+{
+       int ret;
+       ret = i2c_add_driver(&pm860x_driver);
+       if (ret != 0)
+               pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
+       return ret;
+}
+subsys_initcall(pm860x_i2c_init);
+
+static void __exit pm860x_i2c_exit(void)
+{
+       i2c_del_driver(&pm860x_driver);
+}
+module_exit(pm860x_i2c_exit);
+
 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_LICENSE("GPL");
index b2cfdc458561fb5fcba59a6dc11e0a9b70c6b55a..ff8f803ce8334d6e0bd27565601ef767b51007f0 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/err.h>
 #include <linux/regmap.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 int pm860x_reg_read(struct i2c_client *i2c, int reg)
 {
@@ -91,8 +88,18 @@ static int read_device(struct i2c_client *i2c, int reg,
        unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
        unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
        struct i2c_adapter *adap = i2c->adapter;
-       struct i2c_msg msg[2] = {{i2c->addr, 0, 1, msgbuf0},
-                                {i2c->addr, I2C_M_RD, 0, msgbuf1},
+       struct i2c_msg msg[2] = {
+                                       {
+                                               .addr = i2c->addr,
+                                               .flags = 0,
+                                               .len = 1,
+                                               .buf = msgbuf0
+                                       },
+                                       {       .addr = i2c->addr,
+                                               .flags = I2C_M_RD,
+                                               .len = 0,
+                                               .buf = msgbuf1
+                                       },
                                };
        int num = 1, ret = 0;
 
@@ -231,160 +238,3 @@ out:
        return ret;
 }
 EXPORT_SYMBOL(pm860x_page_set_bits);
-
-static const struct i2c_device_id pm860x_id_table[] = {
-       { "88PM860x", 0 },
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
-
-static int verify_addr(struct i2c_client *i2c)
-{
-       unsigned short addr_8607[] = {0x30, 0x34};
-       unsigned short addr_8606[] = {0x10, 0x11};
-       int size, i;
-
-       if (i2c == NULL)
-               return 0;
-       size = ARRAY_SIZE(addr_8606);
-       for (i = 0; i < size; i++) {
-               if (i2c->addr == *(addr_8606 + i))
-                       return CHIP_PM8606;
-       }
-       size = ARRAY_SIZE(addr_8607);
-       for (i = 0; i < size; i++) {
-               if (i2c->addr == *(addr_8607 + i))
-                       return CHIP_PM8607;
-       }
-       return 0;
-}
-
-static struct regmap_config pm860x_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-};
-
-static int __devinit pm860x_probe(struct i2c_client *client,
-                                 const struct i2c_device_id *id)
-{
-       struct pm860x_platform_data *pdata = client->dev.platform_data;
-       struct pm860x_chip *chip;
-       int ret;
-
-       if (!pdata) {
-               pr_info("No platform data in %s!\n", __func__);
-               return -EINVAL;
-       }
-
-       chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
-
-       chip->id = verify_addr(client);
-       chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config);
-       if (IS_ERR(chip->regmap)) {
-               ret = PTR_ERR(chip->regmap);
-               dev_err(&client->dev, "Failed to allocate register map: %d\n",
-                               ret);
-               kfree(chip);
-               return ret;
-       }
-       chip->client = client;
-       i2c_set_clientdata(client, chip);
-       chip->dev = &client->dev;
-       dev_set_drvdata(chip->dev, chip);
-
-       /*
-        * Both client and companion client shares same platform driver.
-        * Driver distinguishes them by pdata->companion_addr.
-        * pdata->companion_addr is only assigned if companion chip exists.
-        * At the same time, the companion_addr shouldn't equal to client
-        * address.
-        */
-       if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
-               chip->companion_addr = pdata->companion_addr;
-               chip->companion = i2c_new_dummy(chip->client->adapter,
-                                               chip->companion_addr);
-               chip->regmap_companion = regmap_init_i2c(chip->companion,
-                                                       &pm860x_regmap_config);
-               if (IS_ERR(chip->regmap_companion)) {
-                       ret = PTR_ERR(chip->regmap_companion);
-                       dev_err(&chip->companion->dev,
-                               "Failed to allocate register map: %d\n", ret);
-                       return ret;
-               }
-               i2c_set_clientdata(chip->companion, chip);
-       }
-
-       pm860x_device_init(chip, pdata);
-       return 0;
-}
-
-static int __devexit pm860x_remove(struct i2c_client *client)
-{
-       struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-       pm860x_device_exit(chip);
-       if (chip->companion) {
-               regmap_exit(chip->regmap_companion);
-               i2c_unregister_device(chip->companion);
-       }
-       regmap_exit(chip->regmap);
-       kfree(chip);
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int pm860x_suspend(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-       if (device_may_wakeup(dev) && chip->wakeup_flag)
-               enable_irq_wake(chip->core_irq);
-       return 0;
-}
-
-static int pm860x_resume(struct device *dev)
-{
-       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-       struct pm860x_chip *chip = i2c_get_clientdata(client);
-
-       if (device_may_wakeup(dev) && chip->wakeup_flag)
-               disable_irq_wake(chip->core_irq);
-       return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(pm860x_pm_ops, pm860x_suspend, pm860x_resume);
-
-static struct i2c_driver pm860x_driver = {
-       .driver = {
-               .name   = "88PM860x",
-               .owner  = THIS_MODULE,
-               .pm     = &pm860x_pm_ops,
-       },
-       .probe          = pm860x_probe,
-       .remove         = __devexit_p(pm860x_remove),
-       .id_table       = pm860x_id_table,
-};
-
-static int __init pm860x_i2c_init(void)
-{
-       int ret;
-       ret = i2c_add_driver(&pm860x_driver);
-       if (ret != 0)
-               pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
-       return ret;
-}
-subsys_initcall(pm860x_i2c_init);
-
-static void __exit pm860x_i2c_exit(void)
-{
-       i2c_del_driver(&pm860x_driver);
-}
-module_exit(pm860x_i2c_exit);
-
-MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_LICENSE("GPL");
index b1a146205c0862587aa81a4a6b32dd7b19322152..acab3ef8a310efb611ccb30868c7f85474807d86 100644 (file)
@@ -298,16 +298,6 @@ config MFD_TWL4030_AUDIO
        select MFD_CORE
        default n
 
-config TWL6030_PWM
-       tristate "TWL6030 PWM (Pulse Width Modulator) Support"
-       depends on TWL4030_CORE
-       select HAVE_PWM
-       depends on !PWM
-       default n
-       help
-         Say yes here if you want support for TWL6030 PWM.
-         This is used to control charging LED brightness.
-
 config TWL6040_CORE
        bool "Support for TWL6040 audio codec"
        depends on I2C=y && GENERIC_HARDIRQS
@@ -385,6 +375,18 @@ config MFD_T7L66XB
        help
          Support for Toshiba Mobile IO Controller T7L66XB
 
+config MFD_SMSC
+       bool "Support for the SMSC ECE1099 series chips"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+        If you say yes here you get support for the
+        ece1099 chips from SMSC.
+
+        To compile this driver as a module, choose M here: the
+        module will be called smsc.
+
 config MFD_TC6387XB
        bool "Support Toshiba TC6387XB"
        depends on ARM && HAVE_CLK
@@ -441,6 +443,23 @@ config MFD_DA9052_I2C
          for accessing the device, additional drivers must be enabled in
          order to use the functionality of the device.
 
+config MFD_DA9055
+       bool "Dialog Semiconductor DA9055 PMIC Support"
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select PMIC_DA9055
+       select MFD_CORE
+       depends on I2C=y
+       help
+         Say yes here for support of Dialog Semiconductor DA9055. This is
+         a Power Management IC. This driver provides common support for
+         accessing the device as well as the I2C interface to the chip itself.
+         Additional drivers must be enabled in order to use the functionality
+         of the device.
+
+         This driver can be built as a module. If built as a module it will be
+         called "da9055"
+
 config PMIC_ADP5520
        bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
        depends on I2C=y
@@ -451,6 +470,16 @@ config PMIC_ADP5520
          individual components like LCD backlight, LEDs, GPIOs and Kepad
          under the corresponding menus.
 
+config MFD_LP8788
+       bool "Texas Instruments LP8788 Power Management Unit Driver"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select IRQ_DOMAIN
+       help
+         TI LP8788 PMU supports regulators, battery charger, RTC,
+         ADC, backlight driver and current sinks.
+
 config MFD_MAX77686
        bool "Maxim Semiconductor MAX77686 PMIC Support"
        depends on I2C=y && GENERIC_HARDIRQS
@@ -477,6 +506,18 @@ config MFD_MAX77693
          additional drivers must be enabled in order to use the functionality
          of the device.
 
+config MFD_MAX8907
+       tristate "Maxim Semiconductor MAX8907 PMIC Support"
+       select MFD_CORE
+       depends on I2C=y && GENERIC_HARDIRQS
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       help
+         Say yes here to support for Maxim Semiconductor MAX8907. This is
+         a Power Management IC. This driver provides common support for
+         accessing the device; additional drivers must be enabled in order
+         to use the functionality of the device.
+
 config MFD_MAX8925
        bool "Maxim Semiconductor MAX8925 PMIC Support"
        depends on I2C=y && GENERIC_HARDIRQS
@@ -896,7 +937,7 @@ config MFD_WL1273_CORE
          audio codec.
 
 config MFD_OMAP_USB_HOST
-       bool "Support OMAP USBHS core driver"
+       bool "Support OMAP USBHS core and TLL driver"
        depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
        default y
        help
@@ -985,13 +1026,13 @@ config MFD_STA2X11
        depends on STA2X11
        select MFD_CORE
 
-config MFD_ANATOP
-       bool "Support for Freescale i.MX on-chip ANATOP controller"
-       depends on SOC_IMX6Q
+config MFD_SYSCON
+       bool "System Controller Register R/W Based on Regmap"
+       depends on OF
+       select REGMAP_MMIO
        help
-         Select this option to enable Freescale i.MX on-chip ANATOP
-         MFD controller. This controller embeds regulator and
-         thermal devices for Freescale i.MX platforms.
+         Select this option to enable accessing system control registers
+         via regmap.
 
 config MFD_PALMAS
        bool "Support for the TI Palmas series chips"
index 79dd22d1dc3d16d68232047b843464e0b743b4b0..d8ccb630ddb07f6fbdf821661181f2c5fe67bbce 100644 (file)
@@ -63,7 +63,6 @@ obj-$(CONFIG_TWL4030_CORE)    += twl-core.o twl4030-irq.o twl6030-irq.o
 obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_MFD_TWL4030_AUDIO)        += twl4030-audio.o
-obj-$(CONFIG_TWL6030_PWM)      += twl6030-pwm.o
 obj-$(CONFIG_TWL6040_CORE)     += twl6040-core.o twl6040-irq.o
 
 obj-$(CONFIG_MFD_MC13XXX)      += mc13xxx-core.o
@@ -77,6 +76,7 @@ obj-$(CONFIG_EZX_PCAP)                += ezx-pcap.o
 obj-$(CONFIG_MCP)              += mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
+obj-$(CONFIG_MFD_SMSC)        += smsc-ece1099.o
 obj-$(CONFIG_MCP_UCB1200_TS)   += ucb1x00-ts.o
 
 ifeq ($(CONFIG_SA1100_ASSABET),y)
@@ -90,8 +90,14 @@ obj-$(CONFIG_PMIC_DA9052)    += da9052-core.o
 obj-$(CONFIG_MFD_DA9052_SPI)   += da9052-spi.o
 obj-$(CONFIG_MFD_DA9052_I2C)   += da9052-i2c.o
 
+obj-$(CONFIG_MFD_LP8788)       += lp8788.o lp8788-irq.o
+
+da9055-objs                    := da9055-core.o da9055-i2c.o
+obj-$(CONFIG_MFD_DA9055)       += da9055.o
+
 obj-$(CONFIG_MFD_MAX77686)     += max77686.o max77686-irq.o
 obj-$(CONFIG_MFD_MAX77693)     += max77693.o max77693-irq.o
+obj-$(CONFIG_MFD_MAX8907)      += max8907.o
 max8925-objs                   := max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)      += max8925.o
 obj-$(CONFIG_MFD_MAX8997)      += max8997.o max8997-irq.o
@@ -120,7 +126,7 @@ obj-$(CONFIG_MFD_TPS6586X)  += tps6586x.o
 obj-$(CONFIG_MFD_VX855)                += vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)  += wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)       += cs5535-mfd.o
-obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o
+obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
@@ -130,5 +136,5 @@ obj-$(CONFIG_MFD_INTEL_MSIC)        += intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)       += palmas.o
 obj-$(CONFIG_MFD_RC5T583)      += rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)     += sec-core.o sec-irq.o
-obj-$(CONFIG_MFD_ANATOP)       += anatop-mfd.o
+obj-$(CONFIG_MFD_SYSCON)       += syscon.o
 obj-$(CONFIG_MFD_LM3533)       += lm3533-core.o lm3533-ctrlbank.o
index 01781ae5d0d7f3de38c811dad727ecc179c94be7..2b3dde571a508c92ca9227b1c7e70f6c43482b14 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/core.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/mfd/abx500.h>
 
 /* These are the only registers inside AB3100 used in this main file */
index 47adf800024e01f8cdf05856eb3b356226c527f3..1667c77b5cdef73d48923f4c7ce6ac614c39b681 100644 (file)
@@ -472,6 +472,22 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+/**
+ * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
+ *
+ * @ab8500: ab8500_irq controller to operate on.
+ * @irq: index of the interrupt requested in the chip IRQs
+ *
+ * Useful for drivers to request their own IRQs.
+ */
+static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
+{
+       if (!ab8500)
+               return -EINVAL;
+
+       return irq_create_mapping(ab8500->domain, irq);
+}
+
 static irqreturn_t ab8500_irq(int irq, void *dev)
 {
        struct ab8500 *ab8500 = dev;
@@ -501,8 +517,9 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
                do {
                        int bit = __ffs(value);
                        int line = i * 8 + bit;
+                       int virq = ab8500_irq_get_virq(ab8500, line);
 
-                       handle_nested_irq(ab8500->irq_base + line);
+                       handle_nested_irq(virq);
                        value &= ~(1 << bit);
 
                } while (value);
@@ -511,23 +528,6 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-/**
- * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
- *
- * @ab8500: ab8500_irq controller to operate on.
- * @irq: index of the interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
-{
-       if (!ab8500)
-               return -EINVAL;
-
-       return irq_create_mapping(ab8500->domain, irq);
-}
-EXPORT_SYMBOL_GPL(ab8500_irq_get_virq);
-
 static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
                                irq_hw_number_t hwirq)
 {
@@ -1076,6 +1076,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
        },
        {
                .name = "ab8500-codec",
+               .of_compatible = "stericsson,ab8500-codec",
        },
 };
 
diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c
deleted file mode 100644 (file)
index 5576e07..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Anatop MFD driver
- *
- * Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
- * Copyright (C) 2012 Linaro
- *
- *  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.
- *  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 <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/mfd/anatop.h>
-
-u32 anatop_read_reg(struct anatop *adata, u32 addr)
-{
-       return readl(adata->ioreg + addr);
-}
-EXPORT_SYMBOL_GPL(anatop_read_reg);
-
-void anatop_write_reg(struct anatop *adata, u32 addr, u32 data, u32 mask)
-{
-       u32 val;
-
-       data &= mask;
-
-       spin_lock(&adata->reglock);
-       val = readl(adata->ioreg + addr);
-       val &= ~mask;
-       val |= data;
-       writel(val, adata->ioreg + addr);
-       spin_unlock(&adata->reglock);
-}
-EXPORT_SYMBOL_GPL(anatop_write_reg);
-
-static const struct of_device_id of_anatop_match[] = {
-       { .compatible = "fsl,imx6q-anatop", },
-       { },
-};
-
-static int __devinit of_anatop_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
-       void *ioreg;
-       struct anatop *drvdata;
-
-       ioreg = of_iomap(np, 0);
-       if (!ioreg)
-               return -EADDRNOTAVAIL;
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-       drvdata->ioreg = ioreg;
-       spin_lock_init(&drvdata->reglock);
-       platform_set_drvdata(pdev, drvdata);
-       of_platform_populate(np, NULL, NULL, dev);
-
-       return 0;
-}
-
-static int __devexit of_anatop_remove(struct platform_device *pdev)
-{
-       struct anatop *drvdata;
-       drvdata = platform_get_drvdata(pdev);
-       iounmap(drvdata->ioreg);
-
-       return 0;
-}
-
-static struct platform_driver anatop_of_driver = {
-       .driver = {
-               .name = "anatop-mfd",
-               .owner = THIS_MODULE,
-               .of_match_table = of_anatop_match,
-       },
-       .probe          = of_anatop_probe,
-       .remove         = of_anatop_remove,
-};
-
-static int __init anatop_init(void)
-{
-       return platform_driver_register(&anatop_of_driver);
-}
-postcore_initcall(anatop_init);
-
-static void __exit anatop_exit(void)
-{
-       platform_driver_unregister(&anatop_of_driver);
-}
-module_exit(anatop_exit);
-
-MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
-MODULE_DESCRIPTION("ANATOP MFD driver");
-MODULE_LICENSE("GPL v2");
index 98ac345f468e23517d904a80ea6035933bac8c9c..ef0f2d001df20524695906c42993b368d9fa8a81 100644 (file)
@@ -94,7 +94,8 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
 static irqreturn_t arizona_irq_thread(int irq, void *data)
 {
        struct arizona *arizona = data;
-       int i, ret;
+       unsigned int val;
+       int ret;
 
        ret = pm_runtime_get_sync(arizona->dev);
        if (ret < 0) {
@@ -102,9 +103,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
                return IRQ_NONE;
        }
 
-       /* Check both domains */
-       for (i = 0; i < 2; i++)
-               handle_nested_irq(irq_find_mapping(arizona->virq, i));
+       /* Always handle the AoD domain */
+       handle_nested_irq(irq_find_mapping(arizona->virq, 0));
+
+       /*
+        * Check if one of the main interrupts is asserted and only
+        * check that domain if it is.
+        */
+       ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS, &val);
+       if (ret == 0 && val & ARIZONA_IRQ1_STS) {
+               handle_nested_irq(irq_find_mapping(arizona->virq, 1));
+       } else if (ret != 0) {
+               dev_err(arizona->dev, "Failed to read main IRQ status: %d\n",
+                       ret);
+       }
 
        pm_runtime_mark_last_busy(arizona->dev);
        pm_runtime_put_autosuspend(arizona->dev);
@@ -156,18 +168,36 @@ int arizona_irq_init(struct arizona *arizona)
        int flags = IRQF_ONESHOT;
        int ret, i;
        const struct regmap_irq_chip *aod, *irq;
+       bool ctrlif_error = true;
 
        switch (arizona->type) {
 #ifdef CONFIG_MFD_WM5102
        case WM5102:
                aod = &wm5102_aod;
                irq = &wm5102_irq;
+
+               switch (arizona->rev) {
+               case 0:
+                       ctrlif_error = false;
+                       break;
+               default:
+                       break;
+               }
                break;
 #endif
 #ifdef CONFIG_MFD_WM5110
        case WM5110:
                aod = &wm5110_aod;
                irq = &wm5110_irq;
+
+               switch (arizona->rev) {
+               case 0:
+               case 1:
+                       ctrlif_error = false;
+                       break;
+               default:
+                       break;
+               }
                break;
 #endif
        default:
@@ -226,13 +256,17 @@ int arizona_irq_init(struct arizona *arizona)
        }
 
        /* Handle control interface errors in the core */
-       i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
-       ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT,
-                                  "Control interface error", arizona);
-       if (ret != 0) {
-               dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
-                       arizona->irq, ret);
-               goto err_ctrlif;
+       if (ctrlif_error) {
+               i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
+               ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
+                                          IRQF_ONESHOT,
+                                          "Control interface error", arizona);
+               if (ret != 0) {
+                       dev_err(arizona->dev,
+                               "Failed to request CTRLIF_ERR %d: %d\n",
+                               arizona->irq, ret);
+                       goto err_ctrlif;
+               }
        }
 
        ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
new file mode 100644 (file)
index 0000000..ff6c77f
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Device access for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.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/device.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/pdata.h>
+#include <linux/mfd/da9055/reg.h>
+
+#define DA9055_IRQ_NONKEY_MASK         0x01
+#define DA9055_IRQ_ALM_MASK            0x02
+#define DA9055_IRQ_TICK_MASK           0x04
+#define DA9055_IRQ_ADC_MASK            0x08
+#define DA9055_IRQ_BUCK_ILIM_MASK      0x08
+
+static bool da9055_register_readable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case DA9055_REG_STATUS_A:
+       case DA9055_REG_STATUS_B:
+       case DA9055_REG_EVENT_A:
+       case DA9055_REG_EVENT_B:
+       case DA9055_REG_EVENT_C:
+       case DA9055_REG_IRQ_MASK_A:
+       case DA9055_REG_IRQ_MASK_B:
+       case DA9055_REG_IRQ_MASK_C:
+
+       case DA9055_REG_CONTROL_A:
+       case DA9055_REG_CONTROL_B:
+       case DA9055_REG_CONTROL_C:
+       case DA9055_REG_CONTROL_D:
+       case DA9055_REG_CONTROL_E:
+
+       case DA9055_REG_ADC_MAN:
+       case DA9055_REG_ADC_CONT:
+       case DA9055_REG_VSYS_MON:
+       case DA9055_REG_ADC_RES_L:
+       case DA9055_REG_ADC_RES_H:
+       case DA9055_REG_VSYS_RES:
+       case DA9055_REG_ADCIN1_RES:
+       case DA9055_REG_ADCIN2_RES:
+       case DA9055_REG_ADCIN3_RES:
+
+       case DA9055_REG_COUNT_S:
+       case DA9055_REG_COUNT_MI:
+       case DA9055_REG_COUNT_H:
+       case DA9055_REG_COUNT_D:
+       case DA9055_REG_COUNT_MO:
+       case DA9055_REG_COUNT_Y:
+       case DA9055_REG_ALARM_H:
+       case DA9055_REG_ALARM_D:
+       case DA9055_REG_ALARM_MI:
+       case DA9055_REG_ALARM_MO:
+       case DA9055_REG_ALARM_Y:
+
+       case DA9055_REG_GPIO0_1:
+       case DA9055_REG_GPIO2:
+       case DA9055_REG_GPIO_MODE0_2:
+
+       case DA9055_REG_BCORE_CONT:
+       case DA9055_REG_BMEM_CONT:
+       case DA9055_REG_LDO1_CONT:
+       case DA9055_REG_LDO2_CONT:
+       case DA9055_REG_LDO3_CONT:
+       case DA9055_REG_LDO4_CONT:
+       case DA9055_REG_LDO5_CONT:
+       case DA9055_REG_LDO6_CONT:
+       case DA9055_REG_BUCK_LIM:
+       case DA9055_REG_BCORE_MODE:
+       case DA9055_REG_VBCORE_A:
+       case DA9055_REG_VBMEM_A:
+       case DA9055_REG_VLDO1_A:
+       case DA9055_REG_VLDO2_A:
+       case DA9055_REG_VLDO3_A:
+       case DA9055_REG_VLDO4_A:
+       case DA9055_REG_VLDO5_A:
+       case DA9055_REG_VLDO6_A:
+       case DA9055_REG_VBCORE_B:
+       case DA9055_REG_VBMEM_B:
+       case DA9055_REG_VLDO1_B:
+       case DA9055_REG_VLDO2_B:
+       case DA9055_REG_VLDO3_B:
+       case DA9055_REG_VLDO4_B:
+       case DA9055_REG_VLDO5_B:
+       case DA9055_REG_VLDO6_B:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool da9055_register_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case DA9055_REG_STATUS_A:
+       case DA9055_REG_STATUS_B:
+       case DA9055_REG_EVENT_A:
+       case DA9055_REG_EVENT_B:
+       case DA9055_REG_EVENT_C:
+       case DA9055_REG_IRQ_MASK_A:
+       case DA9055_REG_IRQ_MASK_B:
+       case DA9055_REG_IRQ_MASK_C:
+
+       case DA9055_REG_CONTROL_A:
+       case DA9055_REG_CONTROL_B:
+       case DA9055_REG_CONTROL_C:
+       case DA9055_REG_CONTROL_D:
+       case DA9055_REG_CONTROL_E:
+
+       case DA9055_REG_ADC_MAN:
+       case DA9055_REG_ADC_CONT:
+       case DA9055_REG_VSYS_MON:
+       case DA9055_REG_ADC_RES_L:
+       case DA9055_REG_ADC_RES_H:
+       case DA9055_REG_VSYS_RES:
+       case DA9055_REG_ADCIN1_RES:
+       case DA9055_REG_ADCIN2_RES:
+       case DA9055_REG_ADCIN3_RES:
+
+       case DA9055_REG_COUNT_S:
+       case DA9055_REG_COUNT_MI:
+       case DA9055_REG_COUNT_H:
+       case DA9055_REG_COUNT_D:
+       case DA9055_REG_COUNT_MO:
+       case DA9055_REG_COUNT_Y:
+       case DA9055_REG_ALARM_H:
+       case DA9055_REG_ALARM_D:
+       case DA9055_REG_ALARM_MI:
+       case DA9055_REG_ALARM_MO:
+       case DA9055_REG_ALARM_Y:
+
+       case DA9055_REG_GPIO0_1:
+       case DA9055_REG_GPIO2:
+       case DA9055_REG_GPIO_MODE0_2:
+
+       case DA9055_REG_BCORE_CONT:
+       case DA9055_REG_BMEM_CONT:
+       case DA9055_REG_LDO1_CONT:
+       case DA9055_REG_LDO2_CONT:
+       case DA9055_REG_LDO3_CONT:
+       case DA9055_REG_LDO4_CONT:
+       case DA9055_REG_LDO5_CONT:
+       case DA9055_REG_LDO6_CONT:
+       case DA9055_REG_BUCK_LIM:
+       case DA9055_REG_BCORE_MODE:
+       case DA9055_REG_VBCORE_A:
+       case DA9055_REG_VBMEM_A:
+       case DA9055_REG_VLDO1_A:
+       case DA9055_REG_VLDO2_A:
+       case DA9055_REG_VLDO3_A:
+       case DA9055_REG_VLDO4_A:
+       case DA9055_REG_VLDO5_A:
+       case DA9055_REG_VLDO6_A:
+       case DA9055_REG_VBCORE_B:
+       case DA9055_REG_VBMEM_B:
+       case DA9055_REG_VLDO1_B:
+       case DA9055_REG_VLDO2_B:
+       case DA9055_REG_VLDO3_B:
+       case DA9055_REG_VLDO4_B:
+       case DA9055_REG_VLDO5_B:
+       case DA9055_REG_VLDO6_B:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool da9055_register_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case DA9055_REG_STATUS_A:
+       case DA9055_REG_STATUS_B:
+       case DA9055_REG_EVENT_A:
+       case DA9055_REG_EVENT_B:
+       case DA9055_REG_EVENT_C:
+
+       case DA9055_REG_CONTROL_A:
+       case DA9055_REG_CONTROL_E:
+
+       case DA9055_REG_ADC_MAN:
+       case DA9055_REG_ADC_RES_L:
+       case DA9055_REG_ADC_RES_H:
+       case DA9055_REG_VSYS_RES:
+       case DA9055_REG_ADCIN1_RES:
+       case DA9055_REG_ADCIN2_RES:
+       case DA9055_REG_ADCIN3_RES:
+
+       case DA9055_REG_COUNT_S:
+       case DA9055_REG_COUNT_MI:
+       case DA9055_REG_COUNT_H:
+       case DA9055_REG_COUNT_D:
+       case DA9055_REG_COUNT_MO:
+       case DA9055_REG_COUNT_Y:
+       case DA9055_REG_ALARM_MI:
+
+       case DA9055_REG_BCORE_CONT:
+       case DA9055_REG_BMEM_CONT:
+       case DA9055_REG_LDO1_CONT:
+       case DA9055_REG_LDO2_CONT:
+       case DA9055_REG_LDO3_CONT:
+       case DA9055_REG_LDO4_CONT:
+       case DA9055_REG_LDO5_CONT:
+       case DA9055_REG_LDO6_CONT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static struct regmap_irq da9055_irqs[] = {
+       [DA9055_IRQ_NONKEY] = {
+               .reg_offset = 0,
+               .mask = DA9055_IRQ_NONKEY_MASK,
+       },
+       [DA9055_IRQ_ALARM] = {
+               .reg_offset = 0,
+               .mask = DA9055_IRQ_ALM_MASK,
+       },
+       [DA9055_IRQ_TICK] = {
+               .reg_offset = 0,
+               .mask = DA9055_IRQ_TICK_MASK,
+       },
+       [DA9055_IRQ_HWMON] = {
+               .reg_offset = 0,
+               .mask = DA9055_IRQ_ADC_MASK,
+       },
+       [DA9055_IRQ_REGULATOR] = {
+               .reg_offset = 1,
+               .mask = DA9055_IRQ_BUCK_ILIM_MASK,
+       },
+};
+
+struct regmap_config da9055_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .cache_type = REGCACHE_RBTREE,
+
+       .max_register = DA9055_MAX_REGISTER_CNT,
+       .readable_reg = da9055_register_readable,
+       .writeable_reg = da9055_register_writeable,
+       .volatile_reg = da9055_register_volatile,
+};
+EXPORT_SYMBOL_GPL(da9055_regmap_config);
+
+static struct resource da9055_onkey_resource = {
+       .name = "ONKEY",
+       .start = DA9055_IRQ_NONKEY,
+       .end   = DA9055_IRQ_NONKEY,
+       .flags = IORESOURCE_IRQ,
+};
+
+static struct resource da9055_rtc_resource[] = {
+       {
+               .name = "ALM",
+               .start = DA9055_IRQ_ALARM,
+               .end   = DA9055_IRQ_ALARM,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "TICK",
+               .start = DA9055_IRQ_TICK,
+               .end   = DA9055_IRQ_TICK,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource da9055_hwmon_resource = {
+       .name = "HWMON",
+       .start = DA9055_IRQ_HWMON,
+       .end   = DA9055_IRQ_HWMON,
+       .flags = IORESOURCE_IRQ,
+};
+
+static struct resource da9055_ld05_6_resource = {
+       .name = "REGULATOR",
+       .start = DA9055_IRQ_REGULATOR,
+       .end   = DA9055_IRQ_REGULATOR,
+       .flags = IORESOURCE_IRQ,
+};
+
+static struct mfd_cell da9055_devs[] = {
+       {
+               .of_compatible = "dialog,da9055-gpio",
+               .name = "da9055-gpio",
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 1,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 2,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 3,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 4,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 5,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 6,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .id = 7,
+               .resources = &da9055_ld05_6_resource,
+               .num_resources = 1,
+       },
+       {
+               .of_compatible = "dialog,da9055-regulator",
+               .name = "da9055-regulator",
+               .resources = &da9055_ld05_6_resource,
+               .num_resources = 1,
+               .id = 8,
+       },
+       {
+               .of_compatible = "dialog,da9055-onkey",
+               .name = "da9055-onkey",
+               .resources = &da9055_onkey_resource,
+               .num_resources = 1,
+       },
+       {
+               .of_compatible = "dialog,da9055-rtc",
+               .name = "da9055-rtc",
+               .resources = da9055_rtc_resource,
+               .num_resources = ARRAY_SIZE(da9055_rtc_resource),
+       },
+       {
+               .of_compatible = "dialog,da9055-hwmon",
+               .name = "da9055-hwmon",
+               .resources = &da9055_hwmon_resource,
+               .num_resources = 1,
+       },
+       {
+               .of_compatible = "dialog,da9055-watchdog",
+               .name = "da9055-watchdog",
+       },
+};
+
+static struct regmap_irq_chip da9055_regmap_irq_chip = {
+       .name = "da9055_irq",
+       .status_base = DA9055_REG_EVENT_A,
+       .mask_base = DA9055_REG_IRQ_MASK_A,
+       .ack_base = DA9055_REG_EVENT_A,
+       .num_regs = 3,
+       .irqs = da9055_irqs,
+       .num_irqs = ARRAY_SIZE(da9055_irqs),
+};
+
+int __devinit da9055_device_init(struct da9055 *da9055)
+{
+       struct da9055_pdata *pdata = da9055->dev->platform_data;
+       int ret;
+
+       if (pdata && pdata->init != NULL)
+               pdata->init(da9055);
+
+       if (!pdata || !pdata->irq_base)
+               da9055->irq_base = -1;
+       else
+               da9055->irq_base = pdata->irq_base;
+
+       ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
+                                 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                 da9055->irq_base, &da9055_regmap_irq_chip,
+                                 &da9055->irq_data);
+       if (ret < 0)
+               return ret;
+
+       da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
+
+       ret = mfd_add_devices(da9055->dev, -1,
+                             da9055_devs, ARRAY_SIZE(da9055_devs),
+                             NULL, da9055->irq_base, NULL);
+       if (ret)
+               goto err;
+
+       return 0;
+
+err:
+       mfd_remove_devices(da9055->dev);
+       return ret;
+}
+
+void __devexit da9055_device_exit(struct da9055 *da9055)
+{
+       regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
+       mfd_remove_devices(da9055->dev);
+}
+
+MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
new file mode 100644 (file)
index 0000000..88f6dca
--- /dev/null
@@ -0,0 +1,93 @@
+ /* I2C access for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.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/device.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+
+#include <linux/mfd/da9055/core.h>
+
+static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct da9055 *da9055;
+       int ret;
+
+       da9055 = devm_kzalloc(&i2c->dev, sizeof(struct da9055), GFP_KERNEL);
+       if (!da9055)
+               return -ENOMEM;
+
+       da9055->regmap = devm_regmap_init_i2c(i2c, &da9055_regmap_config);
+       if (IS_ERR(da9055->regmap)) {
+               ret = PTR_ERR(da9055->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
+       da9055->dev = &i2c->dev;
+       da9055->chip_irq = i2c->irq;
+
+       i2c_set_clientdata(i2c, da9055);
+
+       return da9055_device_init(da9055);
+}
+
+static int __devexit da9055_i2c_remove(struct i2c_client *i2c)
+{
+       struct da9055 *da9055 = i2c_get_clientdata(i2c);
+
+       da9055_device_exit(da9055);
+
+       return 0;
+}
+
+static struct i2c_device_id da9055_i2c_id[] = {
+       {"da9055-pmic", 0},
+       { }
+};
+
+static struct i2c_driver da9055_i2c_driver = {
+       .probe = da9055_i2c_probe,
+       .remove = __devexit_p(da9055_i2c_remove),
+       .id_table = da9055_i2c_id,
+       .driver = {
+               .name = "da9055",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init da9055_i2c_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&da9055_i2c_driver);
+       if (ret != 0) {
+               pr_err("DA9055 I2C registration failed %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+subsys_initcall(da9055_i2c_init);
+
+static void __exit da9055_i2c_exit(void)
+{
+       i2c_del_driver(&da9055_i2c_driver);
+}
+module_exit(da9055_i2c_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("I2C driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
index 6b67edbdbd013e5531527aa3a7316362009e4f4e..00b8b0f3dfb6c998676958be96972476aa7773f3 100644 (file)
@@ -270,6 +270,8 @@ static struct {
        struct prcmu_fw_version version;
 } fw_info;
 
+static struct irq_domain *db8500_irq_domain;
+
 /*
  * This vector maps irq numbers to the bits in the bit field used in
  * communication with the PRCMU firmware.
@@ -2624,7 +2626,7 @@ static void prcmu_irq_mask(struct irq_data *d)
 
        spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 
-       mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE];
+       mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
 
        spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 
@@ -2638,7 +2640,7 @@ static void prcmu_irq_unmask(struct irq_data *d)
 
        spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
 
-       mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_PRCMU_BASE];
+       mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
 
        spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
 
@@ -2678,9 +2680,37 @@ static char *fw_project_name(u8 project)
        }
 }
 
+static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
+                               irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(virq, &prcmu_irq_chip,
+                               handle_simple_irq);
+       set_irq_flags(virq, IRQF_VALID);
+
+       return 0;
+}
+
+static struct irq_domain_ops db8500_irq_ops = {
+        .map    = db8500_irq_map,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int db8500_irq_init(struct device_node *np)
+{
+       db8500_irq_domain = irq_domain_add_legacy(
+               np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE,
+               0, &db8500_irq_ops, NULL);
+
+       if (!db8500_irq_domain) {
+               pr_err("Failed to create irqdomain\n");
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
 void __init db8500_prcmu_early_init(void)
 {
-       unsigned int i;
        if (cpu_is_u8500v2()) {
                void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 
@@ -2725,15 +2755,6 @@ void __init db8500_prcmu_early_init(void)
 
        INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 
-       /* Initalize irqs. */
-       for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) {
-               unsigned int irq;
-
-               irq = IRQ_PRCMU_BASE + i;
-               irq_set_chip_and_handler(irq, &prcmu_irq_chip,
-                                        handle_simple_irq);
-               set_irq_flags(irq, IRQF_VALID);
-       }
        compute_armss_rate();
 }
 
@@ -3041,6 +3062,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
                goto no_irq_return;
        }
 
+       db8500_irq_init(np);
+
        for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
                if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
                        db8500_prcmu_devs[i].platform_data = ab8500_platdata;
diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c
new file mode 100644 (file)
index 0000000..c84ded5
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * TI LP8788 MFD - interrupt handler
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.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 <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/device.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+/* register address */
+#define LP8788_INT_1                   0x00
+#define LP8788_INTEN_1                 0x03
+
+#define BASE_INTEN_ADDR                        LP8788_INTEN_1
+#define SIZE_REG                       8
+#define NUM_REGS                       3
+
+/*
+ * struct lp8788_irq_data
+ * @lp               : used for accessing to lp8788 registers
+ * @irq_lock         : mutex for enabling/disabling the interrupt
+ * @domain           : IRQ domain for handling nested interrupt
+ * @enabled          : status of enabled interrupt
+ */
+struct lp8788_irq_data {
+       struct lp8788 *lp;
+       struct mutex irq_lock;
+       struct irq_domain *domain;
+       int enabled[LP8788_INT_MAX];
+};
+
+static inline u8 _irq_to_addr(enum lp8788_int_id id)
+{
+       return id / SIZE_REG;
+}
+
+static inline u8 _irq_to_enable_addr(enum lp8788_int_id id)
+{
+       return _irq_to_addr(id) + BASE_INTEN_ADDR;
+}
+
+static inline u8 _irq_to_mask(enum lp8788_int_id id)
+{
+       return 1 << (id % SIZE_REG);
+}
+
+static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
+{
+       return enable << (id % SIZE_REG);
+}
+
+static void lp8788_irq_enable(struct irq_data *data)
+{
+       struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+       irqd->enabled[data->hwirq] = 1;
+}
+
+static void lp8788_irq_disable(struct irq_data *data)
+{
+       struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+       irqd->enabled[data->hwirq] = 0;
+}
+
+static void lp8788_irq_bus_lock(struct irq_data *data)
+{
+       struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&irqd->irq_lock);
+}
+
+static void lp8788_irq_bus_sync_unlock(struct irq_data *data)
+{
+       struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
+       enum lp8788_int_id irq = data->hwirq;
+       u8 addr, mask, val;
+
+       addr = _irq_to_enable_addr(irq);
+       mask = _irq_to_mask(irq);
+       val = _irq_to_val(irq, irqd->enabled[irq]);
+
+       lp8788_update_bits(irqd->lp, addr, mask, val);
+
+       mutex_unlock(&irqd->irq_lock);
+}
+
+static struct irq_chip lp8788_irq_chip = {
+       .name                   = "lp8788",
+       .irq_enable             = lp8788_irq_enable,
+       .irq_disable            = lp8788_irq_disable,
+       .irq_bus_lock           = lp8788_irq_bus_lock,
+       .irq_bus_sync_unlock    = lp8788_irq_bus_sync_unlock,
+};
+
+static irqreturn_t lp8788_irq_handler(int irq, void *ptr)
+{
+       struct lp8788_irq_data *irqd = ptr;
+       struct lp8788 *lp = irqd->lp;
+       u8 status[NUM_REGS], addr, mask;
+       bool handled;
+       int i;
+
+       if (lp8788_read_multi_bytes(lp, LP8788_INT_1, status, NUM_REGS))
+               return IRQ_NONE;
+
+       for (i = 0 ; i < LP8788_INT_MAX ; i++) {
+               addr = _irq_to_addr(i);
+               mask = _irq_to_mask(i);
+
+               /* reporting only if the irq is enabled */
+               if (status[addr] & mask) {
+                       handle_nested_irq(irq_find_mapping(irqd->domain, i));
+                       handled = true;
+               }
+       }
+
+       return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int lp8788_irq_map(struct irq_domain *d, unsigned int virq,
+                       irq_hw_number_t hwirq)
+{
+       struct lp8788_irq_data *irqd = d->host_data;
+       struct irq_chip *chip = &lp8788_irq_chip;
+
+       irq_set_chip_data(virq, irqd);
+       irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+       irq_set_nested_thread(virq, 1);
+
+#ifdef CONFIG_ARM
+       set_irq_flags(virq, IRQF_VALID);
+#else
+       irq_set_noprobe(virq);
+#endif
+
+       return 0;
+}
+
+static struct irq_domain_ops lp8788_domain_ops = {
+       .map = lp8788_irq_map,
+};
+
+int lp8788_irq_init(struct lp8788 *lp, int irq)
+{
+       struct lp8788_irq_data *irqd;
+       int ret;
+
+       if (irq <= 0) {
+               dev_warn(lp->dev, "invalid irq number: %d\n", irq);
+               return 0;
+       }
+
+       irqd = devm_kzalloc(lp->dev, sizeof(*irqd), GFP_KERNEL);
+       if (!irqd)
+               return -ENOMEM;
+
+       irqd->lp = lp;
+       irqd->domain = irq_domain_add_linear(lp->dev->of_node, LP8788_INT_MAX,
+                                       &lp8788_domain_ops, irqd);
+       if (!irqd->domain) {
+               dev_err(lp->dev, "failed to add irq domain err\n");
+               return -EINVAL;
+       }
+
+       lp->irqdm = irqd->domain;
+       mutex_init(&irqd->irq_lock);
+
+       ret = request_threaded_irq(irq, NULL, lp8788_irq_handler,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                               "lp8788-irq", irqd);
+       if (ret) {
+               dev_err(lp->dev, "failed to create a thread for IRQ_N\n");
+               return ret;
+       }
+
+       lp->irq = irq;
+
+       return 0;
+}
+
+void lp8788_irq_exit(struct lp8788 *lp)
+{
+       if (lp->irq)
+               free_irq(lp->irq, lp->irqdm);
+}
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
new file mode 100644 (file)
index 0000000..3e94a69
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * TI LP8788 MFD - core interface
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.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 <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#define MAX_LP8788_REGISTERS           0xA2
+
+#define MFD_DEV_SIMPLE(_name)                                  \
+{                                                              \
+       .name = LP8788_DEV_##_name,                             \
+}
+
+#define MFD_DEV_WITH_ID(_name, _id)                            \
+{                                                              \
+       .name = LP8788_DEV_##_name,                             \
+       .id = _id,                                              \
+}
+
+#define MFD_DEV_WITH_RESOURCE(_name, _resource, num_resource)  \
+{                                                              \
+       .name = LP8788_DEV_##_name,                             \
+       .resources = _resource,                                 \
+       .num_resources = num_resource,                          \
+}
+
+static struct resource chg_irqs[] = {
+       /* Charger Interrupts */
+       {
+               .start = LP8788_INT_CHG_INPUT_STATE,
+               .end   = LP8788_INT_PRECHG_TIMEOUT,
+               .name  = LP8788_CHG_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       /* Power Routing Switch Interrupts */
+       {
+               .start = LP8788_INT_ENTER_SYS_SUPPORT,
+               .end   = LP8788_INT_EXIT_SYS_SUPPORT,
+               .name  = LP8788_PRSW_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+       /* Battery Interrupts */
+       {
+               .start = LP8788_INT_BATT_LOW,
+               .end   = LP8788_INT_NO_BATT,
+               .name  = LP8788_BATT_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource rtc_irqs[] = {
+       {
+               .start = LP8788_INT_RTC_ALARM1,
+               .end   = LP8788_INT_RTC_ALARM2,
+               .name  = LP8788_ALM_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct mfd_cell lp8788_devs[] = {
+       /* 4 bucks */
+       MFD_DEV_WITH_ID(BUCK, 1),
+       MFD_DEV_WITH_ID(BUCK, 2),
+       MFD_DEV_WITH_ID(BUCK, 3),
+       MFD_DEV_WITH_ID(BUCK, 4),
+
+       /* 12 digital ldos */
+       MFD_DEV_WITH_ID(DLDO, 1),
+       MFD_DEV_WITH_ID(DLDO, 2),
+       MFD_DEV_WITH_ID(DLDO, 3),
+       MFD_DEV_WITH_ID(DLDO, 4),
+       MFD_DEV_WITH_ID(DLDO, 5),
+       MFD_DEV_WITH_ID(DLDO, 6),
+       MFD_DEV_WITH_ID(DLDO, 7),
+       MFD_DEV_WITH_ID(DLDO, 8),
+       MFD_DEV_WITH_ID(DLDO, 9),
+       MFD_DEV_WITH_ID(DLDO, 10),
+       MFD_DEV_WITH_ID(DLDO, 11),
+       MFD_DEV_WITH_ID(DLDO, 12),
+
+       /* 10 analog ldos */
+       MFD_DEV_WITH_ID(ALDO, 1),
+       MFD_DEV_WITH_ID(ALDO, 2),
+       MFD_DEV_WITH_ID(ALDO, 3),
+       MFD_DEV_WITH_ID(ALDO, 4),
+       MFD_DEV_WITH_ID(ALDO, 5),
+       MFD_DEV_WITH_ID(ALDO, 6),
+       MFD_DEV_WITH_ID(ALDO, 7),
+       MFD_DEV_WITH_ID(ALDO, 8),
+       MFD_DEV_WITH_ID(ALDO, 9),
+       MFD_DEV_WITH_ID(ALDO, 10),
+
+       /* ADC */
+       MFD_DEV_SIMPLE(ADC),
+
+       /* battery charger */
+       MFD_DEV_WITH_RESOURCE(CHARGER, chg_irqs, ARRAY_SIZE(chg_irqs)),
+
+       /* rtc */
+       MFD_DEV_WITH_RESOURCE(RTC, rtc_irqs, ARRAY_SIZE(rtc_irqs)),
+
+       /* backlight */
+       MFD_DEV_SIMPLE(BACKLIGHT),
+
+       /* current sink for vibrator */
+       MFD_DEV_SIMPLE(VIBRATOR),
+
+       /* current sink for keypad LED */
+       MFD_DEV_SIMPLE(KEYLED),
+};
+
+int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data)
+{
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(lp->regmap, reg, &val);
+       if (ret < 0) {
+               dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
+               return ret;
+       }
+
+       *data = (u8)val;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lp8788_read_byte);
+
+int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count)
+{
+       return regmap_bulk_read(lp->regmap, reg, data, count);
+}
+EXPORT_SYMBOL_GPL(lp8788_read_multi_bytes);
+
+int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data)
+{
+       return regmap_write(lp->regmap, reg, data);
+}
+EXPORT_SYMBOL_GPL(lp8788_write_byte);
+
+int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data)
+{
+       return regmap_update_bits(lp->regmap, reg, mask, data);
+}
+EXPORT_SYMBOL_GPL(lp8788_update_bits);
+
+static int lp8788_platform_init(struct lp8788 *lp)
+{
+       struct lp8788_platform_data *pdata = lp->pdata;
+
+       return (pdata && pdata->init_func) ? pdata->init_func(lp) : 0;
+}
+
+static const struct regmap_config lp8788_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX_LP8788_REGISTERS,
+};
+
+static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+       struct lp8788 *lp;
+       struct lp8788_platform_data *pdata = cl->dev.platform_data;
+       int ret;
+
+       lp = devm_kzalloc(&cl->dev, sizeof(struct lp8788), GFP_KERNEL);
+       if (!lp)
+               return -ENOMEM;
+
+       lp->regmap = devm_regmap_init_i2c(cl, &lp8788_regmap_config);
+       if (IS_ERR(lp->regmap)) {
+               ret = PTR_ERR(lp->regmap);
+               dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
+               return ret;
+       }
+
+       lp->pdata = pdata;
+       lp->dev = &cl->dev;
+       i2c_set_clientdata(cl, lp);
+
+       ret = lp8788_platform_init(lp);
+       if (ret)
+               return ret;
+
+       ret = lp8788_irq_init(lp, cl->irq);
+       if (ret)
+               return ret;
+
+       return mfd_add_devices(lp->dev, -1, lp8788_devs,
+                              ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+}
+
+static int __devexit lp8788_remove(struct i2c_client *cl)
+{
+       struct lp8788 *lp = i2c_get_clientdata(cl);
+
+       mfd_remove_devices(lp->dev);
+       lp8788_irq_exit(lp);
+       return 0;
+}
+
+static const struct i2c_device_id lp8788_ids[] = {
+       {"lp8788", 0},
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp8788_ids);
+
+static struct i2c_driver lp8788_driver = {
+       .driver = {
+               .name = "lp8788",
+               .owner = THIS_MODULE,
+       },
+       .probe = lp8788_probe,
+       .remove = __devexit_p(lp8788_remove),
+       .id_table = lp8788_ids,
+};
+
+static int __init lp8788_init(void)
+{
+       return i2c_add_driver(&lp8788_driver);
+}
+subsys_initcall(lp8788_init);
+
+static void __exit lp8788_exit(void)
+{
+       i2c_del_driver(&lp8788_driver);
+}
+module_exit(lp8788_exit);
+
+MODULE_DESCRIPTION("TI LP8788 MFD Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
index 092ad4b44b6d67b9b4ee039fccc73da1748d3a2c..a22544fe53197904f56f0c67f87970ddd727caf5 100644 (file)
@@ -49,6 +49,7 @@
  *     document number TBD : DH89xxCC
  *     document number TBD : Panther Point
  *     document number TBD : Lynx Point
+ *     document number TBD : Lynx Point-LP
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -192,6 +193,7 @@ enum lpc_chipsets {
        LPC_DH89XXCC,   /* DH89xxCC */
        LPC_PPT,        /* Panther Point */
        LPC_LPT,        /* Lynx Point */
+       LPC_LPT_LP,     /* Lynx Point-LP */
 };
 
 struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
@@ -468,6 +470,10 @@ struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
                .name = "Lynx Point",
                .iTCO_version = 2,
        },
+       [LPC_LPT_LP] = {
+               .name = "Lynx Point_LP",
+               .iTCO_version = 2,
+       },
 };
 
 /*
@@ -641,6 +647,14 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
        { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
        { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
+       { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
+       { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
@@ -683,6 +697,30 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
        cell->pdata_size = sizeof(struct lpc_ich_info);
 }
 
+/*
+ * We don't check for resource conflict globally. There are 2 or 3 independent
+ * GPIO groups and it's enough to have access to one of these to instantiate
+ * the device.
+ */
+static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+{
+       int ret;
+       u8 use_gpio = 0;
+
+       if (resource_size(res) >= 0x50 &&
+           !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3"))
+               use_gpio |= 1 << 2;
+
+       if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2"))
+               use_gpio |= 1 << 1;
+
+       ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1");
+       if (!ret)
+               use_gpio |= 1 << 0;
+
+       return use_gpio ? use_gpio : ret;
+}
+
 static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
                                const struct pci_device_id *id)
 {
@@ -740,12 +778,13 @@ gpe0_done:
                break;
        }
 
-       ret = acpi_check_resource_conflict(res);
-       if (ret) {
+       ret = lpc_ich_check_conflict_gpio(res);
+       if (ret < 0) {
                /* this isn't necessarily fatal for the GPIO */
                acpi_conflict = true;
                goto gpio_done;
        }
+       lpc_chipset_info[id->driver_data].use_gpio = ret;
        lpc_ich_enable_gpio_space(dev);
 
        lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
new file mode 100644 (file)
index 0000000..17f2593
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * max8907.c - mfd driver for MAX8907
+ *
+ * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
+ * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max8907.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+static struct mfd_cell max8907_cells[] = {
+       { .name = "max8907-regulator", },
+       { .name = "max8907-rtc", },
+};
+
+static bool max8907_gen_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX8907_REG_ON_OFF_IRQ1:
+       case MAX8907_REG_ON_OFF_STAT:
+       case MAX8907_REG_ON_OFF_IRQ2:
+       case MAX8907_REG_CHG_IRQ1:
+       case MAX8907_REG_CHG_IRQ2:
+       case MAX8907_REG_CHG_STAT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool max8907_gen_is_precious_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX8907_REG_ON_OFF_IRQ1:
+       case MAX8907_REG_ON_OFF_IRQ2:
+       case MAX8907_REG_CHG_IRQ1:
+       case MAX8907_REG_CHG_IRQ2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool max8907_gen_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+       return !max8907_gen_is_volatile_reg(dev, reg);
+}
+
+static const struct regmap_config max8907_regmap_gen_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = max8907_gen_is_volatile_reg,
+       .precious_reg = max8907_gen_is_precious_reg,
+       .writeable_reg = max8907_gen_is_writeable_reg,
+       .max_register = MAX8907_REG_LDO20VOUT,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static bool max8907_rtc_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       if (reg <= MAX8907_REG_RTC_YEAR2)
+               return true;
+
+       switch (reg) {
+       case MAX8907_REG_RTC_STATUS:
+       case MAX8907_REG_RTC_IRQ:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool max8907_rtc_is_precious_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX8907_REG_RTC_IRQ:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool max8907_rtc_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX8907_REG_RTC_STATUS:
+       case MAX8907_REG_RTC_IRQ:
+               return false;
+       default:
+               return true;
+       }
+}
+
+static const struct regmap_config max8907_regmap_rtc_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_reg = max8907_rtc_is_volatile_reg,
+       .precious_reg = max8907_rtc_is_precious_reg,
+       .writeable_reg = max8907_rtc_is_writeable_reg,
+       .max_register = MAX8907_REG_MPL_CNTL,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_irq max8907_chg_irqs[] = {
+       { .reg_offset = 0, .mask = 1 << 0, },
+       { .reg_offset = 0, .mask = 1 << 1, },
+       { .reg_offset = 0, .mask = 1 << 2, },
+       { .reg_offset = 1, .mask = 1 << 0, },
+       { .reg_offset = 1, .mask = 1 << 1, },
+       { .reg_offset = 1, .mask = 1 << 2, },
+       { .reg_offset = 1, .mask = 1 << 3, },
+       { .reg_offset = 1, .mask = 1 << 4, },
+       { .reg_offset = 1, .mask = 1 << 5, },
+       { .reg_offset = 1, .mask = 1 << 6, },
+       { .reg_offset = 1, .mask = 1 << 7, },
+};
+
+static const struct regmap_irq_chip max8907_chg_irq_chip = {
+       .name = "max8907 chg",
+       .status_base = MAX8907_REG_CHG_IRQ1,
+       .mask_base = MAX8907_REG_CHG_IRQ1_MASK,
+       .wake_base = MAX8907_REG_CHG_IRQ1_MASK,
+       .irq_reg_stride = MAX8907_REG_CHG_IRQ2 - MAX8907_REG_CHG_IRQ1,
+       .num_regs = 2,
+       .irqs = max8907_chg_irqs,
+       .num_irqs = ARRAY_SIZE(max8907_chg_irqs),
+};
+
+static const struct regmap_irq max8907_on_off_irqs[] = {
+       { .reg_offset = 0, .mask = 1 << 0, },
+       { .reg_offset = 0, .mask = 1 << 1, },
+       { .reg_offset = 0, .mask = 1 << 2, },
+       { .reg_offset = 0, .mask = 1 << 3, },
+       { .reg_offset = 0, .mask = 1 << 4, },
+       { .reg_offset = 0, .mask = 1 << 5, },
+       { .reg_offset = 0, .mask = 1 << 6, },
+       { .reg_offset = 0, .mask = 1 << 7, },
+       { .reg_offset = 1, .mask = 1 << 0, },
+       { .reg_offset = 1, .mask = 1 << 1, },
+};
+
+static const struct regmap_irq_chip max8907_on_off_irq_chip = {
+       .name = "max8907 on_off",
+       .status_base = MAX8907_REG_ON_OFF_IRQ1,
+       .mask_base = MAX8907_REG_ON_OFF_IRQ1_MASK,
+       .irq_reg_stride = MAX8907_REG_ON_OFF_IRQ2 - MAX8907_REG_ON_OFF_IRQ1,
+       .num_regs = 2,
+       .irqs = max8907_on_off_irqs,
+       .num_irqs = ARRAY_SIZE(max8907_on_off_irqs),
+};
+
+static const struct regmap_irq max8907_rtc_irqs[] = {
+       { .reg_offset = 0, .mask = 1 << 2, },
+       { .reg_offset = 0, .mask = 1 << 3, },
+};
+
+static const struct regmap_irq_chip max8907_rtc_irq_chip = {
+       .name = "max8907 rtc",
+       .status_base = MAX8907_REG_RTC_IRQ,
+       .mask_base = MAX8907_REG_RTC_IRQ_MASK,
+       .num_regs = 1,
+       .irqs = max8907_rtc_irqs,
+       .num_irqs = ARRAY_SIZE(max8907_rtc_irqs),
+};
+
+static struct max8907 *max8907_pm_off;
+static void max8907_power_off(void)
+{
+       regmap_update_bits(max8907_pm_off->regmap_gen, MAX8907_REG_RESET_CNFG,
+                       MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
+}
+
+static __devinit int max8907_i2c_probe(struct i2c_client *i2c,
+                                      const struct i2c_device_id *id)
+{
+       struct max8907 *max8907;
+       int ret;
+       struct max8907_platform_data *pdata = dev_get_platdata(&i2c->dev);
+       bool pm_off = false;
+
+       if (pdata)
+               pm_off = pdata->pm_off;
+       else if (i2c->dev.of_node)
+               pm_off = of_property_read_bool(i2c->dev.of_node,
+                                       "maxim,system-power-controller");
+
+       max8907 = devm_kzalloc(&i2c->dev, sizeof(struct max8907), GFP_KERNEL);
+       if (!max8907) {
+               ret = -ENOMEM;
+               goto err_alloc_drvdata;
+       }
+
+       max8907->dev = &i2c->dev;
+       dev_set_drvdata(max8907->dev, max8907);
+
+       max8907->i2c_gen = i2c;
+       i2c_set_clientdata(i2c, max8907);
+       max8907->regmap_gen = devm_regmap_init_i2c(i2c,
+                                               &max8907_regmap_gen_config);
+       if (IS_ERR(max8907->regmap_gen)) {
+               ret = PTR_ERR(max8907->regmap_gen);
+               dev_err(&i2c->dev, "gen regmap init failed: %d\n", ret);
+               goto err_regmap_gen;
+       }
+
+       max8907->i2c_rtc = i2c_new_dummy(i2c->adapter, MAX8907_RTC_I2C_ADDR);
+       if (!max8907->i2c_rtc) {
+               ret = -ENOMEM;
+               goto err_dummy_rtc;
+       }
+       i2c_set_clientdata(max8907->i2c_rtc, max8907);
+       max8907->regmap_rtc = devm_regmap_init_i2c(max8907->i2c_rtc,
+                                               &max8907_regmap_rtc_config);
+       if (IS_ERR(max8907->regmap_rtc)) {
+               ret = PTR_ERR(max8907->regmap_rtc);
+               dev_err(&i2c->dev, "rtc regmap init failed: %d\n", ret);
+               goto err_regmap_rtc;
+       }
+
+       irq_set_status_flags(max8907->i2c_gen->irq, IRQ_NOAUTOEN);
+
+       ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
+                                 IRQF_ONESHOT | IRQF_SHARED, -1,
+                                 &max8907_chg_irq_chip,
+                                 &max8907->irqc_chg);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "failed to add chg irq chip: %d\n", ret);
+               goto err_irqc_chg;
+       }
+       ret = regmap_add_irq_chip(max8907->regmap_gen, max8907->i2c_gen->irq,
+                                 IRQF_ONESHOT | IRQF_SHARED, -1,
+                                 &max8907_on_off_irq_chip,
+                                 &max8907->irqc_on_off);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "failed to add on off irq chip: %d\n", ret);
+               goto err_irqc_on_off;
+       }
+       ret = regmap_add_irq_chip(max8907->regmap_rtc, max8907->i2c_gen->irq,
+                                 IRQF_ONESHOT | IRQF_SHARED, -1,
+                                 &max8907_rtc_irq_chip,
+                                 &max8907->irqc_rtc);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "failed to add rtc irq chip: %d\n", ret);
+               goto err_irqc_rtc;
+       }
+
+       enable_irq(max8907->i2c_gen->irq);
+
+       ret = mfd_add_devices(max8907->dev, -1, max8907_cells,
+                             ARRAY_SIZE(max8907_cells), NULL, 0, NULL);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "failed to add MFD devices %d\n", ret);
+               goto err_add_devices;
+       }
+
+       if (pm_off && !pm_power_off) {
+               max8907_pm_off = max8907;
+               pm_power_off = max8907_power_off;
+       }
+
+       return 0;
+
+err_add_devices:
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
+err_irqc_rtc:
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
+err_irqc_on_off:
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
+err_irqc_chg:
+err_regmap_rtc:
+       i2c_unregister_device(max8907->i2c_rtc);
+err_dummy_rtc:
+err_regmap_gen:
+err_alloc_drvdata:
+       return ret;
+}
+
+static __devexit int max8907_i2c_remove(struct i2c_client *i2c)
+{
+       struct max8907 *max8907 = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(max8907->dev);
+
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_rtc);
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_on_off);
+       regmap_del_irq_chip(max8907->i2c_gen->irq, max8907->irqc_chg);
+
+       i2c_unregister_device(max8907->i2c_rtc);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id max8907_of_match[] = {
+       { .compatible = "maxim,max8907" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, max8907_of_match);
+#endif
+
+static const struct i2c_device_id max8907_i2c_id[] = {
+       {"max8907", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, max8907_i2c_id);
+
+static struct i2c_driver max8907_i2c_driver = {
+       .driver = {
+               .name = "max8907",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(max8907_of_match),
+       },
+       .probe = max8907_i2c_probe,
+       .remove = max8907_i2c_remove,
+       .id_table = max8907_i2c_id,
+};
+
+static int __init max8907_i2c_init(void)
+{
+       int ret = -ENODEV;
+
+       ret = i2c_add_driver(&max8907_i2c_driver);
+       if (ret != 0)
+               pr_err("Failed to register I2C driver: %d\n", ret);
+
+       return ret;
+}
+subsys_initcall(max8907_i2c_init);
+
+static void __exit max8907_i2c_exit(void)
+{
+       i2c_del_driver(&max8907_i2c_driver);
+}
+module_exit(max8907_i2c_exit);
+
+MODULE_DESCRIPTION("MAX8907 multi-function core driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
+MODULE_LICENSE("GPL v2");
index ee53757beca7e8344c15a66bbe5d51bcce7b9da1..9f54c04912f25bfe31b37a71b9ebd49b44a4edac 100644 (file)
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8925.h>
 
-static struct resource backlight_resources[] = {
-       {
-               .name   = "max8925-backlight",
-               .start  = MAX8925_WLED_MODE_CNTL,
-               .end    = MAX8925_WLED_CNTL,
-               .flags  = IORESOURCE_IO,
-       },
+static struct resource bk_resources[] __devinitdata = {
+       { 0x84, 0x84, "mode control", IORESOURCE_REG, },
+       { 0x85, 0x85, "control",      IORESOURCE_REG, },
 };
 
-static struct mfd_cell backlight_devs[] = {
+static struct mfd_cell bk_devs[] __devinitdata = {
        {
                .name           = "max8925-backlight",
-               .num_resources  = 1,
-               .resources      = &backlight_resources[0],
+               .num_resources  = ARRAY_SIZE(bk_resources),
+               .resources      = &bk_resources[0],
                .id             = -1,
        },
 };
@@ -41,7 +38,7 @@ static struct resource touch_resources[] = {
                .name   = "max8925-tsc",
                .start  = MAX8925_TSC_IRQ,
                .end    = MAX8925_ADC_RES_END,
-               .flags  = IORESOURCE_IO,
+               .flags  = IORESOURCE_REG,
        },
 };
 
@@ -59,7 +56,7 @@ static struct resource power_supply_resources[] = {
                .name   = "max8925-power",
                .start  = MAX8925_CHG_IRQ1,
                .end    = MAX8925_CHG_IRQ1_MASK,
-               .flags  = IORESOURCE_IO,
+               .flags  = IORESOURCE_REG,
        },
 };
 
@@ -113,71 +110,215 @@ static struct mfd_cell onkey_devs[] = {
        },
 };
 
-#define MAX8925_REG_RESOURCE(_start, _end)     \
-{                                              \
-       .start  = MAX8925_##_start,             \
-       .end    = MAX8925_##_end,               \
-       .flags  = IORESOURCE_IO,                \
-}
+static struct resource sd1_resources[] __devinitdata = {
+       {0x06, 0x06, "sdv", IORESOURCE_REG, },
+};
 
-static struct resource regulator_resources[] = {
-       MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
-       MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
-       MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
-       MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
-       MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
-       MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
-       MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
-       MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
-       MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
-       MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
-       MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
-       MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
-       MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
-       MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
-       MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
-       MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
-       MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
-       MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
-       MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
-       MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
-       MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
-       MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
-       MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
-};
-
-#define MAX8925_REG_DEVS(_id)                                          \
-{                                                                      \
-       .name           = "max8925-regulator",                          \
-       .num_resources  = 1,                                            \
-       .resources      = &regulator_resources[MAX8925_ID_##_id],       \
-       .id             = MAX8925_ID_##_id,                             \
-}
+static struct resource sd2_resources[] __devinitdata = {
+       {0x09, 0x09, "sdv", IORESOURCE_REG, },
+};
+
+static struct resource sd3_resources[] __devinitdata = {
+       {0x0c, 0x0c, "sdv", IORESOURCE_REG, },
+};
+
+static struct resource ldo1_resources[] __devinitdata = {
+       {0x1a, 0x1a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo2_resources[] __devinitdata = {
+       {0x1e, 0x1e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo3_resources[] __devinitdata = {
+       {0x22, 0x22, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo4_resources[] __devinitdata = {
+       {0x26, 0x26, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo5_resources[] __devinitdata = {
+       {0x2a, 0x2a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo6_resources[] __devinitdata = {
+       {0x2e, 0x2e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo7_resources[] __devinitdata = {
+       {0x32, 0x32, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo8_resources[] __devinitdata = {
+       {0x36, 0x36, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo9_resources[] __devinitdata = {
+       {0x3a, 0x3a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo10_resources[] __devinitdata = {
+       {0x3e, 0x3e, "ldov", IORESOURCE_REG, },
+};
 
-static struct mfd_cell regulator_devs[] = {
-       MAX8925_REG_DEVS(SD1),
-       MAX8925_REG_DEVS(SD2),
-       MAX8925_REG_DEVS(SD3),
-       MAX8925_REG_DEVS(LDO1),
-       MAX8925_REG_DEVS(LDO2),
-       MAX8925_REG_DEVS(LDO3),
-       MAX8925_REG_DEVS(LDO4),
-       MAX8925_REG_DEVS(LDO5),
-       MAX8925_REG_DEVS(LDO6),
-       MAX8925_REG_DEVS(LDO7),
-       MAX8925_REG_DEVS(LDO8),
-       MAX8925_REG_DEVS(LDO9),
-       MAX8925_REG_DEVS(LDO10),
-       MAX8925_REG_DEVS(LDO11),
-       MAX8925_REG_DEVS(LDO12),
-       MAX8925_REG_DEVS(LDO13),
-       MAX8925_REG_DEVS(LDO14),
-       MAX8925_REG_DEVS(LDO15),
-       MAX8925_REG_DEVS(LDO16),
-       MAX8925_REG_DEVS(LDO17),
-       MAX8925_REG_DEVS(LDO18),
-       MAX8925_REG_DEVS(LDO19),
-       MAX8925_REG_DEVS(LDO20),
+static struct resource ldo11_resources[] __devinitdata = {
+       {0x42, 0x42, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo12_resources[] __devinitdata = {
+       {0x46, 0x46, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo13_resources[] __devinitdata = {
+       {0x4a, 0x4a, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo14_resources[] __devinitdata = {
+       {0x4e, 0x4e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo15_resources[] __devinitdata = {
+       {0x52, 0x52, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo16_resources[] __devinitdata = {
+       {0x12, 0x12, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo17_resources[] __devinitdata = {
+       {0x16, 0x16, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo18_resources[] __devinitdata = {
+       {0x74, 0x74, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo19_resources[] __devinitdata = {
+       {0x5e, 0x5e, "ldov", IORESOURCE_REG, },
+};
+
+static struct resource ldo20_resources[] __devinitdata = {
+       {0x9e, 0x9e, "ldov", IORESOURCE_REG, },
+};
+
+static struct mfd_cell reg_devs[] __devinitdata = {
+       {
+               .name = "max8925-regulator",
+               .id = 0,
+               .num_resources = ARRAY_SIZE(sd1_resources),
+               .resources = sd1_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 1,
+               .num_resources = ARRAY_SIZE(sd2_resources),
+               .resources = sd2_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 2,
+               .num_resources = ARRAY_SIZE(sd3_resources),
+               .resources = sd3_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 3,
+               .num_resources = ARRAY_SIZE(ldo1_resources),
+               .resources = ldo1_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 4,
+               .num_resources = ARRAY_SIZE(ldo2_resources),
+               .resources = ldo2_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 5,
+               .num_resources = ARRAY_SIZE(ldo3_resources),
+               .resources = ldo3_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 6,
+               .num_resources = ARRAY_SIZE(ldo4_resources),
+               .resources = ldo4_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 7,
+               .num_resources = ARRAY_SIZE(ldo5_resources),
+               .resources = ldo5_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 8,
+               .num_resources = ARRAY_SIZE(ldo6_resources),
+               .resources = ldo6_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 9,
+               .num_resources = ARRAY_SIZE(ldo7_resources),
+               .resources = ldo7_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 10,
+               .num_resources = ARRAY_SIZE(ldo8_resources),
+               .resources = ldo8_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 11,
+               .num_resources = ARRAY_SIZE(ldo9_resources),
+               .resources = ldo9_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 12,
+               .num_resources = ARRAY_SIZE(ldo10_resources),
+               .resources = ldo10_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 13,
+               .num_resources = ARRAY_SIZE(ldo11_resources),
+               .resources = ldo11_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 14,
+               .num_resources = ARRAY_SIZE(ldo12_resources),
+               .resources = ldo12_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 15,
+               .num_resources = ARRAY_SIZE(ldo13_resources),
+               .resources = ldo13_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 16,
+               .num_resources = ARRAY_SIZE(ldo14_resources),
+               .resources = ldo14_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 17,
+               .num_resources = ARRAY_SIZE(ldo15_resources),
+               .resources = ldo15_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 18,
+               .num_resources = ARRAY_SIZE(ldo16_resources),
+               .resources = ldo16_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 19,
+               .num_resources = ARRAY_SIZE(ldo17_resources),
+               .resources = ldo17_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 20,
+               .num_resources = ARRAY_SIZE(ldo18_resources),
+               .resources = ldo18_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 21,
+               .num_resources = ARRAY_SIZE(ldo19_resources),
+               .resources = ldo19_resources,
+       }, {
+               .name = "max8925-regulator",
+               .id = 22,
+               .num_resources = ARRAY_SIZE(ldo20_resources),
+               .resources = ldo20_resources,
+       },
 };
 
 enum {
@@ -547,7 +688,7 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq,
                goto tsc_irq;
        }
 
-       ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
+       ret = request_threaded_irq(irq, NULL, max8925_irq, flags | IRQF_ONESHOT,
                                   "max8925", chip);
        if (ret) {
                dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
@@ -565,7 +706,7 @@ tsc_irq:
        chip->tsc_irq = pdata->tsc_irq;
 
        ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
-                                  flags, "max8925-tsc", chip);
+                                  flags | IRQF_ONESHOT, "max8925-tsc", chip);
        if (ret) {
                dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
                chip->tsc_irq = 0;
@@ -573,6 +714,113 @@ tsc_irq:
        return 0;
 }
 
+static void __devinit init_regulator(struct max8925_chip *chip,
+                                    struct max8925_platform_data *pdata)
+{
+       int ret;
+
+       if (!pdata)
+               return;
+       if (pdata->sd1) {
+               reg_devs[0].platform_data = pdata->sd1;
+               reg_devs[0].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->sd2) {
+               reg_devs[1].platform_data = pdata->sd2;
+               reg_devs[1].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->sd3) {
+               reg_devs[2].platform_data = pdata->sd3;
+               reg_devs[2].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo1) {
+               reg_devs[3].platform_data = pdata->ldo1;
+               reg_devs[3].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo2) {
+               reg_devs[4].platform_data = pdata->ldo2;
+               reg_devs[4].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo3) {
+               reg_devs[5].platform_data = pdata->ldo3;
+               reg_devs[5].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo4) {
+               reg_devs[6].platform_data = pdata->ldo4;
+               reg_devs[6].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo5) {
+               reg_devs[7].platform_data = pdata->ldo5;
+               reg_devs[7].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo6) {
+               reg_devs[8].platform_data = pdata->ldo6;
+               reg_devs[8].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo7) {
+               reg_devs[9].platform_data = pdata->ldo7;
+               reg_devs[9].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo8) {
+               reg_devs[10].platform_data = pdata->ldo8;
+               reg_devs[10].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo9) {
+               reg_devs[11].platform_data = pdata->ldo9;
+               reg_devs[11].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo10) {
+               reg_devs[12].platform_data = pdata->ldo10;
+               reg_devs[12].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo11) {
+               reg_devs[13].platform_data = pdata->ldo11;
+               reg_devs[13].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo12) {
+               reg_devs[14].platform_data = pdata->ldo12;
+               reg_devs[14].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo13) {
+               reg_devs[15].platform_data = pdata->ldo13;
+               reg_devs[15].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo14) {
+               reg_devs[16].platform_data = pdata->ldo14;
+               reg_devs[16].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo15) {
+               reg_devs[17].platform_data = pdata->ldo15;
+               reg_devs[17].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo16) {
+               reg_devs[18].platform_data = pdata->ldo16;
+               reg_devs[18].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo17) {
+               reg_devs[19].platform_data = pdata->ldo17;
+               reg_devs[19].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo18) {
+               reg_devs[20].platform_data = pdata->ldo18;
+               reg_devs[20].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo19) {
+               reg_devs[21].platform_data = pdata->ldo19;
+               reg_devs[21].pdata_size = sizeof(struct regulator_init_data);
+       }
+       if (pdata->ldo20) {
+               reg_devs[22].platform_data = pdata->ldo20;
+               reg_devs[22].pdata_size = sizeof(struct regulator_init_data);
+       }
+       ret = mfd_add_devices(chip->dev, 0, reg_devs, ARRAY_SIZE(reg_devs),
+                             NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to add regulator subdev\n");
+               return;
+       }
+}
+
 int __devinit max8925_device_init(struct max8925_chip *chip,
                                  struct max8925_platform_data *pdata)
 {
@@ -612,24 +860,17 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
                goto out_dev;
        }
 
-       if (pdata) {
-               ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
-                                     ARRAY_SIZE(regulator_devs),
-                                     &regulator_resources[0], 0, NULL);
-               if (ret < 0) {
-                       dev_err(chip->dev, "Failed to add regulator subdev\n");
-                       goto out_dev;
-               }
-       }
+       init_regulator(chip, pdata);
 
        if (pdata && pdata->backlight) {
-               ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
-                                     ARRAY_SIZE(backlight_devs),
-                                     &backlight_resources[0], 0, NULL);
-               if (ret < 0) {
-                       dev_err(chip->dev, "Failed to add backlight subdev\n");
-                       goto out_dev;
-               }
+               bk_devs[0].platform_data = &pdata->backlight;
+               bk_devs[0].pdata_size = sizeof(struct max8925_backlight_pdata);
+       }
+       ret = mfd_add_devices(chip->dev, 0, bk_devs, ARRAY_SIZE(bk_devs),
+                             NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to add backlight subdev\n");
+               goto out_dev;
        }
 
        if (pdata && pdata->power) {
index 1ec79b54bd2f12f304c57f92633cc8c125a0d389..1aba0238f426a01935100efbf904b192199a3d9a 100644 (file)
@@ -676,7 +676,6 @@ int mc13xxx_common_init(struct mc13xxx *mc13xxx,
 err_mask:
 err_revision:
                mc13xxx_unlock(mc13xxx);
-               kfree(mc13xxx);
                return ret;
        }
 
index 41088ecbb2a92e3c6350038ad61f77ceb500e8ce..23cec57c02ba9d7e995900ce5d66e1d4e3704bb7 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 
 /* OMAP USBHOST Register addresses  */
 
-/* TLL Register Set */
-#define        OMAP_USBTLL_REVISION                            (0x00)
-#define        OMAP_USBTLL_SYSCONFIG                           (0x10)
-#define        OMAP_USBTLL_SYSCONFIG_CACTIVITY                 (1 << 8)
-#define        OMAP_USBTLL_SYSCONFIG_SIDLEMODE                 (1 << 3)
-#define        OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                 (1 << 2)
-#define        OMAP_USBTLL_SYSCONFIG_SOFTRESET                 (1 << 1)
-#define        OMAP_USBTLL_SYSCONFIG_AUTOIDLE                  (1 << 0)
-
-#define        OMAP_USBTLL_SYSSTATUS                           (0x14)
-#define        OMAP_USBTLL_SYSSTATUS_RESETDONE                 (1 << 0)
-
-#define        OMAP_USBTLL_IRQSTATUS                           (0x18)
-#define        OMAP_USBTLL_IRQENABLE                           (0x1C)
-
-#define        OMAP_TLL_SHARED_CONF                            (0x30)
-#define        OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN             (1 << 6)
-#define        OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN            (1 << 5)
-#define        OMAP_TLL_SHARED_CONF_USB_DIVRATION              (1 << 2)
-#define        OMAP_TLL_SHARED_CONF_FCLK_REQ                   (1 << 1)
-#define        OMAP_TLL_SHARED_CONF_FCLK_IS_ON                 (1 << 0)
-
-#define        OMAP_TLL_CHANNEL_CONF(num)                      (0x040 + 0x004 * num)
-#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT           24
-#define        OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF            (1 << 11)
-#define        OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE         (1 << 10)
-#define        OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE              (1 << 9)
-#define        OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE               (1 << 8)
-#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS            (1 << 1)
-#define        OMAP_TLL_CHANNEL_CONF_CHANEN                    (1 << 0)
-
-#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0             0x0
-#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM               0x1
-#define OMAP_TLL_FSLSMODE_3PIN_PHY                     0x2
-#define OMAP_TLL_FSLSMODE_4PIN_PHY                     0x3
-#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0             0x4
-#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM               0x5
-#define OMAP_TLL_FSLSMODE_3PIN_TLL                     0x6
-#define OMAP_TLL_FSLSMODE_4PIN_TLL                     0x7
-#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0             0xA
-#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM               0xB
-
-#define        OMAP_TLL_ULPI_FUNCTION_CTRL(num)                (0x804 + 0x100 * num)
-#define        OMAP_TLL_ULPI_INTERFACE_CTRL(num)               (0x807 + 0x100 * num)
-#define        OMAP_TLL_ULPI_OTG_CTRL(num)                     (0x80A + 0x100 * num)
-#define        OMAP_TLL_ULPI_INT_EN_RISE(num)                  (0x80D + 0x100 * num)
-#define        OMAP_TLL_ULPI_INT_EN_FALL(num)                  (0x810 + 0x100 * num)
-#define        OMAP_TLL_ULPI_INT_STATUS(num)                   (0x813 + 0x100 * num)
-#define        OMAP_TLL_ULPI_INT_LATCH(num)                    (0x814 + 0x100 * num)
-#define        OMAP_TLL_ULPI_DEBUG(num)                        (0x815 + 0x100 * num)
-#define        OMAP_TLL_ULPI_SCRATCH_REGISTER(num)             (0x816 + 0x100 * num)
-
-#define OMAP_TLL_CHANNEL_COUNT                         3
-#define OMAP_TLL_CHANNEL_1_EN_MASK                     (1 << 0)
-#define OMAP_TLL_CHANNEL_2_EN_MASK                     (1 << 1)
-#define OMAP_TLL_CHANNEL_3_EN_MASK                     (1 << 2)
-
 /* UHH Register Set */
 #define        OMAP_UHH_REVISION                               (0x00)
 #define        OMAP_UHH_SYSCONFIG                              (0x10)
 #define OMAP4_P2_MODE_TLL                              (1 << 18)
 #define OMAP4_P2_MODE_HSIC                             (3 << 18)
 
-#define OMAP_REV2_TLL_CHANNEL_COUNT                    2
-
 #define        OMAP_UHH_DEBUG_CSR                              (0x44)
 
 /* Values of UHH_REVISION - Note: these are not given in the TRM */
@@ -153,15 +93,12 @@ struct usbhs_hcd_omap {
        struct clk                      *xclk60mhsp2_ck;
        struct clk                      *utmi_p1_fck;
        struct clk                      *usbhost_p1_fck;
-       struct clk                      *usbtll_p1_fck;
        struct clk                      *utmi_p2_fck;
        struct clk                      *usbhost_p2_fck;
-       struct clk                      *usbtll_p2_fck;
        struct clk                      *init_60m_fclk;
        struct clk                      *ehci_logic_fck;
 
        void __iomem                    *uhh_base;
-       void __iomem                    *tll_base;
 
        struct usbhs_omap_platform_data platdata;
 
@@ -336,93 +273,6 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
        }
 }
 
-/*
- * convert the port-mode enum to a value we can use in the FSLSMODE
- * field of USBTLL_CHANNEL_CONF
- */
-static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
-{
-       switch (mode) {
-       case OMAP_USBHS_PORT_MODE_UNUSED:
-       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-               return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
-
-       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-               return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
-
-       case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-               return OMAP_TLL_FSLSMODE_3PIN_PHY;
-
-       case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-               return OMAP_TLL_FSLSMODE_4PIN_PHY;
-
-       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-               return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
-
-       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-               return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
-
-       case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-               return OMAP_TLL_FSLSMODE_3PIN_TLL;
-
-       case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-               return OMAP_TLL_FSLSMODE_4PIN_TLL;
-
-       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-               return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
-
-       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-               return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
-       default:
-               pr_warning("Invalid port mode, using default\n");
-               return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
-       }
-}
-
-static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
-{
-       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
-       struct usbhs_omap_platform_data *pdata = dev->platform_data;
-       unsigned                        reg;
-       int                             i;
-
-       /* Program Common TLL register */
-       reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF);
-       reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
-               | OMAP_TLL_SHARED_CONF_USB_DIVRATION);
-       reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-       reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
-
-       usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-       /* Enable channels now */
-       for (i = 0; i < tll_channel_count; i++) {
-               reg = usbhs_read(omap->tll_base,
-                               OMAP_TLL_CHANNEL_CONF(i));
-
-               if (is_ohci_port(pdata->port_mode[i])) {
-                       reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
-                               << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
-                       reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
-               } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) {
-
-                       /* Disable AutoIdle, BitStuffing and use SDR Mode */
-                       reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
-                               | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
-                               | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
-
-               } else
-                       continue;
-
-               reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-               usbhs_write(omap->tll_base,
-                               OMAP_TLL_CHANNEL_CONF(i), reg);
-
-               usbhs_writeb(omap->tll_base,
-                               OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
-       }
-}
-
 static int usbhs_runtime_resume(struct device *dev)
 {
        struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
@@ -436,19 +286,17 @@ static int usbhs_runtime_resume(struct device *dev)
                return  -ENODEV;
        }
 
+       omap_tll_enable();
        spin_lock_irqsave(&omap->lock, flags);
 
        if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
                clk_enable(omap->ehci_logic_fck);
 
-       if (is_ehci_tll_mode(pdata->port_mode[0])) {
+       if (is_ehci_tll_mode(pdata->port_mode[0]))
                clk_enable(omap->usbhost_p1_fck);
-               clk_enable(omap->usbtll_p1_fck);
-       }
-       if (is_ehci_tll_mode(pdata->port_mode[1])) {
+       if (is_ehci_tll_mode(pdata->port_mode[1]))
                clk_enable(omap->usbhost_p2_fck);
-               clk_enable(omap->usbtll_p2_fck);
-       }
+
        clk_enable(omap->utmi_p1_fck);
        clk_enable(omap->utmi_p2_fck);
 
@@ -472,14 +320,11 @@ static int usbhs_runtime_suspend(struct device *dev)
 
        spin_lock_irqsave(&omap->lock, flags);
 
-       if (is_ehci_tll_mode(pdata->port_mode[0])) {
+       if (is_ehci_tll_mode(pdata->port_mode[0]))
                clk_disable(omap->usbhost_p1_fck);
-               clk_disable(omap->usbtll_p1_fck);
-       }
-       if (is_ehci_tll_mode(pdata->port_mode[1])) {
+       if (is_ehci_tll_mode(pdata->port_mode[1]))
                clk_disable(omap->usbhost_p2_fck);
-               clk_disable(omap->usbtll_p2_fck);
-       }
+
        clk_disable(omap->utmi_p2_fck);
        clk_disable(omap->utmi_p1_fck);
 
@@ -487,6 +332,7 @@ static int usbhs_runtime_suspend(struct device *dev)
                clk_disable(omap->ehci_logic_fck);
 
        spin_unlock_irqrestore(&omap->lock, flags);
+       omap_tll_disable();
 
        return 0;
 }
@@ -500,8 +346,6 @@ static void omap_usbhs_init(struct device *dev)
 
        dev_dbg(dev, "starting TI HSUSB Controller\n");
 
-       pm_runtime_get_sync(dev);
-
        if (pdata->ehci_data->phy_reset) {
                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
                        gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
@@ -515,6 +359,7 @@ static void omap_usbhs_init(struct device *dev)
                udelay(10);
        }
 
+       pm_runtime_get_sync(dev);
        spin_lock_irqsave(&omap->lock, flags);
        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
        dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
@@ -580,22 +425,9 @@ static void omap_usbhs_init(struct device *dev)
        usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
        dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
 
-       if (is_ehci_tll_mode(pdata->port_mode[0]) ||
-               is_ehci_tll_mode(pdata->port_mode[1]) ||
-               is_ehci_tll_mode(pdata->port_mode[2]) ||
-               (is_ohci_port(pdata->port_mode[0])) ||
-               (is_ohci_port(pdata->port_mode[1])) ||
-               (is_ohci_port(pdata->port_mode[2]))) {
-
-               /* Enable UTMI mode for required TLL channels */
-               if (is_omap_usbhs_rev2(omap))
-                       usbhs_omap_tll_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT);
-               else
-                       usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
-       }
-
        spin_unlock_irqrestore(&omap->lock, flags);
 
+       pm_runtime_put_sync(dev);
        if (pdata->ehci_data->phy_reset) {
                /* Hold the PHY in RESET for enough time till
                 * PHY is settled and ready
@@ -610,8 +442,6 @@ static void omap_usbhs_init(struct device *dev)
                        gpio_set_value_cansleep
                                (pdata->ehci_data->reset_gpio_port[1], 1);
        }
-
-       pm_runtime_put_sync(dev);
 }
 
 static void omap_usbhs_deinit(struct device *dev)
@@ -714,32 +544,18 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
                goto err_xclk60mhsp2_ck;
        }
 
-       omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
-       if (IS_ERR(omap->usbtll_p1_fck)) {
-               ret = PTR_ERR(omap->usbtll_p1_fck);
-               dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
-               goto err_usbhost_p1_fck;
-       }
-
        omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
        if (IS_ERR(omap->usbhost_p2_fck)) {
                ret = PTR_ERR(omap->usbhost_p2_fck);
                dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
-               goto err_usbtll_p1_fck;
-       }
-
-       omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
-       if (IS_ERR(omap->usbtll_p2_fck)) {
-               ret = PTR_ERR(omap->usbtll_p2_fck);
-               dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
-               goto err_usbhost_p2_fck;
+               goto err_usbhost_p1_fck;
        }
 
        omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
        if (IS_ERR(omap->init_60m_fclk)) {
                ret = PTR_ERR(omap->init_60m_fclk);
                dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
-               goto err_usbtll_p2_fck;
+               goto err_usbhost_p2_fck;
        }
 
        if (is_ehci_phy_mode(pdata->port_mode[0])) {
@@ -785,20 +601,6 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
                goto err_init_60m_fclk;
        }
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
-       if (!res) {
-               dev_err(dev, "UHH EHCI get resource failed\n");
-               ret = -ENODEV;
-               goto err_tll;
-       }
-
-       omap->tll_base = ioremap(res->start, resource_size(res));
-       if (!omap->tll_base) {
-               dev_err(dev, "TLL ioremap failed\n");
-               ret = -ENOMEM;
-               goto err_tll;
-       }
-
        platform_set_drvdata(pdev, omap);
 
        omap_usbhs_init(dev);
@@ -812,23 +614,14 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 
 err_alloc:
        omap_usbhs_deinit(&pdev->dev);
-       iounmap(omap->tll_base);
-
-err_tll:
        iounmap(omap->uhh_base);
 
 err_init_60m_fclk:
        clk_put(omap->init_60m_fclk);
 
-err_usbtll_p2_fck:
-       clk_put(omap->usbtll_p2_fck);
-
 err_usbhost_p2_fck:
        clk_put(omap->usbhost_p2_fck);
 
-err_usbtll_p1_fck:
-       clk_put(omap->usbtll_p1_fck);
-
 err_usbhost_p1_fck:
        clk_put(omap->usbhost_p1_fck);
 
@@ -864,12 +657,9 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
        struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 
        omap_usbhs_deinit(&pdev->dev);
-       iounmap(omap->tll_base);
        iounmap(omap->uhh_base);
        clk_put(omap->init_60m_fclk);
-       clk_put(omap->usbtll_p2_fck);
        clk_put(omap->usbhost_p2_fck);
-       clk_put(omap->usbtll_p1_fck);
        clk_put(omap->usbhost_p1_fck);
        clk_put(omap->xclk60mhsp2_ck);
        clk_put(omap->utmi_p2_fck);
@@ -910,8 +700,10 @@ static int __init omap_usbhs_drvinit(void)
  * init before ehci and ohci drivers;
  * The usbhs core driver should be initialized much before
  * the omap ehci and ohci probe functions are called.
+ * This usbhs core driver should be initialized after
+ * usb tll driver
  */
-fs_initcall(omap_usbhs_drvinit);
+fs_initcall_sync(omap_usbhs_drvinit);
 
 static void __exit omap_usbhs_drvexit(void)
 {
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
new file mode 100644 (file)
index 0000000..4b7757b
--- /dev/null
@@ -0,0 +1,471 @@
+/**
+ * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Keshava Munegowda <keshava_mgowda@ti.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  of
+ * the License 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <plat/usb.h>
+#include <linux/pm_runtime.h>
+
+#define USBTLL_DRIVER_NAME     "usbhs_tll"
+
+/* TLL Register Set */
+#define        OMAP_USBTLL_REVISION                            (0x00)
+#define        OMAP_USBTLL_SYSCONFIG                           (0x10)
+#define        OMAP_USBTLL_SYSCONFIG_CACTIVITY                 (1 << 8)
+#define        OMAP_USBTLL_SYSCONFIG_SIDLEMODE                 (1 << 3)
+#define        OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                 (1 << 2)
+#define        OMAP_USBTLL_SYSCONFIG_SOFTRESET                 (1 << 1)
+#define        OMAP_USBTLL_SYSCONFIG_AUTOIDLE                  (1 << 0)
+
+#define        OMAP_USBTLL_SYSSTATUS                           (0x14)
+#define        OMAP_USBTLL_SYSSTATUS_RESETDONE                 (1 << 0)
+
+#define        OMAP_USBTLL_IRQSTATUS                           (0x18)
+#define        OMAP_USBTLL_IRQENABLE                           (0x1C)
+
+#define        OMAP_TLL_SHARED_CONF                            (0x30)
+#define        OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN             (1 << 6)
+#define        OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN            (1 << 5)
+#define        OMAP_TLL_SHARED_CONF_USB_DIVRATION              (1 << 2)
+#define        OMAP_TLL_SHARED_CONF_FCLK_REQ                   (1 << 1)
+#define        OMAP_TLL_SHARED_CONF_FCLK_IS_ON                 (1 << 0)
+
+#define        OMAP_TLL_CHANNEL_CONF(num)                      (0x040 + 0x004 * num)
+#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT           24
+#define        OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF            (1 << 11)
+#define        OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE         (1 << 10)
+#define        OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE              (1 << 9)
+#define        OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE               (1 << 8)
+#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS            (1 << 1)
+#define        OMAP_TLL_CHANNEL_CONF_CHANEN                    (1 << 0)
+
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0             0x0
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM               0x1
+#define OMAP_TLL_FSLSMODE_3PIN_PHY                     0x2
+#define OMAP_TLL_FSLSMODE_4PIN_PHY                     0x3
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0             0x4
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM               0x5
+#define OMAP_TLL_FSLSMODE_3PIN_TLL                     0x6
+#define OMAP_TLL_FSLSMODE_4PIN_TLL                     0x7
+#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0             0xA
+#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM               0xB
+
+#define        OMAP_TLL_ULPI_FUNCTION_CTRL(num)                (0x804 + 0x100 * num)
+#define        OMAP_TLL_ULPI_INTERFACE_CTRL(num)               (0x807 + 0x100 * num)
+#define        OMAP_TLL_ULPI_OTG_CTRL(num)                     (0x80A + 0x100 * num)
+#define        OMAP_TLL_ULPI_INT_EN_RISE(num)                  (0x80D + 0x100 * num)
+#define        OMAP_TLL_ULPI_INT_EN_FALL(num)                  (0x810 + 0x100 * num)
+#define        OMAP_TLL_ULPI_INT_STATUS(num)                   (0x813 + 0x100 * num)
+#define        OMAP_TLL_ULPI_INT_LATCH(num)                    (0x814 + 0x100 * num)
+#define        OMAP_TLL_ULPI_DEBUG(num)                        (0x815 + 0x100 * num)
+#define        OMAP_TLL_ULPI_SCRATCH_REGISTER(num)             (0x816 + 0x100 * num)
+
+#define OMAP_REV2_TLL_CHANNEL_COUNT                    2
+#define OMAP_TLL_CHANNEL_COUNT                         3
+#define OMAP_TLL_CHANNEL_1_EN_MASK                     (1 << 0)
+#define OMAP_TLL_CHANNEL_2_EN_MASK                     (1 << 1)
+#define OMAP_TLL_CHANNEL_3_EN_MASK                     (1 << 2)
+
+/* Values of USBTLL_REVISION - Note: these are not given in the TRM */
+#define OMAP_USBTLL_REV1               0x00000015      /* OMAP3 */
+#define OMAP_USBTLL_REV2               0x00000018      /* OMAP 3630 */
+#define OMAP_USBTLL_REV3               0x00000004      /* OMAP4 */
+
+#define is_ehci_tll_mode(x)    (x == OMAP_EHCI_PORT_MODE_TLL)
+
+struct usbtll_omap {
+       struct clk                              *usbtll_p1_fck;
+       struct clk                              *usbtll_p2_fck;
+       struct usbtll_omap_platform_data        platdata;
+       /* secure the register updates */
+       spinlock_t                              lock;
+};
+
+/*-------------------------------------------------------------------------*/
+
+const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
+struct platform_device *tll_pdev;
+
+/*-------------------------------------------------------------------------*/
+
+static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
+{
+       __raw_writel(val, base + reg);
+}
+
+static inline u32 usbtll_read(void __iomem *base, u32 reg)
+{
+       return __raw_readl(base + reg);
+}
+
+static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
+{
+       __raw_writeb(val, base + reg);
+}
+
+static inline u8 usbtll_readb(void __iomem *base, u8 reg)
+{
+       return __raw_readb(base + reg);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
+{
+       switch (pmode) {
+       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+       case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+       case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+       case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+       case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+               return true;
+
+       default:
+               return false;
+       }
+}
+
+/*
+ * convert the port-mode enum to a value we can use in the FSLSMODE
+ * field of USBTLL_CHANNEL_CONF
+ */
+static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
+{
+       switch (mode) {
+       case OMAP_USBHS_PORT_MODE_UNUSED:
+       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+               return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+
+       case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+               return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
+
+       case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+               return OMAP_TLL_FSLSMODE_3PIN_PHY;
+
+       case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+               return OMAP_TLL_FSLSMODE_4PIN_PHY;
+
+       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+               return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
+
+       case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+               return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
+
+       case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+               return OMAP_TLL_FSLSMODE_3PIN_TLL;
+
+       case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+               return OMAP_TLL_FSLSMODE_4PIN_TLL;
+
+       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+               return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
+
+       case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+               return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
+       default:
+               pr_warn("Invalid port mode, using default\n");
+               return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+       }
+}
+
+/**
+ * usbtll_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller.
+ */
+static int __devinit usbtll_omap_probe(struct platform_device *pdev)
+{
+       struct device                           *dev =  &pdev->dev;
+       struct usbtll_omap_platform_data        *pdata = dev->platform_data;
+       void __iomem                            *base;
+       struct resource                         *res;
+       struct usbtll_omap                      *tll;
+       unsigned                                reg;
+       unsigned long                           flags;
+       int                                     ret = 0;
+       int                                     i, ver, count;
+
+       dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
+
+       tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL);
+       if (!tll) {
+               dev_err(dev, "Memory allocation failed\n");
+               ret = -ENOMEM;
+               goto end;
+       }
+
+       spin_lock_init(&tll->lock);
+
+       for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
+               tll->platdata.port_mode[i] = pdata->port_mode[i];
+
+       tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
+       if (IS_ERR(tll->usbtll_p1_fck)) {
+               ret = PTR_ERR(tll->usbtll_p1_fck);
+               dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
+               goto err_tll;
+       }
+
+       tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
+       if (IS_ERR(tll->usbtll_p2_fck)) {
+               ret = PTR_ERR(tll->usbtll_p2_fck);
+               dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
+               goto err_usbtll_p1_fck;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "usb tll get resource failed\n");
+               ret = -ENODEV;
+               goto err_usbtll_p2_fck;
+       }
+
+       base = ioremap(res->start, resource_size(res));
+       if (!base) {
+               dev_err(dev, "TLL ioremap failed\n");
+               ret = -ENOMEM;
+               goto err_usbtll_p2_fck;
+       }
+
+       platform_set_drvdata(pdev, tll);
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+
+       spin_lock_irqsave(&tll->lock, flags);
+
+       ver =  usbtll_read(base, OMAP_USBTLL_REVISION);
+       switch (ver) {
+       case OMAP_USBTLL_REV1:
+       case OMAP_USBTLL_REV2:
+               count = OMAP_TLL_CHANNEL_COUNT;
+               break;
+       case OMAP_USBTLL_REV3:
+               count = OMAP_REV2_TLL_CHANNEL_COUNT;
+               break;
+       default:
+               dev_err(dev, "TLL version failed\n");
+               ret = -ENODEV;
+               goto err_ioremap;
+       }
+
+       if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+           is_ehci_tll_mode(pdata->port_mode[1]) ||
+           is_ehci_tll_mode(pdata->port_mode[2]) ||
+           is_ohci_port(pdata->port_mode[0]) ||
+           is_ohci_port(pdata->port_mode[1]) ||
+           is_ohci_port(pdata->port_mode[2])) {
+
+               /* Program Common TLL register */
+               reg = usbtll_read(base, OMAP_TLL_SHARED_CONF);
+               reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
+                       | OMAP_TLL_SHARED_CONF_USB_DIVRATION);
+               reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
+               reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
+
+               usbtll_write(base, OMAP_TLL_SHARED_CONF, reg);
+
+               /* Enable channels now */
+               for (i = 0; i < count; i++) {
+                       reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i));
+
+                       if (is_ohci_port(pdata->port_mode[i])) {
+                               reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
+                               << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
+                               reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
+                       } else if (pdata->port_mode[i] ==
+                                       OMAP_EHCI_PORT_MODE_TLL) {
+                               /*
+                                * Disable AutoIdle, BitStuffing
+                                * and use SDR Mode
+                                */
+                               reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
+                                       | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+                                       | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+                       } else {
+                               continue;
+                       }
+                       reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
+                       usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg);
+
+                       usbtll_writeb(base,
+                                     OMAP_TLL_ULPI_SCRATCH_REGISTER(i),
+                                     0xbe);
+               }
+       }
+
+err_ioremap:
+       spin_unlock_irqrestore(&tll->lock, flags);
+       iounmap(base);
+       pm_runtime_put_sync(dev);
+       tll_pdev = pdev;
+       if (!ret)
+               goto end;
+       pm_runtime_disable(dev);
+
+err_usbtll_p2_fck:
+       clk_put(tll->usbtll_p2_fck);
+
+err_usbtll_p1_fck:
+       clk_put(tll->usbtll_p1_fck);
+
+err_tll:
+       kfree(tll);
+
+end:
+       return ret;
+}
+
+/**
+ * usbtll_omap_remove - shutdown processing for UHH & TLL HCDs
+ * @pdev: USB Host Controller being removed
+ *
+ * Reverses the effect of usbtll_omap_probe().
+ */
+static int __devexit usbtll_omap_remove(struct platform_device *pdev)
+{
+       struct usbtll_omap *tll = platform_get_drvdata(pdev);
+
+       clk_put(tll->usbtll_p2_fck);
+       clk_put(tll->usbtll_p1_fck);
+       pm_runtime_disable(&pdev->dev);
+       kfree(tll);
+       return 0;
+}
+
+static int usbtll_runtime_resume(struct device *dev)
+{
+       struct usbtll_omap                      *tll = dev_get_drvdata(dev);
+       struct usbtll_omap_platform_data        *pdata = &tll->platdata;
+       unsigned long                           flags;
+
+       dev_dbg(dev, "usbtll_runtime_resume\n");
+
+       if (!pdata) {
+               dev_dbg(dev, "missing platform_data\n");
+               return  -ENODEV;
+       }
+
+       spin_lock_irqsave(&tll->lock, flags);
+
+       if (is_ehci_tll_mode(pdata->port_mode[0]))
+               clk_enable(tll->usbtll_p1_fck);
+
+       if (is_ehci_tll_mode(pdata->port_mode[1]))
+               clk_enable(tll->usbtll_p2_fck);
+
+       spin_unlock_irqrestore(&tll->lock, flags);
+
+       return 0;
+}
+
+static int usbtll_runtime_suspend(struct device *dev)
+{
+       struct usbtll_omap                      *tll = dev_get_drvdata(dev);
+       struct usbtll_omap_platform_data        *pdata = &tll->platdata;
+       unsigned long                           flags;
+
+       dev_dbg(dev, "usbtll_runtime_suspend\n");
+
+       if (!pdata) {
+               dev_dbg(dev, "missing platform_data\n");
+               return  -ENODEV;
+       }
+
+       spin_lock_irqsave(&tll->lock, flags);
+
+       if (is_ehci_tll_mode(pdata->port_mode[0]))
+               clk_disable(tll->usbtll_p1_fck);
+
+       if (is_ehci_tll_mode(pdata->port_mode[1]))
+               clk_disable(tll->usbtll_p2_fck);
+
+       spin_unlock_irqrestore(&tll->lock, flags);
+
+       return 0;
+}
+
+static const struct dev_pm_ops usbtllomap_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(usbtll_runtime_suspend,
+                          usbtll_runtime_resume,
+                          NULL)
+};
+
+static struct platform_driver usbtll_omap_driver = {
+       .driver = {
+               .name           = (char *)usbtll_driver_name,
+               .owner          = THIS_MODULE,
+               .pm             = &usbtllomap_dev_pm_ops,
+       },
+       .probe          = usbtll_omap_probe,
+       .remove         = __devexit_p(usbtll_omap_remove),
+};
+
+int omap_tll_enable(void)
+{
+       if (!tll_pdev) {
+               pr_err("missing omap usbhs tll platform_data\n");
+               return  -ENODEV;
+       }
+       return pm_runtime_get_sync(&tll_pdev->dev);
+}
+EXPORT_SYMBOL_GPL(omap_tll_enable);
+
+int omap_tll_disable(void)
+{
+       if (!tll_pdev) {
+               pr_err("missing omap usbhs tll platform_data\n");
+               return  -ENODEV;
+       }
+       return pm_runtime_put_sync(&tll_pdev->dev);
+}
+EXPORT_SYMBOL_GPL(omap_tll_disable);
+
+MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
+MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers");
+
+static int __init omap_usbtll_drvinit(void)
+{
+       return platform_driver_register(&usbtll_omap_driver);
+}
+
+/*
+ * init before usbhs core driver;
+ * The usbtll driver should be initialized before
+ * the usbhs core driver probe function is called.
+ */
+fs_initcall(omap_usbtll_drvinit);
+
+static void __exit omap_usbtll_drvexit(void)
+{
+       platform_driver_unregister(&usbtll_omap_driver);
+}
+module_exit(omap_usbtll_drvexit);
index a345f9bb7b4758765725cf2c056303950ecc1c02..4f8d6e6b19aa3d023173a20537fce2bdf46e5281 100644 (file)
 #include <linux/err.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/palmas.h>
-
-static const struct resource gpadc_resource[] = {
-       {
-               .name = "EOC_SW",
-               .start = PALMAS_GPADC_EOC_SW_IRQ,
-               .end = PALMAS_GPADC_EOC_SW_IRQ,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static const struct resource usb_resource[] = {
-       {
-               .name = "ID",
-               .start = PALMAS_ID_OTG_IRQ,
-               .end = PALMAS_ID_OTG_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "ID_WAKEUP",
-               .start = PALMAS_ID_IRQ,
-               .end = PALMAS_ID_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "VBUS",
-               .start = PALMAS_VBUS_OTG_IRQ,
-               .end = PALMAS_VBUS_OTG_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-       {
-               .name = "VBUS_WAKEUP",
-               .start = PALMAS_VBUS_IRQ,
-               .end = PALMAS_VBUS_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-static const struct resource rtc_resource[] = {
-       {
-               .name = "RTC_ALARM",
-               .start = PALMAS_RTC_ALARM_IRQ,
-               .end = PALMAS_RTC_ALARM_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-static const struct resource pwron_resource[] = {
-       {
-               .name = "PWRON_BUTTON",
-               .start = PALMAS_PWRON_IRQ,
-               .end = PALMAS_PWRON_IRQ,
-               .flags = IORESOURCE_IRQ,
-       },
-};
+#include <linux/of_platform.h>
 
 enum palmas_ids {
        PALMAS_PMIC_ID,
@@ -111,20 +58,14 @@ static const struct mfd_cell palmas_children[] = {
        },
        {
                .name = "palmas-rtc",
-               .num_resources = ARRAY_SIZE(rtc_resource),
-               .resources = rtc_resource,
                .id = PALMAS_RTC_ID,
        },
        {
                .name = "palmas-pwrbutton",
-               .num_resources = ARRAY_SIZE(pwron_resource),
-               .resources = pwron_resource,
                .id = PALMAS_PWRBUTTON_ID,
        },
        {
                .name = "palmas-gpadc",
-               .num_resources = ARRAY_SIZE(gpadc_resource),
-               .resources = gpadc_resource,
                .id = PALMAS_GPADC_ID,
        },
        {
@@ -141,8 +82,6 @@ static const struct mfd_cell palmas_children[] = {
        },
        {
                .name = "palmas-usb",
-               .num_resources = ARRAY_SIZE(usb_resource),
-               .resources = usb_resource,
                .id = PALMAS_USB_ID,
        }
 };
@@ -308,17 +247,56 @@ static struct regmap_irq_chip palmas_irq_chip = {
                        PALMAS_INT1_MASK),
 };
 
+static void __devinit palmas_dt_to_pdata(struct device_node *node,
+               struct palmas_platform_data *pdata)
+{
+       int ret;
+       u32 prop;
+
+       ret = of_property_read_u32(node, "ti,mux_pad1", &prop);
+       if (!ret) {
+               pdata->mux_from_pdata = 1;
+               pdata->pad1 = prop;
+       }
+
+       ret = of_property_read_u32(node, "ti,mux_pad2", &prop);
+       if (!ret) {
+               pdata->mux_from_pdata = 1;
+               pdata->pad2 = prop;
+       }
+
+       /* The default for this register is all masked */
+       ret = of_property_read_u32(node, "ti,power_ctrl", &prop);
+       if (!ret)
+               pdata->power_ctrl = prop;
+       else
+               pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK |
+                                       PALMAS_POWER_CTRL_ENABLE1_MASK |
+                                       PALMAS_POWER_CTRL_ENABLE2_MASK;
+}
+
 static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct palmas *palmas;
        struct palmas_platform_data *pdata;
+       struct device_node *node = i2c->dev.of_node;
        int ret = 0, i;
        unsigned int reg, addr;
        int slave;
        struct mfd_cell *children;
 
        pdata = dev_get_platdata(&i2c->dev);
+
+       if (node && !pdata) {
+               pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+
+               if (!pdata)
+                       return -ENOMEM;
+
+               palmas_dt_to_pdata(node, pdata);
+       }
+
        if (!pdata)
                return -EINVAL;
 
@@ -364,7 +342,7 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
        regmap_write(palmas->regmap[slave], addr, reg);
 
        ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
-                       IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip,
+                       IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
                        &palmas->irq_data);
        if (ret < 0)
                goto err;
@@ -377,11 +355,11 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
                reg = pdata->pad1;
                ret = regmap_write(palmas->regmap[slave], addr, reg);
                if (ret)
-                       goto err;
+                       goto err_irq;
        } else {
                ret = regmap_read(palmas->regmap[slave], addr, &reg);
                if (ret)
-                       goto err;
+                       goto err_irq;
        }
 
        if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0))
@@ -412,11 +390,11 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
                reg = pdata->pad2;
                ret = regmap_write(palmas->regmap[slave], addr, reg);
                if (ret)
-                       goto err;
+                       goto err_irq;
        } else {
                ret = regmap_read(palmas->regmap[slave], addr, &reg);
                if (ret)
-                       goto err;
+                       goto err_irq;
        }
 
        if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4))
@@ -439,18 +417,43 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 
        ret = regmap_write(palmas->regmap[slave], addr, reg);
        if (ret)
-               goto err;
+               goto err_irq;
+
+       /*
+        * If we are probing with DT do this the DT way and return here
+        * otherwise continue and add devices using mfd helpers.
+        */
+       if (node) {
+               ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
+               if (ret < 0)
+                       goto err_irq;
+               else
+                       return ret;
+       }
 
        children = kmemdup(palmas_children, sizeof(palmas_children),
                           GFP_KERNEL);
        if (!children) {
                ret = -ENOMEM;
-               goto err;
+               goto err_irq;
        }
 
        children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
        children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
 
+       children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata;
+       children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata);
+
+       children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata;
+       children[PALMAS_RESOURCE_ID].pdata_size =
+                       sizeof(*pdata->resource_pdata);
+
+       children[PALMAS_USB_ID].platform_data = pdata->usb_pdata;
+       children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata);
+
+       children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata;
+       children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata);
+
        ret = mfd_add_devices(palmas->dev, -1,
                              children, ARRAY_SIZE(palmas_children),
                              NULL, regmap_irq_chip_get_base(palmas->irq_data),
@@ -458,13 +461,15 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
        kfree(children);
 
        if (ret < 0)
-               goto err;
+               goto err_devices;
 
        return ret;
 
-err:
+err_devices:
        mfd_remove_devices(palmas->dev);
-       kfree(palmas);
+err_irq:
+       regmap_del_irq_chip(palmas->irq, palmas->irq_data);
+err:
        return ret;
 }
 
index fa6f80fad5f17aa5fe3e9f12c6efc98705ee8789..fe00cdd6f83da134ebde854613388df07706cfca 100644 (file)
@@ -255,7 +255,7 @@ static irqreturn_t rc5t583_irq(int irq, void *data)
 {
        struct rc5t583 *rc5t583 = data;
        uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
-       uint8_t master_int;
+       uint8_t master_int = 0;
        int i;
        int ret;
        unsigned int rtc_int_sts = 0;
index ff61efc76ce28a288575227dda61dc8ac9056447..f1a024ecdb1ea8e4565c5464e68d823d25fd4fde 100644 (file)
@@ -85,7 +85,7 @@ static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
        int id, int ext_pwr, int slots)
 {
        int ret;
-       uint8_t sleepseq_val;
+       uint8_t sleepseq_val = 0;
        unsigned int en_bit;
        unsigned int slot_bit;
 
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
new file mode 100644 (file)
index 0000000..24ae3d8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * TI SMSC MFD Driver
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.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;  GPL v2.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/smsc.h>
+#include <linux/of_platform.h>
+
+static struct regmap_config smsc_regmap_config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .max_register = SMSC_VEN_ID_H,
+               .cache_type = REGCACHE_RBTREE,
+};
+
+static int smsc_i2c_probe(struct i2c_client *i2c,
+                       const struct i2c_device_id *id)
+{
+       struct smsc *smsc;
+       int devid, rev, venid_l, venid_h;
+       int ret = 0;
+
+       smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
+                               GFP_KERNEL);
+       if (!smsc) {
+               dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
+       if (IS_ERR(smsc->regmap)) {
+               ret = PTR_ERR(smsc->regmap);
+               goto err;
+       }
+
+       i2c_set_clientdata(i2c, smsc);
+       smsc->dev = &i2c->dev;
+
+#ifdef CONFIG_OF
+       of_property_read_u32(i2c->dev.of_node, "clock", &smsc->clk);
+#endif
+
+       regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
+       regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
+       regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
+       regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
+
+       dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
+               devid, rev, (venid_h << 8) | venid_l);
+
+       ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
+       if (ret)
+               goto err;
+
+#ifdef CONFIG_OF
+       if (i2c->dev.of_node)
+               ret = of_platform_populate(i2c->dev.of_node,
+                                          NULL, NULL, &i2c->dev);
+#endif
+
+err:
+       return ret;
+}
+
+static int smsc_i2c_remove(struct i2c_client *i2c)
+{
+       struct smsc *smsc = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(smsc->dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id smsc_i2c_id[] = {
+       { "smscece1099", 0},
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, smsc_i2c_id);
+
+static struct i2c_driver smsc_i2c_driver = {
+       .driver = {
+                  .name = "smsc",
+                  .owner = THIS_MODULE,
+       },
+       .probe = smsc_i2c_probe,
+       .remove = smsc_i2c_remove,
+       .id_table = smsc_i2c_id,
+};
+
+module_i2c_driver(smsc_i2c_driver);
+
+MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
+MODULE_DESCRIPTION("SMSC chip multi-function driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
new file mode 100644 (file)
index 0000000..65fe609
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * System Control Driver
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct platform_driver syscon_driver;
+
+struct syscon {
+       struct device *dev;
+       void __iomem *base;
+       struct regmap *regmap;
+};
+
+static int syscon_match(struct device *dev, void *data)
+{
+       struct syscon *syscon = dev_get_drvdata(dev);
+       struct device_node *dn = data;
+
+       return (syscon->dev->of_node == dn) ? 1 : 0;
+}
+
+struct regmap *syscon_node_to_regmap(struct device_node *np)
+{
+       struct syscon *syscon;
+       struct device *dev;
+
+       dev = driver_find_device(&syscon_driver.driver, NULL, np,
+                                syscon_match);
+       if (!dev)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       syscon = dev_get_drvdata(dev);
+
+       return syscon->regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
+
+struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
+{
+       struct device_node *syscon_np;
+       struct regmap *regmap;
+
+       syscon_np = of_find_compatible_node(NULL, NULL, s);
+       if (!syscon_np)
+               return ERR_PTR(-ENODEV);
+
+       regmap = syscon_node_to_regmap(syscon_np);
+       of_node_put(syscon_np);
+
+       return regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
+
+struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
+                                       const char *property)
+{
+       struct device_node *syscon_np;
+       struct regmap *regmap;
+
+       syscon_np = of_parse_phandle(np, property, 0);
+       if (!syscon_np)
+               return ERR_PTR(-ENODEV);
+
+       regmap = syscon_node_to_regmap(syscon_np);
+       of_node_put(syscon_np);
+
+       return regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
+
+static const struct of_device_id of_syscon_match[] = {
+       { .compatible = "syscon", },
+       { },
+};
+
+static struct regmap_config syscon_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+};
+
+static int __devinit syscon_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct syscon *syscon;
+       struct resource res;
+       int ret;
+
+       if (!np)
+               return -ENOENT;
+
+       syscon = devm_kzalloc(dev, sizeof(struct syscon),
+                           GFP_KERNEL);
+       if (!syscon)
+               return -ENOMEM;
+
+       syscon->base = of_iomap(np, 0);
+       if (!syscon->base)
+               return -EADDRNOTAVAIL;
+
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret)
+               return ret;
+
+       syscon_regmap_config.max_register = res.end - res.start - 3;
+       syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
+                                       &syscon_regmap_config);
+       if (IS_ERR(syscon->regmap)) {
+               dev_err(dev, "regmap init failed\n");
+               return PTR_ERR(syscon->regmap);
+       }
+
+       syscon->dev = dev;
+       platform_set_drvdata(pdev, syscon);
+
+       dev_info(dev, "syscon regmap start 0x%x end 0x%x registered\n",
+               res.start, res.end);
+
+       return 0;
+}
+
+static int __devexit syscon_remove(struct platform_device *pdev)
+{
+       struct syscon *syscon;
+
+       syscon = platform_get_drvdata(pdev);
+       iounmap(syscon->base);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver syscon_driver = {
+       .driver = {
+               .name = "syscon",
+               .owner = THIS_MODULE,
+               .of_match_table = of_syscon_match,
+       },
+       .probe          = syscon_probe,
+       .remove         = __devexit_p(syscon_remove),
+};
+
+static int __init syscon_init(void)
+{
+       return platform_driver_register(&syscon_driver);
+}
+postcore_initcall(syscon_init);
+
+static void __exit syscon_exit(void)
+{
+       platform_driver_unregister(&syscon_driver);
+}
+module_exit(syscon_exit);
+
+MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
+MODULE_DESCRIPTION("System Control driver");
+MODULE_LICENSE("GPL v2");
index b56ba6b43294b77e536b12247c0e8b1d18085701..8f4c853ca116f1b34d73f811545a3c9f49ac4037 100644 (file)
@@ -9,8 +9,10 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tc3589x.h>
 
@@ -145,6 +147,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = {
                .name           = "tc3589x-gpio",
                .num_resources  = ARRAY_SIZE(gpio_resources),
                .resources      = &gpio_resources[0],
+               .of_compatible  = "tc3589x-gpio",
        },
 };
 
@@ -153,6 +156,7 @@ static struct mfd_cell tc3589x_dev_keypad[] = {
                .name           = "tc3589x-keypad",
                .num_resources  = ARRAY_SIZE(keypad_resources),
                .resources      = &keypad_resources[0],
+               .of_compatible  = "tc3589x-keypad",
        },
 };
 
@@ -168,8 +172,9 @@ again:
 
        while (status) {
                int bit = __ffs(status);
+               int virq = irq_create_mapping(tc3589x->domain, bit);
 
-               handle_nested_irq(tc3589x->irq_base + bit);
+               handle_nested_irq(virq);
                status &= ~(1 << bit);
        }
 
@@ -186,38 +191,60 @@ again:
        return IRQ_HANDLED;
 }
 
-static int tc3589x_irq_init(struct tc3589x *tc3589x)
+static int tc3589x_irq_map(struct irq_domain *d, unsigned int virq,
+                               irq_hw_number_t hwirq)
 {
-       int base = tc3589x->irq_base;
-       int irq;
+       struct tc3589x *tc3589x = d->host_data;
 
-       for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
-               irq_set_chip_data(irq, tc3589x);
-               irq_set_chip_and_handler(irq, &dummy_irq_chip,
-                                        handle_edge_irq);
-               irq_set_nested_thread(irq, 1);
+       irq_set_chip_data(virq, tc3589x);
+       irq_set_chip_and_handler(virq, &dummy_irq_chip,
+                               handle_edge_irq);
+       irq_set_nested_thread(virq, 1);
 #ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
+       set_irq_flags(virq, IRQF_VALID);
 #else
-               irq_set_noprobe(irq);
+       irq_set_noprobe(virq);
 #endif
-       }
 
        return 0;
 }
 
-static void tc3589x_irq_remove(struct tc3589x *tc3589x)
+static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
 {
-       int base = tc3589x->irq_base;
-       int irq;
-
-       for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
 #ifdef CONFIG_ARM
-               set_irq_flags(irq, 0);
+       set_irq_flags(virq, 0);
 #endif
-               irq_set_chip_and_handler(irq, NULL, NULL);
-               irq_set_chip_data(irq, NULL);
+       irq_set_chip_and_handler(virq, NULL, NULL);
+       irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops tc3589x_irq_ops = {
+        .map    = tc3589x_irq_map,
+       .unmap  = tc3589x_irq_unmap,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
+{
+       int base = tc3589x->irq_base;
+
+       if (base) {
+               tc3589x->domain = irq_domain_add_legacy(
+                       NULL, TC3589x_NR_INTERNAL_IRQS, base,
+                       0, &tc3589x_irq_ops, tc3589x);
+       }
+       else {
+               tc3589x->domain = irq_domain_add_linear(
+                       np, TC3589x_NR_INTERNAL_IRQS,
+                       &tc3589x_irq_ops, tc3589x);
        }
+
+       if (!tc3589x->domain) {
+               dev_err(tc3589x->dev, "Failed to create irqdomain\n");
+               return -ENOSYS;
+       }
+
+       return 0;
 }
 
 static int tc3589x_chip_init(struct tc3589x *tc3589x)
@@ -263,7 +290,7 @@ 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, NULL);
+                                     tc3589x->irq_base, tc3589x->domain);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to add gpio child\n");
                        return ret;
@@ -274,7 +301,7 @@ 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, NULL);
+                                     tc3589x->irq_base, tc3589x->domain);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to keypad child\n");
                        return ret;
@@ -285,13 +312,47 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
        return ret;
 }
 
+static int tc3589x_of_probe(struct device_node *np,
+                       struct tc3589x_platform_data *pdata)
+{
+       struct device_node *child;
+
+       for_each_child_of_node(np, child) {
+               if (!strcmp(child->name, "tc3589x_gpio")) {
+                       pdata->block |= TC3589x_BLOCK_GPIO;
+               }
+               if (!strcmp(child->name, "tc3589x_keypad")) {
+                       pdata->block |= TC3589x_BLOCK_KEYPAD;
+               }
+       }
+
+       return 0;
+}
+
 static int __devinit tc3589x_probe(struct i2c_client *i2c,
                                   const struct i2c_device_id *id)
 {
        struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
+       struct device_node *np = i2c->dev.of_node;
        struct tc3589x *tc3589x;
        int ret;
 
+       if (!pdata) {
+               if (np) {
+                       pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+                       if (!pdata)
+                               return -ENOMEM;
+
+                       ret = tc3589x_of_probe(np, pdata);
+                       if (ret)
+                               return ret;
+               }
+               else {
+                       dev_err(&i2c->dev, "No platform data or DT found\n");
+                       return -EINVAL;
+               }
+       }
+
        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA
                                     | I2C_FUNC_SMBUS_I2C_BLOCK))
                return -EIO;
@@ -314,7 +375,7 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
        if (ret)
                goto out_free;
 
-       ret = tc3589x_irq_init(tc3589x);
+       ret = tc3589x_irq_init(tc3589x, np);
        if (ret)
                goto out_free;
 
@@ -323,7 +384,7 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
                                   "tc3589x", tc3589x);
        if (ret) {
                dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret);
-               goto out_removeirq;
+               goto out_free;
        }
 
        ret = tc3589x_device_init(tc3589x);
@@ -336,8 +397,6 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c,
 
 out_freeirq:
        free_irq(tc3589x->i2c->irq, tc3589x);
-out_removeirq:
-       tc3589x_irq_remove(tc3589x);
 out_free:
        kfree(tc3589x);
        return ret;
@@ -350,7 +409,6 @@ static int __devexit tc3589x_remove(struct i2c_client *client)
        mfd_remove_devices(tc3589x->dev);
 
        free_irq(tc3589x->i2c->irq, tc3589x);
-       tc3589x_irq_remove(tc3589x);
 
        kfree(tc3589x);
 
index 50fd87c87a1cca64e21104401c1adbff1b4cf45c..074ae32b0d2ad12998394584bd76b2a13ca1b981 100644 (file)
@@ -236,7 +236,7 @@ static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
 
 static bool is_volatile_reg(struct device *dev, unsigned int reg)
 {
-       if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS))
+       if (reg == TPS65090_INT_STS)
                return true;
        else
                return false;
index a95e9421b73580df95402f718a4166898a1c41dd..3fb32e655254789c5035f31b4284e30e2e4225ae 100644 (file)
@@ -34,6 +34,9 @@ static struct mfd_cell tps65217s[] = {
        {
                .name = "tps65217-pmic",
        },
+       {
+               .name = "tps65217-bl",
+       },
 };
 
 /**
index 345960ca2fd8991f1ccb5d2656a2bb877f8d7938..4674643687736679c69d74a337b1a0701f54f0bc 100644 (file)
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
 
+#define TPS6586X_SUPPLYENE     0x14
+#define EXITSLREQ_BIT          BIT(1)
+#define SLEEP_MODE_BIT         BIT(3)
+
 /* interrupt control registers */
 #define TPS6586X_INT_ACK1      0xb5
 #define TPS6586X_INT_ACK2      0xb6
@@ -422,6 +426,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
        pdata->subdevs = devs;
        pdata->gpio_base = -1;
        pdata->irq_base = -1;
+       pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
 
        return pdata;
 }
@@ -454,6 +459,15 @@ static const struct regmap_config tps6586x_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
+static struct device *tps6586x_dev;
+static void tps6586x_power_off(void)
+{
+       if (tps6586x_clr_bits(tps6586x_dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT))
+               return;
+
+       tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+}
+
 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
@@ -519,6 +533,11 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
                goto err_add_devs;
        }
 
+       if (pdata->pm_off && !pm_power_off) {
+               tps6586x_dev = &client->dev;
+               pm_power_off = tps6586x_power_off;
+       }
+
        return 0;
 
 err_add_devs:
index d3ce4d569deb57c2b707dc73d6cb7cf600962cab..0d79ce2b5014c938b0f366d74639eace2508659e 100644 (file)
 #include <linux/mfd/tps65910.h>
 #include <linux/of_device.h>
 
+static struct resource rtc_resources[] = {
+       {
+               .start  = TPS65910_IRQ_RTC_ALARM,
+               .end    = TPS65910_IRQ_RTC_ALARM,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
 static struct mfd_cell tps65910s[] = {
        {
                .name = "tps65910-gpio",
@@ -33,6 +41,8 @@ static struct mfd_cell tps65910s[] = {
        },
        {
                .name = "tps65910-rtc",
+               .num_resources = ARRAY_SIZE(rtc_resources),
+               .resources = &rtc_resources[0],
        },
        {
                .name = "tps65910-power",
@@ -198,6 +208,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
 
        board_info->irq = client->irq;
        board_info->irq_base = -1;
+       board_info->pm_off = of_property_read_bool(np,
+                       "ti,system-power-controller");
 
        return board_info;
 }
@@ -210,6 +222,21 @@ struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
 }
 #endif
 
+static struct i2c_client *tps65910_i2c_client;
+static void tps65910_power_off(void)
+{
+       struct tps65910 *tps65910;
+
+       tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev);
+
+       if (tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
+                       DEVCTRL_PWR_OFF_MASK) < 0)
+               return;
+
+       tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
+                       DEVCTRL_DEV_ON_MASK);
+}
+
 static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
                                        const struct i2c_device_id *id)
 {
@@ -267,6 +294,11 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
        tps65910_ck32k_init(tps65910, pmic_plat_data);
        tps65910_sleepinit(tps65910, pmic_plat_data);
 
+       if (pmic_plat_data->pm_off && !pm_power_off) {
+               tps65910_i2c_client = i2c;
+               pm_power_off = tps65910_power_off;
+       }
+
        return ret;
 }
 
index 9d3a0bc1a65f966a950af39ecb94df0e07a591f3..4ae6423202058c0e1e7d7c9c262b8c25fd38d917 100644 (file)
 
 #define DRIVER_NAME                    "twl"
 
-#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
-#define twl_has_keypad()       true
-#else
-#define twl_has_keypad()       false
-#endif
-
-#if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE)
-#define twl_has_gpio() true
-#else
-#define twl_has_gpio() false
-#endif
-
-#if defined(CONFIG_REGULATOR_TWL4030) \
-       || defined(CONFIG_REGULATOR_TWL4030_MODULE)
-#define twl_has_regulator()    true
-#else
-#define twl_has_regulator()    false
-#endif
-
-#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
-#define twl_has_madc() true
-#else
-#define twl_has_madc() false
-#endif
-
-#ifdef CONFIG_TWL4030_POWER
-#define twl_has_power()        true
-#else
-#define twl_has_power()        false
-#endif
-
-#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE)
-#define twl_has_rtc()  true
-#else
-#define twl_has_rtc()  false
-#endif
-
-#if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) ||\
-       defined(CONFIG_TWL6030_USB) || defined(CONFIG_TWL6030_USB_MODULE)
-#define twl_has_usb()  true
-#else
-#define twl_has_usb()  false
-#endif
-
-#if defined(CONFIG_TWL4030_WATCHDOG) || \
-       defined(CONFIG_TWL4030_WATCHDOG_MODULE)
-#define twl_has_watchdog()        true
-#else
-#define twl_has_watchdog()        false
-#endif
-
-#if defined(CONFIG_MFD_TWL4030_AUDIO) || \
-       defined(CONFIG_MFD_TWL4030_AUDIO_MODULE)
-#define twl_has_codec()        true
-#else
-#define twl_has_codec()        false
-#endif
-
-#if defined(CONFIG_CHARGER_TWL4030) || defined(CONFIG_CHARGER_TWL4030_MODULE)
-#define twl_has_bci()  true
-#else
-#define twl_has_bci()  false
-#endif
-
 /* Triton Core internal information (BEGIN) */
 
 /* Last - for index max*/
 
 #define TWL_NUM_SLAVES         4
 
-#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
-       || defined(CONFIG_INPUT_TWL4030_PWRBUTTON_MODULE)
-#define twl_has_pwrbutton()    true
-#else
-#define twl_has_pwrbutton()    false
-#endif
-
 #define SUB_CHIP_ID0 0
 #define SUB_CHIP_ID1 1
 #define SUB_CHIP_ID2 2
@@ -552,6 +481,38 @@ int twl_get_version(void)
 }
 EXPORT_SYMBOL_GPL(twl_get_version);
 
+/**
+ * twl_get_hfclk_rate - API to get TWL external HFCLK clock rate.
+ *
+ * Api to get the TWL HFCLK rate based on BOOT_CFG register.
+ */
+int twl_get_hfclk_rate(void)
+{
+       u8 ctrl;
+       int rate;
+
+       twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &ctrl, R_CFG_BOOT);
+
+       switch (ctrl & 0x3) {
+       case HFCLK_FREQ_19p2_MHZ:
+               rate = 19200000;
+               break;
+       case HFCLK_FREQ_26_MHZ:
+               rate = 26000000;
+               break;
+       case HFCLK_FREQ_38p4_MHZ:
+               rate = 38400000;
+               break;
+       default:
+               pr_err("TWL4030: HFCLK is not configured\n");
+               rate = -EINVAL;
+               break;
+       }
+
+       return rate;
+}
+EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
+
 static struct device *
 add_numbered_child(unsigned chip, const char *name, int num,
                void *pdata, unsigned pdata_len,
@@ -669,7 +630,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        struct device   *child;
        unsigned sub_chip_id;
 
-       if (twl_has_gpio() && pdata->gpio) {
+       if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
                child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
                                pdata->gpio, sizeof(*pdata->gpio),
                                false, irq_base + GPIO_INTR_OFFSET, 0);
@@ -677,7 +638,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       if (twl_has_keypad() && pdata->keypad) {
+       if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
                child = add_child(SUB_CHIP_ID2, "twl4030_keypad",
                                pdata->keypad, sizeof(*pdata->keypad),
                                true, irq_base + KEYPAD_INTR_OFFSET, 0);
@@ -685,7 +646,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       if (twl_has_madc() && pdata->madc) {
+       if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc) {
                child = add_child(2, "twl4030_madc",
                                pdata->madc, sizeof(*pdata->madc),
                                true, irq_base + MADC_INTR_OFFSET, 0);
@@ -693,7 +654,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       if (twl_has_rtc()) {
+       if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
                /*
                 * REVISIT platform_data here currently might expose the
                 * "msecure" line ... but for now we just expect board
@@ -709,7 +670,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       if (twl_has_usb() && pdata->usb && twl_class_is_4030()) {
+       if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
+               child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+                                 false, 0, 0);
+               if (IS_ERR(child))
+                       return PTR_ERR(child);
+       }
+
+       if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
+           twl_class_is_4030()) {
 
                static struct regulator_consumer_supply usb1v5 = {
                        .supply =       "usb1v5",
@@ -723,7 +692,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                };
 
        /* First add the regulators so that they can be used by transceiver */
-               if (twl_has_regulator()) {
+               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
                        /* this is a template that gets copied */
                        struct regulator_init_data usb_fixed = {
                                .constraints.valid_modes_mask =
@@ -765,18 +734,19 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
 
                /* we need to connect regulators to this transceiver */
-               if (twl_has_regulator() && child) {
+               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
                        usb1v5.dev_name = dev_name(child);
                        usb1v8.dev_name = dev_name(child);
                        usb3v1[0].dev_name = dev_name(child);
                }
        }
-       if (twl_has_usb() && pdata->usb && twl_class_is_6030()) {
+       if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
+           twl_class_is_6030()) {
 
                static struct regulator_consumer_supply usb3v3;
                int regulator;
 
-               if (twl_has_regulator()) {
+               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
                        /* this is a template that gets copied */
                        struct regulator_init_data usb_fixed = {
                                .constraints.valid_modes_mask =
@@ -813,9 +783,10 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                if (IS_ERR(child))
                        return PTR_ERR(child);
                /* we need to connect regulators to this transceiver */
-               if (twl_has_regulator() && child)
+               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
                        usb3v3.dev_name = dev_name(child);
-       } else if (twl_has_regulator() && twl_class_is_6030()) {
+       } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
+                  twl_class_is_6030()) {
                if (features & TWL6025_SUBCLASS)
                        child = add_regulator(TWL6025_REG_LDOUSB,
                                                pdata->ldousb, features);
@@ -827,20 +798,21 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                                        return PTR_ERR(child);
        }
 
-       if (twl_has_watchdog() && twl_class_is_4030()) {
+       if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
                child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
 
-       if (twl_has_pwrbutton() && twl_class_is_4030()) {
+       if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
                child = add_child(1, "twl4030_pwrbutton",
                                NULL, 0, true, irq_base + 8 + 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
 
-       if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
+       if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
+           twl_class_is_4030()) {
                sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
                child = add_child(sub_chip_id, "twl4030-audio",
                                pdata->audio, sizeof(*pdata->audio),
@@ -850,7 +822,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        /* twl4030 regulators */
-       if (twl_has_regulator() && twl_class_is_4030()) {
+       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
                child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
                                        features);
                if (IS_ERR(child))
@@ -905,7 +877,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        /* maybe add LDOs that are omitted on cost-reduced parts */
-       if (twl_has_regulator() && !(features & TPS_SUBSET)
+       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
          && twl_class_is_4030()) {
                child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
                                        features);
@@ -939,7 +911,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        /* twl6030 regulators */
-       if (twl_has_regulator() && twl_class_is_6030() &&
+       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
                        !(features & TWL6025_SUBCLASS)) {
                child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
                                        features);
@@ -1013,7 +985,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        /* 6030 and 6025 share this regulator */
-       if (twl_has_regulator() && twl_class_is_6030()) {
+       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
                child = add_regulator(TWL6030_REG_VANA, pdata->vana,
                                        features);
                if (IS_ERR(child))
@@ -1021,7 +993,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        /* twl6025 regulators */
-       if (twl_has_regulator() && twl_class_is_6030() &&
+       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
                        (features & TWL6025_SUBCLASS)) {
                child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5,
                                        features);
@@ -1080,7 +1052,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
 
        }
 
-       if (twl_has_bci() && pdata->bci &&
+       if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
                        !(features & (TPS_SUBSET | TWL5031))) {
                child = add_child(3, "twl4030_bci",
                                pdata->bci, sizeof(*pdata->bci), false,
@@ -1295,7 +1267,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
        }
 
        /* load power event scripts */
-       if (twl_has_power() && pdata->power)
+       if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power)
                twl4030_power_init(pdata->power);
 
        /* Maybe init the T2 Interrupt subsystem */
index 77c9acb145831c5b03fd04cbc08d0f6e0bfd47ec..5c11acf9e0fd5badb5510dfae23f07bb9b905dd6 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl4030-audio.h>
@@ -156,47 +158,70 @@ unsigned int twl4030_audio_get_mclk(void)
 }
 EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
 
+static bool twl4030_audio_has_codec(struct twl4030_audio_data *pdata,
+                             struct device_node *node)
+{
+       if (pdata && pdata->codec)
+               return true;
+
+       if (of_find_node_by_name(node, "codec"))
+               return true;
+
+       return false;
+}
+
+static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
+                             struct device_node *node)
+{
+       int vibra;
+
+       if (pdata && pdata->vibra)
+               return true;
+
+       if (!of_property_read_u32(node, "ti,enable-vibra", &vibra) && vibra)
+               return true;
+
+       return false;
+}
+
 static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 {
        struct twl4030_audio *audio;
        struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+       struct device_node *node = pdev->dev.of_node;
        struct mfd_cell *cell = NULL;
        int ret, childs = 0;
        u8 val;
 
-       if (!pdata) {
+       if (!pdata && !node) {
                dev_err(&pdev->dev, "Platform data is missing\n");
                return -EINVAL;
        }
 
+       audio = devm_kzalloc(&pdev->dev, sizeof(struct twl4030_audio),
+                            GFP_KERNEL);
+       if (!audio)
+               return -ENOMEM;
+
+       mutex_init(&audio->mutex);
+       audio->audio_mclk = twl_get_hfclk_rate();
+
        /* Configure APLL_INFREQ and disable APLL if enabled */
-       val = 0;
-       switch (pdata->audio_mclk) {
+       switch (audio->audio_mclk) {
        case 19200000:
-               val |= TWL4030_APLL_INFREQ_19200KHZ;
+               val = TWL4030_APLL_INFREQ_19200KHZ;
                break;
        case 26000000:
-               val |= TWL4030_APLL_INFREQ_26000KHZ;
+               val = TWL4030_APLL_INFREQ_26000KHZ;
                break;
        case 38400000:
-               val |= TWL4030_APLL_INFREQ_38400KHZ;
+               val = TWL4030_APLL_INFREQ_38400KHZ;
                break;
        default:
                dev_err(&pdev->dev, "Invalid audio_mclk\n");
                return -EINVAL;
        }
-       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       val, TWL4030_REG_APLL_CTL);
-
-       audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
-       if (!audio)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, audio);
-
-       twl4030_audio_dev = pdev;
-       mutex_init(&audio->mutex);
-       audio->audio_mclk = pdata->audio_mclk;
+       twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, val, TWL4030_REG_APLL_CTL);
 
        /* Codec power */
        audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
@@ -206,21 +231,28 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
        audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
        audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
 
-       if (pdata->codec) {
+       if (twl4030_audio_has_codec(pdata, node)) {
                cell = &audio->cells[childs];
                cell->name = "twl4030-codec";
-               cell->platform_data = pdata->codec;
-               cell->pdata_size = sizeof(*pdata->codec);
+               if (pdata) {
+                       cell->platform_data = pdata->codec;
+                       cell->pdata_size = sizeof(*pdata->codec);
+               }
                childs++;
        }
-       if (pdata->vibra) {
+       if (twl4030_audio_has_vibra(pdata, node)) {
                cell = &audio->cells[childs];
                cell->name = "twl4030-vibra";
-               cell->platform_data = pdata->vibra;
-               cell->pdata_size = sizeof(*pdata->vibra);
+               if (pdata) {
+                       cell->platform_data = pdata->vibra;
+                       cell->pdata_size = sizeof(*pdata->vibra);
+               }
                childs++;
        }
 
+       platform_set_drvdata(pdev, audio);
+       twl4030_audio_dev = pdev;
+
        if (childs)
                ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
                                      childs, NULL, 0, NULL);
@@ -229,39 +261,42 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
                ret = -ENODEV;
        }
 
-       if (!ret)
-               return 0;
+       if (ret) {
+               platform_set_drvdata(pdev, NULL);
+               twl4030_audio_dev = NULL;
+       }
 
-       platform_set_drvdata(pdev, NULL);
-       kfree(audio);
-       twl4030_audio_dev = NULL;
        return ret;
 }
 
 static int __devexit twl4030_audio_remove(struct platform_device *pdev)
 {
-       struct twl4030_audio *audio = platform_get_drvdata(pdev);
-
        mfd_remove_devices(&pdev->dev);
        platform_set_drvdata(pdev, NULL);
-       kfree(audio);
        twl4030_audio_dev = NULL;
 
        return 0;
 }
 
-MODULE_ALIAS("platform:twl4030-audio");
+static const struct of_device_id twl4030_audio_of_match[] = {
+       {.compatible = "ti,twl4030-audio", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, twl4030_audio_of_match);
 
 static struct platform_driver twl4030_audio_driver = {
-       .probe          = twl4030_audio_probe,
-       .remove         = __devexit_p(twl4030_audio_remove),
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "twl4030-audio",
+               .of_match_table = twl4030_audio_of_match,
        },
+       .probe          = twl4030_audio_probe,
+       .remove         = __devexit_p(twl4030_audio_remove),
 };
 
 module_platform_driver(twl4030_audio_driver);
 
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("TWL4030 audio block MFD driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030-audio");
index 3dca5c195a200505c3796c488b34b65f8a32b7e6..3f2a1cf02fc0697d2c56c3fcb3f84cc8106fda21 100644 (file)
@@ -584,7 +584,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
                goto irq_init_err;
 
        ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
-                                  NULL, twl6040_naudint_handler, 0,
+                                  NULL, twl6040_naudint_handler, IRQF_ONESHOT,
                                   "twl6040_irq_ready", twl6040);
        if (ret) {
                dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
@@ -631,6 +631,21 @@ static int __devinit twl6040_probe(struct i2c_client *client,
                children++;
        }
 
+       /*
+        * Enable the GPO driver in the following cases:
+        * DT booted kernel or legacy boot with valid gpo platform_data
+        */
+       if (!pdata || (pdata && pdata->gpo)) {
+               cell = &twl6040->cells[children];
+               cell->name = "twl6040-gpo";
+
+               if (pdata) {
+                       cell->platform_data = pdata->gpo;
+                       cell->pdata_size = sizeof(*pdata->gpo);
+               }
+               children++;
+       }
+
        ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
                              NULL, 0, NULL);
        if (ret)
index bd8782c8896b50d3f0c22cd25d98627909a2d5d8..adda6b10b90d87ff64e29503c20139022f97465c 100644 (file)
@@ -133,15 +133,109 @@ static const struct reg_default wm5110_reva_patch[] = {
        { 0x209, 0x002A },
 };
 
+static const struct reg_default wm5110_revb_patch[] = {
+       { 0x80, 0x3 },
+       { 0x36e, 0x0210 },
+       { 0x370, 0x0210 },
+       { 0x372, 0x0210 },
+       { 0x374, 0x0210 },
+       { 0x376, 0x0210 },
+       { 0x378, 0x0210 },
+       { 0x36d, 0x0028 },
+       { 0x36f, 0x0028 },
+       { 0x371, 0x0028 },
+       { 0x373, 0x0028 },
+       { 0x375, 0x0028 },
+       { 0x377, 0x0028 },
+       { 0x280, 0x2002 },
+       { 0x44, 0x20 },
+       { 0x45, 0x40 },
+       { 0x46, 0x60 },
+       { 0x47, 0x80 },
+       { 0x48, 0xa0 },
+       { 0x51, 0x13 },
+       { 0x52, 0x33 },
+       { 0x53, 0x53 },
+       { 0x54, 0x73 },
+       { 0x55, 0x93 },
+       { 0x56, 0xb3 },
+       { 0xc30, 0x3e3e },
+       { 0xc31, 0x3e },
+       { 0xc32, 0x3e3e },
+       { 0xc33, 0x3e3e },
+       { 0xc34, 0x3e3e },
+       { 0xc35, 0x3e3e },
+       { 0xc36, 0x3e3e },
+       { 0xc37, 0x3e3e },
+       { 0xc38, 0x3e3e },
+       { 0xc39, 0x3e3e },
+       { 0xc3a, 0x3e3e },
+       { 0xc3b, 0x3e3e },
+       { 0xc3c, 0x3e },
+       { 0x201, 0x18a5 },
+       { 0x202, 0x4100 },
+       { 0x460, 0x0c40 },
+       { 0x461, 0x8000 },
+       { 0x462, 0x0c41 },
+       { 0x463, 0x4820 },
+       { 0x464, 0x0c41 },
+       { 0x465, 0x4040 },
+       { 0x466, 0x0841 },
+       { 0x467, 0x3940 },
+       { 0x468, 0x0841 },
+       { 0x469, 0x2030 },
+       { 0x46a, 0x0842 },
+       { 0x46b, 0x1990 },
+       { 0x46c, 0x08c2 },
+       { 0x46d, 0x1450 },
+       { 0x46e, 0x08c6 },
+       { 0x46f, 0x1020 },
+       { 0x470, 0x08c6 },
+       { 0x471, 0x0cd0 },
+       { 0x472, 0x08c6 },
+       { 0x473, 0x0a30 },
+       { 0x474, 0x0442 },
+       { 0x475, 0x0660 },
+       { 0x476, 0x0446 },
+       { 0x477, 0x0510 },
+       { 0x478, 0x04c6 },
+       { 0x479, 0x0400 },
+       { 0x47a, 0x04ce },
+       { 0x47b, 0x0330 },
+       { 0x47c, 0x05df },
+       { 0x47d, 0x0001 },
+       { 0x47e, 0x07ff },
+       { 0x2db, 0x0a00 },
+       { 0x2dd, 0x0023 },
+       { 0x2df, 0x0102 },
+       { 0x2ef, 0x924 },
+       { 0x2f0, 0x924 },
+       { 0x2f1, 0x924 },
+       { 0x2f2, 0x924 },
+       { 0x2f3, 0x924 },
+       { 0x2f4, 0x924 },
+       { 0x2eb, 0x60 },
+       { 0x2ec, 0x60 },
+       { 0x2ed, 0x60 },
+       { 0x4f2, 0x33e },
+       { 0x458, 0x0000 },
+       { 0x15a, 0x0003 },
+       { 0x80, 0x0 },
+};
+
 /* We use a function so we can use ARRAY_SIZE() */
 int wm5110_patch(struct arizona *arizona)
 {
        switch (arizona->rev) {
        case 0:
-       case 1:
                return regmap_register_patch(arizona->regmap,
                                             wm5110_reva_patch,
                                             ARRAY_SIZE(wm5110_reva_patch));
+       case 1:
+               return regmap_register_patch(arizona->regmap,
+                                            wm5110_revb_patch,
+                                            ARRAY_SIZE(wm5110_revb_patch));
+
        default:
                return 0;
        }
index 3017310359403248719495fe39692698271ba7ed..521340a708d3a76d9ae6ef8241f085bcd623439a 100644 (file)
@@ -614,18 +614,11 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
 }
 EXPORT_SYMBOL_GPL(wm831x_set_bits);
 
-static struct resource wm831x_io_parent = {
-       .start = 0,
-       .end   = 0xffffffff,
-       .flags = IORESOURCE_IO,
-};
-
 static struct resource wm831x_dcdc1_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_DC1_CONTROL_1,
                .end   = WM831X_DC1_DVS_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -644,10 +637,9 @@ static struct resource wm831x_dcdc1_resources[] = {
 
 static struct resource wm831x_dcdc2_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_DC2_CONTROL_1,
                .end   = WM831X_DC2_DVS_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -665,10 +657,9 @@ static struct resource wm831x_dcdc2_resources[] = {
 
 static struct resource wm831x_dcdc3_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_DC3_CONTROL_1,
                .end   = WM831X_DC3_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -680,10 +671,9 @@ static struct resource wm831x_dcdc3_resources[] = {
 
 static struct resource wm831x_dcdc4_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_DC4_CONTROL,
                .end   = WM831X_DC4_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -695,10 +685,9 @@ static struct resource wm831x_dcdc4_resources[] = {
 
 static struct resource wm8320_dcdc4_buck_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_DC4_CONTROL,
                .end   = WM832X_DC4_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -718,10 +707,9 @@ static struct resource wm831x_gpio_resources[] = {
 
 static struct resource wm831x_isink1_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_CURRENT_SINK_1,
                .end   = WM831X_CURRENT_SINK_1,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .start = WM831X_IRQ_CS1,
@@ -732,10 +720,9 @@ static struct resource wm831x_isink1_resources[] = {
 
 static struct resource wm831x_isink2_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_CURRENT_SINK_2,
                .end   = WM831X_CURRENT_SINK_2,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .start = WM831X_IRQ_CS2,
@@ -746,10 +733,9 @@ static struct resource wm831x_isink2_resources[] = {
 
 static struct resource wm831x_ldo1_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO1_CONTROL,
                .end   = WM831X_LDO1_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -761,10 +747,9 @@ static struct resource wm831x_ldo1_resources[] = {
 
 static struct resource wm831x_ldo2_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO2_CONTROL,
                .end   = WM831X_LDO2_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -776,10 +761,9 @@ static struct resource wm831x_ldo2_resources[] = {
 
 static struct resource wm831x_ldo3_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO3_CONTROL,
                .end   = WM831X_LDO3_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -791,10 +775,9 @@ static struct resource wm831x_ldo3_resources[] = {
 
 static struct resource wm831x_ldo4_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO4_CONTROL,
                .end   = WM831X_LDO4_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -806,10 +789,9 @@ static struct resource wm831x_ldo4_resources[] = {
 
 static struct resource wm831x_ldo5_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO5_CONTROL,
                .end   = WM831X_LDO5_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -821,10 +803,9 @@ static struct resource wm831x_ldo5_resources[] = {
 
 static struct resource wm831x_ldo6_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO6_CONTROL,
                .end   = WM831X_LDO6_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -836,10 +817,9 @@ static struct resource wm831x_ldo6_resources[] = {
 
 static struct resource wm831x_ldo7_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO7_CONTROL,
                .end   = WM831X_LDO7_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -851,10 +831,9 @@ static struct resource wm831x_ldo7_resources[] = {
 
 static struct resource wm831x_ldo8_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO8_CONTROL,
                .end   = WM831X_LDO8_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -866,10 +845,9 @@ static struct resource wm831x_ldo8_resources[] = {
 
 static struct resource wm831x_ldo9_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO9_CONTROL,
                .end   = WM831X_LDO9_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -881,10 +859,9 @@ static struct resource wm831x_ldo9_resources[] = {
 
 static struct resource wm831x_ldo10_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO10_CONTROL,
                .end   = WM831X_LDO10_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
        {
                .name  = "UV",
@@ -896,10 +873,9 @@ static struct resource wm831x_ldo10_resources[] = {
 
 static struct resource wm831x_ldo11_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_LDO11_ON_CONTROL,
                .end   = WM831X_LDO11_SLEEP_CONTROL,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
 };
 
@@ -998,19 +974,17 @@ static struct resource wm831x_rtc_resources[] = {
 
 static struct resource wm831x_status1_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_STATUS_LED_1,
                .end   = WM831X_STATUS_LED_1,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
 };
 
 static struct resource wm831x_status2_resources[] = {
        {
-               .parent = &wm831x_io_parent,
                .start = WM831X_STATUS_LED_2,
                .end   = WM831X_STATUS_LED_2,
-               .flags = IORESOURCE_IO,
+               .flags = IORESOURCE_REG,
        },
 };
 
index 2febf88cfce8847383be5a4fe8ab80ae89fe48e2..8fefc961ec0663ef4d8147e52058c942bb94a2df 100644 (file)
@@ -374,23 +374,23 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
 }
 #endif
 
-static const __devinitdata struct reg_default wm8994_revc_patch[] = {
+static const __devinitconst struct reg_default wm8994_revc_patch[] = {
        { 0x102, 0x3 },
        { 0x56, 0x3 },
        { 0x817, 0x0 },
        { 0x102, 0x0 },
 };
 
-static const __devinitdata struct reg_default wm8958_reva_patch[] = {
+static const __devinitconst struct reg_default wm8958_reva_patch[] = {
        { 0x102, 0x3 },
        { 0xcb, 0x81 },
        { 0x817, 0x0 },
        { 0x102, 0x0 },
 };
 
-static const __devinitdata struct reg_default wm1811_reva_patch[] = {
+static const __devinitconst struct reg_default wm1811_reva_patch[] = {
        { 0x102, 0x3 },
-       { 0x56, 0x7 },
+       { 0x56, 0xc07 },
        { 0x5d, 0x7e },
        { 0x5e, 0x0 },
        { 0x102, 0x0 },
index 52e9e29449403b1d5b21dc215973f7e4b8de41e6..2fbce9c5950b5fb9657c3589f77e3b5fe5cf5726 100644 (file)
@@ -1136,7 +1136,7 @@ static bool wm1811_volatile_register(struct device *dev, unsigned int reg)
 
        switch (reg) {
        case WM8994_GPIO_6:
-               if (wm8994->revision > 1)
+               if (wm8994->cust_id > 1 || wm8994->revision > 1)
                        return true;
                else
                        return false;
index 504da715a41ae30f3e5670ff305801167ee60935..9722d43d61407d85b45a64ae1cf9a05a7196d231 100644 (file)
@@ -653,7 +653,7 @@ static const struct sdhci_pci_fixes sdhci_via = {
        .probe          = via_probe,
 };
 
-static const struct pci_device_id pci_ids[] __devinitdata = {
+static const struct pci_device_id pci_ids[] __devinitconst = {
        {
                .vendor         = PCI_VENDOR_ID_RICOH,
                .device         = PCI_DEVICE_ID_RICOH_R5C822,
index 9602c1b7e27e8e5a70c66f50a47df04693b4bf1e..01e2f2e87d8c2b7166f548f6ec14d557b596673b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <asm/fsl_ifc.h>
 
+#define FSL_IFC_V1_1_0 0x01010000
 #define ERR_BYTE               0xFF /* Value returned for read
                                        bytes when read failed  */
 #define IFC_TIMEOUT_MSECS      500  /* Maximum number of mSecs to wait
@@ -773,13 +774,62 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
        return 0;
 }
 
+static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
+{
+       struct fsl_ifc_ctrl *ctrl = priv->ctrl;
+       struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
+       uint32_t csor = 0, csor_8k = 0, csor_ext = 0;
+       uint32_t cs = priv->bank;
+
+       /* Save CSOR and CSOR_ext */
+       csor = in_be32(&ifc->csor_cs[cs].csor);
+       csor_ext = in_be32(&ifc->csor_cs[cs].csor_ext);
+
+       /* chage PageSize 8K and SpareSize 1K*/
+       csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
+       out_be32(&ifc->csor_cs[cs].csor, csor_8k);
+       out_be32(&ifc->csor_cs[cs].csor_ext, 0x0000400);
+
+       /* READID */
+       out_be32(&ifc->ifc_nand.nand_fir0,
+                       (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+                       (IFC_FIR_OP_UA  << IFC_NAND_FIR0_OP1_SHIFT) |
+                       (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+       out_be32(&ifc->ifc_nand.nand_fcr0,
+                       NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+       out_be32(&ifc->ifc_nand.row3, 0x0);
+
+       out_be32(&ifc->ifc_nand.nand_fbcr, 0x0);
+
+       /* Program ROW0/COL0 */
+       out_be32(&ifc->ifc_nand.row0, 0x0);
+       out_be32(&ifc->ifc_nand.col0, 0x0);
+
+       /* set the chip select for NAND Transaction */
+       out_be32(&ifc->ifc_nand.nand_csel, cs << IFC_NAND_CSEL_SHIFT);
+
+       /* start read seq */
+       out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+
+       /* wait for command complete flag or timeout */
+       wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
+                          IFC_TIMEOUT_MSECS * HZ/1000);
+
+       if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
+               printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n");
+
+       /* Restore CSOR and CSOR_ext */
+       out_be32(&ifc->csor_cs[cs].csor, csor);
+       out_be32(&ifc->csor_cs[cs].csor_ext, csor_ext);
+}
+
 static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 {
        struct fsl_ifc_ctrl *ctrl = priv->ctrl;
        struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
        struct nand_chip *chip = &priv->chip;
        struct nand_ecclayout *layout;
-       u32 csor;
+       u32 csor, ver;
 
        /* Fill in fsl_ifc_mtd structure */
        priv->mtd.priv = chip;
@@ -874,6 +924,10 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
                chip->ecc.mode = NAND_ECC_SOFT;
        }
 
+       ver = in_be32(&ifc->ifc_rev);
+       if (ver == FSL_IFC_V1_1_0)
+               fsl_ifc_sram_init(priv);
+
        return 0;
 }
 
index 7858c58df4a3a12c47de7c1a015b613781352c19..b721902bb6b4ab785497fb345cd76f683a11f78b 100644 (file)
@@ -4826,6 +4826,7 @@ static int bond_check_params(struct bond_params *params)
 
 static struct lock_class_key bonding_netdev_xmit_lock_key;
 static struct lock_class_key bonding_netdev_addr_lock_key;
+static struct lock_class_key bonding_tx_busylock_key;
 
 static void bond_set_lockdep_class_one(struct net_device *dev,
                                       struct netdev_queue *txq,
@@ -4840,6 +4841,7 @@ static void bond_set_lockdep_class(struct net_device *dev)
        lockdep_set_class(&dev->addr_list_lock,
                          &bonding_netdev_addr_lock_key);
        netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
+       dev->qdisc_tx_busylock = &bonding_tx_busylock_key;
 }
 
 /*
index c975999bb05587e400e635ecd65c7d51c8dd2d24..799c354083c4800cf738837587a202725322cbac 100644 (file)
@@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
 }
 #endif /* CONFIG_PPC_MPC512x */
 
-static struct of_device_id mpc5xxx_can_table[];
+static const struct of_device_id mpc5xxx_can_table[];
 static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
 {
        const struct of_device_id *match;
@@ -380,17 +380,17 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 }
 #endif
 
-static const struct mpc5xxx_can_data __devinitdata mpc5200_can_data = {
+static const struct mpc5xxx_can_data __devinitconst mpc5200_can_data = {
        .type = MSCAN_TYPE_MPC5200,
        .get_clock = mpc52xx_can_get_clock,
 };
 
-static const struct mpc5xxx_can_data __devinitdata mpc5121_can_data = {
+static const struct mpc5xxx_can_data __devinitconst mpc5121_can_data = {
        .type = MSCAN_TYPE_MPC5121,
        .get_clock = mpc512x_can_get_clock,
 };
 
-static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
+static const struct of_device_id __devinitconst mpc5xxx_can_table[] = {
        { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, },
        /* Note that only MPC5121 Rev. 2 (and later) is supported */
        { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
index f0a12962f7b68df338dc3a627317e77975741382..f5b82aeb2540af2646f38dce966096ac221e3eaf 100644 (file)
@@ -583,12 +583,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
        cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
        if (!cfg_base) {
                dev_err(&pdev->dev, "failed to map PCI resource #0\n");
+               err = -ENOMEM;
                goto failure_release_regions;
        }
 
        reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
        if (!reg_base) {
                dev_err(&pdev->dev, "failed to map PCI resource #1\n");
+               err = -ENOMEM;
                goto failure_unmap_cfg_base;
        }
 
index ec6bd9d1b2af93edd67c4c8083e5c90648bbc581..272a85f32b14c86b040bf854b0df541e463a4af7 100644 (file)
@@ -686,8 +686,10 @@ static int __devinit pcan_probe(struct pcmcia_device *pdev)
 
        /* detect available channels */
        pcan_add_channels(card);
-       if (!card->chan_count)
+       if (!card->chan_count) {
+               err = -ENOMEM;
                goto probe_err_4;
+       }
 
        /* init the timer which controls the leds */
        init_timer(&card->led_timer);
index 034c16b60e962c0a33125b924072643be5621f24..adc3708d882929d2caab589caec48e519bf7af24 100644 (file)
@@ -56,7 +56,7 @@
 #include <linux/kernel.h>
 #include <linux/can.h>
 
-static __initdata const char banner[] =
+static __initconst const char banner[] =
        KERN_INFO "slcan: serial line CAN interface driver\n";
 
 MODULE_ALIAS_LDISC(N_SLCAN);
index 4f93c0be00535025bdafc6d42d289b59c2c1bcff..0a2a5ee79a177f1d78d9e4b3deb447f82be62757 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/slab.h>
 #include <net/rtnetlink.h>
 
-static __initdata const char banner[] =
+static __initconst const char banner[] =
        KERN_INFO "vcan: Virtual CAN interface driver\n";
 
 MODULE_DESCRIPTION("virtual CAN interface");
index a2f8b2b8e27cd429dcce71d8f30b1b5ba61c6818..e3f57427d5c51cce6b89687aafdd016308483646 100644 (file)
@@ -81,7 +81,7 @@ static void ne3210_block_output(struct net_device *dev, int count, const unsigne
 
 static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
 static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0};
-static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"};
+static const char * const ifmap[] __initconst = {"UTP", "?", "BNC", "AUI"};
 static int ifmap_val[] __initdata = {
                IF_PORT_10BASET,
                IF_PORT_UNKNOWN,
index d920a529ba22168b17b124552f7149fdba708c83..5b65992c2a0ae4882a3196ce73e0c5ed32cfa6f2 100644 (file)
@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 static const struct chip_info {
        const char *name;
        int drv_flags;
-} netdrv_tbl[] __devinitdata = {
+} netdrv_tbl[] __devinitconst = {
        { "Adaptec Starfire 6915", CanHaveMII },
 };
 
index 55a2e379505549456442a933396cea5dc497a1fc..d19f82f7597a6c3e079a71dffc727cd5fbd9cd21 100644 (file)
@@ -702,7 +702,7 @@ struct atl1c_platform_patch {
        u32 patch_flag;
 #define ATL1C_LINK_PATCH       0x1
 };
-static const struct atl1c_platform_patch plats[] __devinitdata = {
+static const struct atl1c_platform_patch plats[] __devinitconst = {
 {0x2060, 0xC1, 0x1019, 0x8152, 0x1},
 {0x2060, 0xC1, 0x1019, 0x2060, 0x1},
 {0x2060, 0xC1, 0x1019, 0xE000, 0x1},
index 57d64b80fd72c08f493ca42e6157b746291e1dbe..623dd8635c46eb0fd9e209025ff60464627dbcd6 100644 (file)
@@ -2845,7 +2845,7 @@ static void atl2_force_ps(struct atl2_hw *hw)
  */
 
 #define ATL2_PARAM(X, desc) \
-    static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
+    static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
     MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
     MODULE_PARM_DESC(X, desc);
 #else
index 30f04a389227bbfcb9cdaf29b563c005afbfa26a..24220992413ff95fd391e785b4e9edba221422bc 100644 (file)
@@ -3523,15 +3523,18 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
        } else
 #endif
        if (!bp->rx_ring_size) {
-               u32 cfg = SHMEM_RD(bp,
-                            dev_info.port_hw_config[BP_PORT(bp)].default_cfg);
-
                rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
 
-               /* Dercease ring size for 1G functions */
-               if ((cfg & PORT_HW_CFG_NET_SERDES_IF_MASK) ==
-                   PORT_HW_CFG_NET_SERDES_IF_SGMII)
-                       rx_ring_size /= 10;
+               if (CHIP_IS_E3(bp)) {
+                       u32 cfg = SHMEM_RD(bp,
+                                          dev_info.port_hw_config[BP_PORT(bp)].
+                                          default_cfg);
+
+                       /* Decrease ring size for 1G functions */
+                       if ((cfg & PORT_HW_CFG_NET_SERDES_IF_MASK) ==
+                           PORT_HW_CFG_NET_SERDES_IF_SGMII)
+                               rx_ring_size /= 10;
+               }
 
                /* allocate at least number of buffers required by FW */
                rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA :
index f7ed122f40717ee4392041e09e1b2396e640370b..d5648fc666bdf6f663505bbb433abebac08dbd48 100644 (file)
@@ -3052,9 +3052,8 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
        struct eth_stats_info *ether_stat =
                &bp->slowpath->drv_info_to_mcp.ether_stat;
 
-       /* leave last char as NULL */
-       memcpy(ether_stat->version, DRV_MODULE_VERSION,
-              ETH_STAT_INFO_VERSION_LEN - 1);
+       strlcpy(ether_stat->version, DRV_MODULE_VERSION,
+               ETH_STAT_INFO_VERSION_LEN);
 
        bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj,
                                        DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,
index 46280ba4c5d415930746c0cd7dc7c7e8b5790a95..a8800ac10df970b280690272f8618247f80d0823 100644 (file)
@@ -782,7 +782,8 @@ static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us)
        return i == timeout_us / 10;
 }
 
-int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len)
+static int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off,
+                                  u32 len)
 {
        int err;
        u32 i, bufoff, msgoff, maxlen, apedata;
@@ -7763,7 +7764,7 @@ static int tg3_alloc_consistent(struct tg3 *tp)
                sblk = tnapi->hw_status;
 
                if (tg3_flag(tp, ENABLE_RSS)) {
-                       u16 *prodptr = 0;
+                       u16 *prodptr = NULL;
 
                        /*
                         * When RSS is enabled, the status block format changes
@@ -8103,11 +8104,11 @@ static int tg3_chip_reset(struct tg3 *tp)
                u16 val16;
 
                if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
-                       int i;
+                       int j;
                        u32 cfg_val;
 
                        /* Wait for link training to complete.  */
-                       for (i = 0; i < 5000; i++)
+                       for (j = 0; j < 5000; j++)
                                udelay(100);
 
                        pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
@@ -10206,7 +10207,7 @@ static u32 tg3_irq_count(struct tg3 *tp)
 static bool tg3_enable_msix(struct tg3 *tp)
 {
        int i, rc;
-       struct msix_entry msix_ent[tp->irq_max];
+       struct msix_entry msix_ent[TG3_IRQ_MAX_VECS];
 
        tp->txq_cnt = tp->txq_req;
        tp->rxq_cnt = tp->rxq_req;
index 745a1f53361f379b9c075d190f7919c0f0866e4c..31752b24434eaafc348665be8b2be6104bb5c018 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include "cxgb4_uld.h"
 #include "t4_hw.h"
index 35b81d8b59e90707fdb37518f76300871b5fd627..137a24438d9c76532d691158913a9066d38146f0 100644 (file)
@@ -408,7 +408,8 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
                        __be32 *buf, int dir)
 {
        u32 pos, start, end, offset, memoffset;
-       int ret;
+       int ret = 0;
+       __be32 *data;
 
        /*
         * Argument sanity checks ...
@@ -416,6 +417,10 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
        if ((addr & 0x3) || (len & 0x3))
                return -EINVAL;
 
+       data = vmalloc(MEMWIN0_APERTURE/sizeof(__be32));
+       if (!data)
+               return -ENOMEM;
+
        /*
         * Offset into the region of memory which is being accessed
         * MEM_EDC0 = 0
@@ -438,7 +443,6 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
        offset = (addr - start)/sizeof(__be32);
 
        for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) {
-               __be32 data[MEMWIN0_APERTURE/sizeof(__be32)];
 
                /*
                 * If we're writing, copy the data from the caller's memory
@@ -452,7 +456,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
                        if (offset || len < MEMWIN0_APERTURE) {
                                ret = t4_mem_win_rw(adap, pos, data, 1);
                                if (ret)
-                                       return ret;
+                                       break;
                        }
                        while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) &&
                               len > 0) {
@@ -466,7 +470,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
                 */
                ret = t4_mem_win_rw(adap, pos, data, dir);
                if (ret)
-                       return ret;
+                       break;
 
                /*
                 * If we're reading, copy the data into the caller's memory
@@ -480,7 +484,8 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len,
                        }
        }
 
-       return 0;
+       vfree(data);
+       return ret;
 }
 
 int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
@@ -519,16 +524,21 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        u32 cclk_param, cclk_val;
        int i, ret;
        int ec, sn;
-       u8 vpd[VPD_LEN], csum;
+       u8 *vpd, csum;
        unsigned int vpdr_len, kw_offset, id_len;
 
-       ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd);
+       vpd = vmalloc(VPD_LEN);
+       if (!vpd)
+               return -ENOMEM;
+
+       ret = pci_read_vpd(adapter->pdev, VPD_BASE, VPD_LEN, vpd);
        if (ret < 0)
-               return ret;
+               goto out;
 
        if (vpd[0] != PCI_VPD_LRDT_ID_STRING) {
                dev_err(adapter->pdev_dev, "missing VPD ID string\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        id_len = pci_vpd_lrdt_size(vpd);
@@ -538,21 +548,24 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA);
        if (i < 0) {
                dev_err(adapter->pdev_dev, "missing VPD-R section\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        vpdr_len = pci_vpd_lrdt_size(&vpd[i]);
        kw_offset = i + PCI_VPD_LRDT_TAG_SIZE;
        if (vpdr_len + kw_offset > VPD_LEN) {
                dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
 #define FIND_VPD_KW(var, name) do { \
        var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \
        if (var < 0) { \
                dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \
-               return -EINVAL; \
+               ret = -EINVAL; \
+               goto out; \
        } \
        var += PCI_VPD_INFO_FLD_HDR_SIZE; \
 } while (0)
@@ -564,7 +577,8 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        if (csum) {
                dev_err(adapter->pdev_dev,
                        "corrupted VPD EEPROM, actual csum %u\n", csum);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        FIND_VPD_KW(ec, "EC");
@@ -587,6 +601,9 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
                      FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK));
        ret = t4_query_params(adapter, adapter->mbox, 0, 0,
                              1, &cclk_param, &cclk_val);
+
+out:
+       vfree(vpd);
        if (ret)
                return ret;
        p->cclk = cclk_val;
index 61cc0934286582844279338f42d7b80fec942b81..77335853ac364bcedbadcec6449ddac45b71359b 100644 (file)
@@ -661,9 +661,6 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb,
    new frame, not around filling de->setup_frame.  This is non-deterministic
    when re-entered but still correct. */
 
-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
 static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 {
        struct de_private *de = netdev_priv(dev);
@@ -673,12 +670,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
        u16 *eaddrs;
 
        memset(hash_table, 0, sizeof(hash_table));
-       set_bit_le(255, hash_table);                    /* Broadcast entry */
+       __set_bit_le(255, hash_table);                  /* Broadcast entry */
        /* This should work on big-endian machines as well. */
        netdev_for_each_mc_addr(ha, dev) {
                int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;
 
-               set_bit_le(index, hash_table);
+               __set_bit_le(index, hash_table);
        }
 
        for (i = 0; i < 32; i++) {
index ed7d1dcd95669279ae3393d3b03802af6e8ef5bc..44f7e8e82d85dbbdc9b67031b708e41bb9e8cb9e 100644 (file)
@@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
   {NULL}};
 
 
-static const char *block_name[] __devinitdata = {
+static const char *const block_name[] __devinitconst = {
        "21140 non-MII",
        "21140 MII PHY",
        "21142 Serial PHY",
index c4f37aca22699a5700b561bf72253c428a35247e..885700a199785a6b840b5cf4bddb9494d8f5bc67 100644 (file)
@@ -1010,9 +1010,6 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
    new frame, not around filling tp->setup_frame.  This is non-deterministic
    when re-entered but still correct. */
 
-#undef set_bit_le
-#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
-
 static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
 {
        struct tulip_private *tp = netdev_priv(dev);
@@ -1022,12 +1019,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
        u16 *eaddrs;
 
        memset(hash_table, 0, sizeof(hash_table));
-       set_bit_le(255, hash_table);                    /* Broadcast entry */
+       __set_bit_le(255, hash_table);                  /* Broadcast entry */
        /* This should work on big-endian machines as well. */
        netdev_for_each_mc_addr(ha, dev) {
                int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff;
 
-               set_bit_le(index, hash_table);
+               __set_bit_le(index, hash_table);
        }
        for (i = 0; i < 32; i++) {
                *setup_frm++ = hash_table[i];
index 4d1ffca83c82ffabf3e3f602fa6e30075a786e21..7c1ec4d7920bf607e43cd50c5c5624adcc86b08b 100644 (file)
@@ -236,7 +236,7 @@ struct pci_id_info {
         int drv_flags;         /* Driver use, intended as capability flags. */
 };
 
-static const struct pci_id_info pci_id_tbl[] __devinitdata = {
+static const struct pci_id_info pci_id_tbl[] __devinitconst = {
        {                               /* Sometime a Level-One switch card. */
          "Winbond W89c840",    CanHaveMII | HasBrokenTx | FDXOnNoMII},
        { "Winbond W89c840",    CanHaveMII | HasBrokenTx},
index d7bb52a7bda1092c9b828f2b1dacc6d2a029f0cd..3b83588e51f6ad41ac112b06d9f219c33eb957d2 100644 (file)
@@ -218,7 +218,7 @@ enum {
 struct pci_id_info {
         const char *name;
 };
-static const struct pci_id_info pci_id_tbl[] __devinitdata = {
+static const struct pci_id_info pci_id_tbl[] __devinitconst = {
        {"D-Link DFE-550TX FAST Ethernet Adapter"},
        {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
        {"D-Link DFE-580TX 4 port Server Adapter"},
index 9d71c9cc300bbfb90ce362e89f428c1c709ac8b8..0e4a0ac86aa8f1a9ad2d760cb066974abd678c79 100644 (file)
@@ -150,7 +150,7 @@ struct chip_info {
        int flags;
 };
 
-static const struct chip_info skel_netdrv_tbl[] __devinitdata = {
+static const struct chip_info skel_netdrv_tbl[] __devinitconst = {
        { "100/10M Ethernet PCI Adapter",       HAS_MII_XCVR },
        { "100/10M Ethernet PCI Adapter",       HAS_CHIP_XCVR },
        { "1000/100/10M Ethernet PCI Adapter",  HAS_MII_XCVR },
index b8e46cc31e53ecc385c7fcf5740a2bc0f0eed2d6..6be7b9839f35a2ad8ebe567bc76366f80e2896a9 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/if_vlan.h>
 
 #include <asm/ibmebus.h>
-#include <asm/abs_addr.h>
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
index 30f903332e927c58d8ad3f736620640a50163b94..d3a130ccdcc85fa63620a477c7c8e16b5b99cb3f 100644 (file)
@@ -141,7 +141,7 @@ u64 ehea_h_query_ehea_qp(const u64 adapter_handle, const u8 qp_category,
                                       qp_category,             /* R5 */
                                       qp_handle,               /* R6 */
                                       sel_mask,                /* R7 */
-                                      virt_to_abs(cb_addr),    /* R8 */
+                                      __pa(cb_addr),           /* R8 */
                                       0, 0);
 }
 
@@ -415,7 +415,7 @@ u64 ehea_h_modify_ehea_qp(const u64 adapter_handle, const u8 cat,
                                 (u64) cat,                     /* R5 */
                                 qp_handle,                     /* R6 */
                                 sel_mask,                      /* R7 */
-                                virt_to_abs(cb_addr),          /* R8 */
+                                __pa(cb_addr),                 /* R8 */
                                 0, 0, 0, 0);                   /* R9-R12 */
 
        *inv_attr_id = outs[0];
@@ -528,7 +528,7 @@ u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr)
 {
        u64 hret, cb_logaddr;
 
-       cb_logaddr = virt_to_abs(cb_addr);
+       cb_logaddr = __pa(cb_addr);
 
        hret = ehea_plpar_hcall_norets(H_QUERY_HEA,
                                       adapter_handle,          /* R4 */
@@ -545,7 +545,7 @@ u64 ehea_h_query_ehea_port(const u64 adapter_handle, const u16 port_num,
                           void *cb_addr)
 {
        u64 port_info;
-       u64 cb_logaddr = virt_to_abs(cb_addr);
+       u64 cb_logaddr = __pa(cb_addr);
        u64 arr_index = 0;
 
        port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
@@ -567,7 +567,7 @@ u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
        unsigned long outs[PLPAR_HCALL9_BUFSIZE];
        u64 port_info;
        u64 arr_index = 0;
-       u64 cb_logaddr = virt_to_abs(cb_addr);
+       u64 cb_logaddr = __pa(cb_addr);
 
        port_info = EHEA_BMASK_SET(H_MEHEAPORT_CAT, cb_cat)
                  | EHEA_BMASK_SET(H_MEHEAPORT_PN, port_num);
@@ -621,6 +621,6 @@ u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
        return ehea_plpar_hcall_norets(H_ERROR_DATA,
                                       adapter_handle,          /* R4 */
                                       ressource_handle,        /* R5 */
-                                      virt_to_abs(rblock),     /* R6 */
+                                      __pa(rblock),            /* R6 */
                                       0, 0, 0, 0);             /* R7-R12 */
 }
index cb66f574dc97440c56b5c603bff208937a7e5117..27f881758d16c541560d616b22efc16649389241 100644 (file)
@@ -163,7 +163,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
                        goto out_kill_hwq;
                }
 
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
                hret = ehea_h_register_rpage(adapter->handle,
                                             0, EHEA_CQ_REGISTER_ORIG,
                                             cq->fw_handle, rpage, 1);
@@ -290,7 +290,7 @@ struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
                        goto out_kill_hwq;
                }
 
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
 
                hret = ehea_h_register_rpage(adapter->handle, 0,
                                             EHEA_EQ_REGISTER_ORIG,
@@ -395,7 +395,7 @@ static int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
                        pr_err("hw_qpageit_get_inc failed\n");
                        goto out_kill_hwq;
                }
-               rpage = virt_to_abs(vpage);
+               rpage = __pa(vpage);
                hret = ehea_h_register_rpage(adapter->handle,
                                             0, h_call_q_selector,
                                             qp->fw_handle, rpage, 1);
@@ -790,7 +790,7 @@ u64 ehea_map_vaddr(void *caddr)
        if (!ehea_bmap)
                return EHEA_INVAL_ADDR;
 
-       index = virt_to_abs(caddr) >> SECTION_SIZE_BITS;
+       index = __pa(caddr) >> SECTION_SIZE_BITS;
        top = (index >> EHEA_TOP_INDEX_SHIFT) & EHEA_INDEX_MASK;
        if (!ehea_bmap->top[top])
                return EHEA_INVAL_ADDR;
@@ -812,7 +812,7 @@ static inline void *ehea_calc_sectbase(int top, int dir, int idx)
        unsigned long ret = idx;
        ret |= dir << EHEA_DIR_INDEX_SHIFT;
        ret |= top << EHEA_TOP_INDEX_SHIFT;
-       return abs_to_virt(ret << SECTION_SIZE_BITS);
+       return __va(ret << SECTION_SIZE_BITS);
 }
 
 static u64 ehea_reg_mr_section(int top, int dir, int idx, u64 *pt,
@@ -822,7 +822,7 @@ static u64 ehea_reg_mr_section(int top, int dir, int idx, u64 *pt,
        void *pg;
        u64 j, m, hret;
        unsigned long k = 0;
-       u64 pt_abs = virt_to_abs(pt);
+       u64 pt_abs = __pa(pt);
 
        void *sectbase = ehea_calc_sectbase(top, dir, idx);
 
@@ -830,7 +830,7 @@ static u64 ehea_reg_mr_section(int top, int dir, int idx, u64 *pt,
 
                for (m = 0; m < EHEA_MAX_RPAGE; m++) {
                        pg = sectbase + ((k++) * EHEA_PAGESIZE);
-                       pt[m] = virt_to_abs(pg);
+                       pt[m] = __pa(pg);
                }
                hret = ehea_h_register_rpage_mr(adapter->handle, mr->handle, 0,
                                                0, pt_abs, EHEA_MAX_RPAGE);
index 18bf08c9d7a4428e3a82f9f29a5837fddc3f6860..1077cb2b38db15f4123eca7d9d71492df86b0a05 100644 (file)
@@ -1099,7 +1099,7 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
                if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
                                   IXGBE_FDIRCTRL_INIT_DONE)
                        break;
-               udelay(10);
+               usleep_range(1000, 2000);
        }
        if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
                hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
index 90e41db3cb695bd2009d1ec979c4dfc24ab9cdf7..dbf37e4a45fda722df461cc11eaaf8b2bd0449f8 100644 (file)
@@ -70,6 +70,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 
        switch (hw->device_id) {
        case IXGBE_DEV_ID_X540T:
+       case IXGBE_DEV_ID_X540T1:
                return 0;
        case IXGBE_DEV_ID_82599_T3_LOM:
                return 0;
index 4104ea25d81844ec4db050145ee1633099bbe812..56b20d17d0e4c5577828040fddf8bd294868c84d 100644 (file)
@@ -2690,10 +2690,7 @@ static int ixgbe_get_ts_info(struct net_device *dev,
                        (1 << HWTSTAMP_FILTER_NONE) |
                        (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
                        (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
-                       (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
-                       (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
-                       (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
-                       (1 << HWTSTAMP_FILTER_SOME);
+                       (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
                break;
 #endif /* CONFIG_IXGBE_PTP */
        default:
index 868af693821957bfc4c9541e8c99c7117b1d2247..fa3d552e1f4a1e6b0cad19c4e4d5610551866638 100644 (file)
@@ -114,6 +114,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 },
        {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 },
+       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 },
        /* required last entry */
        {0, }
 };
@@ -2322,6 +2323,12 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
        default:
                break;
        }
+
+#ifdef CONFIG_IXGBE_PTP
+       if (adapter->hw.mac.type == ixgbe_mac_X540)
+               mask |= IXGBE_EIMS_TIMESYNC;
+#endif
+
        if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
            !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
                mask |= IXGBE_EIMS_FLOW_DIR;
@@ -2385,8 +2392,10 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
        }
 
        ixgbe_check_fan_failure(adapter, eicr);
+
 #ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_check_pps_event(adapter, eicr);
+       if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
+               ixgbe_ptp_check_pps_event(adapter, eicr);
 #endif
 
        /* re-enable the original interrupt state, no lsc, no queues */
@@ -2580,7 +2589,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
 
        ixgbe_check_fan_failure(adapter, eicr);
 #ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_check_pps_event(adapter, eicr);
+       if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
+               ixgbe_ptp_check_pps_event(adapter, eicr);
 #endif
 
        /* would disable interrupts here but EIAM disabled it */
@@ -7045,6 +7055,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
                is_wol_supported = 1;
                break;
        case IXGBE_DEV_ID_X540T:
+       case IXGBE_DEV_ID_X540T1:
                /* check eeprom to see if enabled wol */
                if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
                    ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
index 39881cb17a4b5fe8958b8e0aead9188feaaf0370..d9291316ee9f3aee8bbe54710a6ebcffb37c6ef7 100644 (file)
@@ -105,6 +105,83 @@ static struct sock_filter ptp_filter[] = {
        PTP_FILTER
 };
 
+/**
+ * ixgbe_ptp_setup_sdp
+ * @hw: the hardware private structure
+ *
+ * this function enables or disables the clock out feature on SDP0 for
+ * the X540 device. It will create a 1second periodic output that can
+ * be used as the PPS (via an interrupt).
+ *
+ * It calculates when the systime will be on an exact second, and then
+ * aligns the start of the PPS signal to that value. The shift is
+ * necessary because it can change based on the link speed.
+ */
+static void ixgbe_ptp_setup_sdp(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       int shift = adapter->cc.shift;
+       u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem;
+       u64 ns = 0, clock_edge = 0;
+
+       if ((adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED) &&
+           (hw->mac.type == ixgbe_mac_X540)) {
+
+               /* disable the pin first */
+               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0);
+               IXGBE_WRITE_FLUSH(hw);
+
+               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
+
+               /*
+                * enable the SDP0 pin as output, and connected to the
+                * native function for Timesync (ClockOut)
+                */
+               esdp |= (IXGBE_ESDP_SDP0_DIR |
+                        IXGBE_ESDP_SDP0_NATIVE);
+
+               /*
+                * enable the Clock Out feature on SDP0, and allow
+                * interrupts to occur when the pin changes
+                */
+               tsauxc = (IXGBE_TSAUXC_EN_CLK |
+                         IXGBE_TSAUXC_SYNCLK |
+                         IXGBE_TSAUXC_SDP0_INT);
+
+               /* clock period (or pulse length) */
+               clktiml = (u32)(NSECS_PER_SEC << shift);
+               clktimh = (u32)((NSECS_PER_SEC << shift) >> 32);
+
+               /*
+                * Account for the cyclecounter wrap-around value by
+                * using the converted ns value of the current time to
+                * check for when the next aligned second would occur.
+                */
+               clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
+               clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
+               ns = timecounter_cyc2time(&adapter->tc, clock_edge);
+
+               div_u64_rem(ns, NSECS_PER_SEC, &rem);
+               clock_edge += ((NSECS_PER_SEC - (u64)rem) << shift);
+
+               /* specify the initial clock start time */
+               trgttiml = (u32)clock_edge;
+               trgttimh = (u32)(clock_edge >> 32);
+
+               IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml);
+               IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh);
+               IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml);
+               IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh);
+
+               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
+               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc);
+       } else {
+               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0);
+       }
+
+       IXGBE_WRITE_FLUSH(hw);
+}
+
 /**
  * ixgbe_ptp_read - read raw cycle counter (to be used by time counter)
  * @cc: the cyclecounter structure
@@ -198,6 +275,9 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
                         now);
 
        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+       ixgbe_ptp_setup_sdp(adapter);
+
        return 0;
 }
 
@@ -251,6 +331,7 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp,
        timecounter_init(&adapter->tc, &adapter->cc, ns);
        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
 
+       ixgbe_ptp_setup_sdp(adapter);
        return 0;
 }
 
@@ -281,8 +362,9 @@ static int ixgbe_ptp_enable(struct ptp_clock_info *ptp,
                        if (on)
                                adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED;
                        else
-                               adapter->flags2 &=
-                                       ~IXGBE_FLAG2_PTP_PPS_ENABLED;
+                               adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED;
+
+                       ixgbe_ptp_setup_sdp(adapter);
                        return 0;
                default:
                        break;
@@ -305,109 +387,15 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
        struct ixgbe_hw *hw = &adapter->hw;
        struct ptp_clock_event event;
 
-       event.type = PTP_CLOCK_PPS;
-
-       /* Make sure ptp clock is valid, and PPS event enabled */
-       if (!adapter->ptp_clock ||
-           !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED))
-               return;
-
-       if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) {
-               switch (hw->mac.type) {
-               case ixgbe_mac_X540:
-                       ptp_clock_event(adapter->ptp_clock, &event);
-                       break;
-               default:
-                       break;
-               }
-       }
-}
-
-/**
- * ixgbe_ptp_enable_sdp
- * @hw: the hardware private structure
- * @shift: the clock shift for calculating nanoseconds
- *
- * this function enables the clock out feature on the sdp0 for the
- * X540 device. It will create a 1second periodic output that can be
- * used as the PPS (via an interrupt).
- *
- * It calculates when the systime will be on an exact second, and then
- * aligns the start of the PPS signal to that value. The shift is
- * necessary because it can change based on the link speed.
- */
-static void ixgbe_ptp_enable_sdp(struct ixgbe_hw *hw, int shift)
-{
-       u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh;
-       u64 clock_edge = 0;
-       u32 rem;
-
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
-               esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
-
-               /*
-                * enable the SDP0 pin as output, and connected to the native
-                * function for Timesync (ClockOut)
-                */
-               esdp |= (IXGBE_ESDP_SDP0_DIR |
-                        IXGBE_ESDP_SDP0_NATIVE);
-
-               /*
-                * enable the Clock Out feature on SDP0, and allow interrupts
-                * to occur when the pin changes
-                */
-               tsauxc = (IXGBE_TSAUXC_EN_CLK |
-                         IXGBE_TSAUXC_SYNCLK |
-                         IXGBE_TSAUXC_SDP0_INT);
-
-               /* clock period (or pulse length) */
-               clktiml = (u32)(NSECS_PER_SEC << shift);
-               clktimh = (u32)((NSECS_PER_SEC << shift) >> 32);
-
-               clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML);
-               clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32;
-
-               /*
-                * account for the fact that we can't do u64 division
-                * with remainder, by converting the clock values into
-                * nanoseconds first
-                */
-               clock_edge >>= shift;
-               div_u64_rem(clock_edge, NSECS_PER_SEC, &rem);
-               clock_edge += (NSECS_PER_SEC - rem);
-               clock_edge <<= shift;
-
-               /* specify the initial clock start time */
-               trgttiml = (u32)clock_edge;
-               trgttimh = (u32)(clock_edge >> 32);
-
-               IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml);
-               IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh);
-               IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml);
-               IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh);
-
-               IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
-               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc);
-
-               IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC);
+               ptp_clock_event(adapter->ptp_clock, &event);
                break;
        default:
                break;
        }
 }
 
-/**
- * ixgbe_ptp_disable_sdp
- * @hw: the private hardware structure
- *
- * this function disables the auxiliary SDP clock out feature
- */
-static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw)
-{
-       IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC);
-       IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0);
-}
 
 /**
  * ixgbe_ptp_overflow_check - delayed work to detect SYSTIME overflow
@@ -822,9 +810,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        if (adapter->cycle_speed == cycle_speed && timinca)
                return;
 
-       /* disable the SDP clock out */
-       ixgbe_ptp_disable_sdp(hw);
-
        /**
         * Scale the NIC cycle counter by a large factor so that
         * relatively small corrections to the frequency can be added
@@ -877,10 +862,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
        IXGBE_WRITE_FLUSH(hw);
 
-       /* now that the shift has been calculated and the systime
-        * registers reset, (re-)enable the Clock out feature*/
-       ixgbe_ptp_enable_sdp(hw, shift);
-
        /* store the new cycle speed */
        adapter->cycle_speed = cycle_speed;
 
@@ -901,6 +882,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
                         ktime_to_ns(ktime_get_real()));
 
        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+       /*
+        * Now that the shift has been calculated and the systime
+        * registers reset, (re-)enable the Clock out feature
+        */
+       ixgbe_ptp_setup_sdp(adapter);
 }
 
 /**
@@ -979,10 +966,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
  */
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
 {
-       ixgbe_ptp_disable_sdp(&adapter->hw);
-
        /* stop the overflow check task */
-       adapter->flags2 &= ~IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
+       adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
+                            IXGBE_FLAG2_PTP_PPS_ENABLED);
+
+       ixgbe_ptp_setup_sdp(adapter);
 
        if (adapter->ptp_clock) {
                ptp_clock_unregister(adapter->ptp_clock);
index 400f86a311740262262f668bd7b4f8bb9de32cee..0722f33680926e9c8e79a0592708cfc0c42806e2 100644 (file)
@@ -65,6 +65,7 @@
 #define IXGBE_DEV_ID_82599_LS            0x154F
 #define IXGBE_DEV_ID_X540T               0x1528
 #define IXGBE_DEV_ID_82599_SFP_SF_QP     0x154A
+#define IXGBE_DEV_ID_X540T1              0x1560
 
 /* VF Device IDs */
 #define IXGBE_DEV_ID_82599_VF           0x10ED
index ba6506ff4abb4553ec498ba93807c8cd1772e52a..926c911c0ac4b184d9d0f3fa70632b5ed84cb33b 100644 (file)
@@ -3094,6 +3094,8 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                if (validate_eth_header_mac(slave, rule_header, rlist))
                        return -EINVAL;
                break;
+       case MLX4_NET_TRANS_RULE_ID_IB:
+               break;
        case MLX4_NET_TRANS_RULE_ID_IPV4:
        case MLX4_NET_TRANS_RULE_ID_TCP:
        case MLX4_NET_TRANS_RULE_ID_UDP:
index bce01641ee6b325f91ee1e29ae4414adfe981b18..97302419a377e82021e4ccb7330a210504db0f48 100644 (file)
@@ -26,7 +26,7 @@ if PCH_GBE
 config PCH_PTP
        bool "PCH PTP clock support"
        default n
-       depends on PTP_1588_CLOCK_PCH
+       select PTP_1588_CLOCK_PCH
        ---help---
          Say Y here if you want to use Precision Time Protocol (PTP) in the
          driver. PTP is a method to precisely synchronize distributed clocks
index b528e52a8ee1388b3ac1b6aecb5e9ac2005efa08..2a0c9dc48eb38a5a3a85a06145ae12ce3db84309 100644 (file)
@@ -38,7 +38,7 @@ static inline void writeq(u64 val, void __iomem *addr)
 }
 #endif
 
-static const struct crb_128M_2M_block_map
+static struct crb_128M_2M_block_map
 crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
     {{{0, 0,         0,         0} } },                /* 0: PCI */
     {{{1, 0x0100000, 0x0102000, 0x120000},     /* 1: PCIE */
index 1d83565cc6af6dca0e61360c1c60394e1fb5682d..3ed7add23c121df0b0a6577ed2ff4c5d327d941d 100644 (file)
@@ -228,7 +228,7 @@ typedef enum {
 static const struct {
        const char *name;
        u32 hw_flags;
-} board_info[] __devinitdata = {
+} board_info[] __devinitconst = {
        { "RealTek RTL8139", RTL8139_CAPS },
        { "RealTek RTL8129", RTL8129_CAPS },
 };
index 96bd980e828da5d28b0bed6329cb85e3655d598f..4f86d0cd516a3db2b4eff785d59d1f1a7c07a978 100644 (file)
@@ -2019,14 +2019,14 @@ static void efx_set_rx_mode(struct net_device *net_dev)
                netdev_for_each_mc_addr(ha, net_dev) {
                        crc = ether_crc_le(ETH_ALEN, ha->addr);
                        bit = crc & (EFX_MCAST_HASH_ENTRIES - 1);
-                       set_bit_le(bit, mc_hash->byte);
+                       __set_bit_le(bit, mc_hash);
                }
 
                /* Broadcast packets go through the multicast hash filter.
                 * ether_crc_le() of the broadcast address is 0xbe2612ff
                 * so we always add bit 0xff to the mask.
                 */
-               set_bit_le(0xff, mc_hash->byte);
+               __set_bit_le(0xff, mc_hash);
        }
 
        if (efx->port_enabled)
index c1a010cda89b92f20afc5657354a42bc592f8568..576a31091165492879ee22edbfd00eee4972047a 100644 (file)
@@ -1101,18 +1101,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue,
        return &rx_queue->buffer[index];
 }
 
-/* Set bit in a little-endian bitfield */
-static inline void set_bit_le(unsigned nr, unsigned char *addr)
-{
-       addr[nr / 8] |= (1 << (nr % 8));
-}
-
-/* Clear bit in a little-endian bitfield */
-static inline void clear_bit_le(unsigned nr, unsigned char *addr)
-{
-       addr[nr / 8] &= ~(1 << (nr % 8));
-}
-
 
 /**
  * EFX_MAX_FRAME_LEN - calculate maximum frame length
index cdff40b65729ad79a8a744933ca9453958305162..aab7cacb2e34a87203d199be8df72c20020b0e0b 100644 (file)
@@ -472,9 +472,9 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 
                efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
                if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD)
-                       clear_bit_le(tx_queue->queue, (void *)&reg);
+                       __clear_bit_le(tx_queue->queue, &reg);
                else
-                       set_bit_le(tx_queue->queue, (void *)&reg);
+                       __set_bit_le(tx_queue->queue, &reg);
                efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
        }
 
index 4613591b43e74ebc34f774dba399802e459f874b..d8166012b7d4f2fe4c72203a54b1b5c2c356f1ee 100644 (file)
@@ -1618,7 +1618,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
 static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
                                                  struct net_device *dev)
 {
-       static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 };
+       static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 };
        struct sis190_private *tp = netdev_priv(dev);
        struct pci_dev *isa_bridge;
        u8 reg, tmp8;
index d15c888e9df8a15b02d104ace349c1926ad81107..49956730cd8db884ac1696d108cb62fe61d49533 100644 (file)
@@ -863,6 +863,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
 
                next_dma = desc_read(desc, hw_next);
                chan->head = desc_from_phys(pool, next_dma);
+               chan->count--;
                chan->stats.teardown_dequeue++;
 
                /* issue callback without locks held */
index 64783a0d545ac0d3fd6ba56c03ab74d73b5cbaef..1450e33fc250e7e0bb4edf73aa6abc06df1a1855 100644 (file)
@@ -811,9 +811,9 @@ static struct tty_ldisc_ops sp_ldisc = {
 
 /* Initialize 6pack control device -- register 6pack line discipline */
 
-static const char msg_banner[]  __initdata = KERN_INFO \
+static const char msg_banner[]  __initconst = KERN_INFO \
        "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
-static const char msg_regfail[] __initdata = KERN_ERR  \
+static const char msg_regfail[] __initconst = KERN_ERR  \
        "6pack: can't register line discipline (err = %d)\n";
 
 static int __init sixpack_init_driver(void)
@@ -829,7 +829,7 @@ static int __init sixpack_init_driver(void)
        return status;
 }
 
-static const char msg_unregfail[] __exitdata = KERN_ERR \
+static const char msg_unregfail[] = KERN_ERR \
        "6pack: can't unregister line discipline (err = %d)\n";
 
 static void __exit sixpack_exit_driver(void)
index 76d54774ba82ac0fba45dc774b556e64dd5124e4..c2e5497397d5ebd3a97bbfe96e394f1030df98a0 100644 (file)
@@ -87,7 +87,7 @@
 
 #include <linux/bpqether.h>
 
-static const char banner[] __initdata = KERN_INFO \
+static const char banner[] __initconst = KERN_INFO \
        "AX.25: bpqether driver version 004\n";
 
 static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
index 2c0894a92abd65cad7807b9f24cbce2b224e4afe..8e01c457015b4dc05c9fd4a85b77a0e3c0ded74b 100644 (file)
@@ -997,9 +997,9 @@ static struct tty_ldisc_ops ax_ldisc = {
        .write_wakeup   = mkiss_write_wakeup
 };
 
-static const char banner[] __initdata = KERN_INFO \
+static const char banner[] __initconst = KERN_INFO \
        "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
-static const char msg_regfail[] __initdata = KERN_ERR \
+static const char msg_regfail[] __initconst = KERN_ERR \
        "mkiss: can't register line discipline (err = %d)\n";
 
 static int __init mkiss_init_driver(void)
@@ -1015,7 +1015,7 @@ static int __init mkiss_init_driver(void)
        return status;
 }
 
-static const char msg_unregfail[] __exitdata = KERN_ERR \
+static const char msg_unregfail[] = KERN_ERR \
        "mkiss: can't unregister line discipline (err = %d)\n";
 
 static void __exit mkiss_exit_driver(void)
index efc6c97163a727a99ef389c2bff4a85991e3a747..1b4a47bd32b7a6e938e5d178899a68e7396594b9 100644 (file)
 
 #include "z8530.h"
 
-static const char banner[] __initdata = KERN_INFO \
+static const char banner[] __initconst = KERN_INFO \
        "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n";
 
 static void t_dwait(unsigned long);
index 5a6412ecce739b7c21b395705742d42e1da6e4c7..c6645f1017afac08dff50c54b63203903bb51031 100644 (file)
@@ -76,7 +76,7 @@
 /* --------------------------------------------------------------------- */
 
 static const char yam_drvname[] = "yam";
-static const char yam_drvinfo[] __initdata = KERN_INFO \
+static const char yam_drvinfo[] __initconst = KERN_INFO \
        "YAM driver version 0.8 by F1OAT/F6FBB\n";
 
 /* --------------------------------------------------------------------- */
index 91d25888a1b98b136b6ec3704a58630d5f9b085c..d8b9b1e8ee0221479e35dd143f36cc7eb4030913 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/ethtool.h>
 
 #define DRV_NAME        "rionet"
-#define DRV_VERSION     "0.2"
+#define DRV_VERSION     "0.3"
 #define DRV_AUTHOR      "Matt Porter <mporter@kernel.crashing.org>"
 #define DRV_DESC        "Ethernet over RapidIO"
 
@@ -47,8 +47,7 @@ MODULE_LICENSE("GPL");
 
 #define RIONET_TX_RING_SIZE    CONFIG_RIONET_TX_SIZE
 #define RIONET_RX_RING_SIZE    CONFIG_RIONET_RX_SIZE
-
-static LIST_HEAD(rionet_peers);
+#define RIONET_MAX_NETS                8
 
 struct rionet_private {
        struct rio_mport *mport;
@@ -69,16 +68,14 @@ struct rionet_peer {
        struct resource *res;
 };
 
-static int rionet_check = 0;
-static int rionet_capable = 1;
+struct rionet_net {
+       struct net_device *ndev;
+       struct list_head peers;
+       struct rio_dev **active;
+       int nact;       /* number of active peers */
+};
 
-/*
- * This is a fast lookup table for translating TX
- * Ethernet packets into a destination RIO device. It
- * could be made into a hash table to save memory depending
- * on system trade-offs.
- */
-static struct rio_dev **rionet_active;
+static struct rionet_net nets[RIONET_MAX_NETS];
 
 #define is_rionet_capable(src_ops, dst_ops)                    \
                        ((src_ops & RIO_SRC_OPS_DATA_MSG) &&    \
@@ -175,6 +172,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        struct ethhdr *eth = (struct ethhdr *)skb->data;
        u16 destid;
        unsigned long flags;
+       int add_num = 1;
 
        local_irq_save(flags);
        if (!spin_trylock(&rnet->tx_lock)) {
@@ -182,7 +180,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                return NETDEV_TX_LOCKED;
        }
 
-       if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) {
+       if (is_multicast_ether_addr(eth->h_dest))
+               add_num = nets[rnet->mport->id].nact;
+
+       if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
                netif_stop_queue(ndev);
                spin_unlock_irqrestore(&rnet->tx_lock, flags);
                printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
@@ -191,15 +192,22 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        }
 
        if (is_multicast_ether_addr(eth->h_dest)) {
+               int count = 0;
+
                for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
                                i++)
-                       if (rionet_active[i])
+                       if (nets[rnet->mport->id].active[i]) {
                                rionet_queue_tx_msg(skb, ndev,
-                                                   rionet_active[i]);
+                                       nets[rnet->mport->id].active[i]);
+                               if (count)
+                                       atomic_inc(&skb->users);
+                               count++;
+                       }
        } else if (RIONET_MAC_MATCH(eth->h_dest)) {
                destid = RIONET_GET_DESTID(eth->h_dest);
-               if (rionet_active[destid])
-                       rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
+               if (nets[rnet->mport->id].active[destid])
+                       rionet_queue_tx_msg(skb, ndev,
+                                       nets[rnet->mport->id].active[destid]);
        }
 
        spin_unlock_irqrestore(&rnet->tx_lock, flags);
@@ -218,16 +226,21 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
                printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
                       DRV_NAME, sid, tid, info);
        if (info == RIONET_DOORBELL_JOIN) {
-               if (!rionet_active[sid]) {
-                       list_for_each_entry(peer, &rionet_peers, node) {
-                               if (peer->rdev->destid == sid)
-                                       rionet_active[sid] = peer->rdev;
+               if (!nets[rnet->mport->id].active[sid]) {
+                       list_for_each_entry(peer,
+                                          &nets[rnet->mport->id].peers, node) {
+                               if (peer->rdev->destid == sid) {
+                                       nets[rnet->mport->id].active[sid] =
+                                                               peer->rdev;
+                                       nets[rnet->mport->id].nact++;
+                               }
                        }
                        rio_mport_send_doorbell(mport, sid,
                                                RIONET_DOORBELL_JOIN);
                }
        } else if (info == RIONET_DOORBELL_LEAVE) {
-               rionet_active[sid] = NULL;
+               nets[rnet->mport->id].active[sid] = NULL;
+               nets[rnet->mport->id].nact--;
        } else {
                if (netif_msg_intr(rnet))
                        printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -321,7 +334,8 @@ static int rionet_open(struct net_device *ndev)
        netif_carrier_on(ndev);
        netif_start_queue(ndev);
 
-       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+       list_for_each_entry_safe(peer, tmp,
+                                &nets[rnet->mport->id].peers, node) {
                if (!(peer->res = rio_request_outb_dbell(peer->rdev,
                                                         RIONET_DOORBELL_JOIN,
                                                         RIONET_DOORBELL_LEAVE)))
@@ -346,7 +360,7 @@ static int rionet_close(struct net_device *ndev)
        int i;
 
        if (netif_msg_ifup(rnet))
-               printk(KERN_INFO "%s: close\n", DRV_NAME);
+               printk(KERN_INFO "%s: close %s\n", DRV_NAME, ndev->name);
 
        netif_stop_queue(ndev);
        netif_carrier_off(ndev);
@@ -354,10 +368,11 @@ static int rionet_close(struct net_device *ndev)
        for (i = 0; i < RIONET_RX_RING_SIZE; i++)
                kfree_skb(rnet->rx_skb[i]);
 
-       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
-               if (rionet_active[peer->rdev->destid]) {
+       list_for_each_entry_safe(peer, tmp,
+                                &nets[rnet->mport->id].peers, node) {
+               if (nets[rnet->mport->id].active[peer->rdev->destid]) {
                        rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
-                       rionet_active[peer->rdev->destid] = NULL;
+                       nets[rnet->mport->id].active[peer->rdev->destid] = NULL;
                }
                rio_release_outb_dbell(peer->rdev, peer->res);
        }
@@ -373,17 +388,21 @@ static int rionet_close(struct net_device *ndev)
 static void rionet_remove(struct rio_dev *rdev)
 {
        struct net_device *ndev = rio_get_drvdata(rdev);
+       unsigned char netid = rdev->net->hport->id;
        struct rionet_peer *peer, *tmp;
 
-       free_pages((unsigned long)rionet_active, get_order(sizeof(void *) *
-                       RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
        unregister_netdev(ndev);
-       free_netdev(ndev);
 
-       list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
+       free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) *
+                       RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
+       nets[netid].active = NULL;
+
+       list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) {
                list_del(&peer->node);
                kfree(peer);
        }
+
+       free_netdev(ndev);
 }
 
 static void rionet_get_drvinfo(struct net_device *ndev,
@@ -435,13 +454,13 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
        const size_t rionet_active_bytes = sizeof(void *) *
                                RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
 
-       rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
-                       get_order(rionet_active_bytes));
-       if (!rionet_active) {
+       nets[mport->id].active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
+                                               get_order(rionet_active_bytes));
+       if (!nets[mport->id].active) {
                rc = -ENOMEM;
                goto out;
        }
-       memset((void *)rionet_active, 0, rionet_active_bytes);
+       memset((void *)nets[mport->id].active, 0, rionet_active_bytes);
 
        /* Set up private area */
        rnet = netdev_priv(ndev);
@@ -470,60 +489,62 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
        if (rc != 0)
                goto out;
 
-       printk("%s: %s %s Version %s, MAC %pM\n",
+       printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s\n",
               ndev->name,
               DRV_NAME,
               DRV_DESC,
               DRV_VERSION,
-              ndev->dev_addr);
+              ndev->dev_addr,
+              mport->name);
 
       out:
        return rc;
 }
 
-/*
- * XXX Make multi-net safe
- */
+static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
+
 static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
 {
        int rc = -ENODEV;
        u32 lsrc_ops, ldst_ops;
        struct rionet_peer *peer;
        struct net_device *ndev = NULL;
+       unsigned char netid = rdev->net->hport->id;
+       int oldnet;
 
-       /* If local device is not rionet capable, give up quickly */
-       if (!rionet_capable)
-               goto out;
+       if (netid >= RIONET_MAX_NETS)
+               return rc;
 
-       /* Allocate our net_device structure */
-       ndev = alloc_etherdev(sizeof(struct rionet_private));
-       if (ndev == NULL) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       oldnet = test_and_set_bit(netid, net_table);
 
        /*
         * First time through, make sure local device is rionet
-        * capable, setup netdev,  and set flags so this is skipped
-        * on later probes
+        * capable, setup netdev (will be skipped on later probes)
         */
-       if (!rionet_check) {
+       if (!oldnet) {
                rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
                                         &lsrc_ops);
                rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
                                         &ldst_ops);
                if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
                        printk(KERN_ERR
-                              "%s: local device is not network capable\n",
-                              DRV_NAME);
-                       rionet_check = 1;
-                       rionet_capable = 0;
+                              "%s: local device %s is not network capable\n",
+                              DRV_NAME, rdev->net->hport->name);
                        goto out;
                }
 
+               /* Allocate our net_device structure */
+               ndev = alloc_etherdev(sizeof(struct rionet_private));
+               if (ndev == NULL) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+               nets[netid].ndev = ndev;
                rc = rionet_setup_netdev(rdev->net->hport, ndev);
-               rionet_check = 1;
-       }
+               INIT_LIST_HEAD(&nets[netid].peers);
+               nets[netid].nact = 0;
+       } else if (nets[netid].ndev == NULL)
+               goto out;
 
        /*
         * If the remote device has mailbox/doorbell capabilities,
@@ -535,10 +556,10 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
                        goto out;
                }
                peer->rdev = rdev;
-               list_add_tail(&peer->node, &rionet_peers);
+               list_add_tail(&peer->node, &nets[netid].peers);
        }
 
-       rio_set_drvdata(rdev, ndev);
+       rio_set_drvdata(rdev, nets[netid].ndev);
 
       out:
        return rc;
index 5c7547c4f802550426c8f9769f9d9ba9a93becf9..d44cca327588858e26023a99cee8c64a940cf173 100644 (file)
@@ -1315,6 +1315,7 @@ static const struct team_option team_options[] = {
 
 static struct lock_class_key team_netdev_xmit_lock_key;
 static struct lock_class_key team_netdev_addr_lock_key;
+static struct lock_class_key team_tx_busylock_key;
 
 static void team_set_lockdep_class_one(struct net_device *dev,
                                       struct netdev_queue *txq,
@@ -1327,6 +1328,7 @@ static void team_set_lockdep_class(struct net_device *dev)
 {
        lockdep_set_class(&dev->addr_list_lock, &team_netdev_addr_lock_key);
        netdev_for_each_tx_queue(dev, team_set_lockdep_class_one, NULL);
+       dev->qdisc_tx_busylock = &team_tx_busylock_key;
 }
 
 static int team_init(struct net_device *dev)
index 0e57690617029ac0bf8d86c7b439dbdfab4a69c0..feacc3b994b7e621570ab93a6c142eb7aa5e9547 100644 (file)
@@ -1775,7 +1775,7 @@ EXPORT_SYMBOL(z8530_queue_xmit);
 /*
  *     Module support
  */
-static const char banner[] __initdata =
+static const char banner[] __initconst =
        KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n";
 
 static int __init z85230_init_driver(void)
index 05593d8820233b72681af9f76510cdc9a5eefb52..4ebfcf3d8a3b26d07c5cd2e742ab59aff3c5ba63 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <net/tcp.h>
 
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/interface/memory.h>
 
index c934fe8583f5f17c33a577993a934205db2d3609..caa011008cd0c9fe11b38507e7f550552bd93170 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <net/ip.h>
 
+#include <asm/xen/page.h>
 #include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
index 1e117c2a3cad032390fe9ab1a12745b6ce405313..b29e20b7862f168673b3ad980200dd3c80fff175 100644 (file)
@@ -388,7 +388,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        /* Remove the EADS bridge device itself */
        BUG_ON(!bus->self);
        pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
-       eeh_remove_bus_device(bus->self);
+       eeh_remove_bus_device(bus->self, true);
        pci_stop_and_remove_bus_device(bus->self);
 
        return 0;
index 1ef6e1e8c6c6dac902c486414c164446cc97b290..33e3df9e39cadf6929e64b9438972a1f84a9fa94 100644 (file)
@@ -175,6 +175,28 @@ config PINCTRL_EXYNOS4
        bool "Pinctrl driver data for Exynos4 SoC"
        select PINCTRL_SAMSUNG
 
+config PINCTRL_MVEBU
+       bool
+       depends on ARCH_MVEBU
+       select PINMUX
+       select PINCONF
+
+config PINCTRL_DOVE
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+       bool
+       select PINCTRL_MVEBU
+
 source "drivers/pinctrl/spear/Kconfig"
 
 endmenu
index 698527dce29dba381062a3425b04dc006b296682..f162e01963006ff6f33070844f50644cf2eaf09e 100644 (file)
@@ -35,5 +35,10 @@ obj-$(CONFIG_PINCTRL_U300)   += pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)   += pinctrl-coh901.o
 obj-$(CONFIG_PINCTRL_SAMSUNG)  += pinctrl-samsung.o
 obj-$(CONFIG_PINCTRL_EXYNOS4)  += pinctrl-exynos.o
+obj-$(CONFIG_PINCTRL_MVEBU)    += pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE)     += pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
 
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/pinctrl-armada-370.c
new file mode 100644 (file)
index 0000000..c907647
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
+       MPP_MODE(0,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "uart0", "rxd")),
+       MPP_MODE(1,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "uart0", "txd")),
+       MPP_MODE(2,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "i2c0", "sck"),
+          MPP_FUNCTION(0x2, "uart0", "txd")),
+       MPP_MODE(3,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "i2c0", "sda"),
+          MPP_FUNCTION(0x2, "uart0", "rxd")),
+       MPP_MODE(4,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "cpu_pd", "vdd")),
+       MPP_MODE(5,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txclko"),
+          MPP_FUNCTION(0x2, "uart1", "txd"),
+          MPP_FUNCTION(0x4, "spi1", "clk"),
+          MPP_FUNCTION(0x5, "audio", "mclk")),
+       MPP_MODE(6,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd0"),
+          MPP_FUNCTION(0x2, "sata0", "prsnt"),
+          MPP_FUNCTION(0x4, "tdm", "rst"),
+          MPP_FUNCTION(0x5, "audio", "sdo")),
+       MPP_MODE(7,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd1"),
+          MPP_FUNCTION(0x4, "tdm", "tdx"),
+          MPP_FUNCTION(0x5, "audio", "lrclk")),
+       MPP_MODE(8,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd2"),
+          MPP_FUNCTION(0x2, "uart0", "rts"),
+          MPP_FUNCTION(0x4, "tdm", "drx"),
+          MPP_FUNCTION(0x5, "audio", "bclk")),
+       MPP_MODE(9,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd3"),
+          MPP_FUNCTION(0x2, "uart1", "txd"),
+          MPP_FUNCTION(0x3, "sd0", "clk"),
+          MPP_FUNCTION(0x5, "audio", "spdifo")),
+       MPP_MODE(10,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txctl"),
+          MPP_FUNCTION(0x2, "uart0", "cts"),
+          MPP_FUNCTION(0x4, "tdm", "fsync"),
+          MPP_FUNCTION(0x5, "audio", "sdi")),
+       MPP_MODE(11,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd0"),
+          MPP_FUNCTION(0x2, "uart1", "rxd"),
+          MPP_FUNCTION(0x3, "sd0", "cmd"),
+          MPP_FUNCTION(0x4, "spi0", "cs1"),
+          MPP_FUNCTION(0x5, "sata1", "prsnt"),
+          MPP_FUNCTION(0x6, "spi1", "cs1")),
+       MPP_MODE(12,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd1"),
+          MPP_FUNCTION(0x2, "i2c1", "sda"),
+          MPP_FUNCTION(0x3, "sd0", "d0"),
+          MPP_FUNCTION(0x4, "spi1", "cs0"),
+          MPP_FUNCTION(0x5, "audio", "spdifi")),
+       MPP_MODE(13,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd2"),
+          MPP_FUNCTION(0x2, "i2c1", "sck"),
+          MPP_FUNCTION(0x3, "sd0", "d1"),
+          MPP_FUNCTION(0x4, "tdm", "pclk"),
+          MPP_FUNCTION(0x5, "audio", "rmclk")),
+       MPP_MODE(14,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd3"),
+          MPP_FUNCTION(0x2, "pcie", "clkreq0"),
+          MPP_FUNCTION(0x3, "sd0", "d2"),
+          MPP_FUNCTION(0x4, "spi1", "mosi"),
+          MPP_FUNCTION(0x5, "spi0", "cs2")),
+       MPP_MODE(15,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxctl"),
+          MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+          MPP_FUNCTION(0x3, "sd0", "d3"),
+          MPP_FUNCTION(0x4, "spi1", "miso"),
+          MPP_FUNCTION(0x5, "spi0", "cs3")),
+       MPP_MODE(16,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxclk"),
+          MPP_FUNCTION(0x2, "uart1", "rxd"),
+          MPP_FUNCTION(0x4, "tdm", "int"),
+          MPP_FUNCTION(0x5, "audio", "extclk")),
+       MPP_MODE(17,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge", "mdc")),
+       MPP_MODE(18,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge", "mdio")),
+       MPP_MODE(19,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txclk"),
+          MPP_FUNCTION(0x2, "ge1", "txclkout"),
+          MPP_FUNCTION(0x4, "tdm", "pclk")),
+       MPP_MODE(20,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd4"),
+          MPP_FUNCTION(0x2, "ge1", "txd0")),
+       MPP_MODE(21,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd5"),
+          MPP_FUNCTION(0x2, "ge1", "txd1"),
+          MPP_FUNCTION(0x4, "uart1", "txd")),
+       MPP_MODE(22,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd6"),
+          MPP_FUNCTION(0x2, "ge1", "txd2"),
+          MPP_FUNCTION(0x4, "uart0", "rts")),
+       MPP_MODE(23,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "ge0", "txd7"),
+          MPP_FUNCTION(0x2, "ge1", "txd3"),
+          MPP_FUNCTION(0x4, "spi1", "mosi")),
+       MPP_MODE(24,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "col"),
+          MPP_FUNCTION(0x2, "ge1", "txctl"),
+          MPP_FUNCTION(0x4, "spi1", "cs0")),
+       MPP_MODE(25,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxerr"),
+          MPP_FUNCTION(0x2, "ge1", "rxd0"),
+          MPP_FUNCTION(0x4, "uart1", "rxd")),
+       MPP_MODE(26,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "crs"),
+          MPP_FUNCTION(0x2, "ge1", "rxd1"),
+          MPP_FUNCTION(0x4, "spi1", "miso")),
+       MPP_MODE(27,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd4"),
+          MPP_FUNCTION(0x2, "ge1", "rxd2"),
+          MPP_FUNCTION(0x4, "uart0", "cts")),
+       MPP_MODE(28,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd5"),
+          MPP_FUNCTION(0x2, "ge1", "rxd3")),
+       MPP_MODE(29,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd6"),
+          MPP_FUNCTION(0x2, "ge1", "rxctl"),
+          MPP_FUNCTION(0x4, "i2c1", "sda")),
+       MPP_MODE(30,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "ge0", "rxd7"),
+          MPP_FUNCTION(0x2, "ge1", "rxclk"),
+          MPP_FUNCTION(0x4, "i2c1", "sck")),
+       MPP_MODE(31,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x3, "tclk", NULL),
+          MPP_FUNCTION(0x4, "ge0", "txerr")),
+       MPP_MODE(32,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "spi0", "cs0")),
+       MPP_MODE(33,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "bootcs"),
+          MPP_FUNCTION(0x2, "spi0", "cs0")),
+       MPP_MODE(34,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "wen0"),
+          MPP_FUNCTION(0x2, "spi0", "mosi")),
+       MPP_MODE(35,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "oen"),
+          MPP_FUNCTION(0x2, "spi0", "sck")),
+       MPP_MODE(36,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "a1"),
+          MPP_FUNCTION(0x2, "spi0", "miso")),
+       MPP_MODE(37,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "a0"),
+          MPP_FUNCTION(0x2, "sata0", "prsnt")),
+       MPP_MODE(38,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ready"),
+          MPP_FUNCTION(0x2, "uart1", "cts"),
+          MPP_FUNCTION(0x3, "uart0", "cts")),
+       MPP_MODE(39,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad0"),
+          MPP_FUNCTION(0x2, "audio", "spdifo")),
+       MPP_MODE(40,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad1"),
+          MPP_FUNCTION(0x2, "uart1", "rts"),
+          MPP_FUNCTION(0x3, "uart0", "rts")),
+       MPP_MODE(41,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad2"),
+          MPP_FUNCTION(0x2, "uart1", "rxd")),
+       MPP_MODE(42,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad3"),
+          MPP_FUNCTION(0x2, "uart1", "txd")),
+       MPP_MODE(43,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad4"),
+          MPP_FUNCTION(0x2, "audio", "bclk")),
+       MPP_MODE(44,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad5"),
+          MPP_FUNCTION(0x2, "audio", "mclk")),
+       MPP_MODE(45,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad6"),
+          MPP_FUNCTION(0x2, "audio", "lrclk")),
+       MPP_MODE(46,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad7"),
+          MPP_FUNCTION(0x2, "audio", "sdo")),
+       MPP_MODE(47,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad8"),
+          MPP_FUNCTION(0x3, "sd0", "clk"),
+          MPP_FUNCTION(0x5, "audio", "spdifo")),
+       MPP_MODE(48,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad9"),
+          MPP_FUNCTION(0x2, "uart0", "rts"),
+          MPP_FUNCTION(0x3, "sd0", "cmd"),
+          MPP_FUNCTION(0x4, "sata1", "prsnt"),
+          MPP_FUNCTION(0x5, "spi0", "cs1")),
+       MPP_MODE(49,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad10"),
+          MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+          MPP_FUNCTION(0x3, "sd0", "d0"),
+          MPP_FUNCTION(0x4, "spi1", "cs0"),
+          MPP_FUNCTION(0x5, "audio", "spdifi")),
+       MPP_MODE(50,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad11"),
+          MPP_FUNCTION(0x2, "uart0", "cts"),
+          MPP_FUNCTION(0x3, "sd0", "d1"),
+          MPP_FUNCTION(0x4, "spi1", "miso"),
+          MPP_FUNCTION(0x5, "audio", "rmclk")),
+       MPP_MODE(51,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad12"),
+          MPP_FUNCTION(0x2, "i2c1", "sda"),
+          MPP_FUNCTION(0x3, "sd0", "d2"),
+          MPP_FUNCTION(0x4, "spi1", "mosi")),
+       MPP_MODE(52,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad13"),
+          MPP_FUNCTION(0x2, "i2c1", "sck"),
+          MPP_FUNCTION(0x3, "sd0", "d3"),
+          MPP_FUNCTION(0x4, "spi1", "sck")),
+       MPP_MODE(53,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad14"),
+          MPP_FUNCTION(0x2, "sd0", "clk"),
+          MPP_FUNCTION(0x3, "tdm", "pclk"),
+          MPP_FUNCTION(0x4, "spi0", "cs2"),
+          MPP_FUNCTION(0x5, "pcie", "clkreq1")),
+       MPP_MODE(54,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ad15"),
+          MPP_FUNCTION(0x3, "tdm", "dtx")),
+       MPP_MODE(55,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "cs1"),
+          MPP_FUNCTION(0x2, "uart1", "txd"),
+          MPP_FUNCTION(0x3, "tdm", "rst"),
+          MPP_FUNCTION(0x4, "sata1", "prsnt"),
+          MPP_FUNCTION(0x5, "sata0", "prsnt")),
+       MPP_MODE(56,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "cs2"),
+          MPP_FUNCTION(0x2, "uart1", "cts"),
+          MPP_FUNCTION(0x3, "uart0", "cts"),
+          MPP_FUNCTION(0x4, "spi0", "cs3"),
+          MPP_FUNCTION(0x5, "pcie", "clkreq0"),
+          MPP_FUNCTION(0x6, "spi1", "cs1")),
+       MPP_MODE(57,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "cs3"),
+          MPP_FUNCTION(0x2, "uart1", "rxd"),
+          MPP_FUNCTION(0x3, "tdm", "fsync"),
+          MPP_FUNCTION(0x4, "sata0", "prsnt"),
+          MPP_FUNCTION(0x5, "audio", "sdo")),
+       MPP_MODE(58,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "cs0"),
+          MPP_FUNCTION(0x2, "uart1", "rts"),
+          MPP_FUNCTION(0x3, "tdm", "int"),
+          MPP_FUNCTION(0x5, "audio", "extclk"),
+          MPP_FUNCTION(0x6, "uart0", "rts")),
+       MPP_MODE(59,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "ale0"),
+          MPP_FUNCTION(0x2, "uart1", "rts"),
+          MPP_FUNCTION(0x3, "uart0", "rts"),
+          MPP_FUNCTION(0x5, "audio", "bclk")),
+       MPP_MODE(60,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "ale1"),
+          MPP_FUNCTION(0x2, "uart1", "rxd"),
+          MPP_FUNCTION(0x3, "sata0", "prsnt"),
+          MPP_FUNCTION(0x4, "pcie", "rst-out"),
+          MPP_FUNCTION(0x5, "audio", "sdi")),
+       MPP_MODE(61,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "dev", "wen1"),
+          MPP_FUNCTION(0x2, "uart1", "txd"),
+          MPP_FUNCTION(0x5, "audio", "rclk")),
+       MPP_MODE(62,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "dev", "a2"),
+          MPP_FUNCTION(0x2, "uart1", "cts"),
+          MPP_FUNCTION(0x3, "tdm", "drx"),
+          MPP_FUNCTION(0x4, "pcie", "clkreq0"),
+          MPP_FUNCTION(0x5, "audio", "mclk"),
+          MPP_FUNCTION(0x6, "uart0", "cts")),
+       MPP_MODE(63,
+          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x1, "spi0", "sck"),
+          MPP_FUNCTION(0x2, "tclk", NULL)),
+       MPP_MODE(64,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "spi0", "miso"),
+          MPP_FUNCTION(0x2, "spi0-1", "cs1")),
+       MPP_MODE(65,
+          MPP_FUNCTION(0x0, "gpio", NULL),
+          MPP_FUNCTION(0x1, "spi0", "mosi"),
+          MPP_FUNCTION(0x2, "spi0-1", "cs2")),
+};
+
+static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
+
+static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = {
+       { .compatible = "marvell,mv88f6710-pinctrl" },
+       { },
+};
+
+static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
+       MPP_REG_CTRL(0, 65),
+};
+
+static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,   0,  0, 32),
+       MPP_GPIO_RANGE(1,  32, 32, 32),
+       MPP_GPIO_RANGE(2,  64, 64,  2),
+};
+
+static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
+
+       soc->variant = 0; /* no variants for Armada 370 */
+       soc->controls = mv88f6710_mpp_controls;
+       soc->ncontrols = ARRAY_SIZE(mv88f6710_mpp_controls);
+       soc->modes = mv88f6710_mpp_modes;
+       soc->nmodes = ARRAY_SIZE(mv88f6710_mpp_modes);
+       soc->gpioranges = mv88f6710_mpp_gpio_ranges;
+       soc->ngpioranges = ARRAY_SIZE(mv88f6710_mpp_gpio_ranges);
+
+       pdev->dev.platform_data = soc;
+
+       return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev)
+{
+       return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_370_pinctrl_driver = {
+       .driver = {
+               .name = "armada-370-pinctrl",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
+       },
+       .probe = armada_370_pinctrl_probe,
+       .remove = __devexit_p(armada_370_pinctrl_remove),
+};
+
+module_platform_driver(armada_370_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/pinctrl-armada-xp.c
new file mode 100644 (file)
index 0000000..40bd52a
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * Marvell Armada XP pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 file supports the three variants of Armada XP SoCs that are
+ * available: mv78230, mv78260 and mv78460. From a pin muxing
+ * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460
+ * both have 67 MPP pins (more GPIOs and address lines for the memory
+ * bus mainly). The only difference between the mv78260 and the
+ * mv78460 in terms of pin muxing is the addition of two functions on
+ * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two
+ * cores, mv78460 has four cores).
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/bitops.h>
+
+#include "pinctrl-mvebu.h"
+
+enum armada_xp_variant {
+       V_MV78230       = BIT(0),
+       V_MV78260       = BIT(1),
+       V_MV78460       = BIT(2),
+       V_MV78230_PLUS  = (V_MV78230 | V_MV78260 | V_MV78460),
+       V_MV78260_PLUS  = (V_MV78260 | V_MV78460),
+};
+
+static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
+       MPP_MODE(0,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txclko",     V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d0",         V_MV78230_PLUS)),
+       MPP_MODE(1,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd0",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d1",         V_MV78230_PLUS)),
+       MPP_MODE(2,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd1",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d2",         V_MV78230_PLUS)),
+       MPP_MODE(3,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd2",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d3",         V_MV78230_PLUS)),
+       MPP_MODE(4,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd3",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d4",         V_MV78230_PLUS)),
+       MPP_MODE(5,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txctl",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d5",         V_MV78230_PLUS)),
+       MPP_MODE(6,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd0",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d6",         V_MV78230_PLUS)),
+       MPP_MODE(7,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd1",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d7",         V_MV78230_PLUS)),
+       MPP_MODE(8,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd2",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d8",         V_MV78230_PLUS)),
+       MPP_MODE(9,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd3",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d9",         V_MV78230_PLUS)),
+       MPP_MODE(10,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxctl",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d10",        V_MV78230_PLUS)),
+       MPP_MODE(11,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxclk",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d11",        V_MV78230_PLUS)),
+       MPP_MODE(12,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd4",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "clkout",     V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d12",        V_MV78230_PLUS)),
+       MPP_MODE(13,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd5",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "txd0",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d13",        V_MV78230_PLUS)),
+       MPP_MODE(14,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd6",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "txd1",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d14",        V_MV78230_PLUS)),
+       MPP_MODE(15,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txd7",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "txd2",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d15",        V_MV78230_PLUS)),
+       MPP_MODE(16,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "txclk",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "txd3",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d16",        V_MV78230_PLUS)),
+       MPP_MODE(17,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "col",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "txctl",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d17",        V_MV78230_PLUS)),
+       MPP_MODE(18,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxerr",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxd0",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "ptp", "trig",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d18",        V_MV78230_PLUS)),
+       MPP_MODE(19,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "crs",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxd1",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "ptp", "evreq",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d19",        V_MV78230_PLUS)),
+       MPP_MODE(20,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd4",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxd2",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "ptp", "clk",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d20",        V_MV78230_PLUS)),
+       MPP_MODE(21,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd5",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxd3",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "mem", "bat",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d21",        V_MV78230_PLUS)),
+       MPP_MODE(22,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd6",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxctl",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "sata0", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d22",        V_MV78230_PLUS)),
+       MPP_MODE(23,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ge0", "rxd7",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "ge1", "rxclk",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "d23",        V_MV78230_PLUS)),
+       MPP_MODE(24,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sata1", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re",   V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "rst",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "hsync",      V_MV78230_PLUS)),
+       MPP_MODE(25,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sata0", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we",   V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "pclk",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "vsync",      V_MV78230_PLUS)),
+       MPP_MODE(26,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "fsync",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "clk",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
+       MPP_MODE(27,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ptp", "trig",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "dtx",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "e",          V_MV78230_PLUS)),
+       MPP_MODE(28,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ptp", "evreq",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "drx",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "pwm",        V_MV78230_PLUS)),
+       MPP_MODE(29,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "ptp", "clk",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int0",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+       MPP_MODE(30,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "clk",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int1",       V_MV78230_PLUS)),
+       MPP_MODE(31,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "cmd",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int2",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+       MPP_MODE(32,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "d0",         V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int3",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd",    V_MV78230_PLUS)),
+       MPP_MODE(33,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "d1",         V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int4",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS)),
+       MPP_MODE(34,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "d2",         V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "sata0", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int5",       V_MV78230_PLUS)),
+       MPP_MODE(35,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "sd0", "d3",         V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "sata1", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int6",       V_MV78230_PLUS)),
+       MPP_MODE(36,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "mosi",       V_MV78230_PLUS)),
+       MPP_MODE(37,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "miso",       V_MV78230_PLUS)),
+       MPP_MODE(38,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "sck",        V_MV78230_PLUS)),
+       MPP_MODE(39,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "cs0",        V_MV78230_PLUS)),
+       MPP_MODE(40,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "cs1",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart2", "cts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync",  V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0",   V_MV78230_PLUS)),
+       MPP_MODE(41,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "spi", "cs2",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart2", "rts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "sata1", "prsnt",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync",  V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1",   V_MV78230_PLUS)),
+       MPP_MODE(42,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart2", "rxd",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart0", "cts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "tdm", "int7",       V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "tdm-1", "timer",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd",    V_MV78230_PLUS)),
+       MPP_MODE(43,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart2", "txd",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart0", "rts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "spi", "cs3",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "pcie", "rstout",    V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd",  V_MV78460)),
+       MPP_MODE(44,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart2", "cts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart3", "rxd",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "spi", "cs4",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "mem", "bat",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2",   V_MV78230_PLUS)),
+       MPP_MODE(45,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart2", "rts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart3", "txd",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "spi", "cs5",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",    V_MV78230_PLUS)),
+       MPP_MODE(46,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart3", "rts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart1", "rts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "spi", "cs6",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",    V_MV78230_PLUS)),
+       MPP_MODE(47,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "uart3", "cts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "uart1", "cts",      V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x3, "spi", "cs7",        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x4, "ref", "clkout",     V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3",   V_MV78230_PLUS)),
+       MPP_MODE(48,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x1, "tclk", NULL,        V_MV78230_PLUS),
+                MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)),
+       MPP_MODE(49,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "we3",        V_MV78260_PLUS)),
+       MPP_MODE(50,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "we2",        V_MV78260_PLUS)),
+       MPP_MODE(51,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad16",       V_MV78260_PLUS)),
+       MPP_MODE(52,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad17",       V_MV78260_PLUS)),
+       MPP_MODE(53,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad18",       V_MV78260_PLUS)),
+       MPP_MODE(54,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad19",       V_MV78260_PLUS)),
+       MPP_MODE(55,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad20",       V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd",    V_MV78260_PLUS)),
+       MPP_MODE(56,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad21",       V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd",    V_MV78260_PLUS)),
+       MPP_MODE(57,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad22",       V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd",  V_MV78460)),
+       MPP_MODE(58,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad23",       V_MV78260_PLUS)),
+       MPP_MODE(59,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad24",       V_MV78260_PLUS)),
+       MPP_MODE(60,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad25",       V_MV78260_PLUS)),
+       MPP_MODE(61,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad26",       V_MV78260_PLUS)),
+       MPP_MODE(62,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad27",       V_MV78260_PLUS)),
+       MPP_MODE(63,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad28",       V_MV78260_PLUS)),
+       MPP_MODE(64,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad29",       V_MV78260_PLUS)),
+       MPP_MODE(65,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad30",       V_MV78260_PLUS)),
+       MPP_MODE(66,
+                MPP_VAR_FUNCTION(0x0, "gpio", NULL,        V_MV78260_PLUS),
+                MPP_VAR_FUNCTION(0x1, "dev", "ad31",       V_MV78260_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
+
+static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = {
+       {
+               .compatible = "marvell,mv78230-pinctrl",
+               .data       = (void *) V_MV78230,
+       },
+       {
+               .compatible = "marvell,mv78260-pinctrl",
+               .data       = (void *) V_MV78260,
+       },
+       {
+               .compatible = "marvell,mv78460-pinctrl",
+               .data       = (void *) V_MV78460,
+       },
+       { },
+};
+
+static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
+       MPP_REG_CTRL(0, 48),
+};
+
+static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,   0,  0, 32),
+       MPP_GPIO_RANGE(1,  32, 32, 17),
+};
+
+static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
+       MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,   0,  0, 32),
+       MPP_GPIO_RANGE(1,  32, 32, 32),
+       MPP_GPIO_RANGE(2,  64, 64,  3),
+};
+
+static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
+       MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,   0,  0, 32),
+       MPP_GPIO_RANGE(1,  32, 32, 32),
+       MPP_GPIO_RANGE(2,  64, 64,  3),
+};
+
+static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
+       const struct of_device_id *match =
+               of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
+
+       if (!match)
+               return -ENODEV;
+
+       soc->variant = (unsigned) match->data & 0xff;
+
+       switch (soc->variant) {
+       case V_MV78230:
+               soc->controls = mv78230_mpp_controls;
+               soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls);
+               soc->modes = armada_xp_mpp_modes;
+               /* We don't necessarily want the full list of the
+                * armada_xp_mpp_modes, but only the first 'n' ones
+                * that are available on this SoC */
+               soc->nmodes = mv78230_mpp_controls[0].npins;
+               soc->gpioranges = mv78230_mpp_gpio_ranges;
+               soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges);
+               break;
+       case V_MV78260:
+               soc->controls = mv78260_mpp_controls;
+               soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls);
+               soc->modes = armada_xp_mpp_modes;
+               /* We don't necessarily want the full list of the
+                * armada_xp_mpp_modes, but only the first 'n' ones
+                * that are available on this SoC */
+               soc->nmodes = mv78260_mpp_controls[0].npins;
+               soc->gpioranges = mv78260_mpp_gpio_ranges;
+               soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges);
+               break;
+       case V_MV78460:
+               soc->controls = mv78460_mpp_controls;
+               soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls);
+               soc->modes = armada_xp_mpp_modes;
+               /* We don't necessarily want the full list of the
+                * armada_xp_mpp_modes, but only the first 'n' ones
+                * that are available on this SoC */
+               soc->nmodes = mv78460_mpp_controls[0].npins;
+               soc->gpioranges = mv78460_mpp_gpio_ranges;
+               soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
+               break;
+       }
+
+       pdev->dev.platform_data = soc;
+
+       return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev)
+{
+       return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_xp_pinctrl_driver = {
+       .driver = {
+               .name = "armada-xp-pinctrl",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
+       },
+       .probe = armada_xp_pinctrl_probe,
+       .remove = __devexit_p(armada_xp_pinctrl_remove),
+};
+
+module_platform_driver(armada_xp_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/pinctrl-dove.c
new file mode 100644 (file)
index 0000000..ffe74b2
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Marvell Dove pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define DOVE_SB_REGS_VIRT_BASE         0xfde00000
+#define DOVE_MPP_VIRT_BASE             (DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_PMU_MPP_GENERAL_CTRL      (DOVE_MPP_VIRT_BASE + 0x10)
+#define  DOVE_AU0_AC97_SEL             BIT(16)
+#define DOVE_GLOBAL_CONFIG_1           (DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define  DOVE_TWSI_ENABLE_OPTION1      BIT(7)
+#define DOVE_GLOBAL_CONFIG_2           (DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define  DOVE_TWSI_ENABLE_OPTION2      BIT(20)
+#define  DOVE_TWSI_ENABLE_OPTION3      BIT(21)
+#define  DOVE_TWSI_OPTION3_GPIO                BIT(22)
+#define DOVE_SSP_CTRL_STATUS_1         (DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define  DOVE_SSP_ON_AU1               BIT(0)
+#define DOVE_MPP_GENERAL_VIRT_BASE     (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define  DOVE_AU1_SPDIFO_GPIO_EN       BIT(1)
+#define  DOVE_NAND_GPIO_EN             BIT(0)
+#define DOVE_GPIO_LO_VIRT_BASE         (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_MPP_CTRL4_VIRT_BASE       (DOVE_GPIO_LO_VIRT_BASE + 0x40)
+#define  DOVE_SPI_GPIO_SEL             BIT(5)
+#define  DOVE_UART1_GPIO_SEL           BIT(4)
+#define  DOVE_AU1_GPIO_SEL             BIT(3)
+#define  DOVE_CAM_GPIO_SEL             BIT(2)
+#define  DOVE_SD1_GPIO_SEL             BIT(1)
+#define  DOVE_SD0_GPIO_SEL             BIT(0)
+
+#define MPPS_PER_REG   8
+#define MPP_BITS       4
+#define MPP_MASK       0xf
+
+#define CONFIG_PMU     BIT(4)
+
+static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                                unsigned long *config)
+{
+       unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+       unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+       unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+       unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+       if (pmu & (1 << ctrl->pid))
+               *config = CONFIG_PMU;
+       else
+               *config = (mpp >> shift) & MPP_MASK;
+       return 0;
+}
+
+static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                                unsigned long config)
+{
+       unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+       unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+       unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+       unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+       if (config == CONFIG_PMU)
+               writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+       else {
+               writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+               mpp &= ~(MPP_MASK << shift);
+               mpp |= config << shift;
+               writel(mpp, DOVE_MPP_VIRT_BASE + off);
+       }
+       return 0;
+}
+
+static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                             unsigned long *config)
+{
+       unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+       unsigned long mask;
+
+       switch (ctrl->pid) {
+       case 24: /* mpp_camera */
+               mask = DOVE_CAM_GPIO_SEL;
+               break;
+       case 40: /* mpp_sdio0 */
+               mask = DOVE_SD0_GPIO_SEL;
+               break;
+       case 46: /* mpp_sdio1 */
+               mask = DOVE_SD1_GPIO_SEL;
+               break;
+       case 58: /* mpp_spi0 */
+               mask = DOVE_SPI_GPIO_SEL;
+               break;
+       case 62: /* mpp_uart1 */
+               mask = DOVE_UART1_GPIO_SEL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       *config = ((mpp4 & mask) != 0);
+
+       return 0;
+}
+
+static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                             unsigned long config)
+{
+       unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+       unsigned long mask;
+
+       switch (ctrl->pid) {
+       case 24: /* mpp_camera */
+               mask = DOVE_CAM_GPIO_SEL;
+               break;
+       case 40: /* mpp_sdio0 */
+               mask = DOVE_SD0_GPIO_SEL;
+               break;
+       case 46: /* mpp_sdio1 */
+               mask = DOVE_SD1_GPIO_SEL;
+               break;
+       case 58: /* mpp_spi0 */
+               mask = DOVE_SPI_GPIO_SEL;
+               break;
+       case 62: /* mpp_uart1 */
+               mask = DOVE_UART1_GPIO_SEL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       mpp4 &= ~mask;
+       if (config)
+               mpp4 |= mask;
+
+       writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+
+       return 0;
+}
+
+static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                             unsigned long *config)
+{
+       unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+       *config = ((gmpp & DOVE_NAND_GPIO_EN) != 0);
+
+       return 0;
+}
+
+static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                             unsigned long config)
+{
+       unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+       gmpp &= ~DOVE_NAND_GPIO_EN;
+       if (config)
+               gmpp |= DOVE_NAND_GPIO_EN;
+
+       writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+
+       return 0;
+}
+
+static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                               unsigned long *config)
+{
+       unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+       *config = ((pmu & DOVE_AU0_AC97_SEL) != 0);
+
+       return 0;
+}
+
+static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                               unsigned long config)
+{
+       unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+       pmu &= ~DOVE_AU0_AC97_SEL;
+       if (config)
+               pmu |= DOVE_AU0_AC97_SEL;
+       writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL);
+
+       return 0;
+}
+
+static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                               unsigned long *config)
+{
+       unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+       unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+       unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+       unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+       *config = 0;
+       if (mpp4 & DOVE_AU1_GPIO_SEL)
+               *config |= BIT(3);
+       if (sspc1 & DOVE_SSP_ON_AU1)
+               *config |= BIT(2);
+       if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN)
+               *config |= BIT(1);
+       if (gcfg2 & DOVE_TWSI_OPTION3_GPIO)
+               *config |= BIT(0);
+
+       /* SSP/TWSI only if I2S1 not set*/
+       if ((*config & BIT(3)) == 0)
+               *config &= ~(BIT(2) | BIT(0));
+       /* TWSI only if SPDIFO not set*/
+       if ((*config & BIT(1)) == 0)
+               *config &= ~BIT(0);
+       return 0;
+}
+
+static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                               unsigned long config)
+{
+       unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+       unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+       unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+       unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+       if (config & BIT(0))
+               gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
+       if (config & BIT(1))
+               gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
+       if (config & BIT(2))
+               sspc1 |= DOVE_SSP_ON_AU1;
+       if (config & BIT(3))
+               mpp4 |= DOVE_AU1_GPIO_SEL;
+
+       writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+       writel(sspc1, DOVE_SSP_CTRL_STATUS_1);
+       writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+       writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+       return 0;
+}
+
+/* mpp[52:57] gpio pins depend heavily on current config;
+ * gpio_req does not try to mux in gpio capabilities to not
+ * break other functions. If you require all mpps as gpio
+ * enforce gpio setting by pinctrl mapping.
+ */
+static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
+{
+       unsigned long config;
+
+       dove_audio1_ctrl_get(ctrl, &config);
+
+       switch (config) {
+       case 0x02: /* i2s1 : gpio[56:57] */
+       case 0x0e: /* ssp  : gpio[56:57] */
+               if (pid >= 56)
+                       return 0;
+               return -ENOTSUPP;
+       case 0x08: /* spdifo : gpio[52:55] */
+       case 0x0b: /* twsi   : gpio[52:55] */
+               if (pid <= 55)
+                       return 0;
+               return -ENOTSUPP;
+       case 0x0a: /* all gpio */
+               return 0;
+       /* 0x00 : i2s1/spdifo : no gpio */
+       /* 0x0c : ssp/spdifo  : no gpio */
+       /* 0x0f : ssp/twsi    : no gpio */
+       }
+       return -ENOTSUPP;
+}
+
+/* mpp[52:57] has gpio pins capable of in and out */
+static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
+                               bool input)
+{
+       if (pid < 52 || pid > 57)
+               return -ENOTSUPP;
+       return 0;
+}
+
+static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+                             unsigned long *config)
+{
+       unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+       unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+       *config = 0;
+       if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1)
+               *config = 1;
+       else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2)
+               *config = 2;
+       else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3)
+               *config = 3;
+
+       return 0;
+}
+
+static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+                               unsigned long config)
+{
+       unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+       unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+       gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
+       gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2);
+
+       switch (config) {
+       case 1:
+               gcfg1 |= DOVE_TWSI_ENABLE_OPTION1;
+               break;
+       case 2:
+               gcfg2 |= DOVE_TWSI_ENABLE_OPTION2;
+               break;
+       case 3:
+               gcfg2 |= DOVE_TWSI_ENABLE_OPTION3;
+               break;
+       }
+
+       writel(gcfg1, DOVE_GLOBAL_CONFIG_1);
+       writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+       return 0;
+}
+
+static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
+       MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
+       MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
+       MPP_REG_CTRL(16, 23),
+       MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
+       MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
+       MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
+       MPP_FUNC_GPIO_CTRL(52, 57, "mpp_audio1", dove_audio1_ctrl),
+       MPP_FUNC_CTRL(58, 61, "mpp_spi0", dove_mpp4_ctrl),
+       MPP_FUNC_CTRL(62, 63, "mpp_uart1", dove_mpp4_ctrl),
+       MPP_FUNC_CTRL(64, 71, "mpp_nand", dove_nand_ctrl),
+       MPP_FUNC_CTRL(72, 72, "audio0", dove_audio0_ctrl),
+       MPP_FUNC_CTRL(73, 73, "twsi", dove_twsi_ctrl),
+};
+
+static struct mvebu_mpp_mode dove_mpp_modes[] = {
+       MPP_MODE(0,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart2", "rts"),
+               MPP_FUNCTION(0x03, "sdio0", "cd"),
+               MPP_FUNCTION(0x0f, "lcd0", "pwm"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(1,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart2", "cts"),
+               MPP_FUNCTION(0x03, "sdio0", "wp"),
+               MPP_FUNCTION(0x0f, "lcd1", "pwm"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(2,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "sata", "prsnt"),
+               MPP_FUNCTION(0x02, "uart2", "txd"),
+               MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+               MPP_FUNCTION(0x04, "uart1", "rts"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(3,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "sata", "act"),
+               MPP_FUNCTION(0x02, "uart2", "rxd"),
+               MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+               MPP_FUNCTION(0x04, "uart1", "cts"),
+               MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(4,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "rts"),
+               MPP_FUNCTION(0x03, "sdio1", "cd"),
+               MPP_FUNCTION(0x04, "spi1", "miso"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(5,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "cts"),
+               MPP_FUNCTION(0x03, "sdio1", "wp"),
+               MPP_FUNCTION(0x04, "spi1", "cs"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(6,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "txd"),
+               MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+               MPP_FUNCTION(0x04, "spi1", "mosi"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(7,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "rxd"),
+               MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+               MPP_FUNCTION(0x04, "spi1", "sck"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(8,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "watchdog", "rstout"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(9,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x05, "pex1", "clkreq"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(10,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x05, "ssp", "sclk"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(11,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "sata", "prsnt"),
+               MPP_FUNCTION(0x02, "sata-1", "act"),
+               MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+               MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+               MPP_FUNCTION(0x05, "pex0", "clkreq"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(12,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "sata", "act"),
+               MPP_FUNCTION(0x02, "uart2", "rts"),
+               MPP_FUNCTION(0x03, "audio0", "extclk"),
+               MPP_FUNCTION(0x04, "sdio1", "cd"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(13,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart2", "cts"),
+               MPP_FUNCTION(0x03, "audio1", "extclk"),
+               MPP_FUNCTION(0x04, "sdio1", "wp"),
+               MPP_FUNCTION(0x05, "ssp", "extclk"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(14,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart2", "txd"),
+               MPP_FUNCTION(0x04, "sdio1", "buspwr"),
+               MPP_FUNCTION(0x05, "ssp", "rxd"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(15,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart2", "rxd"),
+               MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+               MPP_FUNCTION(0x05, "ssp", "sfrm"),
+               MPP_FUNCTION(0x10, "pmu", NULL)),
+       MPP_MODE(16,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "rts"),
+               MPP_FUNCTION(0x03, "sdio0", "cd"),
+               MPP_FUNCTION(0x04, "lcd-spi", "cs1"),
+               MPP_FUNCTION(0x05, "ac97", "sdi1")),
+       MPP_MODE(17,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "ac97-1", "sysclko"),
+               MPP_FUNCTION(0x02, "uart3", "cts"),
+               MPP_FUNCTION(0x03, "sdio0", "wp"),
+               MPP_FUNCTION(0x04, "twsi", "sda"),
+               MPP_FUNCTION(0x05, "ac97", "sdi2")),
+       MPP_MODE(18,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "txd"),
+               MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+               MPP_FUNCTION(0x04, "lcd0", "pwm"),
+               MPP_FUNCTION(0x05, "ac97", "sdi3")),
+       MPP_MODE(19,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "uart3", "rxd"),
+               MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+               MPP_FUNCTION(0x04, "twsi", "sck")),
+       MPP_MODE(20,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "ac97", "sysclko"),
+               MPP_FUNCTION(0x02, "lcd-spi", "miso"),
+               MPP_FUNCTION(0x03, "sdio1", "cd"),
+               MPP_FUNCTION(0x05, "sdio0", "cd"),
+               MPP_FUNCTION(0x06, "spi1", "miso")),
+       MPP_MODE(21,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "uart1", "rts"),
+               MPP_FUNCTION(0x02, "lcd-spi", "cs0"),
+               MPP_FUNCTION(0x03, "sdio1", "wp"),
+               MPP_FUNCTION(0x04, "ssp", "sfrm"),
+               MPP_FUNCTION(0x05, "sdio0", "wp"),
+               MPP_FUNCTION(0x06, "spi1", "cs")),
+       MPP_MODE(22,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x01, "uart1", "cts"),
+               MPP_FUNCTION(0x02, "lcd-spi", "mosi"),
+               MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+               MPP_FUNCTION(0x04, "ssp", "txd"),
+               MPP_FUNCTION(0x05, "sdio0", "buspwr"),
+               MPP_FUNCTION(0x06, "spi1", "mosi")),
+       MPP_MODE(23,
+               MPP_FUNCTION(0x00, "gpio", NULL),
+               MPP_FUNCTION(0x02, "lcd-spi", "sck"),
+               MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+               MPP_FUNCTION(0x04, "ssp", "sclk"),
+               MPP_FUNCTION(0x05, "sdio0", "ledctrl"),
+               MPP_FUNCTION(0x06, "spi1", "sck")),
+       MPP_MODE(24,
+               MPP_FUNCTION(0x00, "camera", NULL),
+               MPP_FUNCTION(0x01, "gpio", NULL)),
+       MPP_MODE(40,
+               MPP_FUNCTION(0x00, "sdio0", NULL),
+               MPP_FUNCTION(0x01, "gpio", NULL)),
+       MPP_MODE(46,
+               MPP_FUNCTION(0x00, "sdio1", NULL),
+               MPP_FUNCTION(0x01, "gpio", NULL)),
+       MPP_MODE(52,
+               MPP_FUNCTION(0x00, "i2s1/spdifo", NULL),
+               MPP_FUNCTION(0x02, "i2s1", NULL),
+               MPP_FUNCTION(0x08, "spdifo", NULL),
+               MPP_FUNCTION(0x0a, "gpio", NULL),
+               MPP_FUNCTION(0x0b, "twsi", NULL),
+               MPP_FUNCTION(0x0c, "ssp/spdifo", NULL),
+               MPP_FUNCTION(0x0e, "ssp", NULL),
+               MPP_FUNCTION(0x0f, "ssp/twsi", NULL)),
+       MPP_MODE(58,
+               MPP_FUNCTION(0x00, "spi0", NULL),
+               MPP_FUNCTION(0x01, "gpio", NULL)),
+       MPP_MODE(62,
+               MPP_FUNCTION(0x00, "uart1", NULL),
+               MPP_FUNCTION(0x01, "gpio", NULL)),
+       MPP_MODE(64,
+               MPP_FUNCTION(0x00, "nand", NULL),
+               MPP_FUNCTION(0x01, "gpo", NULL)),
+       MPP_MODE(72,
+               MPP_FUNCTION(0x00, "i2s", NULL),
+               MPP_FUNCTION(0x01, "ac97", NULL)),
+       MPP_MODE(73,
+               MPP_FUNCTION(0x00, "twsi-none", NULL),
+               MPP_FUNCTION(0x01, "twsi-opt1", NULL),
+               MPP_FUNCTION(0x02, "twsi-opt2", NULL),
+               MPP_FUNCTION(0x03, "twsi-opt3", NULL)),
+};
+
+static struct pinctrl_gpio_range dove_mpp_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,  0,  0, 32),
+       MPP_GPIO_RANGE(1, 32, 32, 32),
+       MPP_GPIO_RANGE(2, 64, 64,  8),
+};
+
+static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
+       .controls = dove_mpp_controls,
+       .ncontrols = ARRAY_SIZE(dove_mpp_controls),
+       .modes = dove_mpp_modes,
+       .nmodes = ARRAY_SIZE(dove_mpp_modes),
+       .gpioranges = dove_mpp_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(dove_mpp_gpio_ranges),
+       .variant = 0,
+};
+
+static struct clk *clk;
+
+static struct of_device_id dove_pinctrl_of_match[] __devinitdata = {
+       { .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
+       { }
+};
+
+static int __devinit dove_pinctrl_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match =
+               of_match_device(dove_pinctrl_of_match, &pdev->dev);
+       pdev->dev.platform_data = match->data;
+
+       /*
+        * General MPP Configuration Register is part of pdma registers.
+        * grab clk to make sure it is ticking.
+        */
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(clk))
+               clk_prepare_enable(clk);
+
+       return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit dove_pinctrl_remove(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = mvebu_pinctrl_remove(pdev);
+       if (!IS_ERR(clk))
+               clk_disable_unprepare(clk);
+       return ret;
+}
+
+static struct platform_driver dove_pinctrl_driver = {
+       .driver = {
+               .name = "dove-pinctrl",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(dove_pinctrl_of_match),
+       },
+       .probe = dove_pinctrl_probe,
+       .remove = __devexit_p(dove_pinctrl_remove),
+};
+
+module_platform_driver(dove_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Dove pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
new file mode 100644 (file)
index 0000000..9a74ef6
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@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.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define V(f6180, f6190, f6192, f6281, f6282)           \
+       ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |   \
+        (f6281 << 3) | (f6282 << 4))
+
+enum kirkwood_variant {
+       VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
+       VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
+       VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
+       VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
+       VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
+};
+
+static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
+       MPP_MODE(0,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io2",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1))),
+       MPP_MODE(1,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io3",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1))),
+       MPP_MODE(2,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io4",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1))),
+       MPP_MODE(3,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io5",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1))),
+       MPP_MODE(4,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io6",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0))),
+       MPP_MODE(5,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io7",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "txd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "ptp", "trig",     V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(6,
+               MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0))),
+       MPP_MODE(7,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(8,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "twsi0", "sda",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "rts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr",  V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xc, "ptp", "clk",      V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
+       MPP_MODE(9,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "twsi0", "sck",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "cts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xc, "ptp", "evreq",    V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
+       MPP_MODE(10,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0X3, "uart0", "txd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xc, "ptp", "trig",     V(1, 1, 1, 1, 0))),
+       MPP_MODE(11,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq",  V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0xc, "ptp-2", "trig",   V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1))),
+       MPP_MODE(12,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 0, 1)),
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "clk",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xb, "spi", "mosi",     V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xd, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(13,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "cmd",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xa, "audio", "rmclk",  V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(14,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "d0",      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xb, "audio-1", "sdi",  V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
+       MPP_MODE(15,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "d1",      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "sata0", "act",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "spi", "cs",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(16,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "d2",      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "sata1", "act",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "extclk",   V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
+       MPP_MODE(17,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "sdio", "d3",      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xa, "sata1", "act",    V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xd, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(18,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io0",     V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "pex", "clkreq",   V(0, 0, 0, 0, 1))),
+       MPP_MODE(19,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "nand", "io1",     V(1, 1, 1, 1, 1))),
+       MPP_MODE(20,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txd0",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d0",       V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(1, 0, 0, 0, 0))),
+       MPP_MODE(21,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txd1",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d1",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(22,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txd2",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d2",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(23,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txd3",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d3",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(24,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxd0",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d4",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(25,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxd1",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d5",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(26,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxd2",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d6",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(27,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxd3",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d7",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(28,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "col",      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d8",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(29,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txclk",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d9",       V(0, 0, 0, 0, 1))),
+       MPP_MODE(30,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxctl",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d10",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(31,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxclk",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d11",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(32,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txclko",   V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d12",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(33,
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txctl",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d13",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(34,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "txen",     V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d14",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(35,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x3, "ge1", "rxerr",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d15",      V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(0, 1, 1, 1, 1))),
+       MPP_MODE(36,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(37,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(38,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d18",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(39,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d19",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(40,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d20",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(41,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d21",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(42,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d22",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(43,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d23",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(44,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "clk",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(45,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "e",        V(0, 0, 0, 0, 1))),
+       MPP_MODE(46,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(47,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
+       MPP_MODE(48,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d16",      V(0, 0, 0, 0, 1))),
+       MPP_MODE(49,
+               MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
+               MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 0)),
+               MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 0, 1, 1)),
+               MPP_VAR_FUNCTION(0x5, "ptp", "clk",      V(0, 0, 0, 1, 0)),
+               MPP_VAR_FUNCTION(0xa, "pex", "clkreq",   V(0, 0, 0, 0, 1)),
+               MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1))),
+};
+
+static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+       MPP_REG_CTRL(0, 29),
+};
+
+static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0, 0, 0, 30),
+};
+
+static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+       MPP_REG_CTRL(0, 35),
+};
+
+static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,  0,  0, 32),
+       MPP_GPIO_RANGE(1, 32, 32,  4),
+};
+
+static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+       MPP_REG_CTRL(0, 49),
+};
+
+static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
+       MPP_GPIO_RANGE(0,  0,  0, 32),
+       MPP_GPIO_RANGE(1, 32, 32, 18),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6180_info = {
+       .variant = VARIANT_MV88F6180,
+       .controls = mv88f6180_mpp_controls,
+       .ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
+       .modes = mv88f6xxx_mpp_modes,
+       .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+       .gpioranges = mv88f6180_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6190_info = {
+       .variant = VARIANT_MV88F6190,
+       .controls = mv88f619x_mpp_controls,
+       .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+       .modes = mv88f6xxx_mpp_modes,
+       .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+       .gpioranges = mv88f619x_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6192_info = {
+       .variant = VARIANT_MV88F6192,
+       .controls = mv88f619x_mpp_controls,
+       .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+       .modes = mv88f6xxx_mpp_modes,
+       .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+       .gpioranges = mv88f619x_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6281_info = {
+       .variant = VARIANT_MV88F6281,
+       .controls = mv88f628x_mpp_controls,
+       .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+       .modes = mv88f6xxx_mpp_modes,
+       .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+       .gpioranges = mv88f628x_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6282_info = {
+       .variant = VARIANT_MV88F6282,
+       .controls = mv88f628x_mpp_controls,
+       .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+       .modes = mv88f6xxx_mpp_modes,
+       .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+       .gpioranges = mv88f628x_gpio_ranges,
+       .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+       { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
+       { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
+       { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
+       { .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
+       { .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+       { }
+};
+
+static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match =
+               of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
+       pdev->dev.platform_data = match->data;
+       return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+{
+       return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver kirkwood_pinctrl_driver = {
+       .driver = {
+               .name = "kirkwood-pinctrl",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+       },
+       .probe = kirkwood_pinctrl_probe,
+       .remove = __devexit_p(kirkwood_pinctrl_remove),
+};
+
+module_platform_driver(kirkwood_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/pinctrl-mvebu.c
new file mode 100644 (file)
index 0000000..8e6266c
--- /dev/null
@@ -0,0 +1,754 @@
+/*
+ * Marvell MVEBU pinctrl core driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *          Thomas Petazzoni <thomas.petazzoni@free-electrons.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/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinctrl-mvebu.h"
+
+#define MPPS_PER_REG   8
+#define MPP_BITS       4
+#define MPP_MASK       0xf
+
+struct mvebu_pinctrl_function {
+       const char *name;
+       const char **groups;
+       unsigned num_groups;
+};
+
+struct mvebu_pinctrl_group {
+       const char *name;
+       struct mvebu_mpp_ctrl *ctrl;
+       struct mvebu_mpp_ctrl_setting *settings;
+       unsigned num_settings;
+       unsigned gid;
+       unsigned *pins;
+       unsigned npins;
+};
+
+struct mvebu_pinctrl {
+       struct device *dev;
+       struct pinctrl_dev *pctldev;
+       struct pinctrl_desc desc;
+       void __iomem *base;
+       struct mvebu_pinctrl_group *groups;
+       unsigned num_groups;
+       struct mvebu_pinctrl_function *functions;
+       unsigned num_functions;
+       u8 variant;
+};
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
+       struct mvebu_pinctrl *pctl, unsigned pid)
+{
+       unsigned n;
+       for (n = 0; n < pctl->num_groups; n++) {
+               if (pid >= pctl->groups[n].pins[0] &&
+                   pid < pctl->groups[n].pins[0] +
+                       pctl->groups[n].npins)
+                       return &pctl->groups[n];
+       }
+       return NULL;
+}
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name(
+       struct mvebu_pinctrl *pctl, const char *name)
+{
+       unsigned n;
+       for (n = 0; n < pctl->num_groups; n++) {
+               if (strcmp(name, pctl->groups[n].name) == 0)
+                       return &pctl->groups[n];
+       }
+       return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val(
+       struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+       unsigned long config)
+{
+       unsigned n;
+       for (n = 0; n < grp->num_settings; n++) {
+               if (config == grp->settings[n].val) {
+                       if (!pctl->variant || (pctl->variant &
+                                              grp->settings[n].variant))
+                               return &grp->settings[n];
+               }
+       }
+       return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name(
+       struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+       const char *name)
+{
+       unsigned n;
+       for (n = 0; n < grp->num_settings; n++) {
+               if (strcmp(name, grp->settings[n].name) == 0) {
+                       if (!pctl->variant || (pctl->variant &
+                                              grp->settings[n].variant))
+                               return &grp->settings[n];
+               }
+       }
+       return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting(
+       struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp)
+{
+       unsigned n;
+       for (n = 0; n < grp->num_settings; n++) {
+               if (grp->settings[n].flags &
+                       (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+                       if (!pctl->variant || (pctl->variant &
+                                               grp->settings[n].variant))
+                               return &grp->settings[n];
+               }
+       }
+       return NULL;
+}
+
+static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
+       struct mvebu_pinctrl *pctl, const char *name)
+{
+       unsigned n;
+       for (n = 0; n < pctl->num_functions; n++) {
+               if (strcmp(name, pctl->functions[n].name) == 0)
+                       return &pctl->functions[n];
+       }
+       return NULL;
+}
+
+/*
+ * Common mpp pin configuration registers on MVEBU are
+ * registers of eight 4-bit values for each mpp setting.
+ * Register offset and bit mask are calculated accordingly below.
+ */
+static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
+                               struct mvebu_pinctrl_group *grp,
+                               unsigned long *config)
+{
+       unsigned pin = grp->gid;
+       unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+       unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+
+       *config = readl(pctl->base + off);
+       *config >>= shift;
+       *config &= MPP_MASK;
+
+       return 0;
+}
+
+static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
+                               struct mvebu_pinctrl_group *grp,
+                               unsigned long config)
+{
+       unsigned pin = grp->gid;
+       unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+       unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+       unsigned long reg;
+
+       reg = readl(pctl->base + off);
+       reg &= ~(MPP_MASK << shift);
+       reg |= (config << shift);
+       writel(reg, pctl->base + off);
+
+       return 0;
+}
+
+static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
+                               unsigned gid, unsigned long *config)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+       if (!grp->ctrl)
+               return -EINVAL;
+
+       if (grp->ctrl->mpp_get)
+               return grp->ctrl->mpp_get(grp->ctrl, config);
+
+       return mvebu_common_mpp_get(pctl, grp, config);
+}
+
+static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
+                               unsigned gid, unsigned long config)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+       if (!grp->ctrl)
+               return -EINVAL;
+
+       if (grp->ctrl->mpp_set)
+               return grp->ctrl->mpp_set(grp->ctrl, config);
+
+       return mvebu_common_mpp_set(pctl, grp, config);
+}
+
+static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+                                       struct seq_file *s, unsigned gid)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+       struct mvebu_mpp_ctrl_setting *curr;
+       unsigned long config;
+       unsigned n;
+
+       if (mvebu_pinconf_group_get(pctldev, gid, &config))
+               return;
+
+       curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config);
+
+       if (curr) {
+               seq_printf(s, "current: %s", curr->name);
+               if (curr->subname)
+                       seq_printf(s, "(%s)", curr->subname);
+               if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+                       seq_printf(s, "(");
+                       if (curr->flags & MVEBU_SETTING_GPI)
+                               seq_printf(s, "i");
+                       if (curr->flags & MVEBU_SETTING_GPO)
+                               seq_printf(s, "o");
+                       seq_printf(s, ")");
+               }
+       } else
+               seq_printf(s, "current: UNKNOWN");
+
+       if (grp->num_settings > 1) {
+               seq_printf(s, ", available = [");
+               for (n = 0; n < grp->num_settings; n++) {
+                       if (curr == &grp->settings[n])
+                               continue;
+
+                       /* skip unsupported settings for this variant */
+                       if (pctl->variant &&
+                           !(pctl->variant & grp->settings[n].variant))
+                               continue;
+
+                       seq_printf(s, " %s", grp->settings[n].name);
+                       if (grp->settings[n].subname)
+                               seq_printf(s, "(%s)", grp->settings[n].subname);
+                       if (grp->settings[n].flags &
+                               (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+                               seq_printf(s, "(");
+                               if (grp->settings[n].flags & MVEBU_SETTING_GPI)
+                                       seq_printf(s, "i");
+                               if (grp->settings[n].flags & MVEBU_SETTING_GPO)
+                                       seq_printf(s, "o");
+                               seq_printf(s, ")");
+                       }
+               }
+               seq_printf(s, " ]");
+       }
+       return;
+}
+
+static struct pinconf_ops mvebu_pinconf_ops = {
+       .pin_config_group_get = mvebu_pinconf_group_get,
+       .pin_config_group_set = mvebu_pinconf_group_set,
+       .pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
+};
+
+static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->num_functions;
+}
+
+static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+                                       unsigned fid)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->functions[fid].name;
+}
+
+static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid,
+                               const char * const **groups,
+                               unsigned * const num_groups)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pctl->functions[fid].groups;
+       *num_groups = pctl->functions[fid].num_groups;
+       return 0;
+}
+
+static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
+                       unsigned gid)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_function *func = &pctl->functions[fid];
+       struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+       struct mvebu_mpp_ctrl_setting *setting;
+       int ret;
+
+       setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,
+                                                    func->name);
+       if (!setting) {
+               dev_err(pctl->dev,
+                       "unable to find setting %s in group %s\n",
+                       func->name, func->groups[gid]);
+               return -EINVAL;
+       }
+
+       ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+       if (ret) {
+               dev_err(pctl->dev, "cannot set group %s to %s\n",
+                       func->groups[gid], func->name);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+                       struct pinctrl_gpio_range *range, unsigned offset)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_group *grp;
+       struct mvebu_mpp_ctrl_setting *setting;
+
+       grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+       if (!grp)
+               return -EINVAL;
+
+       if (grp->ctrl->mpp_gpio_req)
+               return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
+
+       setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+       if (!setting)
+               return -ENOTSUPP;
+
+       return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+}
+
+static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+          struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mvebu_pinctrl_group *grp;
+       struct mvebu_mpp_ctrl_setting *setting;
+
+       grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+       if (!grp)
+               return -EINVAL;
+
+       if (grp->ctrl->mpp_gpio_dir)
+               return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
+
+       setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+       if (!setting)
+               return -ENOTSUPP;
+
+       if ((input && (setting->flags & MVEBU_SETTING_GPI)) ||
+           (!input && (setting->flags & MVEBU_SETTING_GPO)))
+               return 0;
+
+       return -ENOTSUPP;
+}
+
+static struct pinmux_ops mvebu_pinmux_ops = {
+       .get_functions_count = mvebu_pinmux_get_funcs_count,
+       .get_function_name = mvebu_pinmux_get_func_name,
+       .get_function_groups = mvebu_pinmux_get_groups,
+       .gpio_request_enable = mvebu_pinmux_gpio_request_enable,
+       .gpio_set_direction = mvebu_pinmux_gpio_set_direction,
+       .enable = mvebu_pinmux_enable,
+};
+
+static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       return pctl->num_groups;
+}
+
+static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                               unsigned gid)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       return pctl->groups[gid].name;
+}
+
+static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                       unsigned gid, const unsigned **pins,
+                                       unsigned *num_pins)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       *pins = pctl->groups[gid].pins;
+       *num_pins = pctl->groups[gid].npins;
+       return 0;
+}
+
+static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                       struct device_node *np,
+                                       struct pinctrl_map **map,
+                                       unsigned *num_maps)
+{
+       struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct property *prop;
+       const char *function;
+       const char *group;
+       int ret, nmaps, n;
+
+       *map = NULL;
+       *num_maps = 0;
+
+       ret = of_property_read_string(np, "marvell,function", &function);
+       if (ret) {
+               dev_err(pctl->dev,
+                       "missing marvell,function in node %s\n", np->name);
+               return 0;
+       }
+
+       nmaps = of_property_count_strings(np, "marvell,pins");
+       if (nmaps < 0) {
+               dev_err(pctl->dev,
+                       "missing marvell,pins in node %s\n", np->name);
+               return 0;
+       }
+
+       *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
+       if (map == NULL) {
+               dev_err(pctl->dev,
+                       "cannot allocate pinctrl_map memory for %s\n",
+                       np->name);
+               return -ENOMEM;
+       }
+
+       n = 0;
+       of_property_for_each_string(np, "marvell,pins", prop, group) {
+               struct mvebu_pinctrl_group *grp =
+                       mvebu_pinctrl_find_group_by_name(pctl, group);
+
+               if (!grp) {
+                       dev_err(pctl->dev, "unknown pin %s", group);
+                       continue;
+               }
+
+               if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) {
+                       dev_err(pctl->dev, "unsupported function %s on pin %s",
+                               function, group);
+                       continue;
+               }
+
+               (*map)[n].type = PIN_MAP_TYPE_MUX_GROUP;
+               (*map)[n].data.mux.group = group;
+               (*map)[n].data.mux.function = function;
+               n++;
+       }
+
+       *num_maps = nmaps;
+
+       return 0;
+}
+
+static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+                               struct pinctrl_map *map, unsigned num_maps)
+{
+       kfree(map);
+}
+
+static struct pinctrl_ops mvebu_pinctrl_ops = {
+       .get_groups_count = mvebu_pinctrl_get_groups_count,
+       .get_group_name = mvebu_pinctrl_get_group_name,
+       .get_group_pins = mvebu_pinctrl_get_group_pins,
+       .dt_node_to_map = mvebu_pinctrl_dt_node_to_map,
+       .dt_free_map = mvebu_pinctrl_dt_free_map,
+};
+
+static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
+                                  const char *name)
+{
+       while (funcs->num_groups) {
+               /* function already there */
+               if (strcmp(funcs->name, name) == 0) {
+                       funcs->num_groups++;
+                       return -EEXIST;
+               }
+               funcs++;
+       }
+       funcs->name = name;
+       funcs->num_groups = 1;
+       return 0;
+}
+
+static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
+                                                  struct mvebu_pinctrl *pctl)
+{
+       struct mvebu_pinctrl_function *funcs;
+       int num = 0;
+       int n, s;
+
+       /* we allocate functions for number of pins and hope
+        * there are less unique functions than pins available */
+       funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+                            sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
+       if (!funcs)
+               return -ENOMEM;
+
+       for (n = 0; n < pctl->num_groups; n++) {
+               struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+               for (s = 0; s < grp->num_settings; s++) {
+                       /* skip unsupported settings on this variant */
+                       if (pctl->variant &&
+                           !(pctl->variant & grp->settings[s].variant))
+                               continue;
+
+                       /* check for unique functions and count groups */
+                       if (_add_function(funcs, grp->settings[s].name))
+                               continue;
+
+                       num++;
+               }
+       }
+
+       /* with the number of unique functions and it's groups known,
+          reallocate functions and assign group names */
+       funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
+                        GFP_KERNEL);
+       if (!funcs)
+               return -ENOMEM;
+
+       pctl->num_functions = num;
+       pctl->functions = funcs;
+
+       for (n = 0; n < pctl->num_groups; n++) {
+               struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+               for (s = 0; s < grp->num_settings; s++) {
+                       struct mvebu_pinctrl_function *f;
+                       const char **groups;
+
+                       /* skip unsupported settings on this variant */
+                       if (pctl->variant &&
+                           !(pctl->variant & grp->settings[s].variant))
+                               continue;
+
+                       f = mvebu_pinctrl_find_function_by_name(pctl,
+                                                       grp->settings[s].name);
+
+                       /* allocate group name array if not done already */
+                       if (!f->groups) {
+                               f->groups = devm_kzalloc(&pdev->dev,
+                                                f->num_groups * sizeof(char *),
+                                                GFP_KERNEL);
+                               if (!f->groups)
+                                       return -ENOMEM;
+                       }
+
+                       /* find next free group name and assign current name */
+                       groups = f->groups;
+                       while (*groups)
+                               groups++;
+                       *groups = grp->name;
+               }
+       }
+
+       return 0;
+}
+
+int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
+       struct mvebu_pinctrl *pctl;
+       void __iomem *base;
+       struct pinctrl_pin_desc *pdesc;
+       unsigned gid, n, k;
+       int ret;
+
+       if (!soc || !soc->controls || !soc->modes) {
+               dev_err(&pdev->dev, "wrong pinctrl soc info\n");
+               return -EINVAL;
+       }
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               dev_err(&pdev->dev, "unable to get base address\n");
+               return -ENODEV;
+       }
+
+       pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
+                       GFP_KERNEL);
+       if (!pctl) {
+               dev_err(&pdev->dev, "unable to alloc driver\n");
+               return -ENOMEM;
+       }
+
+       pctl->desc.name = dev_name(&pdev->dev);
+       pctl->desc.owner = THIS_MODULE;
+       pctl->desc.pctlops = &mvebu_pinctrl_ops;
+       pctl->desc.pmxops = &mvebu_pinmux_ops;
+       pctl->desc.confops = &mvebu_pinconf_ops;
+       pctl->variant = soc->variant;
+       pctl->base = base;
+       pctl->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pctl);
+
+       /* count controls and create names for mvebu generic
+          register controls; also does sanity checks */
+       pctl->num_groups = 0;
+       pctl->desc.npins = 0;
+       for (n = 0; n < soc->ncontrols; n++) {
+               struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+               char *names;
+
+               pctl->desc.npins += ctrl->npins;
+               /* initial control pins */
+               for (k = 0; k < ctrl->npins; k++)
+                       ctrl->pins[k] = ctrl->pid + k;
+
+               /* special soc specific control */
+               if (ctrl->mpp_get || ctrl->mpp_set) {
+                       if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) {
+                               dev_err(&pdev->dev, "wrong soc control info\n");
+                               return -EINVAL;
+                       }
+                       pctl->num_groups += 1;
+                       continue;
+               }
+
+               /* generic mvebu register control */
+               names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
+               if (!names) {
+                       dev_err(&pdev->dev, "failed to alloc mpp names\n");
+                       return -ENOMEM;
+               }
+               for (k = 0; k < ctrl->npins; k++)
+                       sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
+               ctrl->name = names;
+               pctl->num_groups += ctrl->npins;
+       }
+
+       pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+                            sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
+       if (!pdesc) {
+               dev_err(&pdev->dev, "failed to alloc pinctrl pins\n");
+               return -ENOMEM;
+       }
+
+       for (n = 0; n < pctl->desc.npins; n++)
+               pdesc[n].number = n;
+       pctl->desc.pins = pdesc;
+
+       pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
+                            sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
+       if (!pctl->groups) {
+               dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
+               return -ENOMEM;
+       }
+
+       /* assign mpp controls to groups */
+       gid = 0;
+       for (n = 0; n < soc->ncontrols; n++) {
+               struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+               pctl->groups[gid].gid = gid;
+               pctl->groups[gid].ctrl = ctrl;
+               pctl->groups[gid].name = ctrl->name;
+               pctl->groups[gid].pins = ctrl->pins;
+               pctl->groups[gid].npins = ctrl->npins;
+
+               /* generic mvebu register control maps to a number of groups */
+               if (!ctrl->mpp_get && !ctrl->mpp_set) {
+                       pctl->groups[gid].npins = 1;
+
+                       for (k = 1; k < ctrl->npins; k++) {
+                               gid++;
+                               pctl->groups[gid].gid = gid;
+                               pctl->groups[gid].ctrl = ctrl;
+                               pctl->groups[gid].name = &ctrl->name[8*k];
+                               pctl->groups[gid].pins = &ctrl->pins[k];
+                               pctl->groups[gid].npins = 1;
+                       }
+               }
+               gid++;
+       }
+
+       /* assign mpp modes to groups */
+       for (n = 0; n < soc->nmodes; n++) {
+               struct mvebu_mpp_mode *mode = &soc->modes[n];
+               struct mvebu_pinctrl_group *grp =
+                       mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
+               unsigned num_settings;
+
+               if (!grp) {
+                       dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
+                               mode->pid);
+                       continue;
+               }
+
+               for (num_settings = 0; ;) {
+                       struct mvebu_mpp_ctrl_setting *set =
+                               &mode->settings[num_settings];
+
+                       if (!set->name)
+                               break;
+                       num_settings++;
+
+                       /* skip unsupported settings for this variant */
+                       if (pctl->variant && !(pctl->variant & set->variant))
+                               continue;
+
+                       /* find gpio/gpo/gpi settings */
+                       if (strcmp(set->name, "gpio") == 0)
+                               set->flags = MVEBU_SETTING_GPI |
+                                       MVEBU_SETTING_GPO;
+                       else if (strcmp(set->name, "gpo") == 0)
+                               set->flags = MVEBU_SETTING_GPO;
+                       else if (strcmp(set->name, "gpi") == 0)
+                               set->flags = MVEBU_SETTING_GPI;
+               }
+
+               grp->settings = mode->settings;
+               grp->num_settings = num_settings;
+       }
+
+       ret = mvebu_pinctrl_build_functions(pdev, pctl);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to build functions\n");
+               return ret;
+       }
+
+       pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+       if (!pctl->pctldev) {
+               dev_err(&pdev->dev, "unable to register pinctrl driver\n");
+               return -EINVAL;
+       }
+
+       dev_info(&pdev->dev, "registered pinctrl driver\n");
+
+       /* register gpio ranges */
+       for (n = 0; n < soc->ngpioranges; n++)
+               pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]);
+
+       return 0;
+}
+
+int __devexit mvebu_pinctrl_remove(struct platform_device *pdev)
+{
+       struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
+       pinctrl_unregister(pctl->pctldev);
+       return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/pinctrl-mvebu.h
new file mode 100644 (file)
index 0000000..90bd3be
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Marvell MVEBU pinctrl driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *          Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
+ */
+
+#ifndef __PINCTRL_MVEBU_H__
+#define __PINCTRL_MVEBU_H__
+
+/**
+ * struct mvebu_mpp_ctrl - describe a mpp control
+ * @name: name of the control group
+ * @pid: first pin id handled by this control
+ * @npins: number of pins controlled by this control
+ * @mpp_get: (optional) special function to get mpp setting
+ * @mpp_set: (optional) special function to set mpp setting
+ * @mpp_gpio_req: (optional) special function to request gpio
+ * @mpp_gpio_dir: (optional) special function to set gpio direction
+ *
+ * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or
+ * internal function, inside the SoC. Each muxable unit can be switched
+ * between two or more different settings, e.g. assign mpp pin 13 to
+ * uart1 or sata.
+ *
+ * If optional mpp_get/_set functions are set these are used to get/set
+ * a specific mode. Otherwise it is assumed that the mpp control is based
+ * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
+ * functions can be used to allow pin settings with varying gpio pins.
+ */
+struct mvebu_mpp_ctrl {
+       const char *name;
+       u8 pid;
+       u8 npins;
+       unsigned *pins;
+       int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
+       int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
+       int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
+       int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
+};
+
+/**
+ * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting
+ * @val: ctrl setting value
+ * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode
+ * @subname: (optional) additional ctrl setting name, e.g. rts, cts
+ * @variant: (optional) variant identifier mask
+ * @flags: (private) flags to store gpi/gpo/gpio capabilities
+ *
+ * A ctrl_setting describes a specific internal mux function that a mpp pin
+ * can be switched to. The value (val) will be written in the corresponding
+ * register for common mpp pin configuration registers on MVEBU. SoC specific
+ * mpp_get/_set function may use val to distinguish between different settings.
+ *
+ * The name will be used to switch to this setting in DT description, e.g.
+ * marvell,function = "uart2". subname is only for debugging purposes.
+ *
+ * If name is one of "gpi", "gpo", "gpio" gpio capabilities are
+ * parsed during initialization and stored in flags.
+ *
+ * The variant can be used to combine different revisions of one SoC to a
+ * common pinctrl driver. It is matched (AND) with variant of soc_info to
+ * determine if a setting is available on the current SoC revision.
+ */
+struct mvebu_mpp_ctrl_setting {
+       u8 val;
+       const char *name;
+       const char *subname;
+       u8 variant;
+       u8 flags;
+#define  MVEBU_SETTING_GPO     (1 << 0)
+#define  MVEBU_SETTING_GPI     (1 << 1)
+};
+
+/**
+ * struct mvebu_mpp_mode - link ctrl and settings
+ * @pid: first pin id handled by this mode
+ * @settings: list of settings available for this mode
+ *
+ * A mode connects all available settings with the corresponding mpp_ctrl
+ * given by pid.
+ */
+struct mvebu_mpp_mode {
+       u8 pid;
+       struct mvebu_mpp_ctrl_setting *settings;
+};
+
+/**
+ * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
+ * @variant: variant mask of soc_info
+ * @controls: list of available mvebu_mpp_ctrls
+ * @ncontrols: number of available mvebu_mpp_ctrls
+ * @modes: list of available mvebu_mpp_modes
+ * @nmodes: number of available mvebu_mpp_modes
+ * @gpioranges: list of pinctrl_gpio_ranges
+ * @ngpioranges: number of available pinctrl_gpio_ranges
+ *
+ * This struct describes all pinctrl related information for a specific SoC.
+ * If variant is unequal 0 it will be matched (AND) with variant of each
+ * setting and allows to distinguish between different revisions of one SoC.
+ */
+struct mvebu_pinctrl_soc_info {
+       u8 variant;
+       struct mvebu_mpp_ctrl *controls;
+       int ncontrols;
+       struct mvebu_mpp_mode *modes;
+       int nmodes;
+       struct pinctrl_gpio_range *gpioranges;
+       int ngpioranges;
+};
+
+#define MPP_REG_CTRL(_idl, _idh)                               \
+       {                                                       \
+               .name = NULL,                                   \
+               .pid = _idl,                                    \
+               .npins = _idh - _idl + 1,                       \
+               .pins = (unsigned[_idh - _idl + 1]) { },        \
+               .mpp_get = NULL,                                \
+               .mpp_set = NULL,                                \
+               .mpp_gpio_req = NULL,                           \
+               .mpp_gpio_dir = NULL,                           \
+       }
+
+#define MPP_FUNC_CTRL(_idl, _idh, _name, _func)                        \
+       {                                                       \
+               .name = _name,                                  \
+               .pid = _idl,                                    \
+               .npins = _idh - _idl + 1,                       \
+               .pins = (unsigned[_idh - _idl + 1]) { },        \
+               .mpp_get = _func ## _get,                       \
+               .mpp_set = _func ## _set,                       \
+               .mpp_gpio_req = NULL,                           \
+               .mpp_gpio_dir = NULL,                           \
+       }
+
+#define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func)           \
+       {                                                       \
+               .name = _name,                                  \
+               .pid = _idl,                                    \
+               .npins = _idh - _idl + 1,                       \
+               .pins = (unsigned[_idh - _idl + 1]) { },        \
+               .mpp_get = _func ## _get,                       \
+               .mpp_set = _func ## _set,                       \
+               .mpp_gpio_req = _func ## _gpio_req,             \
+               .mpp_gpio_dir = _func ## _gpio_dir,             \
+       }
+
+#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)                \
+       {                                                       \
+               .val = _val,                                    \
+               .name = _name,                                  \
+               .subname = _subname,                            \
+               .variant = _mask,                               \
+               .flags = 0,                                     \
+       }
+
+#if defined(CONFIG_DEBUG_FS)
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)         \
+       _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)
+#else
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask)         \
+       _MPP_VAR_FUNCTION(_val, _name, NULL, _mask)
+#endif
+
+#define MPP_FUNCTION(_val, _name, _subname)                    \
+       MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1)
+
+#define MPP_MODE(_id, ...)                                     \
+       {                                                       \
+               .pid = _id,                                     \
+               .settings = (struct mvebu_mpp_ctrl_setting[]){  \
+                       __VA_ARGS__, { } },                     \
+       }
+
+#define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins)       \
+       {                                                       \
+               .name = "mvebu-gpio",                           \
+               .id = _id,                                      \
+               .pin_base = _pinbase,                           \
+               .base = _gpiobase,                              \
+               .npins = _npins,                                \
+       }
+
+int mvebu_pinctrl_probe(struct platform_device *pdev);
+int mvebu_pinctrl_remove(struct platform_device *pdev);
+
+#endif
index a514bf66fdd7e2a6532fd5be9a97f6aa2a417fb6..1deca7f6c4eace047cd2c871105aab77da43d08b 100644 (file)
@@ -74,7 +74,7 @@ static const struct rfkill_ops amilo_m7440_rfkill_ops = {
        .set_block = amilo_m7440_rfkill_set_block
 };
 
-static const struct dmi_system_id __devinitdata amilo_rfkill_id_table[] = {
+static const struct dmi_system_id __devinitconst amilo_rfkill_id_table[] = {
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
index 7acae3f85f3b180cfe57865e08bb4fbf08bde40d..f77484528b1b2a74c1d0c483b637e810623cc585 100644 (file)
@@ -52,7 +52,7 @@ struct fujitsu_config {
        unsigned int quirks;
 };
 
-static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initconst = {
+static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initdata = {
        KEY_RESERVED,
        KEY_RESERVED,
        KEY_RESERVED,
@@ -71,7 +71,7 @@ static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initconst = {
        KEY_LEFTALT
 };
 
-static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initconst = {
+static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initdata = {
        KEY_RESERVED,
        KEY_RESERVED,
        KEY_RESERVED,
@@ -90,7 +90,7 @@ static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initconst = {
        KEY_LEFTALT
 };
 
-static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initconst = {
+static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initdata = {
        KEY_RESERVED,
        KEY_RESERVED,
        KEY_RESERVED,
@@ -109,7 +109,7 @@ static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initconst = {
        KEY_LEFTALT
 };
 
-static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initconst = {
+static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initdata = {
        KEY_RESERVED,
        KEY_RESERVED,
        KEY_RESERVED,
@@ -299,7 +299,7 @@ static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
        return 1;
 }
 
-static struct dmi_system_id dmi_ids[] __initconst = {
+static const struct dmi_system_id dmi_ids[] __initconst = {
        {
                .callback = fujitsu_dmi_lifebook,
                .ident = "Fujitsu Siemens P/T Series",
index 9da5fe715e6a2a92364fcacfb46e6158314b88b8..75dd651664ae6f14dbfc43ce42d2a9632368b513 100644 (file)
@@ -522,7 +522,7 @@ static acpi_handle ec_handle;
 
 #define TPACPI_HANDLE(object, parent, paths...)                        \
        static acpi_handle  object##_handle;                    \
-       static const acpi_handle *object##_parent __initdata =  \
+       static const acpi_handle * const object##_parent __initconst =  \
                                                &parent##_handle; \
        static char *object##_paths[] __initdata = { paths }
 
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
new file mode 100644 (file)
index 0000000..beed5ec
--- /dev/null
@@ -0,0 +1,1041 @@
+/*
+ * Battery driver for Marvell 88PM860x PMIC
+ *
+ * Copyright (c) 2012 Marvell International Ltd.
+ * Author:     Jett Zhou <jtzhou@marvell.com>
+ *             Haojian Zhuang <haojian.zhuang@marvell.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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/delay.h>
+
+/* bit definitions of Status Query Interface 2 */
+#define STATUS2_CHG                    (1 << 2)
+#define STATUS2_BAT                    (1 << 3)
+#define STATUS2_VBUS                   (1 << 4)
+
+/* bit definitions of Measurement Enable 1 Register */
+#define MEAS1_TINT                     (1 << 3)
+#define MEAS1_GP1                      (1 << 5)
+
+/* bit definitions of Measurement Enable 3 Register */
+#define MEAS3_IBAT                     (1 << 0)
+#define MEAS3_BAT_DET                  (1 << 1)
+#define MEAS3_CC                       (1 << 2)
+
+/* bit definitions of Measurement Off Time Register */
+#define MEAS_OFF_SLEEP_EN              (1 << 1)
+
+/* bit definitions of GPADC Bias Current 2 Register */
+#define GPBIAS2_GPADC1_SET             (2 << 4)
+/* GPADC1 Bias Current value in uA unit */
+#define GPBIAS2_GPADC1_UA              ((GPBIAS2_GPADC1_SET >> 4) * 5 + 1)
+
+/* bit definitions of GPADC Misc 1 Register */
+#define GPMISC1_GPADC_EN               (1 << 0)
+
+/* bit definitions of Charger Control 6 Register */
+#define CC6_BAT_DET_GPADC1             1
+
+/* bit definitions of Coulomb Counter Reading Register */
+#define CCNT_AVG_SEL                   (4 << 3)
+
+/* bit definitions of RTC miscellaneous Register1 */
+#define RTC_SOC_5LSB           (0x1F << 3)
+
+/* bit definitions of RTC Register1 */
+#define RTC_SOC_3MSB           (0x7)
+
+/* bit definitions of Power up Log register */
+#define BAT_WU_LOG                     (1<<6)
+
+/* coulomb counter index */
+#define CCNT_POS1                      0
+#define CCNT_POS2                      1
+#define CCNT_NEG1                      2
+#define CCNT_NEG2                      3
+#define CCNT_SPOS                      4
+#define CCNT_SNEG                      5
+
+/* OCV -- Open Circuit Voltage */
+#define OCV_MODE_ACTIVE                        0
+#define OCV_MODE_SLEEP                 1
+
+/* Vbat range of CC for measuring Rbat */
+#define LOW_BAT_THRESHOLD              3600
+#define VBATT_RESISTOR_MIN             3800
+#define VBATT_RESISTOR_MAX             4100
+
+/* TBAT for batt, TINT for chip itself */
+#define PM860X_TEMP_TINT               (0)
+#define PM860X_TEMP_TBAT               (1)
+
+/*
+ * Battery temperature based on NTC resistor, defined
+ * corresponding resistor value  -- Ohm / C degeree.
+ */
+#define TBAT_NEG_25D           127773  /* -25 */
+#define TBAT_NEG_10D           54564   /* -10 */
+#define TBAT_0D                        32330   /* 0 */
+#define TBAT_10D               19785   /* 10 */
+#define TBAT_20D               12468   /* 20 */
+#define TBAT_30D               8072    /* 30 */
+#define TBAT_40D               5356    /* 40 */
+
+struct pm860x_battery_info {
+       struct pm860x_chip *chip;
+       struct i2c_client *i2c;
+       struct device *dev;
+
+       struct power_supply battery;
+       struct mutex lock;
+       int status;
+       int irq_cc;
+       int irq_batt;
+       int max_capacity;
+       int resistor;           /* Battery Internal Resistor */
+       int last_capacity;
+       int start_soc;
+       unsigned present:1;
+       unsigned temp_type:1;   /* TINT or TBAT */
+};
+
+struct ccnt {
+       unsigned long long int pos;
+       unsigned long long int neg;
+       unsigned int spos;
+       unsigned int sneg;
+
+       int total_chg;          /* mAh(3.6C) */
+       int total_dischg;       /* mAh(3.6C) */
+};
+
+/*
+ * State of Charge.
+ * The first number is mAh(=3.6C), and the second number is percent point.
+ */
+static int array_soc[][2] = {
+       {4170, 100}, {4154, 99}, {4136, 98}, {4122, 97}, {4107, 96},
+       {4102, 95}, {4088, 94}, {4081, 93}, {4070, 92}, {4060, 91},
+       {4053, 90}, {4044, 89}, {4035, 88}, {4028, 87}, {4019, 86},
+       {4013, 85}, {4006, 84}, {3995, 83}, {3987, 82}, {3982, 81},
+       {3976, 80}, {3968, 79}, {3962, 78}, {3954, 77}, {3946, 76},
+       {3941, 75}, {3934, 74}, {3929, 73}, {3922, 72}, {3916, 71},
+       {3910, 70}, {3904, 69}, {3898, 68}, {3892, 67}, {3887, 66},
+       {3880, 65}, {3874, 64}, {3868, 63}, {3862, 62}, {3854, 61},
+       {3849, 60}, {3843, 59}, {3840, 58}, {3833, 57}, {3829, 56},
+       {3824, 55}, {3818, 54}, {3815, 53}, {3810, 52}, {3808, 51},
+       {3804, 50}, {3801, 49}, {3798, 48}, {3796, 47}, {3792, 46},
+       {3789, 45}, {3785, 44}, {3784, 43}, {3782, 42}, {3780, 41},
+       {3777, 40}, {3776, 39}, {3774, 38}, {3772, 37}, {3771, 36},
+       {3769, 35}, {3768, 34}, {3764, 33}, {3763, 32}, {3760, 31},
+       {3760, 30}, {3754, 29}, {3750, 28}, {3749, 27}, {3744, 26},
+       {3740, 25}, {3734, 24}, {3732, 23}, {3728, 22}, {3726, 21},
+       {3720, 20}, {3716, 19}, {3709, 18}, {3703, 17}, {3698, 16},
+       {3692, 15}, {3683, 14}, {3675, 13}, {3670, 12}, {3665, 11},
+       {3661, 10}, {3649, 9}, {3637, 8}, {3622, 7}, {3609, 6},
+       {3580, 5}, {3558, 4}, {3540, 3}, {3510, 2}, {3429, 1},
+};
+
+static struct ccnt ccnt_data;
+
+/*
+ * register 1 bit[7:0] -- bit[11:4] of measured value of voltage
+ * register 0 bit[3:0] -- bit[3:0] of measured value of voltage
+ */
+static int measure_12bit_voltage(struct pm860x_battery_info *info,
+                                int offset, int *data)
+{
+       unsigned char buf[2];
+       int ret;
+
+       ret = pm860x_bulk_read(info->i2c, offset, 2, buf);
+       if (ret < 0)
+               return ret;
+
+       *data = ((buf[0] & 0xff) << 4) | (buf[1] & 0x0f);
+       /* V_MEAS(mV) = data * 1.8 * 1000 / (2^12) */
+       *data = ((*data & 0xfff) * 9 * 25) >> 9;
+       return 0;
+}
+
+static int measure_vbatt(struct pm860x_battery_info *info, int state,
+                        int *data)
+{
+       unsigned char buf[5];
+       int ret;
+
+       switch (state) {
+       case OCV_MODE_ACTIVE:
+               ret = measure_12bit_voltage(info, PM8607_VBAT_MEAS1, data);
+               if (ret)
+                       return ret;
+               /* V_BATT_MEAS(mV) = value * 3 * 1.8 * 1000 / (2^12) */
+               *data *= 3;
+               break;
+       case OCV_MODE_SLEEP:
+               /*
+                * voltage value of VBATT in sleep mode is saved in different
+                * registers.
+                * bit[11:10] -- bit[7:6] of LDO9(0x18)
+                * bit[9:8] -- bit[7:6] of LDO8(0x17)
+                * bit[7:6] -- bit[7:6] of LDO7(0x16)
+                * bit[5:4] -- bit[7:6] of LDO6(0x15)
+                * bit[3:0] -- bit[7:4] of LDO5(0x14)
+                */
+               ret = pm860x_bulk_read(info->i2c, PM8607_LDO5, 5, buf);
+               if (ret < 0)
+                       return ret;
+               ret = ((buf[4] >> 6) << 10) | ((buf[3] >> 6) << 8)
+                   | ((buf[2] >> 6) << 6) | ((buf[1] >> 6) << 4)
+                   | (buf[0] >> 4);
+               /* V_BATT_MEAS(mV) = data * 3 * 1.8 * 1000 / (2^12) */
+               *data = ((*data & 0xff) * 27 * 25) >> 9;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * Return value is signed data.
+ * Negative value means discharging, and positive value means charging.
+ */
+static int measure_current(struct pm860x_battery_info *info, int *data)
+{
+       unsigned char buf[2];
+       short s;
+       int ret;
+
+       ret = pm860x_bulk_read(info->i2c, PM8607_IBAT_MEAS1, 2, buf);
+       if (ret < 0)
+               return ret;
+
+       s = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
+       /* current(mA) = value * 0.125 */
+       *data = s >> 3;
+       return 0;
+}
+
+static int set_charger_current(struct pm860x_battery_info *info, int data,
+                              int *old)
+{
+       int ret;
+
+       if (data < 50 || data > 1600 || !old)
+               return -EINVAL;
+
+       data = ((data - 50) / 50) & 0x1f;
+       *old = pm860x_reg_read(info->i2c, PM8607_CHG_CTRL2);
+       *old = (*old & 0x1f) * 50 + 50;
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL2, 0x1f, data);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+static int read_ccnt(struct pm860x_battery_info *info, int offset,
+                    int *ccnt)
+{
+       unsigned char buf[2];
+       int ret;
+
+       ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7, offset & 7);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_bulk_read(info->i2c, PM8607_CCNT_MEAS1, 2, buf);
+       if (ret < 0)
+               goto out;
+       *ccnt = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
+       return 0;
+out:
+       return ret;
+}
+
+static int calc_ccnt(struct pm860x_battery_info *info, struct ccnt *ccnt)
+{
+       unsigned int sum;
+       int ret;
+       int data;
+
+       ret = read_ccnt(info, CCNT_POS1, &data);
+       if (ret)
+               goto out;
+       sum = data & 0xffff;
+       ret = read_ccnt(info, CCNT_POS2, &data);
+       if (ret)
+               goto out;
+       sum |= (data & 0xffff) << 16;
+       ccnt->pos += sum;
+
+       ret = read_ccnt(info, CCNT_NEG1, &data);
+       if (ret)
+               goto out;
+       sum = data & 0xffff;
+       ret = read_ccnt(info, CCNT_NEG2, &data);
+       if (ret)
+               goto out;
+       sum |= (data & 0xffff) << 16;
+       sum = ~sum + 1;         /* since it's negative */
+       ccnt->neg += sum;
+
+       ret = read_ccnt(info, CCNT_SPOS, &data);
+       if (ret)
+               goto out;
+       ccnt->spos += data;
+       ret = read_ccnt(info, CCNT_SNEG, &data);
+       if (ret)
+               goto out;
+
+       /*
+        * charge(mAh)  = count * 1.6984 * 1e(-8)
+        *              = count * 16984 * 1.024 * 1.024 * 1.024 / (2 ^ 40)
+        *              = count * 18236 / (2 ^ 40)
+        */
+       ccnt->total_chg = (int) ((ccnt->pos * 18236) >> 40);
+       ccnt->total_dischg = (int) ((ccnt->neg * 18236) >> 40);
+       return 0;
+out:
+       return ret;
+}
+
+static int clear_ccnt(struct pm860x_battery_info *info, struct ccnt *ccnt)
+{
+       int data;
+
+       memset(ccnt, 0, sizeof(*ccnt));
+       /* read to clear ccnt */
+       read_ccnt(info, CCNT_POS1, &data);
+       read_ccnt(info, CCNT_POS2, &data);
+       read_ccnt(info, CCNT_NEG1, &data);
+       read_ccnt(info, CCNT_NEG2, &data);
+       read_ccnt(info, CCNT_SPOS, &data);
+       read_ccnt(info, CCNT_SNEG, &data);
+       return 0;
+}
+
+/* Calculate Open Circuit Voltage */
+static int calc_ocv(struct pm860x_battery_info *info, int *ocv)
+{
+       int ret;
+       int i;
+       int data;
+       int vbatt_avg;
+       int vbatt_sum;
+       int ibatt_avg;
+       int ibatt_sum;
+
+       if (!ocv)
+               return -EINVAL;
+
+       for (i = 0, ibatt_sum = 0, vbatt_sum = 0; i < 10; i++) {
+               ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+               if (ret)
+                       goto out;
+               vbatt_sum += data;
+               ret = measure_current(info, &data);
+               if (ret)
+                       goto out;
+               ibatt_sum += data;
+       }
+       vbatt_avg = vbatt_sum / 10;
+       ibatt_avg = ibatt_sum / 10;
+
+       mutex_lock(&info->lock);
+       if (info->present)
+               *ocv = vbatt_avg - ibatt_avg * info->resistor / 1000;
+       else
+               *ocv = vbatt_avg;
+       mutex_unlock(&info->lock);
+       dev_dbg(info->dev, "VBAT average:%d, OCV:%d\n", vbatt_avg, *ocv);
+       return 0;
+out:
+       return ret;
+}
+
+/* Calculate State of Charge (percent points) */
+static int calc_soc(struct pm860x_battery_info *info, int state, int *soc)
+{
+       int i;
+       int ocv;
+       int count;
+       int ret = -EINVAL;
+
+       if (!soc)
+               return -EINVAL;
+
+       switch (state) {
+       case OCV_MODE_ACTIVE:
+               ret = calc_ocv(info, &ocv);
+               break;
+       case OCV_MODE_SLEEP:
+               ret = measure_vbatt(info, OCV_MODE_SLEEP, &ocv);
+               break;
+       }
+       if (ret)
+               return ret;
+
+       count = ARRAY_SIZE(array_soc);
+       if (ocv < array_soc[count - 1][0]) {
+               *soc = 0;
+               return 0;
+       }
+
+       for (i = 0; i < count; i++) {
+               if (ocv >= array_soc[i][0]) {
+                       *soc = array_soc[i][1];
+                       break;
+               }
+       }
+       return 0;
+}
+
+static irqreturn_t pm860x_coulomb_handler(int irq, void *data)
+{
+       struct pm860x_battery_info *info = data;
+
+       calc_ccnt(info, &ccnt_data);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_batt_handler(int irq, void *data)
+{
+       struct pm860x_battery_info *info = data;
+       int ret;
+
+       mutex_lock(&info->lock);
+       ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+       if (ret & STATUS2_BAT) {
+               info->present = 1;
+               info->temp_type = PM860X_TEMP_TBAT;
+       } else {
+               info->present = 0;
+               info->temp_type = PM860X_TEMP_TINT;
+       }
+       mutex_unlock(&info->lock);
+       /* clear ccnt since battery is attached or dettached */
+       clear_ccnt(info, &ccnt_data);
+       return IRQ_HANDLED;
+}
+
+static void pm860x_init_battery(struct pm860x_battery_info *info)
+{
+       unsigned char buf[2];
+       int ret;
+       int data;
+       int bat_remove;
+       int soc;
+
+       /* measure enable on GPADC1 */
+       data = MEAS1_GP1;
+       if (info->temp_type == PM860X_TEMP_TINT)
+               data |= MEAS1_TINT;
+       ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN1, data, data);
+       if (ret)
+               goto out;
+
+       /* measure enable on IBAT, BAT_DET, CC. IBAT is depend on CC. */
+       data = MEAS3_IBAT | MEAS3_BAT_DET | MEAS3_CC;
+       ret = pm860x_set_bits(info->i2c, PM8607_MEAS_EN3, data, data);
+       if (ret)
+               goto out;
+
+       /* measure disable CC in sleep time  */
+       ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME1, 0x82);
+       if (ret)
+               goto out;
+       ret = pm860x_reg_write(info->i2c, PM8607_MEAS_OFF_TIME2, 0x6c);
+       if (ret)
+               goto out;
+
+       /* enable GPADC */
+       ret = pm860x_set_bits(info->i2c, PM8607_GPADC_MISC1,
+                           GPMISC1_GPADC_EN, GPMISC1_GPADC_EN);
+       if (ret < 0)
+               goto out;
+
+       /* detect battery via GPADC1 */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL6,
+                           CC6_BAT_DET_GPADC1, CC6_BAT_DET_GPADC1);
+       if (ret < 0)
+               goto out;
+
+       ret = pm860x_set_bits(info->i2c, PM8607_CCNT, 7 << 3,
+                             CCNT_AVG_SEL);
+       if (ret < 0)
+               goto out;
+
+       /* set GPADC1 bias */
+       ret = pm860x_set_bits(info->i2c, PM8607_GP_BIAS2, 0xF << 4,
+                             GPBIAS2_GPADC1_SET);
+       if (ret < 0)
+               goto out;
+
+       /* check whether battery present) */
+       mutex_lock(&info->lock);
+       ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+       if (ret < 0) {
+               mutex_unlock(&info->lock);
+               goto out;
+       }
+       if (ret & STATUS2_BAT) {
+               info->present = 1;
+               info->temp_type = PM860X_TEMP_TBAT;
+       } else {
+               info->present = 0;
+               info->temp_type = PM860X_TEMP_TINT;
+       }
+       mutex_unlock(&info->lock);
+
+       calc_soc(info, OCV_MODE_ACTIVE, &soc);
+
+       data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG);
+       bat_remove = data & BAT_WU_LOG;
+
+       dev_dbg(info->dev, "battery wake up? %s\n",
+               bat_remove != 0 ? "yes" : "no");
+
+       /* restore SOC from RTC domain register */
+       if (bat_remove == 0) {
+               buf[0] = pm860x_reg_read(info->i2c, PM8607_RTC_MISC2);
+               buf[1] = pm860x_reg_read(info->i2c, PM8607_RTC1);
+               data = ((buf[1] & 0x3) << 5) | ((buf[0] >> 3) & 0x1F);
+               if (data > soc + 15)
+                       info->start_soc = soc;
+               else if (data < soc - 15)
+                       info->start_soc = soc;
+               else
+                       info->start_soc = data;
+               dev_dbg(info->dev, "soc_rtc %d, soc_ocv :%d\n", data, soc);
+       } else {
+               pm860x_set_bits(info->i2c, PM8607_POWER_UP_LOG,
+                               BAT_WU_LOG, BAT_WU_LOG);
+               info->start_soc = soc;
+       }
+       info->last_capacity = info->start_soc;
+       dev_dbg(info->dev, "init soc : %d\n", info->last_capacity);
+out:
+       return;
+}
+
+static void set_temp_threshold(struct pm860x_battery_info *info,
+                              int min, int max)
+{
+       int data;
+
+       /* (tmp << 8) / 1800 */
+       if (min <= 0)
+               data = 0;
+       else
+               data = (min << 8) / 1800;
+       pm860x_reg_write(info->i2c, PM8607_GPADC1_HIGHTH, data);
+       dev_dbg(info->dev, "TEMP_HIGHTH : min: %d, 0x%x\n", min, data);
+
+       if (max <= 0)
+               data = 0xff;
+       else
+               data = (max << 8) / 1800;
+       pm860x_reg_write(info->i2c, PM8607_GPADC1_LOWTH, data);
+       dev_dbg(info->dev, "TEMP_LOWTH:max : %d, 0x%x\n", max, data);
+}
+
+static int measure_temp(struct pm860x_battery_info *info, int *data)
+{
+       int ret;
+       int temp;
+       int min;
+       int max;
+
+       if (info->temp_type == PM860X_TEMP_TINT) {
+               ret = measure_12bit_voltage(info, PM8607_TINT_MEAS1, data);
+               if (ret)
+                       return ret;
+               *data = (*data - 884) * 1000 / 3611;
+       } else {
+               ret = measure_12bit_voltage(info, PM8607_GPADC1_MEAS1, data);
+               if (ret)
+                       return ret;
+               /* meausered Vtbat(mV) / Ibias_current(11uA)*/
+               *data = (*data * 1000) / GPBIAS2_GPADC1_UA;
+
+               if (*data > TBAT_NEG_25D) {
+                       temp = -30;     /* over cold , suppose -30 roughly */
+                       max = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, 0, max);
+               } else if (*data > TBAT_NEG_10D) {
+                       temp = -15;     /* -15 degree, code */
+                       max = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, 0, max);
+               } else if (*data > TBAT_0D) {
+                       temp = -5;      /* -5 degree */
+                       min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, max);
+               } else if (*data > TBAT_10D) {
+                       temp = 5;       /* in range of (0, 10) */
+                       min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, max);
+               } else if (*data > TBAT_20D) {
+                       temp = 15;      /* in range of (10, 20) */
+                       min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, max);
+               } else if (*data > TBAT_30D) {
+                       temp = 25;      /* in range of (20, 30) */
+                       min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, max);
+               } else if (*data > TBAT_40D) {
+                       temp = 35;      /* in range of (30, 40) */
+                       min = TBAT_NEG_10D * GPBIAS2_GPADC1_UA / 1000;
+                       max = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, max);
+               } else {
+                       min = TBAT_40D * GPBIAS2_GPADC1_UA / 1000;
+                       set_temp_threshold(info, min, 0);
+                       temp = 45;      /* over heat ,suppose 45 roughly */
+               }
+
+               dev_dbg(info->dev, "temp_C:%d C,temp_mv:%d mv\n", temp, *data);
+               *data = temp;
+       }
+       return 0;
+}
+
+static int calc_resistor(struct pm860x_battery_info *info)
+{
+       int vbatt_sum1;
+       int vbatt_sum2;
+       int chg_current;
+       int ibatt_sum1;
+       int ibatt_sum2;
+       int data;
+       int ret;
+       int i;
+
+       ret = measure_current(info, &data);
+       /* make sure that charging is launched by data > 0 */
+       if (ret || data < 0)
+               goto out;
+
+       ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+       if (ret)
+               goto out;
+       /* calculate resistor only in CC charge mode */
+       if (data < VBATT_RESISTOR_MIN || data > VBATT_RESISTOR_MAX)
+               goto out;
+
+       /* current is saved */
+       if (set_charger_current(info, 500, &chg_current))
+               goto out;
+
+       /*
+        * set charge current as 500mA, wait about 500ms till charging
+        * process is launched and stable with the newer charging current.
+        */
+       msleep(500);
+
+       for (i = 0, vbatt_sum1 = 0, ibatt_sum1 = 0; i < 10; i++) {
+               ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+               if (ret)
+                       goto out_meas;
+               vbatt_sum1 += data;
+               ret = measure_current(info, &data);
+               if (ret)
+                       goto out_meas;
+
+               if (data < 0)
+                       ibatt_sum1 = ibatt_sum1 - data; /* discharging */
+               else
+                       ibatt_sum1 = ibatt_sum1 + data; /* charging */
+       }
+
+       if (set_charger_current(info, 100, &ret))
+               goto out_meas;
+       /*
+        * set charge current as 100mA, wait about 500ms till charging
+        * process is launched and stable with the newer charging current.
+        */
+       msleep(500);
+
+       for (i = 0, vbatt_sum2 = 0, ibatt_sum2 = 0; i < 10; i++) {
+               ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+               if (ret)
+                       goto out_meas;
+               vbatt_sum2 += data;
+               ret = measure_current(info, &data);
+               if (ret)
+                       goto out_meas;
+
+               if (data < 0)
+                       ibatt_sum2 = ibatt_sum2 - data; /* discharging */
+               else
+                       ibatt_sum2 = ibatt_sum2 + data; /* charging */
+       }
+
+       /* restore current setting */
+       if (set_charger_current(info, chg_current, &ret))
+               goto out_meas;
+
+       if ((vbatt_sum1 > vbatt_sum2) && (ibatt_sum1 > ibatt_sum2) &&
+                       (ibatt_sum2 > 0)) {
+               /* calculate resistor in discharging case */
+               data = 1000 * (vbatt_sum1 - vbatt_sum2)
+                   / (ibatt_sum1 - ibatt_sum2);
+               if ((data - info->resistor > 0) &&
+                               (data - info->resistor < info->resistor))
+                       info->resistor = data;
+               if ((info->resistor - data > 0) &&
+                               (info->resistor - data < data))
+                       info->resistor = data;
+       }
+       return 0;
+
+out_meas:
+       set_charger_current(info, chg_current, &ret);
+out:
+       return -EINVAL;
+}
+
+static int calc_capacity(struct pm860x_battery_info *info, int *cap)
+{
+       int ret;
+       int data;
+       int ibat;
+       int cap_ocv = 0;
+       int cap_cc = 0;
+
+       ret = calc_ccnt(info, &ccnt_data);
+       if (ret)
+               goto out;
+soc:
+       data = info->max_capacity * info->start_soc / 100;
+       if (ccnt_data.total_dischg - ccnt_data.total_chg <= data) {
+               cap_cc =
+                   data + ccnt_data.total_chg - ccnt_data.total_dischg;
+       } else {
+               clear_ccnt(info, &ccnt_data);
+               calc_soc(info, OCV_MODE_ACTIVE, &info->start_soc);
+               dev_dbg(info->dev, "restart soc = %d !\n",
+                       info->start_soc);
+               goto soc;
+       }
+
+       cap_cc = cap_cc * 100 / info->max_capacity;
+       if (cap_cc < 0)
+               cap_cc = 0;
+       else if (cap_cc > 100)
+               cap_cc = 100;
+
+       dev_dbg(info->dev, "%s, last cap : %d", __func__,
+               info->last_capacity);
+
+       ret = measure_current(info, &ibat);
+       if (ret)
+               goto out;
+       /* Calculate the capacity when discharging(ibat < 0) */
+       if (ibat < 0) {
+               ret = calc_soc(info, OCV_MODE_ACTIVE, &cap_ocv);
+               if (ret)
+                       cap_ocv = info->last_capacity;
+               ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+               if (ret)
+                       goto out;
+               if (data <= LOW_BAT_THRESHOLD) {
+                       /* choose the lower capacity value to report
+                        * between vbat and CC when vbat < 3.6v;
+                        * than 3.6v;
+                        */
+                       *cap = min(cap_ocv, cap_cc);
+               } else {
+                       /* when detect vbat > 3.6v, but cap_cc < 15,and
+                        * cap_ocv is 10% larger than cap_cc, we can think
+                        * CC have some accumulation error, switch to OCV
+                        * to estimate capacity;
+                        * */
+                       if (cap_cc < 15 && cap_ocv - cap_cc > 10)
+                               *cap = cap_ocv;
+                       else
+                               *cap = cap_cc;
+               }
+               /* when discharging, make sure current capacity
+                * is lower than last*/
+               if (*cap > info->last_capacity)
+                       *cap = info->last_capacity;
+       } else {
+               *cap = cap_cc;
+       }
+       info->last_capacity = *cap;
+
+       dev_dbg(info->dev, "%s, cap_ocv:%d cap_cc:%d, cap:%d\n",
+               (ibat < 0) ? "discharging" : "charging",
+                cap_ocv, cap_cc, *cap);
+       /*
+        * store the current capacity to RTC domain register,
+        * after next power up , it will be restored.
+        */
+       pm860x_set_bits(info->i2c, PM8607_RTC_MISC2, RTC_SOC_5LSB,
+                       (*cap & 0x1F) << 3);
+       pm860x_set_bits(info->i2c, PM8607_RTC1, RTC_SOC_3MSB,
+                       ((*cap >> 5) & 0x3));
+       return 0;
+out:
+       return ret;
+}
+
+static void pm860x_external_power_changed(struct power_supply *psy)
+{
+       struct pm860x_battery_info *info;
+
+       info = container_of(psy, struct pm860x_battery_info, battery);
+       calc_resistor(info);
+}
+
+static int pm860x_batt_get_prop(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               union power_supply_propval *val)
+{
+       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent);
+       int data;
+       int ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = info->present;
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               ret = calc_capacity(info, &data);
+               if (ret)
+                       return ret;
+               if (data < 0)
+                       data = 0;
+               else if (data > 100)
+                       data = 100;
+               /* return 100 if battery is not attached */
+               if (!info->present)
+                       data = 100;
+               val->intval = data;
+               break;
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               /* return real vbatt Voltage */
+               ret = measure_vbatt(info, OCV_MODE_ACTIVE, &data);
+               if (ret)
+                       return ret;
+               val->intval = data * 1000;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               /* return Open Circuit Voltage (not measured voltage) */
+               ret = calc_ocv(info, &data);
+               if (ret)
+                       return ret;
+               val->intval = data * 1000;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               ret = measure_current(info, &data);
+               if (ret)
+                       return ret;
+               val->intval = data;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               if (info->present) {
+                       ret = measure_temp(info, &data);
+                       if (ret)
+                               return ret;
+                       data *= 10;
+               } else {
+                       /* Fake Temp 25C Without Battery */
+                       data = 250;
+               }
+               val->intval = data;
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int pm860x_batt_set_prop(struct power_supply *psy,
+                                      enum power_supply_property psp,
+                                      const union power_supply_propval *val)
+{
+       struct pm860x_battery_info *info = dev_get_drvdata(psy->dev->parent);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               clear_ccnt(info, &ccnt_data);
+               info->start_soc = 100;
+               dev_dbg(info->dev, "chg done, update soc = %d\n",
+                       info->start_soc);
+               break;
+       default:
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+
+static enum power_supply_property pm860x_batt_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_AVG,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_TEMP,
+};
+
+static __devinit int pm860x_battery_probe(struct platform_device *pdev)
+{
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct pm860x_battery_info *info;
+       struct pm860x_power_pdata *pdata;
+       int ret;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->irq_cc = platform_get_irq(pdev, 0);
+       if (info->irq_cc <= 0) {
+               dev_err(&pdev->dev, "No IRQ resource!\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       info->irq_batt = platform_get_irq(pdev, 1);
+       if (info->irq_batt <= 0) {
+               dev_err(&pdev->dev, "No IRQ resource!\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       info->chip = chip;
+       info->i2c =
+           (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+       info->dev = &pdev->dev;
+       info->status = POWER_SUPPLY_STATUS_UNKNOWN;
+       pdata = pdev->dev.platform_data;
+
+       mutex_init(&info->lock);
+       platform_set_drvdata(pdev, info);
+
+       pm860x_init_battery(info);
+
+       info->battery.name = "battery-monitor";
+       info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       info->battery.properties = pm860x_batt_props;
+       info->battery.num_properties = ARRAY_SIZE(pm860x_batt_props);
+       info->battery.get_property = pm860x_batt_get_prop;
+       info->battery.set_property = pm860x_batt_set_prop;
+       info->battery.external_power_changed = pm860x_external_power_changed;
+
+       if (pdata && pdata->max_capacity)
+               info->max_capacity = pdata->max_capacity;
+       else
+               info->max_capacity = 1500;      /* set default capacity */
+       if (pdata && pdata->resistor)
+               info->resistor = pdata->resistor;
+       else
+               info->resistor = 300;   /* set default internal resistor */
+
+       ret = power_supply_register(&pdev->dev, &info->battery);
+       if (ret)
+               goto out;
+       info->battery.dev->parent = &pdev->dev;
+
+       ret = request_threaded_irq(info->irq_cc, NULL,
+                               pm860x_coulomb_handler, IRQF_ONESHOT,
+                               "coulomb", info);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+                       info->irq_cc, ret);
+               goto out_reg;
+       }
+
+       ret = request_threaded_irq(info->irq_batt, NULL, pm860x_batt_handler,
+                               IRQF_ONESHOT, "battery", info);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+                       info->irq_batt, ret);
+               goto out_coulomb;
+       }
+
+
+       return 0;
+
+out_coulomb:
+       free_irq(info->irq_cc, info);
+out_reg:
+       power_supply_unregister(&info->battery);
+out:
+       kfree(info);
+       return ret;
+}
+
+static int __devexit pm860x_battery_remove(struct platform_device *pdev)
+{
+       struct pm860x_battery_info *info = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&info->battery);
+       free_irq(info->irq_batt, info);
+       free_irq(info->irq_cc, info);
+       kfree(info);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pm860x_battery_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag |= 1 << PM8607_IRQ_CC;
+       return 0;
+}
+
+static int pm860x_battery_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+       if (device_may_wakeup(dev))
+               chip->wakeup_flag &= ~(1 << PM8607_IRQ_CC);
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pm860x_battery_pm_ops,
+                       pm860x_battery_suspend, pm860x_battery_resume);
+
+static struct platform_driver pm860x_battery_driver = {
+       .driver = {
+                  .name = "88pm860x-battery",
+                  .owner = THIS_MODULE,
+                  .pm = &pm860x_battery_pm_ops,
+       },
+       .probe = pm860x_battery_probe,
+       .remove = __devexit_p(pm860x_battery_remove),
+};
+module_platform_driver(pm860x_battery_driver);
+
+MODULE_DESCRIPTION("Marvell 88PM860x Battery driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
new file mode 100644 (file)
index 0000000..2dbeb14
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ * Battery driver for Marvell 88PM860x PMIC
+ *
+ * Copyright (c) 2012 Marvell International Ltd.
+ * Author:     Jett Zhou <jtzhou@marvell.com>
+ *             Haojian Zhuang <haojian.zhuang@marvell.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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <asm/div64.h>
+
+/* bit definitions of Status Query Interface 2 */
+#define STATUS2_CHG            (1 << 2)
+
+/* bit definitions of Reset Out Register */
+#define RESET_SW_PD            (1 << 7)
+
+/* bit definitions of PreReg 1 */
+#define PREREG1_90MA           (0x0)
+#define PREREG1_180MA          (0x1)
+#define PREREG1_450MA          (0x4)
+#define PREREG1_540MA          (0x5)
+#define PREREG1_1350MA         (0xE)
+#define PREREG1_VSYS_4_5V      (3 << 4)
+
+/* bit definitions of Charger Control 1 Register */
+#define CC1_MODE_OFF           (0)
+#define CC1_MODE_PRECHARGE     (1)
+#define CC1_MODE_FASTCHARGE    (2)
+#define CC1_MODE_PULSECHARGE   (3)
+#define CC1_ITERM_20MA         (0 << 2)
+#define CC1_ITERM_60MA         (2 << 2)
+#define CC1_VFCHG_4_2V         (9 << 4)
+
+/* bit definitions of Charger Control 2 Register */
+#define CC2_ICHG_100MA         (0x1)
+#define CC2_ICHG_500MA         (0x9)
+#define CC2_ICHG_1000MA                (0x13)
+
+/* bit definitions of Charger Control 3 Register */
+#define CC3_180MIN_TIMEOUT     (0x6 << 4)
+#define CC3_270MIN_TIMEOUT     (0x7 << 4)
+#define CC3_360MIN_TIMEOUT     (0xA << 4)
+#define CC3_DISABLE_TIMEOUT    (0xF << 4)
+
+/* bit definitions of Charger Control 4 Register */
+#define CC4_IPRE_40MA          (7)
+#define CC4_VPCHG_3_2V         (3 << 4)
+#define CC4_IFCHG_MON_EN       (1 << 6)
+#define CC4_BTEMP_MON_EN       (1 << 7)
+
+/* bit definitions of Charger Control 6 Register */
+#define CC6_BAT_OV_EN          (1 << 2)
+#define CC6_BAT_UV_EN          (1 << 3)
+#define CC6_UV_VBAT_SET                (0x3 << 6)      /* 2.8v */
+
+/* bit definitions of Charger Control 7 Register */
+#define CC7_BAT_REM_EN         (1 << 3)
+#define CC7_IFSM_EN            (1 << 7)
+
+/* bit definitions of Measurement Enable 1 Register */
+#define MEAS1_VBAT             (1 << 0)
+
+/* bit definitions of Measurement Enable 3 Register */
+#define MEAS3_IBAT_EN          (1 << 0)
+#define MEAS3_CC_EN            (1 << 2)
+
+#define FSM_INIT               0
+#define FSM_DISCHARGE          1
+#define FSM_PRECHARGE          2
+#define FSM_FASTCHARGE         3
+
+#define PRECHARGE_THRESHOLD    3100
+#define POWEROFF_THRESHOLD     3400
+#define CHARGE_THRESHOLD       4000
+#define DISCHARGE_THRESHOLD    4180
+
+/* over-temperature on PM8606 setting */
+#define OVER_TEMP_FLAG         (1 << 6)
+#define OVTEMP_AUTORECOVER     (1 << 3)
+
+/* over-voltage protect on vchg setting mv */
+#define VCHG_NORMAL_LOW                4200
+#define VCHG_NORMAL_CHECK      5800
+#define VCHG_NORMAL_HIGH       6000
+#define VCHG_OVP_LOW           5500
+
+struct pm860x_charger_info {
+       struct pm860x_chip *chip;
+       struct i2c_client *i2c;
+       struct i2c_client *i2c_8606;
+       struct device *dev;
+
+       struct power_supply usb;
+       struct mutex lock;
+       int irq_nums;
+       int irq[7];
+       unsigned state:3;       /* fsm state */
+       unsigned online:1;      /* usb charger */
+       unsigned present:1;     /* battery present */
+       unsigned allowed:1;
+};
+
+static char *pm860x_supplied_to[] = {
+       "battery-monitor",
+};
+
+static int measure_vchg(struct pm860x_charger_info *info, int *data)
+{
+       unsigned char buf[2];
+       int ret = 0;
+
+       ret = pm860x_bulk_read(info->i2c, PM8607_VCHG_MEAS1, 2, buf);
+       if (ret < 0)
+               return ret;
+
+       *data = ((buf[0] & 0xff) << 4) | (buf[1] & 0x0f);
+       /* V_BATT_MEAS(mV) = value * 5 * 1.8 * 1000 / (2^12) */
+       *data = ((*data & 0xfff) * 9 * 125) >> 9;
+
+       dev_dbg(info->dev, "%s, vchg: %d mv\n", __func__, *data);
+
+       return ret;
+}
+
+static void set_vchg_threshold(struct pm860x_charger_info *info,
+                              int min, int max)
+{
+       int data;
+
+       /* (tmp << 8) * / 5 / 1800 */
+       if (min <= 0)
+               data = 0;
+       else
+               data = (min << 5) / 1125;
+       pm860x_reg_write(info->i2c, PM8607_VCHG_LOWTH, data);
+       dev_dbg(info->dev, "VCHG_LOWTH:%dmv, 0x%x\n", min, data);
+
+       if (max <= 0)
+               data = 0xff;
+       else
+               data = (max << 5) / 1125;
+       pm860x_reg_write(info->i2c, PM8607_VCHG_HIGHTH, data);
+       dev_dbg(info->dev, "VCHG_HIGHTH:%dmv, 0x%x\n", max, data);
+
+}
+
+static void set_vbatt_threshold(struct pm860x_charger_info *info,
+                               int min, int max)
+{
+       int data;
+
+       /* (tmp << 8) * 3 / 1800 */
+       if (min <= 0)
+               data = 0;
+       else
+               data = (min << 5) / 675;
+       pm860x_reg_write(info->i2c, PM8607_VBAT_LOWTH, data);
+       dev_dbg(info->dev, "VBAT Min:%dmv, LOWTH:0x%x\n", min, data);
+
+       if (max <= 0)
+               data = 0xff;
+       else
+               data = (max << 5) / 675;
+       pm860x_reg_write(info->i2c, PM8607_VBAT_HIGHTH, data);
+       dev_dbg(info->dev, "VBAT Max:%dmv, HIGHTH:0x%x\n", max, data);
+
+       return;
+}
+
+static int start_precharge(struct pm860x_charger_info *info)
+{
+       int ret;
+
+       dev_dbg(info->dev, "Start Pre-charging!\n");
+       set_vbatt_threshold(info, 0, 0);
+
+       ret = pm860x_reg_write(info->i2c_8606, PM8606_PREREGULATORA,
+                              PREREG1_1350MA | PREREG1_VSYS_4_5V);
+       if (ret < 0)
+               goto out;
+       /* stop charging */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3,
+                             CC1_MODE_OFF);
+       if (ret < 0)
+               goto out;
+       /* set 270 minutes timeout */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL3, (0xf << 4),
+                             CC3_270MIN_TIMEOUT);
+       if (ret < 0)
+               goto out;
+       /* set precharge current, termination voltage, IBAT & TBAT monitor */
+       ret = pm860x_reg_write(info->i2c, PM8607_CHG_CTRL4,
+                              CC4_IPRE_40MA | CC4_VPCHG_3_2V |
+                              CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL7,
+                             CC7_BAT_REM_EN | CC7_IFSM_EN,
+                             CC7_BAT_REM_EN | CC7_IFSM_EN);
+       if (ret < 0)
+               goto out;
+       /* trigger precharge */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3,
+                             CC1_MODE_PRECHARGE);
+out:
+       return ret;
+}
+
+static int start_fastcharge(struct pm860x_charger_info *info)
+{
+       int ret;
+
+       dev_dbg(info->dev, "Start Fast-charging!\n");
+
+       /* set fastcharge termination current & voltage, disable charging */
+       ret = pm860x_reg_write(info->i2c, PM8607_CHG_CTRL1,
+                              CC1_MODE_OFF | CC1_ITERM_60MA |
+                              CC1_VFCHG_4_2V);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_reg_write(info->i2c_8606, PM8606_PREREGULATORA,
+                              PREREG1_540MA | PREREG1_VSYS_4_5V);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL2, 0x1f,
+                             CC2_ICHG_500MA);
+       if (ret < 0)
+               goto out;
+       /* set 270 minutes timeout */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL3, (0xf << 4),
+                             CC3_270MIN_TIMEOUT);
+       if (ret < 0)
+               goto out;
+       /* set IBAT & TBAT monitor */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL4,
+                             CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN,
+                             CC4_IFCHG_MON_EN | CC4_BTEMP_MON_EN);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL6,
+                             CC6_BAT_OV_EN | CC6_BAT_UV_EN |
+                             CC6_UV_VBAT_SET,
+                             CC6_BAT_OV_EN | CC6_BAT_UV_EN |
+                             CC6_UV_VBAT_SET);
+       if (ret < 0)
+               goto out;
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL7,
+                             CC7_BAT_REM_EN | CC7_IFSM_EN,
+                             CC7_BAT_REM_EN | CC7_IFSM_EN);
+       if (ret < 0)
+               goto out;
+       /* launch fast-charge */
+       ret = pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3,
+                             CC1_MODE_FASTCHARGE);
+       /* vchg threshold setting */
+       set_vchg_threshold(info, VCHG_NORMAL_LOW, VCHG_NORMAL_HIGH);
+out:
+       return ret;
+}
+
+static void stop_charge(struct pm860x_charger_info *info, int vbatt)
+{
+       dev_dbg(info->dev, "Stop charging!\n");
+       pm860x_set_bits(info->i2c, PM8607_CHG_CTRL1, 3, CC1_MODE_OFF);
+       if (vbatt > CHARGE_THRESHOLD && info->online)
+               set_vbatt_threshold(info, CHARGE_THRESHOLD, 0);
+}
+
+static void power_off_notification(struct pm860x_charger_info *info)
+{
+       dev_dbg(info->dev, "Power-off notification!\n");
+}
+
+static int set_charging_fsm(struct pm860x_charger_info *info)
+{
+       struct power_supply *psy;
+       union power_supply_propval data;
+       unsigned char fsm_state[][16] = { "init", "discharge", "precharge",
+               "fastcharge",
+       };
+       int ret;
+       int vbatt;
+
+       psy = power_supply_get_by_name(pm860x_supplied_to[0]);
+       if (!psy)
+               return -EINVAL;
+       ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &data);
+       if (ret)
+               return ret;
+       vbatt = data.intval / 1000;
+
+       ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
+       if (ret)
+               return ret;
+
+       mutex_lock(&info->lock);
+       info->present = data.intval;
+
+       dev_dbg(info->dev, "Entering FSM:%s, Charger:%s, Battery:%s, "
+               "Allowed:%d\n",
+               &fsm_state[info->state][0],
+               (info->online) ? "online" : "N/A",
+               (info->present) ? "present" : "N/A", info->allowed);
+       dev_dbg(info->dev, "set_charging_fsm:vbatt:%d(mV)\n", vbatt);
+
+       switch (info->state) {
+       case FSM_INIT:
+               if (info->online && info->present && info->allowed) {
+                       if (vbatt < PRECHARGE_THRESHOLD) {
+                               info->state = FSM_PRECHARGE;
+                               start_precharge(info);
+                       } else if (vbatt > DISCHARGE_THRESHOLD) {
+                               info->state = FSM_DISCHARGE;
+                               stop_charge(info, vbatt);
+                       } else if (vbatt < DISCHARGE_THRESHOLD) {
+                               info->state = FSM_FASTCHARGE;
+                               start_fastcharge(info);
+                       }
+               } else {
+                       if (vbatt < POWEROFF_THRESHOLD) {
+                               power_off_notification(info);
+                       } else {
+                               info->state = FSM_DISCHARGE;
+                               stop_charge(info, vbatt);
+                       }
+               }
+               break;
+       case FSM_PRECHARGE:
+               if (info->online && info->present && info->allowed) {
+                       if (vbatt > PRECHARGE_THRESHOLD) {
+                               info->state = FSM_FASTCHARGE;
+                               start_fastcharge(info);
+                       }
+               } else {
+                       info->state = FSM_DISCHARGE;
+                       stop_charge(info, vbatt);
+               }
+               break;
+       case FSM_FASTCHARGE:
+               if (info->online && info->present && info->allowed) {
+                       if (vbatt < PRECHARGE_THRESHOLD) {
+                               info->state = FSM_PRECHARGE;
+                               start_precharge(info);
+                       }
+               } else {
+                       info->state = FSM_DISCHARGE;
+                       stop_charge(info, vbatt);
+               }
+               break;
+       case FSM_DISCHARGE:
+               if (info->online && info->present && info->allowed) {
+                       if (vbatt < PRECHARGE_THRESHOLD) {
+                               info->state = FSM_PRECHARGE;
+                               start_precharge(info);
+                       } else if (vbatt < DISCHARGE_THRESHOLD) {
+                               info->state = FSM_FASTCHARGE;
+                               start_fastcharge(info);
+                       }
+               } else {
+                       if (vbatt < POWEROFF_THRESHOLD)
+                               power_off_notification(info);
+                       else if (vbatt > CHARGE_THRESHOLD && info->online)
+                               set_vbatt_threshold(info, CHARGE_THRESHOLD, 0);
+               }
+               break;
+       default:
+               dev_warn(info->dev, "FSM meets wrong state:%d\n",
+                        info->state);
+               break;
+       }
+       dev_dbg(info->dev,
+               "Out FSM:%s, Charger:%s, Battery:%s, Allowed:%d\n",
+               &fsm_state[info->state][0],
+               (info->online) ? "online" : "N/A",
+               (info->present) ? "present" : "N/A", info->allowed);
+       mutex_unlock(&info->lock);
+
+       return 0;
+}
+
+static irqreturn_t pm860x_charger_handler(int irq, void *data)
+{
+       struct pm860x_charger_info *info = data;
+       int ret;
+
+       mutex_lock(&info->lock);
+       ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+       if (ret < 0) {
+               mutex_unlock(&info->lock);
+               goto out;
+       }
+       if (ret & STATUS2_CHG) {
+               info->online = 1;
+               info->allowed = 1;
+       } else {
+               info->online = 0;
+               info->allowed = 0;
+       }
+       mutex_unlock(&info->lock);
+       dev_dbg(info->dev, "%s, Charger:%s, Allowed:%d\n", __func__,
+               (info->online) ? "online" : "N/A", info->allowed);
+
+       set_charging_fsm(info);
+
+       power_supply_changed(&info->usb);
+out:
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_temp_handler(int irq, void *data)
+{
+       struct power_supply *psy;
+       struct pm860x_charger_info *info = data;
+       union power_supply_propval temp;
+       int value;
+       int ret;
+
+       psy = power_supply_get_by_name(pm860x_supplied_to[0]);
+       if (!psy)
+               goto out;
+       ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &temp);
+       if (ret)
+               goto out;
+       value = temp.intval / 10;
+
+       mutex_lock(&info->lock);
+       /* Temperature < -10 C or >40 C, Will not allow charge */
+       if (value < -10 || value > 40)
+               info->allowed = 0;
+       else
+               info->allowed = 1;
+       dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
+       mutex_unlock(&info->lock);
+
+       set_charging_fsm(info);
+out:
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_exception_handler(int irq, void *data)
+{
+       struct pm860x_charger_info *info = data;
+
+       mutex_lock(&info->lock);
+       info->allowed = 0;
+       mutex_unlock(&info->lock);
+       dev_dbg(info->dev, "%s, irq: %d\n", __func__, irq);
+
+       set_charging_fsm(info);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_done_handler(int irq, void *data)
+{
+       struct pm860x_charger_info *info = data;
+       struct power_supply *psy;
+       union power_supply_propval val;
+       int ret;
+       int vbatt;
+
+       mutex_lock(&info->lock);
+       /* pre-charge done, will transimit to fast-charge stage */
+       if (info->state == FSM_PRECHARGE) {
+               info->allowed = 1;
+               goto out;
+       }
+       /*
+        * Fast charge done, delay to read
+        * the correct status of CHG_DET.
+        */
+       mdelay(5);
+       info->allowed = 0;
+       psy = power_supply_get_by_name(pm860x_supplied_to[0]);
+       if (!psy)
+               goto out;
+       ret = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+       if (ret)
+               goto out;
+       vbatt = val.intval / 1000;
+       /*
+        * CHG_DONE interrupt is faster than CHG_DET interrupt when
+        * plug in/out usb, So we can not rely on info->online, we
+        * need check pm8607 status register to check usb is online
+        * or not, then we can decide it is real charge done
+        * automatically or it is triggered by usb plug out;
+        */
+       ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+       if (ret < 0)
+               goto out;
+       if (vbatt > CHARGE_THRESHOLD && ret & STATUS2_CHG)
+               psy->set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &val);
+
+out:
+       mutex_unlock(&info->lock);
+       dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
+       set_charging_fsm(info);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_vbattery_handler(int irq, void *data)
+{
+       struct pm860x_charger_info *info = data;
+
+       mutex_lock(&info->lock);
+
+       set_vbatt_threshold(info, 0, 0);
+
+       if (info->present && info->online)
+               info->allowed = 1;
+       else
+               info->allowed = 0;
+       mutex_unlock(&info->lock);
+       dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
+
+       set_charging_fsm(info);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t pm860x_vchg_handler(int irq, void *data)
+{
+       struct pm860x_charger_info *info = data;
+       int vchg = 0;
+
+       if (info->present)
+               goto out;
+
+       measure_vchg(info, &vchg);
+
+       mutex_lock(&info->lock);
+       if (!info->online) {
+               int status;
+               /* check if over-temp on pm8606 or not */
+               status = pm860x_reg_read(info->i2c_8606, PM8606_FLAGS);
+               if (status & OVER_TEMP_FLAG) {
+                       /* clear over temp flag and set auto recover */
+                       pm860x_set_bits(info->i2c_8606, PM8606_FLAGS,
+                                       OVER_TEMP_FLAG, OVER_TEMP_FLAG);
+                       pm860x_set_bits(info->i2c_8606,
+                                       PM8606_VSYS,
+                                       OVTEMP_AUTORECOVER,
+                                       OVTEMP_AUTORECOVER);
+                       dev_dbg(info->dev,
+                               "%s, pm8606 over-temp occure\n", __func__);
+               }
+       }
+
+       if (vchg > VCHG_NORMAL_CHECK) {
+               set_vchg_threshold(info, VCHG_OVP_LOW, 0);
+               info->allowed = 0;
+               dev_dbg(info->dev,
+                       "%s,pm8607 over-vchg occure,vchg = %dmv\n",
+                       __func__, vchg);
+       } else if (vchg < VCHG_OVP_LOW) {
+               set_vchg_threshold(info, VCHG_NORMAL_LOW,
+                                  VCHG_NORMAL_HIGH);
+               info->allowed = 1;
+               dev_dbg(info->dev,
+                       "%s,pm8607 over-vchg recover,vchg = %dmv\n",
+                       __func__, vchg);
+       }
+       mutex_unlock(&info->lock);
+
+       dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed);
+       set_charging_fsm(info);
+out:
+       return IRQ_HANDLED;
+}
+
+static int pm860x_usb_get_prop(struct power_supply *psy,
+                              enum power_supply_property psp,
+                              union power_supply_propval *val)
+{
+       struct pm860x_charger_info *info =
+           dev_get_drvdata(psy->dev->parent);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               if (info->state == FSM_FASTCHARGE ||
+                               info->state == FSM_PRECHARGE)
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = info->online;
+               break;
+       default:
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static enum power_supply_property pm860x_usb_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int pm860x_init_charger(struct pm860x_charger_info *info)
+{
+       int ret;
+
+       ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&info->lock);
+       info->state = FSM_INIT;
+       if (ret & STATUS2_CHG) {
+               info->online = 1;
+               info->allowed = 1;
+       } else {
+               info->online = 0;
+               info->allowed = 0;
+       }
+       mutex_unlock(&info->lock);
+
+       set_charging_fsm(info);
+       return 0;
+}
+
+static struct pm860x_irq_desc {
+       const char *name;
+       irqreturn_t (*handler)(int irq, void *data);
+} pm860x_irq_descs[] = {
+       { "usb supply detect", pm860x_charger_handler },
+       { "charge done", pm860x_done_handler },
+       { "charge timeout", pm860x_exception_handler },
+       { "charge fault", pm860x_exception_handler },
+       { "temperature", pm860x_temp_handler },
+       { "vbatt", pm860x_vbattery_handler },
+       { "vchg", pm860x_vchg_handler },
+};
+
+static __devinit int pm860x_charger_probe(struct platform_device *pdev)
+{
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct pm860x_charger_info *info;
+       int ret;
+       int count;
+       int i;
+       int j;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       count = pdev->num_resources;
+       for (i = 0, j = 0; i < count; i++) {
+               info->irq[j] = platform_get_irq(pdev, i);
+               if (info->irq[j] < 0)
+                       continue;
+               j++;
+       }
+       info->irq_nums = j;
+
+       info->chip = chip;
+       info->i2c =
+           (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+       info->i2c_8606 =
+           (chip->id == CHIP_PM8607) ? chip->companion : chip->client;
+       if (!info->i2c_8606) {
+               dev_err(&pdev->dev, "Missed I2C address of 88PM8606!\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       info->dev = &pdev->dev;
+
+       /* set init value for the case we are not using battery */
+       set_vchg_threshold(info, VCHG_NORMAL_LOW, VCHG_OVP_LOW);
+
+       mutex_init(&info->lock);
+       platform_set_drvdata(pdev, info);
+
+       info->usb.name = "usb";
+       info->usb.type = POWER_SUPPLY_TYPE_USB;
+       info->usb.supplied_to = pm860x_supplied_to;
+       info->usb.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
+       info->usb.properties = pm860x_usb_props;
+       info->usb.num_properties = ARRAY_SIZE(pm860x_usb_props);
+       info->usb.get_property = pm860x_usb_get_prop;
+       ret = power_supply_register(&pdev->dev, &info->usb);
+       if (ret)
+               goto out;
+
+       pm860x_init_charger(info);
+
+       for (i = 0; i < ARRAY_SIZE(info->irq); i++) {
+               ret = request_threaded_irq(info->irq[i], NULL,
+                       pm860x_irq_descs[i].handler,
+                       IRQF_ONESHOT, pm860x_irq_descs[i].name, info);
+               if (ret < 0) {
+                       dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+                               info->irq[i], ret);
+                       goto out_irq;
+               }
+       }
+       return 0;
+
+out_irq:
+       while (--i >= 0)
+               free_irq(info->irq[i], info);
+out:
+       kfree(info);
+       return ret;
+}
+
+static int __devexit pm860x_charger_remove(struct platform_device *pdev)
+{
+       struct pm860x_charger_info *info = platform_get_drvdata(pdev);
+       int i;
+
+       platform_set_drvdata(pdev, NULL);
+       power_supply_unregister(&info->usb);
+       free_irq(info->irq[0], info);
+       for (i = 0; i < info->irq_nums; i++)
+               free_irq(info->irq[i], info);
+       kfree(info);
+       return 0;
+}
+
+static struct platform_driver pm860x_charger_driver = {
+       .driver = {
+                  .name = "88pm860x-charger",
+                  .owner = THIS_MODULE,
+       },
+       .probe = pm860x_charger_probe,
+       .remove = __devexit_p(pm860x_charger_remove),
+};
+module_platform_driver(pm860x_charger_driver);
+
+MODULE_DESCRIPTION("Marvell 88PM860x Charger driver");
+MODULE_LICENSE("GPL");
index 80978196aae8b0a59d100a3bc09818dccdd6200b..49a89397231834a67fc1436026f563fadfe57e10 100644 (file)
@@ -69,6 +69,12 @@ config TEST_POWER
        help
          This driver is used for testing. It's safe to say M here.
 
+config BATTERY_88PM860X
+       tristate "Marvell 88PM860x battery driver"
+       depends on MFD_88PM860X
+       help
+         Say Y here to enable battery monitor for Marvell 88PM860x chip.
+
 config BATTERY_DS2760
        tristate "DS2760 battery driver (HP iPAQ & others)"
        depends on W1 && W1_SLAVE_DS2760
@@ -174,7 +180,6 @@ config BATTERY_DA9030
 config BATTERY_DA9052
        tristate "Dialog DA9052 Battery"
        depends on PMIC_DA9052
-       depends on BROKEN
        help
          Say Y here to enable support for batteries charger integrated into
          DA9052 PMIC.
@@ -210,6 +215,12 @@ config BATTERY_S3C_ADC
        help
          Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery
 
+config CHARGER_88PM860X
+       tristate "Marvell 88PM860x Charger driver"
+       depends on MFD_88PM860X && BATTERY_88PM860X
+       help
+         Say Y here to enable charger for Marvell 88PM860x chip.
+
 config CHARGER_PCF50633
        tristate "NXP PCF50633 MBC"
        depends on MFD_PCF50633
@@ -262,6 +273,13 @@ config CHARGER_LP8727
        help
          Say Y here to enable support for LP8727 Charger Driver.
 
+config CHARGER_LP8788
+       tristate "TI LP8788 charger driver"
+       depends on MFD_LP8788
+       depends on LP8788_ADC
+       help
+         Say Y to enable support for the LP8788 linear charger.
+
 config CHARGER_GPIO
        tristate "GPIO charger"
        depends on GPIOLIB
index e0b4d4284e1d56508d815b860cc56cff71101e12..b949cf85590c623610f1ada865114c3d709372f9 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_WM831X_POWER)    += wm831x_power.o
 obj-$(CONFIG_WM8350_POWER)     += wm8350_power.o
 obj-$(CONFIG_TEST_POWER)       += test_power.o
 
+obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
 obj-$(CONFIG_BATTERY_DS2760)   += ds2760_battery.o
 obj-$(CONFIG_BATTERY_DS2780)   += ds2780_battery.o
 obj-$(CONFIG_BATTERY_DS2781)   += ds2781_battery.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_BATTERY_MAX17040)        += max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
 obj-$(CONFIG_BATTERY_Z2)       += z2_battery.o
 obj-$(CONFIG_BATTERY_S3C_ADC)  += s3c_adc_battery.o
+obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o
 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)   += jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)        += intel_mid_battery.o
@@ -40,6 +42,7 @@ obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
 obj-$(CONFIG_CHARGER_MAX8903)  += max8903_charger.o
 obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
 obj-$(CONFIG_CHARGER_LP8727)   += lp8727_charger.o
+obj-$(CONFIG_CHARGER_LP8788)   += lp8788-charger.o
 obj-$(CONFIG_CHARGER_GPIO)     += gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)  += charger-manager.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
index 3041514f4d3f2d38469048dbf5ee96bf879483b6..e3b6395b20ddc226f2324ddfecbf820469accd03 100644 (file)
@@ -1014,6 +1014,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
                create_singlethread_workqueue("ab8500_btemp_wq");
        if (di->btemp_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
+               ret = -ENOMEM;
                goto free_device_info;
        }
 
index 0701dbc2b7e1fe4b506cd0394a12bdaed6e0b91d..26ff759e2220572579ba9f01c319d21b0cdb96ec 100644 (file)
@@ -2614,6 +2614,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
                create_singlethread_workqueue("ab8500_charger_wq");
        if (di->charger_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
+               ret = -ENOMEM;
                goto free_device_info;
        }
 
index 5c9e7c263c382f93244a70e4be7f7ddb7a455fcc..2db8cc254399c8093ffcfbbc78c965d68d73f14e 100644 (file)
@@ -2506,6 +2506,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
        di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
        if (di->fg_wq == NULL) {
                dev_err(di->dev, "failed to create work queue\n");
+               ret = -ENOMEM;
                goto free_device_info;
        }
 
index 181ddece5181afceb5d025fbdcf9bfb7f641f007..5860d4dfbe9cdaf3fbeed4870429c5e918166c3c 100644 (file)
@@ -814,7 +814,8 @@ static int bq27x00_battery_probe(struct i2c_client *client,
        di->bat.name = name;
        di->bus.read = &bq27x00_read_i2c;
 
-       if (bq27x00_powersupply_init(di))
+       retval = bq27x00_powersupply_init(di);
+       if (retval)
                goto batt_failed_3;
 
        i2c_set_clientdata(client, di);
index 7ff83cf43c8c1ad5d06407b9eba1358f0bdb9053..8a0aca6364c7e8ba9ab68261b598afe2e155ad18 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/power/charger-manager.h>
 #include <linux/regulator/consumer.h>
+#include <linux/sysfs.h>
 
 static const char * const default_event_names[] = {
        [CM_EVENT_UNKNOWN] = "Unknown",
@@ -226,6 +227,58 @@ static bool is_charging(struct charger_manager *cm)
        return charging;
 }
 
+/**
+ * is_full_charged - Returns true if the battery is fully charged.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_full_charged(struct charger_manager *cm)
+{
+       struct charger_desc *desc = cm->desc;
+       union power_supply_propval val;
+       int ret = 0;
+       int uV;
+
+       /* If there is no battery, it cannot be charged */
+       if (!is_batt_present(cm)) {
+               val.intval = 0;
+               goto out;
+       }
+
+       if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) {
+               /* Not full if capacity of fuel gauge isn't full */
+               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+                               POWER_SUPPLY_PROP_CHARGE_FULL, &val);
+               if (!ret && val.intval > desc->fullbatt_full_capacity) {
+                       val.intval = 1;
+                       goto out;
+               }
+       }
+
+       /* Full, if it's over the fullbatt voltage */
+       if (desc->fullbatt_uV > 0) {
+               ret = get_batt_uV(cm, &uV);
+               if (!ret && uV >= desc->fullbatt_uV) {
+                       val.intval = 1;
+                       goto out;
+               }
+       }
+
+       /* Full, if the capacity is more than fullbatt_soc */
+       if (cm->fuel_gauge && desc->fullbatt_soc > 0) {
+               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+                               POWER_SUPPLY_PROP_CAPACITY, &val);
+               if (!ret && val.intval >= desc->fullbatt_soc) {
+                       val.intval = 1;
+                       goto out;
+               }
+       }
+
+       val.intval = 0;
+
+out:
+       return val.intval ? true : false;
+}
+
 /**
  * is_polling_required - Return true if need to continue polling for this CM.
  * @cm: the Charger Manager representing the battery.
@@ -271,9 +324,45 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
        if (enable) {
                if (cm->emergency_stop)
                        return -EAGAIN;
-               for (i = 0 ; i < desc->num_charger_regulators ; i++)
-                       regulator_enable(desc->charger_regulators[i].consumer);
+
+               /*
+                * Save start time of charging to limit
+                * maximum possible charging time.
+                */
+               cm->charging_start_time = ktime_to_ms(ktime_get());
+               cm->charging_end_time = 0;
+
+               for (i = 0 ; i < desc->num_charger_regulators ; i++) {
+                       if (desc->charger_regulators[i].externally_control)
+                               continue;
+
+                       err = regulator_enable(desc->charger_regulators[i].consumer);
+                       if (err < 0) {
+                               dev_warn(cm->dev,
+                                       "Cannot enable %s regulator\n",
+                                       desc->charger_regulators[i].regulator_name);
+                       }
+               }
        } else {
+               /*
+                * Save end time of charging to maintain fully charged state
+                * of battery after full-batt.
+                */
+               cm->charging_start_time = 0;
+               cm->charging_end_time = ktime_to_ms(ktime_get());
+
+               for (i = 0 ; i < desc->num_charger_regulators ; i++) {
+                       if (desc->charger_regulators[i].externally_control)
+                               continue;
+
+                       err = regulator_disable(desc->charger_regulators[i].consumer);
+                       if (err < 0) {
+                               dev_warn(cm->dev,
+                                       "Cannot disable %s regulator\n",
+                                       desc->charger_regulators[i].regulator_name);
+                       }
+               }
+
                /*
                 * Abnormal battery state - Stop charging forcibly,
                 * even if charger was enabled at the other places
@@ -400,15 +489,62 @@ static void fullbatt_vchk(struct work_struct *work)
                return;
        }
 
-       diff = cm->fullbatt_vchk_uV;
+       diff = desc->fullbatt_uV;
        diff -= batt_uV;
 
-       dev_dbg(cm->dev, "VBATT dropped %duV after full-batt.\n", diff);
+       dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff);
 
        if (diff > desc->fullbatt_vchkdrop_uV) {
                try_charger_restart(cm);
-               uevent_notify(cm, "Recharge");
+               uevent_notify(cm, "Recharging");
+       }
+}
+
+/**
+ * check_charging_duration - Monitor charging/discharging duration
+ * @cm: the Charger Manager representing the battery.
+ *
+ * If whole charging duration exceed 'charging_max_duration_ms',
+ * cm stop charging to prevent overcharge/overheat. If discharging
+ * duration exceed 'discharging _max_duration_ms', charger cable is
+ * attached, after full-batt, cm start charging to maintain fully
+ * charged state for battery.
+ */
+static int check_charging_duration(struct charger_manager *cm)
+{
+       struct charger_desc *desc = cm->desc;
+       u64 curr = ktime_to_ms(ktime_get());
+       u64 duration;
+       int ret = false;
+
+       if (!desc->charging_max_duration_ms &&
+                       !desc->discharging_max_duration_ms)
+               return ret;
+
+       if (cm->charger_enabled) {
+               duration = curr - cm->charging_start_time;
+
+               if (duration > desc->charging_max_duration_ms) {
+                       dev_info(cm->dev, "Charging duration exceed %lldms",
+                                desc->charging_max_duration_ms);
+                       uevent_notify(cm, "Discharging");
+                       try_charger_enable(cm, false);
+                       ret = true;
+               }
+       } else if (is_ext_pwr_online(cm) && !cm->charger_enabled) {
+               duration = curr - cm->charging_end_time;
+
+               if (duration > desc->charging_max_duration_ms &&
+                               is_ext_pwr_online(cm)) {
+                       dev_info(cm->dev, "DisCharging duration exceed %lldms",
+                                desc->discharging_max_duration_ms);
+                       uevent_notify(cm, "Recharing");
+                       try_charger_enable(cm, true);
+                       ret = true;
+               }
        }
+
+       return ret;
 }
 
 /**
@@ -426,10 +562,14 @@ static bool _cm_monitor(struct charger_manager *cm)
        dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n",
                cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
 
-       /* It has been stopped or charging already */
-       if (!!temp == !!cm->emergency_stop)
+       /* It has been stopped already */
+       if (temp && cm->emergency_stop)
                return false;
 
+       /*
+        * Check temperature whether overheat or cold.
+        * If temperature is out of range normal state, stop charging.
+        */
        if (temp) {
                cm->emergency_stop = temp;
                if (!try_charger_enable(cm, false)) {
@@ -438,10 +578,41 @@ static bool _cm_monitor(struct charger_manager *cm)
                        else
                                uevent_notify(cm, "COLD");
                }
+
+       /*
+        * Check whole charging duration and discharing duration
+        * after full-batt.
+        */
+       } else if (!cm->emergency_stop && check_charging_duration(cm)) {
+               dev_dbg(cm->dev,
+                       "Charging/Discharging duration is out of range");
+       /*
+        * Check dropped voltage of battery. If battery voltage is more
+        * dropped than fullbatt_vchkdrop_uV after fully charged state,
+        * charger-manager have to recharge battery.
+        */
+       } else if (!cm->emergency_stop && is_ext_pwr_online(cm) &&
+                       !cm->charger_enabled) {
+               fullbatt_vchk(&cm->fullbatt_vchk_work.work);
+
+       /*
+        * Check whether fully charged state to protect overcharge
+        * if charger-manager is charging for battery.
+        */
+       } else if (!cm->emergency_stop && is_full_charged(cm) &&
+                       cm->charger_enabled) {
+               dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n");
+               uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]);
+
+               try_charger_enable(cm, false);
+
+               fullbatt_vchk(&cm->fullbatt_vchk_work.work);
        } else {
                cm->emergency_stop = 0;
-               if (!try_charger_enable(cm, true))
-                       uevent_notify(cm, "CHARGING");
+               if (is_ext_pwr_online(cm)) {
+                       if (!try_charger_enable(cm, true))
+                               uevent_notify(cm, "CHARGING");
+               }
        }
 
        return true;
@@ -701,47 +872,10 @@ static int charger_get_property(struct power_supply *psy,
                        val->intval = 0;
                break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
-               if (cm->fuel_gauge) {
-                       if (cm->fuel_gauge->get_property(cm->fuel_gauge,
-                           POWER_SUPPLY_PROP_CHARGE_FULL, val) == 0)
-                               break;
-               }
-
-               if (is_ext_pwr_online(cm)) {
-                       /* Not full if it's charging. */
-                       if (is_charging(cm)) {
-                               val->intval = 0;
-                               break;
-                       }
-                       /*
-                        * Full if it's powered but not charging andi
-                        * not forced stop by emergency
-                        */
-                       if (!cm->emergency_stop) {
-                               val->intval = 1;
-                               break;
-                       }
-               }
-
-               /* Full if it's over the fullbatt voltage */
-               ret = get_batt_uV(cm, &uV);
-               if (!ret && desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
-                   !is_charging(cm)) {
+               if (is_full_charged(cm))
                        val->intval = 1;
-                       break;
-               }
-
-               /* Full if the cap is 100 */
-               if (cm->fuel_gauge) {
-                       ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
-                                       POWER_SUPPLY_PROP_CAPACITY, val);
-                       if (!ret && val->intval >= 100 && !is_charging(cm)) {
-                               val->intval = 1;
-                               break;
-                       }
-               }
-
-               val->intval = 0;
+               else
+                       val->intval = 0;
                ret = 0;
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
@@ -1031,7 +1165,26 @@ static int charger_extcon_notifier(struct notifier_block *self,
        struct charger_cable *cable =
                container_of(self, struct charger_cable, nb);
 
+       /*
+        * The newly state of charger cable.
+        * If cable is attached, cable->attached is true.
+        */
        cable->attached = event;
+
+       /*
+        * Setup monitoring to check battery state
+        * when charger cable is attached.
+        */
+       if (cable->attached && is_polling_required(cable->cm)) {
+               if (work_pending(&setup_polling))
+                       cancel_work_sync(&setup_polling);
+               schedule_work(&setup_polling);
+       }
+
+       /*
+        * Setup work for controlling charger(regulator)
+        * according to charger cable.
+        */
        schedule_work(&cable->wq);
 
        return NOTIFY_DONE;
@@ -1068,12 +1221,101 @@ static int charger_extcon_init(struct charger_manager *cm,
        return ret;
 }
 
+/* help function of sysfs node to control charger(regulator) */
+static ssize_t charger_name_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct charger_regulator *charger
+               = container_of(attr, struct charger_regulator, attr_name);
+
+       return sprintf(buf, "%s\n", charger->regulator_name);
+}
+
+static ssize_t charger_state_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct charger_regulator *charger
+               = container_of(attr, struct charger_regulator, attr_state);
+       int state = 0;
+
+       if (!charger->externally_control)
+               state = regulator_is_enabled(charger->consumer);
+
+       return sprintf(buf, "%s\n", state ? "enabled" : "disabled");
+}
+
+static ssize_t charger_externally_control_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct charger_regulator *charger = container_of(attr,
+                       struct charger_regulator, attr_externally_control);
+
+       return sprintf(buf, "%d\n", charger->externally_control);
+}
+
+static ssize_t charger_externally_control_store(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       struct charger_regulator *charger
+               = container_of(attr, struct charger_regulator,
+                                       attr_externally_control);
+       struct charger_manager *cm = charger->cm;
+       struct charger_desc *desc = cm->desc;
+       int i;
+       int ret;
+       int externally_control;
+       int chargers_externally_control = 1;
+
+       ret = sscanf(buf, "%d", &externally_control);
+       if (ret == 0) {
+               ret = -EINVAL;
+               return ret;
+       }
+
+       if (!externally_control) {
+               charger->externally_control = 0;
+               return count;
+       }
+
+       for (i = 0; i < desc->num_charger_regulators; i++) {
+               if (&desc->charger_regulators[i] != charger &&
+                             !desc->charger_regulators[i].externally_control) {
+                       /*
+                        * At least, one charger is controlled by
+                        * charger-manager
+                        */
+                       chargers_externally_control = 0;
+                       break;
+               }
+       }
+
+       if (!chargers_externally_control) {
+               if (cm->charger_enabled) {
+                       try_charger_enable(charger->cm, false);
+                       charger->externally_control = externally_control;
+                       try_charger_enable(charger->cm, true);
+               } else {
+                       charger->externally_control = externally_control;
+               }
+       } else {
+               dev_warn(cm->dev,
+                       "'%s' regulator should be controlled "
+                       "in charger-manager because charger-manager "
+                       "must need at least one charger for charging\n",
+                       charger->regulator_name);
+       }
+
+       return count;
+}
+
 static int charger_manager_probe(struct platform_device *pdev)
 {
        struct charger_desc *desc = dev_get_platdata(&pdev->dev);
        struct charger_manager *cm;
        int ret = 0, i = 0;
        int j = 0;
+       int chargers_externally_control = 1;
        union power_supply_propval val;
 
        if (g_desc && !rtc_dev && g_desc->rtc_name) {
@@ -1125,6 +1367,15 @@ static int charger_manager_probe(struct platform_device *pdev)
                desc->fullbatt_vchkdrop_ms = 0;
                desc->fullbatt_vchkdrop_uV = 0;
        }
+       if (desc->fullbatt_soc == 0) {
+               dev_info(&pdev->dev, "Ignoring full-battery soc(state of"
+                                       " charge) threshold as it is not"
+                                       " supplied.");
+       }
+       if (desc->fullbatt_full_capacity == 0) {
+               dev_info(&pdev->dev, "Ignoring full-battery full capacity"
+                                       " threshold as it is not supplied.");
+       }
 
        if (!desc->charger_regulators || desc->num_charger_regulators < 1) {
                ret = -EINVAL;
@@ -1182,6 +1433,15 @@ static int charger_manager_probe(struct platform_device *pdev)
                goto err_chg_stat;
        }
 
+       if (!desc->charging_max_duration_ms ||
+                       !desc->discharging_max_duration_ms) {
+               dev_info(&pdev->dev, "Cannot limit charging duration "
+                        "checking mechanism to prevent overcharge/overheat "
+                        "and control discharging duration");
+               desc->charging_max_duration_ms = 0;
+               desc->discharging_max_duration_ms = 0;
+       }
+
        platform_set_drvdata(pdev, cm);
 
        memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
@@ -1245,6 +1505,8 @@ static int charger_manager_probe(struct platform_device *pdev)
        for (i = 0 ; i < desc->num_charger_regulators ; i++) {
                struct charger_regulator *charger
                                        = &desc->charger_regulators[i];
+               char buf[11];
+               char *str;
 
                charger->consumer = regulator_get(&pdev->dev,
                                        charger->regulator_name);
@@ -1254,6 +1516,7 @@ static int charger_manager_probe(struct platform_device *pdev)
                        ret = -EINVAL;
                        goto err_chg_get;
                }
+               charger->cm = cm;
 
                for (j = 0 ; j < charger->num_cables ; j++) {
                        struct charger_cable *cable = &charger->cables[j];
@@ -1267,6 +1530,71 @@ static int charger_manager_probe(struct platform_device *pdev)
                        cable->charger = charger;
                        cable->cm = cm;
                }
+
+               /* Create sysfs entry to control charger(regulator) */
+               snprintf(buf, 10, "charger.%d", i);
+               str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL);
+               if (!str) {
+                       for (i--; i >= 0; i--) {
+                               charger = &desc->charger_regulators[i];
+                               kfree(charger->attr_g.name);
+                       }
+                       ret = -ENOMEM;
+
+                       goto err_extcon;
+               }
+               strcpy(str, buf);
+
+               charger->attrs[0] = &charger->attr_name.attr;
+               charger->attrs[1] = &charger->attr_state.attr;
+               charger->attrs[2] = &charger->attr_externally_control.attr;
+               charger->attrs[3] = NULL;
+               charger->attr_g.name = str;
+               charger->attr_g.attrs = charger->attrs;
+
+               sysfs_attr_init(&charger->attr_name.attr);
+               charger->attr_name.attr.name = "name";
+               charger->attr_name.attr.mode = 0444;
+               charger->attr_name.show = charger_name_show;
+
+               sysfs_attr_init(&charger->attr_state.attr);
+               charger->attr_state.attr.name = "state";
+               charger->attr_state.attr.mode = 0444;
+               charger->attr_state.show = charger_state_show;
+
+               sysfs_attr_init(&charger->attr_externally_control.attr);
+               charger->attr_externally_control.attr.name
+                               = "externally_control";
+               charger->attr_externally_control.attr.mode = 0644;
+               charger->attr_externally_control.show
+                               = charger_externally_control_show;
+               charger->attr_externally_control.store
+                               = charger_externally_control_store;
+
+               if (!desc->charger_regulators[i].externally_control ||
+                               !chargers_externally_control) {
+                       chargers_externally_control = 0;
+               }
+               dev_info(&pdev->dev, "'%s' regulator's externally_control"
+                               "is %d\n", charger->regulator_name,
+                               charger->externally_control);
+
+               ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
+                               &charger->attr_g);
+               if (ret < 0) {
+                       dev_info(&pdev->dev, "Cannot create sysfs entry"
+                                       "of %s regulator\n",
+                                       charger->regulator_name);
+               }
+       }
+
+       if (chargers_externally_control) {
+               dev_err(&pdev->dev, "Cannot register regulator because "
+                               "charger-manager must need at least "
+                               "one charger for charging battery\n");
+
+               ret = -EINVAL;
+               goto err_chg_enable;
        }
 
        ret = try_charger_enable(cm, true);
@@ -1292,6 +1620,14 @@ static int charger_manager_probe(struct platform_device *pdev)
        return 0;
 
 err_chg_enable:
+       for (i = 0; i < desc->num_charger_regulators; i++) {
+               struct charger_regulator *charger;
+
+               charger = &desc->charger_regulators[i];
+               sysfs_remove_group(&cm->charger_psy.dev->kobj,
+                               &charger->attr_g);
+               kfree(charger->attr_g.name);
+       }
 err_extcon:
        for (i = 0 ; i < desc->num_charger_regulators ; i++) {
                struct charger_regulator *charger
index 3fd3e95d2b8517d101e7dbab63e0bafdb0c25513..94762e67e22b69d50c28a587586a83e9266323f9 100644 (file)
@@ -187,8 +187,8 @@ static const struct file_operations bat_debug_fops = {
 
 static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
 {
-       charger->debug_file = debugfs_create_file("charger", 0666, 0, charger,
-                                                &bat_debug_fops);
+       charger->debug_file = debugfs_create_file("charger", 0666, NULL,
+                                                 charger, &bat_debug_fops);
        return charger->debug_file;
 }
 
index a5f6a0ec15726b8e93180ea51b1a4facde4474a5..d9d034d7496f7c3adeaf4af5e0d72bf02f522a7d 100644 (file)
@@ -327,7 +327,7 @@ static int da9052_bat_interpolate(int vbat_lower, int  vbat_upper,
        return tmp;
 }
 
-unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
+static unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
 {
        int i;
 
@@ -345,6 +345,13 @@ unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
                     && (adc_temp <= vc_tbl_ref[i]))
                                return i + 1;
        }
+       /*
+        * For some reason authors of the driver didn't presume that we can
+        * end up here. It might be OK, but might be not, no one knows for
+        * sure. Go check your battery, is it on fire?
+        */
+       WARN_ON(1);
+       return 0;
 }
 
 static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity)
@@ -616,7 +623,7 @@ static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
        return 0;
 
 err:
-       for (; i >= 0; i--) {
+       while (--i >= 0) {
                irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
                free_irq(bat->da9052->irq_base + irq, bat);
        }
index 7a1ff4e4cf9a6452f1b58b2074638aac105cdc93..22b3c8c93552dbe63b33e8f167cba111f96a3c62 100644 (file)
@@ -755,11 +755,9 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev)
        int ret = 0;
        struct ds2781_device_info *dev_info;
 
-       dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
-       if (!dev_info) {
-               ret = -ENOMEM;
-               goto fail;
-       }
+       dev_info = devm_kzalloc(&pdev->dev, sizeof(*dev_info), GFP_KERNEL);
+       if (!dev_info)
+               return -ENOMEM;
 
        platform_set_drvdata(pdev, dev_info);
 
@@ -774,7 +772,7 @@ static int __devinit ds2781_battery_probe(struct platform_device *pdev)
        ret = power_supply_register(&pdev->dev, &dev_info->bat);
        if (ret) {
                dev_err(dev_info->dev, "failed to register battery\n");
-               goto fail_free_info;
+               goto fail;
        }
 
        ret = sysfs_create_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
@@ -808,8 +806,6 @@ fail_remove_group:
        sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2781_attr_group);
 fail_unregister:
        power_supply_unregister(&dev_info->bat);
-fail_free_info:
-       kfree(dev_info);
 fail:
        return ret;
 }
@@ -823,7 +819,6 @@ static int __devexit ds2781_battery_remove(struct platform_device *pdev)
 
        power_supply_unregister(&dev_info->bat);
 
-       kfree(dev_info);
        return 0;
 }
 
@@ -834,20 +829,7 @@ static struct platform_driver ds2781_battery_driver = {
        .probe    = ds2781_battery_probe,
        .remove   = __devexit_p(ds2781_battery_remove),
 };
-
-static int __init ds2781_battery_init(void)
-{
-       return platform_driver_register(&ds2781_battery_driver);
-}
-
-static void __exit ds2781_battery_exit(void)
-{
-       platform_driver_unregister(&ds2781_battery_driver);
-}
-
-module_init(ds2781_battery_init);
-module_exit(ds2781_battery_exit);
-
+module_platform_driver(ds2781_battery_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>");
index 6a364f4798f78765b40298451474a876e10f71da..c628224b7f58788b94df718fb087c1b56e5a03ed 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/platform_data/lp8727.h>
 
-#define DEBOUNCE_MSEC  270
+#define LP8788_NUM_INTREGS     2
+#define DEFAULT_DEBOUNCE_MSEC  270
 
 /* Registers */
-#define CTRL1          0x1
-#define CTRL2          0x2
-#define        SWCTRL          0x3
-#define INT1           0x4
-#define INT2           0x5
-#define STATUS1                0x6
-#define STATUS2                0x7
-#define CHGCTRL2       0x9
+#define LP8727_CTRL1           0x1
+#define LP8727_CTRL2           0x2
+#define LP8727_SWCTRL          0x3
+#define LP8727_INT1            0x4
+#define LP8727_INT2            0x5
+#define LP8727_STATUS1         0x6
+#define LP8727_STATUS2         0x7
+#define LP8727_CHGCTRL2                0x9
 
 /* CTRL1 register */
-#define CP_EN          (1 << 0)
-#define ADC_EN         (1 << 1)
-#define ID200_EN       (1 << 4)
+#define LP8727_CP_EN           BIT(0)
+#define LP8727_ADC_EN          BIT(1)
+#define LP8727_ID200_EN                BIT(4)
 
 /* CTRL2 register */
-#define CHGDET_EN      (1 << 1)
-#define INT_EN         (1 << 6)
+#define LP8727_CHGDET_EN       BIT(1)
+#define LP8727_INT_EN          BIT(6)
 
 /* SWCTRL register */
-#define SW_DM1_DM      (0x0 << 0)
-#define SW_DM1_U1      (0x1 << 0)
-#define SW_DM1_HiZ     (0x7 << 0)
-#define SW_DP2_DP      (0x0 << 3)
-#define SW_DP2_U2      (0x1 << 3)
-#define SW_DP2_HiZ     (0x7 << 3)
+#define LP8727_SW_DM1_DM       (0x0 << 0)
+#define LP8727_SW_DM1_HiZ      (0x7 << 0)
+#define LP8727_SW_DP2_DP       (0x0 << 3)
+#define LP8727_SW_DP2_HiZ      (0x7 << 3)
 
 /* INT1 register */
-#define IDNO           (0xF << 0)
-#define VBUS           (1 << 4)
+#define LP8727_IDNO            (0xF << 0)
+#define LP8727_VBUS            BIT(4)
 
 /* STATUS1 register */
-#define CHGSTAT                (3 << 4)
-#define CHPORT         (1 << 6)
-#define DCPORT         (1 << 7)
+#define LP8727_CHGSTAT         (3 << 4)
+#define LP8727_CHPORT          BIT(6)
+#define LP8727_DCPORT          BIT(7)
+#define LP8727_STAT_EOC                0x30
 
 /* STATUS2 register */
-#define TEMP_STAT      (3 << 5)
+#define LP8727_TEMP_STAT       (3 << 5)
+#define LP8727_TEMP_SHIFT      5
+
+/* CHGCTRL2 register */
+#define LP8727_ICHG_SHIFT      4
 
 enum lp8727_dev_id {
-       ID_NONE,
-       ID_TA,
-       ID_DEDICATED_CHG,
-       ID_USB_CHG,
-       ID_USB_DS,
-       ID_MAX,
+       LP8727_ID_NONE,
+       LP8727_ID_TA,
+       LP8727_ID_DEDICATED_CHG,
+       LP8727_ID_USB_CHG,
+       LP8727_ID_USB_DS,
+       LP8727_ID_MAX,
 };
 
-enum lp8727_chg_stat {
-       PRECHG,
-       CC,
-       CV,
-       EOC,
+enum lp8727_die_temp {
+       LP8788_TEMP_75C,
+       LP8788_TEMP_95C,
+       LP8788_TEMP_115C,
+       LP8788_TEMP_135C,
 };
 
 struct lp8727_psy {
@@ -84,12 +88,17 @@ struct lp8727_chg {
        struct device *dev;
        struct i2c_client *client;
        struct mutex xfer_lock;
-       struct delayed_work work;
-       struct workqueue_struct *irqthread;
-       struct lp8727_platform_data *pdata;
        struct lp8727_psy *psy;
-       struct lp8727_chg_param *chg_parm;
+       struct lp8727_platform_data *pdata;
+
+       /* Charger Data */
        enum lp8727_dev_id devid;
+       struct lp8727_chg_param *chg_param;
+
+       /* Interrupt Handling */
+       int irq;
+       struct delayed_work work;
+       unsigned long debounce_jiffies;
 };
 
 static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
@@ -119,81 +128,84 @@ static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data)
        return ret;
 }
 
-static int lp8727_is_charger_attached(const char *name, int id)
+static bool lp8727_is_charger_attached(const char *name, int id)
 {
-       if (name) {
-               if (!strcmp(name, "ac"))
-                       return (id == ID_TA || id == ID_DEDICATED_CHG) ? 1 : 0;
-               else if (!strcmp(name, "usb"))
-                       return (id == ID_USB_CHG) ? 1 : 0;
-       }
+       if (!strcmp(name, "ac"))
+               return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG;
+       else if (!strcmp(name, "usb"))
+               return id == LP8727_ID_USB_CHG;
 
-       return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0;
+       return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG;
 }
 
 static int lp8727_init_device(struct lp8727_chg *pchg)
 {
        u8 val;
        int ret;
+       u8 intstat[LP8788_NUM_INTREGS];
 
-       val = ID200_EN | ADC_EN | CP_EN;
-       ret = lp8727_write_byte(pchg, CTRL1, val);
+       /* clear interrupts */
+       ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS);
        if (ret)
                return ret;
 
-       val = INT_EN | CHGDET_EN;
-       ret = lp8727_write_byte(pchg, CTRL2, val);
+       val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN;
+       ret = lp8727_write_byte(pchg, LP8727_CTRL1, val);
        if (ret)
                return ret;
 
-       return 0;
+       val = LP8727_INT_EN | LP8727_CHGDET_EN;
+       return lp8727_write_byte(pchg, LP8727_CTRL2, val);
 }
 
 static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
 {
        u8 val;
-       lp8727_read_byte(pchg, STATUS1, &val);
-       return val & DCPORT;
+
+       lp8727_read_byte(pchg, LP8727_STATUS1, &val);
+       return val & LP8727_DCPORT;
 }
 
 static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
 {
        u8 val;
-       lp8727_read_byte(pchg, STATUS1, &val);
-       return val & CHPORT;
+
+       lp8727_read_byte(pchg, LP8727_STATUS1, &val);
+       return val & LP8727_CHPORT;
 }
 
-static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
+static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
 {
-       lp8727_write_byte(pchg, SWCTRL, sw);
+       lp8727_write_byte(pchg, LP8727_SWCTRL, sw);
 }
 
 static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
 {
-       u8 devid = ID_NONE;
-       u8 swctrl = SW_DM1_HiZ | SW_DP2_HiZ;
+       struct lp8727_platform_data *pdata = pchg->pdata;
+       u8 devid = LP8727_ID_NONE;
+       u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ;
 
        switch (id) {
        case 0x5:
-               devid = ID_TA;
-               pchg->chg_parm = &pchg->pdata->ac;
+               devid = LP8727_ID_TA;
+               pchg->chg_param = pdata ? pdata->ac : NULL;
                break;
        case 0xB:
                if (lp8727_is_dedicated_charger(pchg)) {
-                       pchg->chg_parm = &pchg->pdata->ac;
-                       devid = ID_DEDICATED_CHG;
+                       pchg->chg_param = pdata ? pdata->ac : NULL;
+                       devid = LP8727_ID_DEDICATED_CHG;
                } else if (lp8727_is_usb_charger(pchg)) {
-                       pchg->chg_parm = &pchg->pdata->usb;
-                       devid = ID_USB_CHG;
-                       swctrl = SW_DM1_DM | SW_DP2_DP;
+                       pchg->chg_param = pdata ? pdata->usb : NULL;
+                       devid = LP8727_ID_USB_CHG;
+                       swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
                } else if (vbusin) {
-                       devid = ID_USB_DS;
-                       swctrl = SW_DM1_DM | SW_DP2_DP;
+                       devid = LP8727_ID_USB_DS;
+                       swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
                }
                break;
        default:
-               devid = ID_NONE;
-               pchg->chg_parm = NULL;
+               devid = LP8727_ID_NONE;
+               pchg->chg_param = NULL;
                break;
        }
 
@@ -205,24 +217,26 @@ static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
 {
        u8 val;
 
-       lp8727_read_byte(pchg, CTRL2, &val);
-       val |= CHGDET_EN;
-       lp8727_write_byte(pchg, CTRL2, val);
+       lp8727_read_byte(pchg, LP8727_CTRL2, &val);
+       val |= LP8727_CHGDET_EN;
+       lp8727_write_byte(pchg, LP8727_CTRL2, val);
 }
 
 static void lp8727_delayed_func(struct work_struct *_work)
 {
-       u8 intstat[2], idno, vbus;
-       struct lp8727_chg *pchg =
-           container_of(_work, struct lp8727_chg, work.work);
+       struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg,
+                                               work.work);
+       u8 intstat[LP8788_NUM_INTREGS];
+       u8 idno;
+       u8 vbus;
 
-       if (lp8727_read_bytes(pchg, INT1, intstat, 2)) {
+       if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) {
                dev_err(pchg->dev, "can not read INT registers\n");
                return;
        }
 
-       idno = intstat[0] & IDNO;
-       vbus = intstat[0] & VBUS;
+       idno = intstat[0] & LP8727_IDNO;
+       vbus = intstat[0] & LP8727_VBUS;
 
        lp8727_id_detection(pchg, idno, vbus);
        lp8727_enable_chgdet(pchg);
@@ -235,29 +249,44 @@ static void lp8727_delayed_func(struct work_struct *_work)
 static irqreturn_t lp8727_isr_func(int irq, void *ptr)
 {
        struct lp8727_chg *pchg = ptr;
-       unsigned long delay = msecs_to_jiffies(DEBOUNCE_MSEC);
-
-       queue_delayed_work(pchg->irqthread, &pchg->work, delay);
 
+       schedule_delayed_work(&pchg->work, pchg->debounce_jiffies);
        return IRQ_HANDLED;
 }
 
-static int lp8727_intr_config(struct lp8727_chg *pchg)
+static int lp8727_setup_irq(struct lp8727_chg *pchg)
 {
+       int ret;
+       int irq = pchg->client->irq;
+       unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec :
+                                               DEFAULT_DEBOUNCE_MSEC;
+
        INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
 
-       pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd");
-       if (!pchg->irqthread) {
-               dev_err(pchg->dev, "can not create thread for lp8727\n");
-               return -ENOMEM;
+       if (irq <= 0) {
+               dev_warn(pchg->dev, "invalid irq number: %d\n", irq);
+               return 0;
        }
 
-       return request_threaded_irq(pchg->client->irq,
-                               NULL,
-                               lp8727_isr_func,
-                               IRQF_TRIGGER_FALLING,
-                               "lp8727_irq",
-                               pchg);
+       ret = request_threaded_irq(irq, NULL, lp8727_isr_func,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                               "lp8727_irq", pchg);
+
+       if (ret)
+               return ret;
+
+       pchg->irq = irq;
+       pchg->debounce_jiffies = msecs_to_jiffies(delay_msec);
+
+       return 0;
+}
+
+static void lp8727_release_irq(struct lp8727_chg *pchg)
+{
+       cancel_delayed_work_sync(&pchg->work);
+
+       if (pchg->irq)
+               free_irq(pchg->irq, pchg);
 }
 
 static enum power_supply_property lp8727_charger_prop[] = {
@@ -283,54 +312,82 @@ static int lp8727_charger_get_property(struct power_supply *psy,
 {
        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
 
-       if (psp == POWER_SUPPLY_PROP_ONLINE)
-               val->intval = lp8727_is_charger_attached(psy->name,
-                                                        pchg->devid);
+       if (psp != POWER_SUPPLY_PROP_ONLINE)
+               return -EINVAL;
+
+       val->intval = lp8727_is_charger_attached(psy->name, pchg->devid);
 
        return 0;
 }
 
+static bool lp8727_is_high_temperature(enum lp8727_die_temp temp)
+{
+       switch (temp) {
+       case LP8788_TEMP_95C:
+       case LP8788_TEMP_115C:
+       case LP8788_TEMP_135C:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static int lp8727_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property psp,
                                       union power_supply_propval *val)
 {
        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+       struct lp8727_platform_data *pdata = pchg->pdata;
+       enum lp8727_die_temp temp;
        u8 read;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
-               if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
-                       lp8727_read_byte(pchg, STATUS1, &read);
-                       if (((read & CHGSTAT) >> 4) == EOC)
-                               val->intval = POWER_SUPPLY_STATUS_FULL;
-                       else
-                               val->intval = POWER_SUPPLY_STATUS_CHARGING;
-               } else {
+               if (!lp8727_is_charger_attached(psy->name, pchg->devid)) {
                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+                       return 0;
                }
+
+               lp8727_read_byte(pchg, LP8727_STATUS1, &read);
+
+               val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ?
+                               POWER_SUPPLY_STATUS_FULL :
+                               POWER_SUPPLY_STATUS_CHARGING;
                break;
        case POWER_SUPPLY_PROP_HEALTH:
-               lp8727_read_byte(pchg, STATUS2, &read);
-               read = (read & TEMP_STAT) >> 5;
-               if (read >= 0x1 && read <= 0x3)
-                       val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
-               else
-                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               lp8727_read_byte(pchg, LP8727_STATUS2, &read);
+               temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT;
+
+               val->intval = lp8727_is_high_temperature(temp) ?
+                       POWER_SUPPLY_HEALTH_OVERHEAT :
+                       POWER_SUPPLY_HEALTH_GOOD;
                break;
        case POWER_SUPPLY_PROP_PRESENT:
-               if (pchg->pdata->get_batt_present)
+               if (!pdata)
+                       return -EINVAL;
+
+               if (pdata->get_batt_present)
                        val->intval = pchg->pdata->get_batt_present();
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-               if (pchg->pdata->get_batt_level)
+               if (!pdata)
+                       return -EINVAL;
+
+               if (pdata->get_batt_level)
                        val->intval = pchg->pdata->get_batt_level();
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
-               if (pchg->pdata->get_batt_capacity)
+               if (!pdata)
+                       return -EINVAL;
+
+               if (pdata->get_batt_capacity)
                        val->intval = pchg->pdata->get_batt_capacity();
                break;
        case POWER_SUPPLY_PROP_TEMP:
-               if (pchg->pdata->get_batt_temp)
+               if (!pdata)
+                       return -EINVAL;
+
+               if (pdata->get_batt_temp)
                        val->intval = pchg->pdata->get_batt_temp();
                break;
        default:
@@ -343,16 +400,20 @@ static int lp8727_battery_get_property(struct power_supply *psy,
 static void lp8727_charger_changed(struct power_supply *psy)
 {
        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+       u8 eoc_level;
+       u8 ichg;
        u8 val;
-       u8 eoc_level, ichg;
-
-       if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
-               if (pchg->chg_parm) {
-                       eoc_level = pchg->chg_parm->eoc_level;
-                       ichg = pchg->chg_parm->ichg;
-                       val = (ichg << 4) | eoc_level;
-                       lp8727_write_byte(pchg, CHGCTRL2, val);
-               }
+
+       /* skip if no charger exists */
+       if (!lp8727_is_charger_attached(psy->name, pchg->devid))
+               return;
+
+       /* update charging parameters */
+       if (pchg->chg_param) {
+               eoc_level = pchg->chg_param->eoc_level;
+               ichg = pchg->chg_param->ichg;
+               val = (ichg << LP8727_ICHG_SHIFT) | eoc_level;
+               lp8727_write_byte(pchg, LP8727_CHGCTRL2, val);
        }
 }
 
@@ -360,9 +421,9 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
 {
        struct lp8727_psy *psy;
 
-       psy = kzalloc(sizeof(*psy), GFP_KERNEL);
+       psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
        if (!psy)
-               goto err_mem;
+               return -ENOMEM;
 
        pchg->psy = psy;
 
@@ -375,7 +436,7 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
        psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
        if (power_supply_register(pchg->dev, &psy->ac))
-               goto err_psy;
+               goto err_psy_ac;
 
        psy->usb.name = "usb";
        psy->usb.type = POWER_SUPPLY_TYPE_USB;
@@ -386,7 +447,7 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
        psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 
        if (power_supply_register(pchg->dev, &psy->usb))
-               goto err_psy;
+               goto err_psy_usb;
 
        psy->batt.name = "main_batt";
        psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -396,14 +457,15 @@ static int lp8727_register_psy(struct lp8727_chg *pchg)
        psy->batt.external_power_changed = lp8727_charger_changed;
 
        if (power_supply_register(pchg->dev, &psy->batt))
-               goto err_psy;
+               goto err_psy_batt;
 
        return 0;
 
-err_mem:
-       return -ENOMEM;
-err_psy:
-       kfree(psy);
+err_psy_batt:
+       power_supply_unregister(&psy->usb);
+err_psy_usb:
+       power_supply_unregister(&psy->ac);
+err_psy_ac:
        return -EPERM;
 }
 
@@ -417,7 +479,6 @@ static void lp8727_unregister_psy(struct lp8727_chg *pchg)
        power_supply_unregister(&psy->ac);
        power_supply_unregister(&psy->usb);
        power_supply_unregister(&psy->batt);
-       kfree(psy);
 }
 
 static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
@@ -428,7 +489,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
                return -EIO;
 
-       pchg = kzalloc(sizeof(*pchg), GFP_KERNEL);
+       pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
        if (!pchg)
                return -ENOMEM;
 
@@ -442,37 +503,31 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        ret = lp8727_init_device(pchg);
        if (ret) {
                dev_err(pchg->dev, "i2c communication err: %d", ret);
-               goto error;
+               return ret;
        }
 
-       ret = lp8727_intr_config(pchg);
+       ret = lp8727_register_psy(pchg);
        if (ret) {
-               dev_err(pchg->dev, "irq handler err: %d", ret);
-               goto error;
+               dev_err(pchg->dev, "power supplies register err: %d", ret);
+               return ret;
        }
 
-       ret = lp8727_register_psy(pchg);
+       ret = lp8727_setup_irq(pchg);
        if (ret) {
-               dev_err(pchg->dev, "power supplies register err: %d", ret);
-               goto error;
+               dev_err(pchg->dev, "irq handler err: %d", ret);
+               lp8727_unregister_psy(pchg);
+               return ret;
        }
 
        return 0;
-
-error:
-       kfree(pchg);
-       return ret;
 }
 
 static int __devexit lp8727_remove(struct i2c_client *cl)
 {
        struct lp8727_chg *pchg = i2c_get_clientdata(cl);
 
+       lp8727_release_irq(pchg);
        lp8727_unregister_psy(pchg);
-       free_irq(pchg->client->irq, pchg);
-       flush_workqueue(pchg->irqthread);
-       destroy_workqueue(pchg->irqthread);
-       kfree(pchg);
        return 0;
 }
 
@@ -493,6 +548,5 @@ static struct i2c_driver lp8727_driver = {
 module_i2c_driver(lp8727_driver);
 
 MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
-MODULE_AUTHOR("Woogyom Kim <milo.kim@ti.com>, "
-             "Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
new file mode 100644 (file)
index 0000000..e852d12
--- /dev/null
@@ -0,0 +1,795 @@
+/*
+ * TI LP8788 MFD - battery charger driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.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 <linux/err.h>
+#include <linux/iio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+/* register address */
+#define LP8788_CHG_STATUS              0x07
+#define LP8788_CHG_IDCIN               0x13
+#define LP8788_CHG_IBATT               0x14
+#define LP8788_CHG_VTERM               0x15
+#define LP8788_CHG_EOC                 0x16
+
+/* mask/shift bits */
+#define LP8788_CHG_INPUT_STATE_M       0x03    /* Addr 07h */
+#define LP8788_CHG_STATE_M             0x3C
+#define LP8788_CHG_STATE_S             2
+#define LP8788_NO_BATT_M               BIT(6)
+#define LP8788_BAD_BATT_M              BIT(7)
+#define LP8788_CHG_IBATT_M             0x1F    /* Addr 14h */
+#define LP8788_CHG_VTERM_M             0x0F    /* Addr 15h */
+#define LP8788_CHG_EOC_LEVEL_M         0x30    /* Addr 16h */
+#define LP8788_CHG_EOC_LEVEL_S         4
+#define LP8788_CHG_EOC_TIME_M          0x0E
+#define LP8788_CHG_EOC_TIME_S          1
+#define LP8788_CHG_EOC_MODE_M          BIT(0)
+
+#define LP8788_CHARGER_NAME            "charger"
+#define LP8788_BATTERY_NAME            "main_batt"
+
+#define LP8788_CHG_START               0x11
+#define LP8788_CHG_END                 0x1C
+
+#define LP8788_BUF_SIZE                        40
+#define LP8788_ISEL_MAX                        23
+#define LP8788_ISEL_STEP               50
+#define LP8788_VTERM_MIN               4100
+#define LP8788_VTERM_STEP              25
+#define LP8788_MAX_BATT_CAPACITY       100
+#define LP8788_MAX_CHG_IRQS            11
+
+enum lp8788_charging_state {
+       LP8788_OFF,
+       LP8788_WARM_UP,
+       LP8788_LOW_INPUT = 0x3,
+       LP8788_PRECHARGE,
+       LP8788_CC,
+       LP8788_CV,
+       LP8788_MAINTENANCE,
+       LP8788_BATTERY_FAULT,
+       LP8788_SYSTEM_SUPPORT = 0xC,
+       LP8788_HIGH_CURRENT = 0xF,
+       LP8788_MAX_CHG_STATE,
+};
+
+enum lp8788_charger_adc_sel {
+       LP8788_VBATT,
+       LP8788_BATT_TEMP,
+       LP8788_NUM_CHG_ADC,
+};
+
+enum lp8788_charger_input_state {
+       LP8788_SYSTEM_SUPPLY = 1,
+       LP8788_FULL_FUNCTION,
+};
+
+/*
+ * struct lp8788_chg_irq
+ * @which        : lp8788 interrupt id
+ * @virq         : Linux IRQ number from irq_domain
+ */
+struct lp8788_chg_irq {
+       enum lp8788_int_id which;
+       int virq;
+};
+
+/*
+ * struct lp8788_charger
+ * @lp           : used for accessing the registers of mfd lp8788 device
+ * @charger      : power supply driver for the battery charger
+ * @battery      : power supply driver for the battery
+ * @charger_work : work queue for charger input interrupts
+ * @chan         : iio channels for getting adc values
+ *                 eg) battery voltage, capacity and temperature
+ * @irqs         : charger dedicated interrupts
+ * @num_irqs     : total numbers of charger interrupts
+ * @pdata        : charger platform specific data
+ */
+struct lp8788_charger {
+       struct lp8788 *lp;
+       struct power_supply charger;
+       struct power_supply battery;
+       struct work_struct charger_work;
+       struct iio_channel *chan[LP8788_NUM_CHG_ADC];
+       struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS];
+       int num_irqs;
+       struct lp8788_charger_platform_data *pdata;
+};
+
+static char *battery_supplied_to[] = {
+       LP8788_BATTERY_NAME,
+};
+
+static enum power_supply_property lp8788_charger_prop[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
+static enum power_supply_property lp8788_battery_prop[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_TEMP,
+};
+
+static bool lp8788_is_charger_detected(struct lp8788_charger *pchg)
+{
+       u8 data;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
+       data &= LP8788_CHG_INPUT_STATE_M;
+
+       return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION;
+}
+
+static int lp8788_charger_get_property(struct power_supply *psy,
+                                       enum power_supply_property psp,
+                                       union power_supply_propval *val)
+{
+       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent);
+       u8 read;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = lp8788_is_charger_detected(pchg);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read);
+               val->intval = LP8788_ISEL_STEP *
+                               (min_t(int, read, LP8788_ISEL_MAX) + 1);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int lp8788_get_battery_status(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       enum lp8788_charging_state state;
+       u8 data;
+       int ret;
+
+       ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
+       if (ret)
+               return ret;
+
+       state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
+       switch (state) {
+       case LP8788_OFF:
+               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               break;
+       case LP8788_PRECHARGE:
+       case LP8788_CC:
+       case LP8788_CV:
+       case LP8788_HIGH_CURRENT:
+               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               break;
+       case LP8788_MAINTENANCE:
+               val->intval = POWER_SUPPLY_STATUS_FULL;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       }
+
+       return 0;
+}
+
+static int lp8788_get_battery_health(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       u8 data;
+       int ret;
+
+       ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
+       if (ret)
+               return ret;
+
+       if (data & LP8788_NO_BATT_M)
+               val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+       else if (data & LP8788_BAD_BATT_M)
+               val->intval = POWER_SUPPLY_HEALTH_DEAD;
+       else
+               val->intval = POWER_SUPPLY_HEALTH_GOOD;
+
+       return 0;
+}
+
+static int lp8788_get_battery_present(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       u8 data;
+       int ret;
+
+       ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
+       if (ret)
+               return ret;
+
+       val->intval = !(data & LP8788_NO_BATT_M);
+       return 0;
+}
+
+static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg,
+                               unsigned int *result)
+{
+       struct iio_channel *channel = pchg->chan[LP8788_VBATT];
+       int scaleint;
+       int scalepart;
+       int ret;
+
+       if (!channel)
+               return -EINVAL;
+
+       ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
+       if (ret != IIO_VAL_INT_PLUS_MICRO)
+               return -EINVAL;
+
+       /* unit: mV */
+       *result = (scaleint + scalepart * 1000000) / 1000;
+
+       return 0;
+}
+
+static int lp8788_get_battery_voltage(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       return lp8788_get_vbatt_adc(pchg, &val->intval);
+}
+
+static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       struct lp8788 *lp = pchg->lp;
+       struct lp8788_charger_platform_data *pdata = pchg->pdata;
+       unsigned int max_vbatt;
+       unsigned int vbatt;
+       enum lp8788_charging_state state;
+       u8 data;
+       int ret;
+
+       if (!pdata)
+               return -EINVAL;
+
+       max_vbatt = pdata->max_vbatt_mv;
+       if (max_vbatt == 0)
+               return -EINVAL;
+
+       ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data);
+       if (ret)
+               return ret;
+
+       state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
+
+       if (state == LP8788_MAINTENANCE) {
+               val->intval = LP8788_MAX_BATT_CAPACITY;
+       } else {
+               ret = lp8788_get_vbatt_adc(pchg, &vbatt);
+               if (ret)
+                       return ret;
+
+               val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt;
+               val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY);
+       }
+
+       return 0;
+}
+
+static int lp8788_get_battery_temperature(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP];
+       int scaleint;
+       int scalepart;
+       int ret;
+
+       if (!channel)
+               return -EINVAL;
+
+       ret = iio_read_channel_scale(channel, &scaleint, &scalepart);
+       if (ret != IIO_VAL_INT_PLUS_MICRO)
+               return -EINVAL;
+
+       /* unit: 0.1 'C */
+       val->intval = (scaleint + scalepart * 1000000) / 100;
+
+       return 0;
+}
+
+static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       u8 read;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read);
+       read &= LP8788_CHG_IBATT_M;
+       val->intval = LP8788_ISEL_STEP *
+                       (min_t(int, read, LP8788_ISEL_MAX) + 1);
+
+       return 0;
+}
+
+static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg,
+                               union power_supply_propval *val)
+{
+       u8 read;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read);
+       read &= LP8788_CHG_VTERM_M;
+       val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read;
+
+       return 0;
+}
+
+static int lp8788_battery_get_property(struct power_supply *psy,
+                                       enum power_supply_property psp,
+                                       union power_supply_propval *val)
+{
+       struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               return lp8788_get_battery_status(pchg, val);
+       case POWER_SUPPLY_PROP_HEALTH:
+               return lp8788_get_battery_health(pchg, val);
+       case POWER_SUPPLY_PROP_PRESENT:
+               return lp8788_get_battery_present(pchg, val);
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               return lp8788_get_battery_voltage(pchg, val);
+       case POWER_SUPPLY_PROP_CAPACITY:
+               return lp8788_get_battery_capacity(pchg, val);
+       case POWER_SUPPLY_PROP_TEMP:
+               return lp8788_get_battery_temperature(pchg, val);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               return lp8788_get_battery_charging_current(pchg, val);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+               return lp8788_get_charging_termination_voltage(pchg, val);
+       default:
+               return -EINVAL;
+       }
+}
+
+static inline bool lp8788_is_valid_charger_register(u8 addr)
+{
+       return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END;
+}
+
+static int lp8788_update_charger_params(struct lp8788_charger *pchg)
+{
+       struct lp8788 *lp = pchg->lp;
+       struct lp8788_charger_platform_data *pdata = pchg->pdata;
+       struct lp8788_chg_param *param;
+       int i;
+       int ret;
+
+       if (!pdata || !pdata->chg_params) {
+               dev_info(lp->dev, "skip updating charger parameters\n");
+               return 0;
+       }
+
+       /* settting charging parameters */
+       for (i = 0; i < pdata->num_chg_params; i++) {
+               param = pdata->chg_params + i;
+
+               if (!param)
+                       continue;
+
+               if (lp8788_is_valid_charger_register(param->addr)) {
+                       ret = lp8788_write_byte(lp, param->addr, param->val);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int lp8788_psy_register(struct platform_device *pdev,
+                               struct lp8788_charger *pchg)
+{
+       pchg->charger.name = LP8788_CHARGER_NAME;
+       pchg->charger.type = POWER_SUPPLY_TYPE_MAINS;
+       pchg->charger.properties = lp8788_charger_prop;
+       pchg->charger.num_properties = ARRAY_SIZE(lp8788_charger_prop);
+       pchg->charger.get_property = lp8788_charger_get_property;
+       pchg->charger.supplied_to = battery_supplied_to;
+       pchg->charger.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+       if (power_supply_register(&pdev->dev, &pchg->charger))
+               return -EPERM;
+
+       pchg->battery.name = LP8788_BATTERY_NAME;
+       pchg->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       pchg->battery.properties = lp8788_battery_prop;
+       pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
+       pchg->battery.get_property = lp8788_battery_get_property;
+
+       if (power_supply_register(&pdev->dev, &pchg->battery))
+               return -EPERM;
+
+       return 0;
+}
+
+static void lp8788_psy_unregister(struct lp8788_charger *pchg)
+{
+       power_supply_unregister(&pchg->battery);
+       power_supply_unregister(&pchg->charger);
+}
+
+static void lp8788_charger_event(struct work_struct *work)
+{
+       struct lp8788_charger *pchg =
+               container_of(work, struct lp8788_charger, charger_work);
+       struct lp8788_charger_platform_data *pdata = pchg->pdata;
+       enum lp8788_charger_event event = lp8788_is_charger_detected(pchg);
+
+       pdata->charger_event(pchg->lp, event);
+}
+
+static bool lp8788_find_irq_id(struct lp8788_charger *pchg, int virq, int *id)
+{
+       bool found;
+       int i;
+
+       for (i = 0; i < pchg->num_irqs; i++) {
+               if (pchg->irqs[i].virq == virq) {
+                       *id = pchg->irqs[i].which;
+                       found = true;
+                       break;
+               }
+       }
+
+       return found;
+}
+
+static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr)
+{
+       struct lp8788_charger *pchg = ptr;
+       struct lp8788_charger_platform_data *pdata = pchg->pdata;
+       int id = -1;
+
+       if (!lp8788_find_irq_id(pchg, virq, &id))
+               return IRQ_NONE;
+
+       switch (id) {
+       case LP8788_INT_CHG_INPUT_STATE:
+       case LP8788_INT_CHG_STATE:
+       case LP8788_INT_EOC:
+       case LP8788_INT_BATT_LOW:
+       case LP8788_INT_NO_BATT:
+               power_supply_changed(&pchg->charger);
+               power_supply_changed(&pchg->battery);
+               break;
+       default:
+               break;
+       }
+
+       /* report charger dectection event if used */
+       if (!pdata)
+               goto irq_handled;
+
+       if (pdata->charger_event && id == LP8788_INT_CHG_INPUT_STATE)
+               schedule_work(&pchg->charger_work);
+
+irq_handled:
+       return IRQ_HANDLED;
+}
+
+static int lp8788_set_irqs(struct platform_device *pdev,
+                       struct lp8788_charger *pchg, const char *name)
+{
+       struct resource *r;
+       struct irq_domain *irqdm = pchg->lp->irqdm;
+       int irq_start;
+       int irq_end;
+       int virq;
+       int nr_irq;
+       int i;
+       int ret;
+
+       /* no error even if no irq resource */
+       r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, name);
+       if (!r)
+               return 0;
+
+       irq_start = r->start;
+       irq_end = r->end;
+
+       for (i = irq_start; i <= irq_end; i++) {
+               nr_irq = pchg->num_irqs;
+
+               virq = irq_create_mapping(irqdm, i);
+               pchg->irqs[nr_irq].virq = virq;
+               pchg->irqs[nr_irq].which = i;
+               pchg->num_irqs++;
+
+               ret = request_threaded_irq(virq, NULL,
+                                       lp8788_charger_irq_thread,
+                                       0, name, pchg);
+               if (ret)
+                       break;
+       }
+
+       if (i <= irq_end)
+               goto err_free_irq;
+
+       return 0;
+
+err_free_irq:
+       for (i = 0; i < pchg->num_irqs; i++)
+               free_irq(pchg->irqs[i].virq, pchg);
+       return ret;
+}
+
+static int lp8788_irq_register(struct platform_device *pdev,
+                               struct lp8788_charger *pchg)
+{
+       struct lp8788 *lp = pchg->lp;
+       const char *name[] = {
+               LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ
+       };
+       int i;
+       int ret;
+
+       INIT_WORK(&pchg->charger_work, lp8788_charger_event);
+       pchg->num_irqs = 0;
+
+       for (i = 0; i < ARRAY_SIZE(name); i++) {
+               ret = lp8788_set_irqs(pdev, pchg, name[i]);
+               if (ret) {
+                       dev_warn(lp->dev, "irq setup failed: %s\n", name[i]);
+                       return ret;
+               }
+       }
+
+       if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) {
+               dev_err(lp->dev, "invalid total number of irqs: %d\n",
+                       pchg->num_irqs);
+               return -EINVAL;
+       }
+
+
+       return 0;
+}
+
+static void lp8788_irq_unregister(struct platform_device *pdev,
+                                 struct lp8788_charger *pchg)
+{
+       int i;
+       int irq;
+
+       for (i = 0; i < pchg->num_irqs; i++) {
+               irq = pchg->irqs[i].virq;
+               if (!irq)
+                       continue;
+
+               free_irq(irq, pchg);
+       }
+}
+
+static void lp8788_setup_adc_channel(struct lp8788_charger *pchg)
+{
+       struct lp8788_charger_platform_data *pdata = pchg->pdata;
+       struct device *dev = pchg->lp->dev;
+       struct iio_channel *chan;
+       enum lp8788_adc_id id;
+       const char *chan_name[LPADC_MAX] = {
+               [LPADC_VBATT_5P5] = "vbatt-5p5",
+               [LPADC_VBATT_6P0] = "vbatt-6p0",
+               [LPADC_VBATT_5P0] = "vbatt-5p0",
+               [LPADC_ADC1]      = "adc1",
+               [LPADC_ADC2]      = "adc2",
+               [LPADC_ADC3]      = "adc3",
+               [LPADC_ADC4]      = "adc4",
+       };
+
+       if (!pdata)
+               return;
+
+       id = pdata->vbatt_adc;
+       switch (id) {
+       case LPADC_VBATT_5P5:
+       case LPADC_VBATT_6P0:
+       case LPADC_VBATT_5P0:
+               chan = iio_channel_get(NULL, chan_name[id]);
+               pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
+               break;
+       default:
+               dev_err(dev, "invalid ADC id for VBATT: %d\n", id);
+               pchg->chan[LP8788_VBATT] = NULL;
+               break;
+       }
+
+       id = pdata->batt_temp_adc;
+       switch (id) {
+       case LPADC_ADC1:
+       case LPADC_ADC2:
+       case LPADC_ADC3:
+       case LPADC_ADC4:
+               chan = iio_channel_get(NULL, chan_name[id]);
+               pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
+               break;
+       default:
+               dev_err(dev, "invalid ADC id for BATT_TEMP : %d\n", id);
+               pchg->chan[LP8788_BATT_TEMP] = NULL;
+               break;
+       }
+}
+
+static void lp8788_release_adc_channel(struct lp8788_charger *pchg)
+{
+       int i;
+
+       for (i = 0; i < LP8788_NUM_CHG_ADC; i++) {
+               if (!pchg->chan[i])
+                       continue;
+
+               iio_channel_release(pchg->chan[i]);
+               pchg->chan[i] = NULL;
+       }
+}
+
+static ssize_t lp8788_show_charger_status(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct lp8788_charger *pchg = dev_get_drvdata(dev);
+       enum lp8788_charging_state state;
+       char *desc[LP8788_MAX_CHG_STATE] = {
+               [LP8788_OFF] = "CHARGER OFF",
+               [LP8788_WARM_UP] = "WARM UP",
+               [LP8788_LOW_INPUT] = "LOW INPUT STATE",
+               [LP8788_PRECHARGE] = "CHARGING - PRECHARGE",
+               [LP8788_CC] = "CHARGING - CC",
+               [LP8788_CV] = "CHARGING - CV",
+               [LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE",
+               [LP8788_BATTERY_FAULT] = "BATTERY FAULT",
+               [LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT",
+               [LP8788_HIGH_CURRENT] = "HIGH CURRENT",
+       };
+       u8 data;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
+       state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
+
+       return scnprintf(buf, LP8788_BUF_SIZE, "%s\n", desc[state]);
+}
+
+static ssize_t lp8788_show_eoc_time(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct lp8788_charger *pchg = dev_get_drvdata(dev);
+       char *stime[] = { "400ms", "5min", "10min", "15min",
+                       "20min", "25min", "30min" "No timeout" };
+       u8 val;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
+       val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S;
+
+       return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Time: %s\n",
+                       stime[val]);
+}
+
+static ssize_t lp8788_show_eoc_level(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct lp8788_charger *pchg = dev_get_drvdata(dev);
+       char *abs_level[] = { "25mA", "49mA", "75mA", "98mA" };
+       char *relative_level[] = { "5%", "10%", "15%", "20%" };
+       char *level;
+       u8 val;
+       u8 mode;
+
+       lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
+
+       mode = val & LP8788_CHG_EOC_MODE_M;
+       val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S;
+       level = mode ? abs_level[val] : relative_level[val];
+
+       return scnprintf(buf, LP8788_BUF_SIZE, "End Of Charge Level: %s\n",
+                       level);
+}
+
+static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL);
+static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL);
+static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL);
+
+static struct attribute *lp8788_charger_attr[] = {
+       &dev_attr_charger_status.attr,
+       &dev_attr_eoc_time.attr,
+       &dev_attr_eoc_level.attr,
+       NULL,
+};
+
+static const struct attribute_group lp8788_attr_group = {
+       .attrs = lp8788_charger_attr,
+};
+
+static __devinit int lp8788_charger_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       struct lp8788_charger *pchg;
+       int ret;
+
+       pchg = devm_kzalloc(lp->dev, sizeof(struct lp8788_charger), GFP_KERNEL);
+       if (!pchg)
+               return -ENOMEM;
+
+       pchg->lp = lp;
+       pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL;
+       platform_set_drvdata(pdev, pchg);
+
+       ret = lp8788_update_charger_params(pchg);
+       if (ret)
+               return ret;
+
+       lp8788_setup_adc_channel(pchg);
+
+       ret = lp8788_psy_register(pdev, pchg);
+       if (ret)
+               return ret;
+
+       ret = sysfs_create_group(&pdev->dev.kobj, &lp8788_attr_group);
+       if (ret) {
+               lp8788_psy_unregister(pchg);
+               return ret;
+       }
+
+       ret = lp8788_irq_register(pdev, pchg);
+       if (ret)
+               dev_warn(lp->dev, "failed to register charger irq: %d\n", ret);
+
+       return 0;
+}
+
+static int __devexit lp8788_charger_remove(struct platform_device *pdev)
+{
+       struct lp8788_charger *pchg = platform_get_drvdata(pdev);
+
+       flush_work(&pchg->charger_work);
+       lp8788_irq_unregister(pdev, pchg);
+       sysfs_remove_group(&pdev->dev.kobj, &lp8788_attr_group);
+       lp8788_psy_unregister(pchg);
+       lp8788_release_adc_channel(pchg);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_charger_driver = {
+       .probe = lp8788_charger_probe,
+       .remove = __devexit_p(lp8788_charger_remove),
+       .driver = {
+               .name = LP8788_DEV_CHARGER,
+               .owner = THIS_MODULE,
+       },
+};
+module_platform_driver(lp8788_charger_driver);
+
+MODULE_DESCRIPTION("TI LP8788 Charger Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-charger");
index 7312f2651647fbb97e64caa56fe03e778f2508a0..7df7c5facc10fee68e4d9a89b0f1e549ea16b3f7 100644 (file)
@@ -281,6 +281,12 @@ static int pda_power_probe(struct platform_device *pdev)
                        goto init_failed;
        }
 
+       ac_draw = regulator_get(dev, "ac_draw");
+       if (IS_ERR(ac_draw)) {
+               dev_dbg(dev, "couldn't get ac_draw regulator\n");
+               ac_draw = NULL;
+       }
+
        update_status();
        update_charger();
 
@@ -309,13 +315,6 @@ static int pda_power_probe(struct platform_device *pdev)
                pda_psy_usb.num_supplicants = pdata->num_supplicants;
        }
 
-       ac_draw = regulator_get(dev, "ac_draw");
-       if (IS_ERR(ac_draw)) {
-               dev_dbg(dev, "couldn't get ac_draw regulator\n");
-               ac_draw = NULL;
-               ret = PTR_ERR(ac_draw);
-       }
-
 #ifdef CONFIG_USB_OTG_UTILS
        transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
        if (!IS_ERR_OR_NULL(transceiver)) {
index 1d96614a17a42d7e8c48d4bb0421301c6ea997ea..395c2cfa16c0bbd3bb200b31f5d2de343e2cd7e3 100644 (file)
@@ -138,6 +138,7 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(health),
        POWER_SUPPLY_ATTR(present),
        POWER_SUPPLY_ATTR(online),
+       POWER_SUPPLY_ATTR(authentic),
        POWER_SUPPLY_ATTR(technology),
        POWER_SUPPLY_ATTR(cycle_count),
        POWER_SUPPLY_ATTR(voltage_max),
@@ -160,7 +161,9 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(charge_avg),
        POWER_SUPPLY_ATTR(charge_counter),
        POWER_SUPPLY_ATTR(constant_charge_current),
+       POWER_SUPPLY_ATTR(constant_charge_current_max),
        POWER_SUPPLY_ATTR(constant_charge_voltage),
+       POWER_SUPPLY_ATTR(constant_charge_voltage_max),
        POWER_SUPPLY_ATTR(energy_full_design),
        POWER_SUPPLY_ATTR(energy_empty_design),
        POWER_SUPPLY_ATTR(energy_full),
index a65e8f54157efe4fe046367e6a28d10fefe0c141..4146596d254b9f8f7c8eaa325fb0714d495edec5 100644 (file)
@@ -759,6 +759,16 @@ static int __devinit sbs_probe(struct i2c_client *client,
        chip->irq = irq;
 
 skip_gpio:
+       /*
+        * Before we register, we need to make sure we can actually talk
+        * to the battery.
+        */
+       rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr);
+       if (rc < 0) {
+               dev_err(&client->dev, "%s: Failed to get device status\n",
+                       __func__);
+               goto exit_psupply;
+       }
 
        rc = power_supply_register(&client->dev, &chip->power_supply);
        if (rc) {
index 332dd0110bda36e6c7c09a60c98d5bed23d5d3cd..a9707c11fbed47a9cc8444b6f0b4812d50fcd8d9 100644 (file)
@@ -80,6 +80,7 @@
 #define CFG_FAULT_IRQ_DCIN_UV                  BIT(2)
 #define CFG_STATUS_IRQ                         0x0d
 #define CFG_STATUS_IRQ_TERMINATION_OR_TAPER    BIT(4)
+#define CFG_STATUS_IRQ_CHARGE_TIMEOUT          BIT(7)
 #define CFG_ADDRESS                            0x0e
 
 /* Command registers */
@@ -96,6 +97,9 @@
 #define IRQSTAT_C_TERMINATION_STAT             BIT(0)
 #define IRQSTAT_C_TERMINATION_IRQ              BIT(1)
 #define IRQSTAT_C_TAPER_IRQ                    BIT(3)
+#define IRQSTAT_D                              0x38
+#define IRQSTAT_D_CHARGE_TIMEOUT_STAT          BIT(2)
+#define IRQSTAT_D_CHARGE_TIMEOUT_IRQ           BIT(3)
 #define IRQSTAT_E                              0x39
 #define IRQSTAT_E_USBIN_UV_STAT                        BIT(0)
 #define IRQSTAT_E_USBIN_UV_IRQ                 BIT(1)
 #define STAT_B                                 0x3c
 #define STAT_C                                 0x3d
 #define STAT_C_CHG_ENABLED                     BIT(0)
+#define STAT_C_HOLDOFF_STAT                    BIT(3)
 #define STAT_C_CHG_MASK                                0x06
 #define STAT_C_CHG_SHIFT                       1
+#define STAT_C_CHG_TERM                                BIT(5)
 #define STAT_C_CHARGER_ERROR                   BIT(6)
 #define STAT_E                                 0x3f
 
@@ -701,7 +707,7 @@ fail:
 static irqreturn_t smb347_interrupt(int irq, void *data)
 {
        struct smb347_charger *smb = data;
-       unsigned int stat_c, irqstat_e, irqstat_c;
+       unsigned int stat_c, irqstat_c, irqstat_d, irqstat_e;
        bool handled = false;
        int ret;
 
@@ -717,6 +723,12 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
                return IRQ_NONE;
        }
 
+       ret = regmap_read(smb->regmap, IRQSTAT_D, &irqstat_d);
+       if (ret < 0) {
+               dev_warn(smb->dev, "reading IRQSTAT_D failed\n");
+               return IRQ_NONE;
+       }
+
        ret = regmap_read(smb->regmap, IRQSTAT_E, &irqstat_e);
        if (ret < 0) {
                dev_warn(smb->dev, "reading IRQSTAT_E failed\n");
@@ -724,13 +736,11 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
        }
 
        /*
-        * If we get charger error we report the error back to user and
-        * disable charging.
+        * If we get charger error we report the error back to user.
+        * If the error is recovered charging will resume again.
         */
        if (stat_c & STAT_C_CHARGER_ERROR) {
-               dev_err(smb->dev, "error in charger, disabling charging\n");
-
-               smb347_charging_disable(smb);
+               dev_err(smb->dev, "charging stopped due to charger error\n");
                power_supply_changed(&smb->battery);
                handled = true;
        }
@@ -743,6 +753,20 @@ static irqreturn_t smb347_interrupt(int irq, void *data)
        if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) {
                if (irqstat_c & IRQSTAT_C_TERMINATION_STAT)
                        power_supply_changed(&smb->battery);
+               dev_dbg(smb->dev, "going to HW maintenance mode\n");
+               handled = true;
+       }
+
+       /*
+        * If we got a charger timeout INT that means the charge
+        * full is not detected with in charge timeout value.
+        */
+       if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_IRQ) {
+               dev_dbg(smb->dev, "total Charge Timeout INT received\n");
+
+               if (irqstat_d & IRQSTAT_D_CHARGE_TIMEOUT_STAT)
+                       dev_warn(smb->dev, "charging stopped due to timeout\n");
+               power_supply_changed(&smb->battery);
                handled = true;
        }
 
@@ -776,6 +800,7 @@ static int smb347_irq_set(struct smb347_charger *smb, bool enable)
         * Enable/disable interrupts for:
         *      - under voltage
         *      - termination current reached
+        *      - charger timeout
         *      - charger error
         */
        ret = regmap_update_bits(smb->regmap, CFG_FAULT_IRQ, 0xff,
@@ -784,7 +809,8 @@ static int smb347_irq_set(struct smb347_charger *smb, bool enable)
                goto fail;
 
        ret = regmap_update_bits(smb->regmap, CFG_STATUS_IRQ, 0xff,
-                       enable ? CFG_STATUS_IRQ_TERMINATION_OR_TAPER : 0);
+                       enable ? (CFG_STATUS_IRQ_TERMINATION_OR_TAPER |
+                                       CFG_STATUS_IRQ_CHARGE_TIMEOUT) : 0);
        if (ret < 0)
                goto fail;
 
@@ -988,6 +1014,51 @@ static enum power_supply_property smb347_usb_properties[] = {
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 };
 
+static int smb347_get_charging_status(struct smb347_charger *smb)
+{
+       int ret, status;
+       unsigned int val;
+
+       if (!smb347_is_ps_online(smb))
+               return POWER_SUPPLY_STATUS_DISCHARGING;
+
+       ret = regmap_read(smb->regmap, STAT_C, &val);
+       if (ret < 0)
+               return ret;
+
+       if ((val & STAT_C_CHARGER_ERROR) ||
+                       (val & STAT_C_HOLDOFF_STAT)) {
+               /*
+                * set to NOT CHARGING upon charger error
+                * or charging has stopped.
+                */
+               status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+       } else {
+               if ((val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT) {
+                       /*
+                        * set to charging if battery is in pre-charge,
+                        * fast charge or taper charging mode.
+                        */
+                       status = POWER_SUPPLY_STATUS_CHARGING;
+               } else if (val & STAT_C_CHG_TERM) {
+                       /*
+                        * set the status to FULL if battery is not in pre
+                        * charge, fast charge or taper charging mode AND
+                        * charging is terminated at least once.
+                        */
+                       status = POWER_SUPPLY_STATUS_FULL;
+               } else {
+                       /*
+                        * in this case no charger error or termination
+                        * occured but charging is not in progress!!!
+                        */
+                       status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               }
+       }
+
+       return status;
+}
+
 static int smb347_battery_get_property(struct power_supply *psy,
                                       enum power_supply_property prop,
                                       union power_supply_propval *val)
@@ -1003,14 +1074,10 @@ static int smb347_battery_get_property(struct power_supply *psy,
 
        switch (prop) {
        case POWER_SUPPLY_PROP_STATUS:
-               if (!smb347_is_ps_online(smb)) {
-                       val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
-                       break;
-               }
-               if (smb347_charging_status(smb))
-                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
-               else
-                       val->intval = POWER_SUPPLY_STATUS_FULL;
+               ret = smb347_get_charging_status(smb);
+               if (ret < 0)
+                       return ret;
+               val->intval = ret;
                break;
 
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
index 15f4d5d8611b554b5750b77a7fee430ba3448ead..f9e70cf08199121b0a9e8b5d4297cf1951106b93 100644 (file)
 #define TWL4030_STS_VBUS       BIT(7)
 #define TWL4030_STS_USB_ID     BIT(2)
 #define TWL4030_BBCHEN         BIT(4)
-#define TWL4030_BBSEL_MASK     0b1100
-#define TWL4030_BBSEL_2V5      0b0000
-#define TWL4030_BBSEL_3V0      0b0100
-#define TWL4030_BBSEL_3V1      0b1000
-#define TWL4030_BBSEL_3V2      0b1100
-#define TWL4030_BBISEL_MASK    0b11
-#define TWL4030_BBISEL_25uA    0b00
-#define TWL4030_BBISEL_150uA   0b01
-#define TWL4030_BBISEL_500uA   0b10
-#define TWL4030_BBISEL_1000uA  0b11
+#define TWL4030_BBSEL_MASK     0x0c
+#define TWL4030_BBSEL_2V5      0x00
+#define TWL4030_BBSEL_3V0      0x04
+#define TWL4030_BBSEL_3V1      0x08
+#define TWL4030_BBSEL_3V2      0x0c
+#define TWL4030_BBISEL_MASK    0x03
+#define TWL4030_BBISEL_25uA    0x00
+#define TWL4030_BBISEL_150uA   0x01
+#define TWL4030_BBISEL_500uA   0x02
+#define TWL4030_BBISEL_1000uA  0x03
 
 /* BCI interrupts */
 #define TWL4030_WOVF           BIT(0) /* Watchdog overflow */
@@ -534,7 +534,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        }
 
        ret = request_threaded_irq(bci->irq_chg, NULL,
-                       twl4030_charger_interrupt, 0, pdev->name, bci);
+                       twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
+                       bci);
        if (ret < 0) {
                dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                        bci->irq_chg, ret);
@@ -542,7 +543,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
        }
 
        ret = request_threaded_irq(bci->irq_bci, NULL,
-                       twl4030_bci_interrupt, 0, pdev->name, bci);
+                       twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
        if (ret < 0) {
                dev_err(&pdev->dev, "could not request irq %d, status %d\n",
                        bci->irq_bci, ret);
index 1245fe1f48c336d588a7d2f42a3263d84a18524d..e128a813dc24c33ea54f476c618cdf9218fa0431 100644 (file)
@@ -212,8 +212,10 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
                props++;        /* POWER_SUPPLY_PROP_VOLTAGE_MIN */
 
        prop = kzalloc(props * sizeof(*prop), GFP_KERNEL);
-       if (!prop)
+       if (!prop) {
+               ret = -ENOMEM;
                goto err3;
+       }
 
        prop[i++] = POWER_SUPPLY_PROP_PRESENT;
        if (pdata->charge_gpio >= 0)
index e771487132f7542123a0e8a669cd8582481ab051..2420d5af05839a8403bf6b0bd00fe07ad9c5ae42 100644 (file)
@@ -306,7 +306,7 @@ int pps_register_cdev(struct pps_device *pps)
        if (err < 0)
                return err;
 
-       pps->id &= MAX_ID_MASK;
+       pps->id &= MAX_IDR_MASK;
        if (pps->id >= PPS_MAX_SOURCES) {
                pr_err("%s: too many PPS sources in the system\n",
                                        pps->info.name);
index 90c5c7357a5041041f518f564849fa98240f50f4..d7c6b83097c1d3e856c8a0da50bdb8c4b6726fcd 100644 (file)
@@ -115,6 +115,15 @@ config  PWM_TIEHRPWM
          To compile this driver as a module, choose M here: the module
          will be called pwm-tiehrpwm.
 
+config PWM_TWL6030
+       tristate "TWL6030 PWM support"
+       depends on TWL4030_CORE
+       help
+         Generic PWM framework driver for TWL6030.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-twl6030.
+
 config PWM_VT8500
        tristate "vt8500 pwm support"
        depends on ARCH_VT8500
index e4b2c898964d4b8d32232efd672a858ae3f74b08..78f123dca30d27336cf086b8b5494f1de3df7162 100644 (file)
@@ -8,4 +8,5 @@ obj-$(CONFIG_PWM_SAMSUNG)       += pwm-samsung.o
 obj-$(CONFIG_PWM_TEGRA)                += pwm-tegra.o
 obj-$(CONFIG_PWM_TIECAP)       += pwm-tiecap.o
 obj-$(CONFIG_PWM_TIEHRPWM)     += pwm-tiehrpwm.o
+obj-$(CONFIG_PWM_TWL6030)      += pwm-twl6030.o
 obj-$(CONFIG_PWM_VT8500)       += pwm-vt8500.o
similarity index 55%
rename from drivers/mfd/twl6030-pwm.c
rename to drivers/pwm/pwm-twl6030.c
index e8fee147678d31e57e4d6c9d7272a998ba95029b..8e6387864ca2c81672b6e565e757d296b01c0566 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pwm.h>
 #include <linux/i2c/twl.h>
 #include <linux/slab.h>
 
 
 #define PWM_CTRL2_MODE_MASK    0x3
 
-struct pwm_device {
-       const char *label;
-       unsigned int pwm_id;
+struct twl6030_pwm_chip {
+       struct pwm_chip chip;
 };
 
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+static int twl6030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       u8 duty_cycle;
        int ret;
+       u8 val;
 
-       if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
-               return -EINVAL;
+       /* Configure PWM */
+       val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
+             PWM_CTRL2_MODE_HW;
 
-       duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
+       ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
+       if (ret < 0) {
+               dev_err(chip->dev, "%s: Failed to configure PWM, Error %d\n",
+                       pwm->label, ret);
+               return ret;
+       }
 
-       ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
+       return 0;
+}
 
+static int twl6030_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                             int duty_ns, int period_ns)
+{
+       u8 duty_cycle = (duty_ns * PWM_CTRL1_MAX) / period_ns;
+       int ret;
+
+       ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, duty_cycle, LED_PWM_CTRL1);
        if (ret < 0) {
                pr_err("%s: Failed to configure PWM, Error %d\n",
                        pwm->label, ret);
                return ret;
        }
+
        return 0;
 }
-EXPORT_SYMBOL(pwm_config);
 
-int pwm_enable(struct pwm_device *pwm)
+static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       u8 val;
        int ret;
+       u8 val;
 
        ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
        if (ret < 0) {
-               pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
+               dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
+                       pwm->label, ret);
                return ret;
        }
 
@@ -88,23 +103,23 @@ int pwm_enable(struct pwm_device *pwm)
 
        ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
        if (ret < 0) {
-               pr_err("%s: Failed to enable PWM, Error %d\n", pwm->label, ret);
+               dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
+                       pwm->label, ret);
                return ret;
        }
 
        twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
        return 0;
 }
-EXPORT_SYMBOL(pwm_enable);
 
-void pwm_disable(struct pwm_device *pwm)
+static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       u8 val;
        int ret;
+       u8 val;
 
        ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, LED_PWM_CTRL2);
        if (ret < 0) {
-               pr_err("%s: Failed to disable PWM, Error %d\n",
+               dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
                        pwm->label, ret);
                return;
        }
@@ -114,52 +129,56 @@ void pwm_disable(struct pwm_device *pwm)
 
        ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
        if (ret < 0) {
-               pr_err("%s: Failed to disable PWM, Error %d\n",
+               dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
                        pwm->label, ret);
-               return;
        }
-       return;
 }
-EXPORT_SYMBOL(pwm_disable);
 
-struct pwm_device *pwm_request(int pwm_id, const char *label)
+static const struct pwm_ops twl6030_pwm_ops = {
+       .request = twl6030_pwm_request,
+       .config = twl6030_pwm_config,
+       .enable = twl6030_pwm_enable,
+       .disable = twl6030_pwm_disable,
+};
+
+static int twl6030_pwm_probe(struct platform_device *pdev)
 {
-       u8 val;
+       struct twl6030_pwm_chip *twl6030;
        int ret;
-       struct pwm_device *pwm;
-
-       pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
-       if (pwm == NULL) {
-               pr_err("%s: failed to allocate memory\n", label);
-               return NULL;
-       }
 
-       pwm->label = label;
-       pwm->pwm_id = pwm_id;
-
-       /* Configure PWM */
-       val = PWM_CTRL2_DIS_PD | PWM_CTRL2_CURR_02 | PWM_CTRL2_SRC_VAC |
-               PWM_CTRL2_MODE_HW;
+       twl6030 = devm_kzalloc(&pdev->dev, sizeof(*twl6030), GFP_KERNEL);
+       if (!twl6030)
+               return -ENOMEM;
 
-       ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, LED_PWM_CTRL2);
+       twl6030->chip.dev = &pdev->dev;
+       twl6030->chip.ops = &twl6030_pwm_ops;
+       twl6030->chip.base = -1;
+       twl6030->chip.npwm = 1;
 
-       if (ret < 0) {
-               pr_err("%s: Failed to configure PWM, Error %d\n",
-                        pwm->label, ret);
+       ret = pwmchip_add(&twl6030->chip);
+       if (ret < 0)
+               return ret;
 
-               kfree(pwm);
-               return NULL;
-       }
+       platform_set_drvdata(pdev, twl6030);
 
-       return pwm;
+       return 0;
 }
-EXPORT_SYMBOL(pwm_request);
 
-void pwm_free(struct pwm_device *pwm)
+static int twl6030_pwm_remove(struct platform_device *pdev)
 {
-       pwm_disable(pwm);
-       kfree(pwm);
+       struct twl6030_pwm_chip *twl6030 = platform_get_drvdata(pdev);
+
+       return pwmchip_remove(&twl6030->chip);
 }
-EXPORT_SYMBOL(pwm_free);
 
+static struct platform_driver twl6030_pwm_driver = {
+       .driver = {
+               .name = "twl6030-pwm",
+       },
+       .probe = twl6030_pwm_probe,
+       .remove = __devexit_p(twl6030_pwm_remove),
+};
+module_platform_driver(twl6030_pwm_driver);
+
+MODULE_ALIAS("platform:twl6030-pwm");
 MODULE_LICENSE("GPL");
index d5e1625bbac2432ff7965a2b70ab438b98aa4959..38ecd8f4d60e28a3eade51815f0b5eb22cb1361d 100644 (file)
@@ -861,6 +861,90 @@ static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv)
                iowrite32(0, priv->regs + TSI721_OBWINLB(i));
 }
 
+/**
+ * tsi721_rio_map_inb_mem -- Mapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ * @rstart: RapidIO space start address.
+ * @size: The mapping region size.
+ * @flags: Flags for mapping. 0 for using default flags.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the inbound mapping
+ * from rstart to lstart.
+ */
+static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart,
+               u64 rstart, u32 size, u32 flags)
+{
+       struct tsi721_device *priv = mport->priv;
+       int i;
+       u32 regval;
+
+       if (!is_power_of_2(size) || size < 0x1000 ||
+           ((u64)lstart & (size - 1)) || (rstart & (size - 1)))
+               return -EINVAL;
+
+       /* Search for free inbound translation window */
+       for (i = 0; i < TSI721_IBWIN_NUM; i++) {
+               regval = ioread32(priv->regs + TSI721_IBWIN_LB(i));
+               if (!(regval & TSI721_IBWIN_LB_WEN))
+                       break;
+       }
+
+       if (i >= TSI721_IBWIN_NUM) {
+               dev_err(&priv->pdev->dev,
+                       "Unable to find free inbound window\n");
+               return -EBUSY;
+       }
+
+       iowrite32(TSI721_IBWIN_SIZE(size) << 8,
+                       priv->regs + TSI721_IBWIN_SZ(i));
+
+       iowrite32(((u64)lstart >> 32), priv->regs + TSI721_IBWIN_TUA(i));
+       iowrite32(((u64)lstart & TSI721_IBWIN_TLA_ADD),
+                 priv->regs + TSI721_IBWIN_TLA(i));
+
+       iowrite32(rstart >> 32, priv->regs + TSI721_IBWIN_UB(i));
+       iowrite32((rstart & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN,
+               priv->regs + TSI721_IBWIN_LB(i));
+       dev_dbg(&priv->pdev->dev,
+               "Configured IBWIN%d mapping (RIO_0x%llx -> PCIe_0x%llx)\n",
+               i, rstart, (unsigned long long)lstart);
+
+       return 0;
+}
+
+/**
+ * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region.
+ * @mport: RapidIO master port
+ * @lstart: Local memory space start address.
+ */
+static void tsi721_rio_unmap_inb_mem(struct rio_mport *mport,
+                               dma_addr_t lstart)
+{
+       struct tsi721_device *priv = mport->priv;
+       int i;
+       u64 addr;
+       u32 regval;
+
+       /* Search for matching active inbound translation window */
+       for (i = 0; i < TSI721_IBWIN_NUM; i++) {
+               regval = ioread32(priv->regs + TSI721_IBWIN_LB(i));
+               if (regval & TSI721_IBWIN_LB_WEN) {
+                       regval = ioread32(priv->regs + TSI721_IBWIN_TUA(i));
+                       addr = (u64)regval << 32;
+                       regval = ioread32(priv->regs + TSI721_IBWIN_TLA(i));
+                       addr |= regval & TSI721_IBWIN_TLA_ADD;
+
+                       if (addr == (u64)lstart) {
+                               iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
+                               break;
+                       }
+               }
+       }
+}
+
 /**
  * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe)
  * translation regions.
@@ -874,7 +958,7 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv)
 
        /* Disable all SR2PC inbound windows */
        for (i = 0; i < TSI721_IBWIN_NUM; i++)
-               iowrite32(0, priv->regs + TSI721_IBWINLB(i));
+               iowrite32(0, priv->regs + TSI721_IBWIN_LB(i));
 }
 
 /**
@@ -2144,6 +2228,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
        ops->add_outb_message = tsi721_add_outb_message;
        ops->add_inb_buffer = tsi721_add_inb_buffer;
        ops->get_inb_message = tsi721_get_inb_message;
+       ops->map_inb = tsi721_rio_map_inb_mem;
+       ops->unmap_inb = tsi721_rio_unmap_inb_mem;
 
        mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
        if (!mport) {
@@ -2165,7 +2251,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
        rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
        rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3);
        rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3);
-       strcpy(mport->name, "Tsi721 mport");
+       snprintf(mport->name, RIO_MAX_MPORT_NAME, "%s(%s)",
+                dev_driver_string(&pdev->dev), dev_name(&pdev->dev));
 
        /* Hook up interrupt handler */
 
@@ -2315,7 +2402,8 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,
 
        /* Configure DMA attributes. */
        if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               if (err) {
                        dev_info(&pdev->dev, "Unable to set DMA mask\n");
                        goto err_unmap_bars;
                }
index 59de9d7be3460a08250bcd197dc858bed0af6dee..7d5b13ba8d4f49fa3a2d7f364940214f3a5ce6bb 100644 (file)
 
 #define TSI721_IBWIN_NUM       8
 
-#define TSI721_IBWINLB(x)      (0x29000 + (x) * 0x20)
-#define TSI721_IBWINLB_BA      0xfffff000
-#define TSI721_IBWINLB_WEN     0x00000001
+#define TSI721_IBWIN_LB(x)     (0x29000 + (x) * 0x20)
+#define TSI721_IBWIN_LB_BA     0xfffff000
+#define TSI721_IBWIN_LB_WEN    0x00000001
+
+#define TSI721_IBWIN_UB(x)     (0x29004 + (x) * 0x20)
+#define TSI721_IBWIN_SZ(x)     (0x29008 + (x) * 0x20)
+#define TSI721_IBWIN_SZ_SIZE   0x00001f00
+#define TSI721_IBWIN_SIZE(size)        (__fls(size) - 12)
+
+#define TSI721_IBWIN_TLA(x)    (0x2900c + (x) * 0x20)
+#define TSI721_IBWIN_TLA_ADD   0xfffff000
+#define TSI721_IBWIN_TUA(x)    (0x29010 + (x) * 0x20)
 
 #define TSI721_SR2PC_GEN_INTE  0x29800
 #define TSI721_SR2PC_PWE       0x29804
index 2bebd791a09243703da9d531eda1cec3ebd0941d..48e9041dd1e29b016b7997c2f8c74726ce90223d 100644 (file)
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <linux/sched.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 
 #include "rio.h"
 
 LIST_HEAD(rio_devices);
-static LIST_HEAD(rio_switches);
-
-static void rio_enum_timeout(unsigned long);
 
 static void rio_init_em(struct rio_dev *rdev);
 
 DEFINE_SPINLOCK(rio_global_list_lock);
 
 static int next_destid = 0;
-static int next_net = 0;
 static int next_comptag = 1;
 
-static struct timer_list rio_enum_timer =
-TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
-
 static int rio_mport_phys_table[] = {
        RIO_EFB_PAR_EP_ID,
        RIO_EFB_PAR_EP_REC_ID,
@@ -60,6 +54,114 @@ static int rio_mport_phys_table[] = {
        -1,
 };
 
+
+/*
+ * rio_destid_alloc - Allocate next available destID for given network
+ * net: RIO network
+ *
+ * Returns next available device destination ID for the specified RIO network.
+ * Marks allocated ID as one in use.
+ * Returns RIO_INVALID_DESTID if new destID is not available.
+ */
+static u16 rio_destid_alloc(struct rio_net *net)
+{
+       int destid;
+       struct rio_id_table *idtab = &net->destid_table;
+
+       spin_lock(&idtab->lock);
+       destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next);
+       if (destid >= idtab->max)
+               destid = find_first_zero_bit(idtab->table, idtab->max);
+
+       if (destid < idtab->max) {
+               idtab->next = destid + 1;
+               if (idtab->next >= idtab->max)
+                       idtab->next = 0;
+               set_bit(destid, idtab->table);
+               destid += idtab->start;
+       } else
+               destid = RIO_INVALID_DESTID;
+
+       spin_unlock(&idtab->lock);
+       return (u16)destid;
+}
+
+/*
+ * rio_destid_reserve - Reserve the specivied destID
+ * net: RIO network
+ * destid: destID to reserve
+ *
+ * Tries to reserve the specified destID.
+ * Returns 0 if successfull.
+ */
+static int rio_destid_reserve(struct rio_net *net, u16 destid)
+{
+       int oldbit;
+       struct rio_id_table *idtab = &net->destid_table;
+
+       destid -= idtab->start;
+       spin_lock(&idtab->lock);
+       oldbit = test_and_set_bit(destid, idtab->table);
+       spin_unlock(&idtab->lock);
+       return oldbit;
+}
+
+/*
+ * rio_destid_free - free a previously allocated destID
+ * net: RIO network
+ * destid: destID to free
+ *
+ * Makes the specified destID available for use.
+ */
+static void rio_destid_free(struct rio_net *net, u16 destid)
+{
+       struct rio_id_table *idtab = &net->destid_table;
+
+       destid -= idtab->start;
+       spin_lock(&idtab->lock);
+       clear_bit(destid, idtab->table);
+       spin_unlock(&idtab->lock);
+}
+
+/*
+ * rio_destid_first - return first destID in use
+ * net: RIO network
+ */
+static u16 rio_destid_first(struct rio_net *net)
+{
+       int destid;
+       struct rio_id_table *idtab = &net->destid_table;
+
+       spin_lock(&idtab->lock);
+       destid = find_first_bit(idtab->table, idtab->max);
+       if (destid >= idtab->max)
+               destid = RIO_INVALID_DESTID;
+       else
+               destid += idtab->start;
+       spin_unlock(&idtab->lock);
+       return (u16)destid;
+}
+
+/*
+ * rio_destid_next - return next destID in use
+ * net: RIO network
+ * from: destination ID from which search shall continue
+ */
+static u16 rio_destid_next(struct rio_net *net, u16 from)
+{
+       int destid;
+       struct rio_id_table *idtab = &net->destid_table;
+
+       spin_lock(&idtab->lock);
+       destid = find_next_bit(idtab->table, idtab->max, from);
+       if (destid >= idtab->max)
+               destid = RIO_INVALID_DESTID;
+       else
+               destid += idtab->start;
+       spin_unlock(&idtab->lock);
+       return (u16)destid;
+}
+
 /**
  * rio_get_device_id - Get the base/extended device id for a device
  * @port: RIO master port
@@ -108,14 +210,15 @@ static void rio_local_set_device_id(struct rio_mport *port, u16 did)
 
 /**
  * rio_clear_locks- Release all host locks and signal enumeration complete
- * @port: Master port to issue transaction
+ * @net: RIO network to run on
  *
  * Marks the component tag CSR on each device with the enumeration
  * complete flag. When complete, it then release the host locks on
  * each device. Returns 0 on success or %-EINVAL on failure.
  */
-static int rio_clear_locks(struct rio_mport *port)
+static int rio_clear_locks(struct rio_net *net)
 {
+       struct rio_mport *port = net->hport;
        struct rio_dev *rdev;
        u32 result;
        int ret = 0;
@@ -130,7 +233,7 @@ static int rio_clear_locks(struct rio_mport *port)
                       result);
                ret = -EINVAL;
        }
-       list_for_each_entry(rdev, &rio_devices, global_list) {
+       list_for_each_entry(rdev, &net->devices, net_list) {
                rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
                                    port->host_deviceid);
                rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result);
@@ -176,10 +279,6 @@ static int rio_enum_host(struct rio_mport *port)
 
        /* Set master port destid and init destid ctr */
        rio_local_set_device_id(port, port->host_deviceid);
-
-       if (next_destid == port->host_deviceid)
-               next_destid++;
-
        return 0;
 }
 
@@ -446,9 +545,8 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
        if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
                if (do_enum) {
                        rio_set_device_id(port, destid, hopcount, next_destid);
-                       rdev->destid = next_destid++;
-                       if (next_destid == port->host_deviceid)
-                               next_destid++;
+                       rdev->destid = next_destid;
+                       next_destid = rio_destid_alloc(net);
                } else
                        rdev->destid = rio_get_device_id(port, destid, hopcount);
 
@@ -483,7 +581,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
                        rswitch->clr_table(port, destid, hopcount,
                                           RIO_GLOBAL_TABLE);
 
-               list_add_tail(&rswitch->node, &rio_switches);
+               list_add_tail(&rswitch->node, &net->switches);
 
        } else {
                if (do_enum)
@@ -747,12 +845,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
 static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                         u8 hopcount, struct rio_dev *prev, int prev_port)
 {
-       int port_num;
-       int cur_destid;
-       int sw_destid;
-       int sw_inport;
        struct rio_dev *rdev;
-       u16 destid;
        u32 regval;
        int tmp;
 
@@ -818,19 +911,26 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                return -1;
 
        if (rio_is_switch(rdev)) {
+               int sw_destid;
+               int cur_destid;
+               int sw_inport;
+               u16 destid;
+               int port_num;
+
                sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
                rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
                                    port->host_deviceid, sw_inport, 0);
                rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
 
-               for (destid = 0; destid < next_destid; destid++) {
-                       if (destid == port->host_deviceid)
-                               continue;
-                       rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
-                                           destid, sw_inport, 0);
-                       rdev->rswitch->route_table[destid] = sw_inport;
+               destid = rio_destid_first(net);
+               while (destid != RIO_INVALID_DESTID && destid < next_destid) {
+                       if (destid != port->host_deviceid) {
+                               rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
+                                                   destid, sw_inport, 0);
+                               rdev->rswitch->route_table[destid] = sw_inport;
+                       }
+                       destid = rio_destid_next(net, destid + 1);
                }
-
                pr_debug(
                    "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
                    rio_name(rdev), rdev->vid, rdev->did,
@@ -839,12 +939,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                for (port_num = 0;
                     port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
                     port_num++) {
-                       /*Enable Input Output Port (transmitter reviever)*/
-                       rio_enable_rx_tx_port(port, 0,
+                       if (sw_inport == port_num) {
+                               rio_enable_rx_tx_port(port, 0,
                                              RIO_ANY_DESTID(port->sys_size),
                                              hopcount, port_num);
-
-                       if (sw_inport == port_num) {
                                rdev->rswitch->port_ok |= (1 << port_num);
                                continue;
                        }
@@ -857,6 +955,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                                pr_debug(
                                    "RIO: scanning device on port %d\n",
                                    port_num);
+                               rio_enable_rx_tx_port(port, 0,
+                                             RIO_ANY_DESTID(port->sys_size),
+                                             hopcount, port_num);
                                rdev->rswitch->port_ok |= (1 << port_num);
                                rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
                                                RIO_ANY_DESTID(port->sys_size),
@@ -867,19 +968,22 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                                        return -1;
 
                                /* Update routing tables */
-                               if (next_destid > cur_destid) {
+                               destid = rio_destid_next(net, cur_destid + 1);
+                               if (destid != RIO_INVALID_DESTID) {
                                        for (destid = cur_destid;
-                                            destid < next_destid; destid++) {
-                                               if (destid == port->host_deviceid)
-                                                       continue;
-                                               rio_route_add_entry(rdev,
+                                            destid < next_destid;) {
+                                               if (destid != port->host_deviceid) {
+                                                       rio_route_add_entry(rdev,
                                                                    RIO_GLOBAL_TABLE,
                                                                    destid,
                                                                    port_num,
                                                                    0);
-                                               rdev->rswitch->
-                                                   route_table[destid] =
-                                                   port_num;
+                                                       rdev->rswitch->
+                                                               route_table[destid] =
+                                                               port_num;
+                                               }
+                                               destid = rio_destid_next(net,
+                                                               destid + 1);
                                        }
                                }
                        } else {
@@ -905,11 +1009,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                rio_init_em(rdev);
 
                /* Check for empty switch */
-               if (next_destid == sw_destid) {
-                       next_destid++;
-                       if (next_destid == port->host_deviceid)
-                               next_destid++;
-               }
+               if (next_destid == sw_destid)
+                       next_destid = rio_destid_alloc(net);
 
                rdev->destid = sw_destid;
        } else
@@ -1047,48 +1148,71 @@ static int rio_mport_is_active(struct rio_mport *port)
 /**
  * rio_alloc_net- Allocate and configure a new RIO network
  * @port: Master port associated with the RIO network
+ * @do_enum: Enumeration/Discovery mode flag
+ * @start: logical minimal start id for new net
  *
  * Allocates a RIO network structure, initializes per-network
  * list heads, and adds the associated master port to the
  * network list of associated master ports. Returns a
  * RIO network pointer on success or %NULL on failure.
  */
-static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
+static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
+                                              int do_enum, u16 start)
 {
        struct rio_net *net;
 
        net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
+       if (net && do_enum) {
+               net->destid_table.table = kzalloc(
+                       BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)) *
+                       sizeof(long),
+                       GFP_KERNEL);
+
+               if (net->destid_table.table == NULL) {
+                       pr_err("RIO: failed to allocate destID table\n");
+                       kfree(net);
+                       net = NULL;
+               } else {
+                       net->destid_table.start = start;
+                       net->destid_table.next = 0;
+                       net->destid_table.max =
+                                       RIO_MAX_ROUTE_ENTRIES(port->sys_size);
+                       spin_lock_init(&net->destid_table.lock);
+               }
+       }
+
        if (net) {
                INIT_LIST_HEAD(&net->node);
                INIT_LIST_HEAD(&net->devices);
+               INIT_LIST_HEAD(&net->switches);
                INIT_LIST_HEAD(&net->mports);
                list_add_tail(&port->nnode, &net->mports);
                net->hport = port;
-               net->id = next_net++;
+               net->id = port->id;
        }
        return net;
 }
 
 /**
  * rio_update_route_tables- Updates route tables in switches
- * @port: Master port associated with the RIO network
+ * @net: RIO network to run update on
  *
  * For each enumerated device, ensure that each switch in a system
  * has correct routing entries. Add routes for devices that where
  * unknown dirung the first enumeration pass through the switch.
  */
-static void rio_update_route_tables(struct rio_mport *port)
+static void rio_update_route_tables(struct rio_net *net)
 {
        struct rio_dev *rdev, *swrdev;
        struct rio_switch *rswitch;
        u8 sport;
        u16 destid;
 
-       list_for_each_entry(rdev, &rio_devices, global_list) {
+       list_for_each_entry(rdev, &net->devices, net_list) {
 
                destid = rdev->destid;
 
-               list_for_each_entry(rswitch, &rio_switches, node) {
+               list_for_each_entry(rswitch, &net->switches, node) {
 
                        if (rio_is_switch(rdev) && (rdev->rswitch == rswitch))
                                continue;
@@ -1166,12 +1290,16 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
 
        /* If master port has an active link, allocate net and enum peers */
        if (rio_mport_is_active(mport)) {
-               if (!(net = rio_alloc_net(mport))) {
+               net = rio_alloc_net(mport, 1, 0);
+               if (!net) {
                        printk(KERN_ERR "RIO: failed to allocate new net\n");
                        rc = -ENOMEM;
                        goto out;
                }
 
+               /* reserve mport destID in new net */
+               rio_destid_reserve(net, mport->host_deviceid);
+
                /* Enable Input Output Port (transmitter reviever) */
                rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
 
@@ -1179,17 +1307,21 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
                rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR,
                                          next_comptag++);
 
+               next_destid = rio_destid_alloc(net);
+
                if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
                        /* A higher priority host won enumeration, bail. */
                        printk(KERN_INFO
                               "RIO: master port %d device has lost enumeration to a remote host\n",
                               mport->id);
-                       rio_clear_locks(mport);
+                       rio_clear_locks(net);
                        rc = -EBUSY;
                        goto out;
                }
-               rio_update_route_tables(mport);
-               rio_clear_locks(mport);
+               /* free the last allocated destID (unused) */
+               rio_destid_free(net, next_destid);
+               rio_update_route_tables(net);
+               rio_clear_locks(net);
                rio_pw_enable(mport, 1);
        } else {
                printk(KERN_INFO "RIO: master port %d link inactive\n",
@@ -1203,47 +1335,34 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
 
 /**
  * rio_build_route_tables- Generate route tables from switch route entries
+ * @net: RIO network to run route tables scan on
  *
  * For each switch device, generate a route table by copying existing
  * route entries from the switch.
  */
-static void rio_build_route_tables(void)
+static void rio_build_route_tables(struct rio_net *net)
 {
+       struct rio_switch *rswitch;
        struct rio_dev *rdev;
        int i;
        u8 sport;
 
-       list_for_each_entry(rdev, &rio_devices, global_list)
-               if (rio_is_switch(rdev)) {
-                       rio_lock_device(rdev->net->hport, rdev->destid,
-                                       rdev->hopcount, 1000);
-                       for (i = 0;
-                            i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
-                            i++) {
-                               if (rio_route_get_entry(rdev,
-                                       RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
-                                       continue;
-                               rdev->rswitch->route_table[i] = sport;
-                       }
+       list_for_each_entry(rswitch, &net->switches, node) {
+               rdev = sw_to_rio_dev(rswitch);
 
-                       rio_unlock_device(rdev->net->hport,
-                                         rdev->destid,
-                                         rdev->hopcount);
+               rio_lock_device(net->hport, rdev->destid,
+                               rdev->hopcount, 1000);
+               for (i = 0;
+                    i < RIO_MAX_ROUTE_ENTRIES(net->hport->sys_size);
+                    i++) {
+                       if (rio_route_get_entry(rdev, RIO_GLOBAL_TABLE,
+                                               i, &sport, 0) < 0)
+                               continue;
+                       rswitch->route_table[i] = sport;
                }
-}
 
-/**
- * rio_enum_timeout- Signal that enumeration timed out
- * @data: Address of timeout flag.
- *
- * When the enumeration complete timer expires, set a flag that
- * signals to the discovery process that enumeration did not
- * complete in a sane amount of time.
- */
-static void rio_enum_timeout(unsigned long data)
-{
-       /* Enumeration timed out, set flag */
-       *(int *)data = 1;
+               rio_unlock_device(net->hport, rdev->destid, rdev->hopcount);
+       }
 }
 
 /**
@@ -1259,34 +1378,33 @@ static void rio_enum_timeout(unsigned long data)
 int __devinit rio_disc_mport(struct rio_mport *mport)
 {
        struct rio_net *net = NULL;
-       int enum_timeout_flag = 0;
+       unsigned long to_end;
 
        printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id,
               mport->name);
 
        /* If master port has an active link, allocate net and discover peers */
        if (rio_mport_is_active(mport)) {
-               if (!(net = rio_alloc_net(mport))) {
-                       printk(KERN_ERR "RIO: Failed to allocate new net\n");
-                       goto bail;
-               }
+               pr_debug("RIO: wait for enumeration to complete...\n");
 
-               pr_debug("RIO: wait for enumeration complete...");
-
-               rio_enum_timer.expires =
-                   jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
-               rio_enum_timer.data = (unsigned long)&enum_timeout_flag;
-               add_timer(&rio_enum_timer);
-               while (!rio_enum_complete(mport)) {
-                       mdelay(1);
-                       if (enum_timeout_flag) {
-                               del_timer_sync(&rio_enum_timer);
-                               goto timeout;
-                       }
+               to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
+               while (time_before(jiffies, to_end)) {
+                       if (rio_enum_complete(mport))
+                               goto enum_done;
+                       schedule_timeout_uninterruptible(msecs_to_jiffies(10));
                }
-               del_timer_sync(&rio_enum_timer);
 
-               pr_debug("done\n");
+               pr_debug("RIO: discovery timeout on mport %d %s\n",
+                        mport->id, mport->name);
+               goto bail;
+enum_done:
+               pr_debug("RIO: ... enumeration done\n");
+
+               net = rio_alloc_net(mport, 0, 0);
+               if (!net) {
+                       printk(KERN_ERR "RIO: Failed to allocate new net\n");
+                       goto bail;
+               }
 
                /* Read DestID assigned by enumerator */
                rio_local_read_config_32(mport, RIO_DID_CSR,
@@ -1302,13 +1420,10 @@ int __devinit rio_disc_mport(struct rio_mport *mport)
                        goto bail;
                }
 
-               rio_build_route_tables();
+               rio_build_route_tables(net);
        }
 
        return 0;
-
-      timeout:
-       pr_debug("timeout\n");
-      bail:
+bail:
        return -EBUSY;
 }
index c40665a4fa3347a8b9bdb1edd12c4b48eacb5d43..d4bd69013c501010fc5ba76ce58c949d46708a9e 100644 (file)
@@ -33,6 +33,7 @@
 
 static LIST_HEAD(rio_mports);
 static unsigned char next_portid;
+static DEFINE_SPINLOCK(rio_mmap_lock);
 
 /**
  * rio_local_get_device_id - Get the base/extended device id for a port
@@ -397,6 +398,49 @@ int rio_release_inb_pwrite(struct rio_dev *rdev)
 }
 EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
 
+/**
+ * rio_map_inb_region -- Map inbound memory region.
+ * @mport: Master port.
+ * @lstart: physical address of memory region to be mapped
+ * @rbase: RIO base address assigned to this window
+ * @size: Size of the memory region
+ * @rflags: Flags for mapping.
+ *
+ * Return: 0 -- Success.
+ *
+ * This function will create the mapping from RIO space to local memory.
+ */
+int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local,
+                       u64 rbase, u32 size, u32 rflags)
+{
+       int rc = 0;
+       unsigned long flags;
+
+       if (!mport->ops->map_inb)
+               return -1;
+       spin_lock_irqsave(&rio_mmap_lock, flags);
+       rc = mport->ops->map_inb(mport, local, rbase, size, rflags);
+       spin_unlock_irqrestore(&rio_mmap_lock, flags);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(rio_map_inb_region);
+
+/**
+ * rio_unmap_inb_region -- Unmap the inbound memory region
+ * @mport: Master port
+ * @lstart: physical address of memory region to be unmapped
+ */
+void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart)
+{
+       unsigned long flags;
+       if (!mport->ops->unmap_inb)
+               return;
+       spin_lock_irqsave(&rio_mmap_lock, flags);
+       mport->ops->unmap_inb(mport, lstart);
+       spin_unlock_irqrestore(&rio_mmap_lock, flags);
+}
+EXPORT_SYMBOL_GPL(rio_unmap_inb_region);
+
 /**
  * rio_mport_get_physefb - Helper function that returns register offset
  *                      for Physical Layer Extended Features Block.
@@ -1216,15 +1260,62 @@ static int __devinit rio_init(void)
        return 0;
 }
 
+static struct workqueue_struct *rio_wq;
+
+struct rio_disc_work {
+       struct work_struct      work;
+       struct rio_mport        *mport;
+};
+
+static void __devinit disc_work_handler(struct work_struct *_work)
+{
+       struct rio_disc_work *work;
+
+       work = container_of(_work, struct rio_disc_work, work);
+       pr_debug("RIO: discovery work for mport %d %s\n",
+                work->mport->id, work->mport->name);
+       rio_disc_mport(work->mport);
+
+       kfree(work);
+}
+
 int __devinit rio_init_mports(void)
 {
        struct rio_mport *port;
+       struct rio_disc_work *work;
+       int no_disc = 0;
 
        list_for_each_entry(port, &rio_mports, node) {
                if (port->host_deviceid >= 0)
                        rio_enum_mport(port);
-               else
-                       rio_disc_mport(port);
+               else if (!no_disc) {
+                       if (!rio_wq) {
+                               rio_wq = alloc_workqueue("riodisc", 0, 0);
+                               if (!rio_wq) {
+                                       pr_err("RIO: unable allocate rio_wq\n");
+                                       no_disc = 1;
+                                       continue;
+                               }
+                       }
+
+                       work = kzalloc(sizeof *work, GFP_KERNEL);
+                       if (!work) {
+                               pr_err("RIO: no memory for work struct\n");
+                               no_disc = 1;
+                               continue;
+                       }
+
+                       work->mport = port;
+                       INIT_WORK(&work->work, disc_work_handler);
+                       queue_work(rio_wq, &work->work);
+               }
+       }
+
+       if (rio_wq) {
+               pr_debug("RIO: flush discovery workqueue\n");
+               flush_workqueue(rio_wq);
+               pr_debug("RIO: flush discovery workqueue finished\n");
+               destroy_workqueue(rio_wq);
        }
 
        rio_init();
index c3482b954cb7540c0392f66ddb330ef92c300e2a..1c5ab0172ea282c73b0835d07be67e4172a8a6af 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
@@ -23,6 +25,7 @@ struct pm8607_regulator_info {
        struct pm860x_chip      *chip;
        struct regulator_dev    *regulator;
        struct i2c_client       *i2c;
+       struct i2c_client       *i2c_8606;
 
        unsigned int    *vol_table;
        unsigned int    *vol_suspend;
@@ -242,6 +245,35 @@ static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
        return ret;
 }
 
+static int pm8606_preg_enable(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+
+       return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
+                              1 << rdev->desc->enable_mask, 0);
+}
+
+static int pm8606_preg_disable(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+
+       return pm860x_set_bits(info->i2c, rdev->desc->enable_reg,
+                              1 << rdev->desc->enable_mask,
+                              1 << rdev->desc->enable_mask);
+}
+
+static int pm8606_preg_is_enabled(struct regulator_dev *rdev)
+{
+       struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+       int ret;
+
+       ret = pm860x_reg_read(info->i2c, rdev->desc->enable_reg);
+       if (ret < 0)
+               return ret;
+
+       return !((unsigned char)ret & (1 << rdev->desc->enable_mask));
+}
+
 static struct regulator_ops pm8607_regulator_ops = {
        .list_voltage   = pm8607_list_voltage,
        .set_voltage_sel = pm8607_set_voltage_sel,
@@ -251,6 +283,25 @@ static struct regulator_ops pm8607_regulator_ops = {
        .is_enabled = regulator_is_enabled_regmap,
 };
 
+static struct regulator_ops pm8606_preg_ops = {
+       .enable         = pm8606_preg_enable,
+       .disable        = pm8606_preg_disable,
+       .is_enabled     = pm8606_preg_is_enabled,
+};
+
+#define PM8606_PREG(ereg, ebit)                                                \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = "PREG",                                       \
+               .ops    = &pm8606_preg_ops,                             \
+               .type   = REGULATOR_CURRENT,                            \
+               .id     = PM8606_ID_PREG,                               \
+               .owner  = THIS_MODULE,                                  \
+               .enable_reg = PM8606_##ereg,                            \
+               .enable_mask = (ebit),                                  \
+       },                                                              \
+}
+
 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit)                       \
 {                                                                      \
        .desc   = {                                                     \
@@ -311,6 +362,38 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
        PM8607_LDO(14,        LDO14, 0, SUPPLIES_EN12, 6),
 };
 
+static struct pm8607_regulator_info pm8606_regulator_info[] = {
+       PM8606_PREG(PREREGULATORB, 5),
+};
+
+#ifdef CONFIG_OF
+static int pm8607_regulator_dt_init(struct platform_device *pdev,
+                                   struct pm8607_regulator_info *info,
+                                   struct regulator_config *config)
+{
+       struct device_node *nproot, *np;
+       nproot = pdev->dev.parent->of_node;
+       if (!nproot)
+               return -ENODEV;
+       nproot = of_find_node_by_name(nproot, "regulators");
+       if (!nproot) {
+               dev_err(&pdev->dev, "failed to find regulators node\n");
+               return -ENODEV;
+       }
+       for_each_child_of_node(nproot, np) {
+               if (!of_node_cmp(np->name, info->desc.name)) {
+                       config->init_data =
+                               of_get_regulator_init_data(&pdev->dev, np);
+                       config->of_node = np;
+                       break;
+               }
+       }
+       return 0;
+}
+#else
+#define pm8607_regulator_dt_init(x, y, z)      (-1)
+#endif
+
 static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -320,22 +403,28 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
        struct resource *res;
        int i;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource!\n");
-               return -EINVAL;
-       }
-       for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
-               info = &pm8607_regulator_info[i];
-               if (info->desc.id == res->start)
-                       break;
-       }
-       if (i == ARRAY_SIZE(pm8607_regulator_info)) {
-               dev_err(&pdev->dev, "Failed to find regulator %llu\n",
-                       (unsigned long long)res->start);
-               return -EINVAL;
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+       if (res) {
+               /* There're resources in 88PM8607 regulator driver */
+               for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
+                       info = &pm8607_regulator_info[i];
+                       if (info->desc.vsel_reg == res->start)
+                               break;
+               }
+               if (i == ARRAY_SIZE(pm8607_regulator_info)) {
+                       dev_err(&pdev->dev, "Failed to find regulator %llu\n",
+                               (unsigned long long)res->start);
+                       return -EINVAL;
+               }
+       } else {
+               /* There's no resource in 88PM8606 PREG regulator driver */
+               info = &pm8606_regulator_info[0];
+               /* i is used to check regulator ID */
+               i = -1;
        }
        info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+       info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
+                       chip->client;
        info->chip = chip;
 
        /* check DVC ramp slope double */
@@ -343,15 +432,17 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
                info->slope_double = 1;
 
        config.dev = &pdev->dev;
-       config.init_data = pdata;
        config.driver_data = info;
 
+       if (pm8607_regulator_dt_init(pdev, info, &config))
+               if (pdata)
+                       config.init_data = pdata;
+
        if (chip->id == CHIP_PM8607)
                config.regmap = chip->regmap;
        else
                config.regmap = chip->regmap_companion;
 
-       /* replace driver_data with info */
        info->regulator = regulator_register(&info->desc, &config);
        if (IS_ERR(info->regulator)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -372,6 +463,18 @@ static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
+static struct platform_device_id pm8607_regulator_driver_ids[] = {
+       {
+               .name   = "88pm860x-regulator",
+               .driver_data    = 0,
+       }, {
+               .name   = "88pm860x-preg",
+               .driver_data    = 0,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
+
 static struct platform_driver pm8607_regulator_driver = {
        .driver         = {
                .name   = "88pm860x-regulator",
@@ -379,6 +482,7 @@ static struct platform_driver pm8607_regulator_driver = {
        },
        .probe          = pm8607_regulator_probe,
        .remove         = __devexit_p(pm8607_regulator_remove),
+       .id_table       = pm8607_regulator_driver_ids,
 };
 
 static int __init pm8607_regulator_init(void)
index e98a5e7827df86d9b6b691adb07134f26e2a2f0e..67d47b59a66d878c9188afaaa62b92f255d657bb 100644 (file)
@@ -122,7 +122,7 @@ config REGULATOR_FAN53555
 
 config REGULATOR_ANATOP
        tristate "Freescale i.MX on-chip ANATOP LDO regulators"
-       depends on MFD_ANATOP
+       depends on MFD_SYSCON
        help
          Say y here to support Freescale i.MX on-chip ANATOP LDOs
          regulators. It is recommended that this option be
index 65ad2b36ce364c39b965fb202794a019b8673ae3..df4ad8927f0ce88257cb70db8fdfed535f8d17f2 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/mfd/abx500.h>
 
 /* LDO registers and some handy masking definitions for AB3100 */
index ce0fe72a428e811418aa8190c7f534ce1009d5a4..1af97686f4448864d92b7dbfdf58e79c883edbb8 100644 (file)
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/mfd/syscon.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/mfd/anatop.h>
+#include <linux/regmap.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 
 struct anatop_regulator {
        const char *name;
        u32 control_reg;
-       struct anatop *mfd;
+       struct regmap *anatop;
        int vol_bit_shift;
        int vol_bit_width;
        int min_bit_val;
@@ -43,7 +44,8 @@ struct anatop_regulator {
        struct regulator_init_data *initdata;
 };
 
-static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
+static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
+                                       unsigned selector)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
        u32 val, mask;
@@ -56,12 +58,13 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
        mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
                anatop_reg->vol_bit_shift;
        val <<= anatop_reg->vol_bit_shift;
-       anatop_write_reg(anatop_reg->mfd, anatop_reg->control_reg, val, mask);
+       regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
+                               mask, val);
 
        return 0;
 }
 
-static int anatop_get_voltage_sel(struct regulator_dev *reg)
+static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
        u32 val, mask;
@@ -69,7 +72,7 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg);
+       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
        mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
                anatop_reg->vol_bit_shift;
        val = (val & mask) >> anatop_reg->vol_bit_shift;
@@ -78,8 +81,8 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
 }
 
 static struct regulator_ops anatop_rops = {
-       .set_voltage_sel = anatop_set_voltage_sel,
-       .get_voltage_sel = anatop_get_voltage_sel,
+       .set_voltage_sel = anatop_regmap_set_voltage_sel,
+       .get_voltage_sel = anatop_regmap_get_voltage_sel,
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
 };
@@ -88,11 +91,11 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
+       struct device_node *anatop_np;
        struct regulator_desc *rdesc;
        struct regulator_dev *rdev;
        struct anatop_regulator *sreg;
        struct regulator_init_data *initdata;
-       struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
        int ret = 0;
 
@@ -109,7 +112,15 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
        rdesc->ops = &anatop_rops;
        rdesc->type = REGULATOR_VOLTAGE;
        rdesc->owner = THIS_MODULE;
-       sreg->mfd = anatopmfd;
+
+       anatop_np = of_get_parent(np);
+       if (!anatop_np)
+               return -ENODEV;
+       sreg->anatop = syscon_node_to_regmap(anatop_np);
+       of_node_put(anatop_np);
+       if (IS_ERR(sreg->anatop))
+               return PTR_ERR(sreg->anatop);
+
        ret = of_property_read_u32(np, "anatop-reg-offset",
                                   &sreg->control_reg);
        if (ret) {
index 43dc97ec3932bb5e51c2851c72c53f996fedb383..9bb0be37495f417d65728720f2d13217d51962d5 100644 (file)
@@ -214,37 +214,36 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static struct max8925_regulator_info * __devinit find_regulator_info(int id)
-{
-       struct max8925_regulator_info *ri;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
-               ri = &max8925_regulator_info[i];
-               if (ri->desc.id == id)
-                       return ri;
-       }
-       return NULL;
-}
-
 static int __devinit max8925_regulator_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct max8925_platform_data *pdata = chip->dev->platform_data;
+       struct regulator_init_data *pdata = pdev->dev.platform_data;
        struct regulator_config config = { };
        struct max8925_regulator_info *ri;
+       struct resource *res;
        struct regulator_dev *rdev;
+       int i;
 
-       ri = find_regulator_info(pdev->id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource!\n");
+               return -EINVAL;
+       }
+       for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
+               ri = &max8925_regulator_info[i];
+               if (ri->vol_reg == res->start)
+                       break;
+       }
+       if (i == ARRAY_SIZE(max8925_regulator_info)) {
+               dev_err(&pdev->dev, "Failed to find regulator %llu\n",
+                       (unsigned long long)res->start);
                return -EINVAL;
        }
        ri->i2c = chip->i2c;
        ri->chip = chip;
 
        config.dev = &pdev->dev;
-       config.init_data = pdata->regulator[pdev->id];
+       config.init_data = pdata;
        config.driver_data = ri;
 
        rdev = regulator_register(&ri->desc, &config);
index 2ba7502fa3b2563731893cb327249cf7d33a8433..07aee694ba92abc4c8eab282b519a89dbff69ff1 100644 (file)
@@ -22,6 +22,9 @@
 #include <linux/slab.h>
 #include <linux/regmap.h>
 #include <linux/mfd/palmas.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regulator/of_regulator.h>
 
 struct regs_info {
        char    *name;
@@ -568,10 +571,103 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
        return 0;
 }
 
+static struct of_regulator_match palmas_matches[] = {
+       { .name = "smps12", },
+       { .name = "smps123", },
+       { .name = "smps3", },
+       { .name = "smps45", },
+       { .name = "smps457", },
+       { .name = "smps6", },
+       { .name = "smps7", },
+       { .name = "smps8", },
+       { .name = "smps9", },
+       { .name = "smps10", },
+       { .name = "ldo1", },
+       { .name = "ldo2", },
+       { .name = "ldo3", },
+       { .name = "ldo4", },
+       { .name = "ldo5", },
+       { .name = "ldo6", },
+       { .name = "ldo7", },
+       { .name = "ldo8", },
+       { .name = "ldo9", },
+       { .name = "ldoln", },
+       { .name = "ldousb", },
+};
+
+static void __devinit palmas_dt_to_pdata(struct device *dev,
+               struct device_node *node,
+               struct palmas_pmic_platform_data *pdata)
+{
+       struct device_node *regulators;
+       u32 prop;
+       int idx, ret;
+
+       regulators = of_find_node_by_name(node, "regulators");
+       if (!regulators) {
+               dev_info(dev, "regulator node not found\n");
+               return;
+       }
+
+       ret = of_regulator_match(dev, regulators, palmas_matches,
+                       PALMAS_NUM_REGS);
+       if (ret < 0) {
+               dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+               return;
+       }
+
+       for (idx = 0; idx < PALMAS_NUM_REGS; idx++) {
+               if (!palmas_matches[idx].init_data ||
+                               !palmas_matches[idx].of_node)
+                       continue;
+
+               pdata->reg_data[idx] = palmas_matches[idx].init_data;
+
+               pdata->reg_init[idx] = devm_kzalloc(dev,
+                               sizeof(struct palmas_reg_init), GFP_KERNEL);
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,warm_reset", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->warm_reset = prop;
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,roof_floor", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->roof_floor = prop;
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,mode_sleep", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->mode_sleep = prop;
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,warm_reset", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->warm_reset = prop;
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,tstep", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->tstep = prop;
+
+               ret = of_property_read_u32(palmas_matches[idx].of_node,
+                               "ti,vsel", &prop);
+               if (!ret)
+                       pdata->reg_init[idx]->vsel = prop;
+       }
+
+       ret = of_property_read_u32(node, "ti,ldo6_vibrator", &prop);
+       if (!ret)
+               pdata->ldo6_vibrator = prop;
+}
+
+
 static __devinit int palmas_probe(struct platform_device *pdev)
 {
        struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
        struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
+       struct device_node *node = pdev->dev.of_node;
        struct regulator_dev *rdev;
        struct regulator_config config = { };
        struct palmas_pmic *pmic;
@@ -579,10 +675,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
        int id = 0, ret;
        unsigned int addr, reg;
 
-       if (!pdata)
-               return -EINVAL;
-       if (!pdata->reg_data)
-               return -EINVAL;
+       if (node && !pdata) {
+               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+
+               if (!pdata)
+                       return -ENOMEM;
+
+               palmas_dt_to_pdata(&pdev->dev, node, pdata);
+       }
 
        pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
        if (!pmic)
@@ -661,7 +761,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                pmic->desc[id].owner = THIS_MODULE;
 
                /* Initialise sleep/init values from platform data */
-               if (pdata && pdata->reg_init) {
+               if (pdata) {
                        reg_init = pdata->reg_init[id];
                        if (reg_init) {
                                ret = palmas_smps_init(palmas, id, reg_init);
@@ -685,11 +785,13 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                pmic->range[id] = 1;
                }
 
-               if (pdata && pdata->reg_data)
+               if (pdata)
                        config.init_data = pdata->reg_data[id];
                else
                        config.init_data = NULL;
 
+               config.of_node = palmas_matches[id].of_node;
+
                rdev = regulator_register(&pmic->desc[id], &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
@@ -726,11 +828,13 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                                palmas_regs_info[id].ctrl_addr);
                pmic->desc[id].enable_mask = PALMAS_LDO1_CTRL_MODE_ACTIVE;
 
-               if (pdata && pdata->reg_data)
+               if (pdata)
                        config.init_data = pdata->reg_data[id];
                else
                        config.init_data = NULL;
 
+               config.of_node = palmas_matches[id].of_node;
+
                rdev = regulator_register(&pmic->desc[id], &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
@@ -744,7 +848,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                pmic->rdev[id] = rdev;
 
                /* Initialise sleep/init values from platform data */
-               if (pdata->reg_init) {
+               if (pdata) {
                        reg_init = pdata->reg_init[id];
                        if (reg_init) {
                                ret = palmas_ldo_init(palmas, id, reg_init);
@@ -774,9 +878,15 @@ static int __devexit palmas_remove(struct platform_device *pdev)
        return 0;
 }
 
+static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+       { .compatible = "ti,palmas-pmic", },
+       { /* end */ }
+};
+
 static struct platform_driver palmas_driver = {
        .driver = {
                .name = "palmas-pmic",
+               .of_match_table = of_palmas_match_tbl,
                .owner = THIS_MODULE,
        },
        .probe = palmas_probe,
@@ -799,3 +909,4 @@ MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("Palmas voltage regulator driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:palmas-pmic");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);
index 90cbcc683704b748c032653f5827e2704b95e8f2..782c228a19bd503ccda868ac67f46cce7fbba2e7 100644 (file)
@@ -475,9 +475,9 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 
        dcdc->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
@@ -650,9 +650,9 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
 
        dcdc->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
@@ -794,9 +794,9 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
 
        dcdc->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
index 0d207c297714ed2c7fff51e1e3c06de18c29d361..2646a1902b33fe6287ee4bfea055c5c0d952fba5 100644 (file)
@@ -172,9 +172,9 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
 
        isink->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
index 9af512672be1570871e2576730f792bb58f036cd..c2dc03993dc7011d5ce9c87726cea6f25579d8c3 100644 (file)
@@ -273,9 +273,9 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
 
        ldo->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
@@ -530,9 +530,9 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
 
        ldo->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
@@ -687,9 +687,9 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
 
        ldo->wm831x = wm831x;
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource\n");
+               dev_err(&pdev->dev, "No REG resource\n");
                ret = -EINVAL;
                goto err;
        }
index 3541b4492f644efa200509e09531b3e0a383bbe6..e7a4780e93db4fb8ab9c3134debc960930cd6906 100644 (file)
@@ -84,6 +84,9 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
        if (id >= ARRAY_SIZE(rvdev->vring))
                return ERR_PTR(-EINVAL);
 
+       if (!name)
+               return NULL;
+
        ret = rproc_alloc_vring(rvdev, id);
        if (ret)
                return ERR_PTR(ret);
@@ -103,7 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
         * Create the new vq, and tell virtio we're not interested in
         * the 'weak' smp barriers, since we're talking with a real device.
         */
-       vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr,
+       vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr,
                                        rproc_virtio_notify, callback, name);
        if (!vq) {
                dev_err(dev, "vring_new_virtqueue %s failed\n", name);
index 32aead65735adf4389d2708d73babc0635a5e879..2bd911f125710ca74bdaaa0d8fa1933c7e43953f 100644 (file)
@@ -4,7 +4,6 @@ menu "Rpmsg drivers (EXPERIMENTAL)"
 config RPMSG
        tristate
        select VIRTIO
-       select VIRTIO_RING
        depends on EXPERIMENTAL
 
 endmenu
index fabc99a75c6596d2b797e55a59fa7ecd2db49fc8..e069f176a82d0f05c6d6ec94a619ebd164e501c9 100644 (file)
@@ -19,7 +19,6 @@ if RTC_CLASS
 
 config RTC_HCTOSYS
        bool "Set system time from RTC on startup and resume"
-       depends on RTC_CLASS = y
        default y
        help
          If you say yes here, the system time (wall clock) will be set using
@@ -51,7 +50,6 @@ config RTC_HCTOSYS_DEVICE
 
 config RTC_DEBUG
        bool "RTC debug support"
-       depends on RTC_CLASS = y
        help
          Say yes here to enable debugging support in the RTC framework
          and individual RTC drivers.
@@ -61,7 +59,6 @@ comment "RTC interfaces"
 config RTC_INTF_SYSFS
        boolean "/sys/class/rtc/rtcN (sysfs)"
        depends on SYSFS
-       default RTC_CLASS
        help
          Say yes here if you want to use your RTCs using sysfs interfaces,
          /sys/class/rtc/rtc0 through /sys/.../rtcN.
@@ -69,19 +66,19 @@ config RTC_INTF_SYSFS
          If unsure, say Y.
 
 config RTC_INTF_PROC
-       boolean "/proc/driver/rtc (procfs for rtc0)"
+       boolean "/proc/driver/rtc (procfs for rtcN)"
        depends on PROC_FS
-       default RTC_CLASS
        help
-         Say yes here if you want to use your first RTC through the proc
-         interface, /proc/driver/rtc. Other RTCs will not be available
-         through that API.
+         Say yes here if you want to use your system clock RTC through
+         the proc interface, /proc/driver/rtc.
+         Other RTCs will not be available through that API.
+         If there is no RTC for the system clock, then the first RTC(rtc0)
+         is used by default.
 
          If unsure, say Y.
 
 config RTC_INTF_DEV
        boolean "/dev/rtcN (character devices)"
-       default RTC_CLASS
        help
          Say yes here if you want to use your RTCs using the /dev
          interfaces, which "udev" sets up as /dev/rtc0 through
@@ -127,7 +124,7 @@ if I2C
 
 config RTC_DRV_88PM860X
        tristate "Marvell 88PM860x"
-       depends on RTC_CLASS && I2C && MFD_88PM860X
+       depends on I2C && MFD_88PM860X
        help
          If you say yes here you get support for RTC function in Marvell
          88PM860x chips.
@@ -137,7 +134,7 @@ config RTC_DRV_88PM860X
 
 config RTC_DRV_88PM80X
        tristate "Marvell 88PM80x"
-       depends on RTC_CLASS && I2C && MFD_88PM800
+       depends on I2C && MFD_88PM800
        help
          If you say yes here you get support for RTC function in Marvell
          88PM80x chips.
@@ -165,7 +162,7 @@ config RTC_DRV_DS1307
 
 config RTC_DRV_DS1374
        tristate "Dallas/Maxim DS1374"
-       depends on RTC_CLASS && I2C
+       depends on I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1374 real-time clock chips. If an interrupt is associated
@@ -185,7 +182,7 @@ config RTC_DRV_DS1672
 
 config RTC_DRV_DS3232
        tristate "Dallas/Maxim DS3232"
-       depends on RTC_CLASS && I2C
+       depends on I2C
        help
          If you say yes here you get support for Dallas Semiconductor
          DS3232 real-time clock chips. If an interrupt is associated
@@ -203,6 +200,16 @@ config RTC_DRV_MAX6900
          This driver can also be built as a module. If so, the module
          will be called rtc-max6900.
 
+config RTC_DRV_MAX8907
+       tristate "Maxim MAX8907"
+       depends on MFD_MAX8907
+       help
+         If you say yes here you will get support for the
+         RTC of Maxim MAX8907 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-max8907.
+
 config RTC_DRV_MAX8925
        tristate "Maxim MAX8925"
        depends on MFD_MAX8925
@@ -325,7 +332,7 @@ config RTC_DRV_TWL92330
 
 config RTC_DRV_TWL4030
        tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0"
-       depends on RTC_CLASS && TWL4030_CORE
+       depends on TWL4030_CORE
        help
          If you say yes here you get support for the RTC on the
          TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms.
@@ -333,6 +340,26 @@ config RTC_DRV_TWL4030
          This driver can also be built as a module. If so, the module
          will be called rtc-twl.
 
+config RTC_DRV_TPS65910
+       tristate "TI TPS65910 RTC driver"
+       depends on RTC_CLASS && MFD_TPS65910
+       help
+         If you say yes here you get support for the RTC on the
+         TPS65910 chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-tps65910.
+
+config RTC_DRV_RC5T583
+       tristate "RICOH 5T583 RTC driver"
+       depends on MFD_RC5T583
+       help
+         If you say yes here you get support for the RTC on the
+         RICOH 5T583 chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-rc5t583.
+
 config RTC_DRV_S35390A
        tristate "Seiko Instruments S-35390A"
        select BITREVERSE
@@ -538,7 +565,6 @@ config RTC_DRV_DS1302
 
 config RTC_DRV_DS1511
        tristate "Dallas DS1511"
-       depends on RTC_CLASS
        help
          If you say yes here you get support for the
          Dallas DS1511 timekeeping/watchdog chip.
@@ -583,7 +609,6 @@ config RTC_DRV_EFI
 
 config RTC_DRV_STK17TA8
        tristate "Simtek STK17TA8"
-       depends on RTC_CLASS
        help
          If you say yes here you get support for the
          Simtek STK17TA8 timekeeping chip.
@@ -658,6 +683,15 @@ config RTC_DRV_V3020
          This driver can also be built as a module. If so, the module
          will be called rtc-v3020.
 
+config RTC_DRV_DS2404
+       tristate "Dallas DS2404"
+       help
+         If you say yes here you get support for the
+         Dallas DS2404 RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-ds2404.
+
 config RTC_DRV_WM831X
        tristate "Wolfson Microelectronics WM831x RTC"
        depends on MFD_WM831X
@@ -704,6 +738,7 @@ config RTC_DRV_AB3100
 config RTC_DRV_AB8500
        tristate "ST-Ericsson AB8500 RTC"
        depends on AB8500_CORE
+       select RTC_INTF_DEV
        select RTC_INTF_DEV_UIE_EMUL
        help
          Select this to enable the ST-Ericsson AB8500 power management IC RTC
@@ -711,7 +746,7 @@ config RTC_DRV_AB8500
 
 config RTC_DRV_NUC900
        tristate "NUC910/NUC920 RTC driver"
-       depends on RTC_CLASS && ARCH_W90X900
+       depends on ARCH_W90X900
        help
          If you say yes here you get support for the RTC subsystem of the
          NUC910/NUC920 used in embedded systems.
@@ -731,7 +766,6 @@ config RTC_DRV_DAVINCI
 config RTC_DRV_IMXDI
        tristate "Freescale IMX DryIce Real Time Clock"
        depends on SOC_IMX25
-       depends on RTC_CLASS
        help
           Support for Freescale IMX DryIce RTC
 
@@ -791,7 +825,7 @@ config RTC_DRV_SA1100
 
 config RTC_DRV_SH
        tristate "SuperH On-Chip RTC"
-       depends on RTC_CLASS && SUPERH && HAVE_CLK
+       depends on SUPERH && HAVE_CLK
        help
          Say Y here to enable support for the on-chip RTC found in
          most SuperH processors.
@@ -1023,7 +1057,6 @@ config RTC_DRV_MPC5121
 
 config RTC_DRV_JZ4740
        tristate "Ingenic JZ4740 SoC"
-       depends on RTC_CLASS
        depends on MACH_JZ4740
        help
          If you say yes here you get support for the Ingenic JZ4740 SoC RTC
@@ -1053,7 +1086,7 @@ config RTC_DRV_PM8XXX
 
 config RTC_DRV_TEGRA
        tristate "NVIDIA Tegra Internal RTC driver"
-       depends on RTC_CLASS && ARCH_TEGRA
+       depends on ARCH_TEGRA
        help
          If you say yes here you get support for the
          Tegra 200 series internal RTC module.
@@ -1090,7 +1123,6 @@ config RTC_DRV_LOONGSON1
 config RTC_DRV_MXC
        tristate "Freescale MXC Real Time Clock"
        depends on ARCH_MXC
-       depends on RTC_CLASS
        help
           If you say yes here you get support for the Freescale MXC
           RTC module.
@@ -1098,4 +1130,15 @@ config RTC_DRV_MXC
           This driver can also be built as a module, if so, the module
           will be called "rtc-mxc".
 
+config RTC_DRV_SNVS
+       tristate "Freescale SNVS RTC support"
+       depends on HAS_IOMEM
+       depends on OF
+       help
+          If you say yes here you get support for the Freescale SNVS
+          Low Power (LP) RTC module.
+
+          This driver can also be built as a module, if so, the module
+          will be called "rtc-snvs".
+
 endif # RTC_CLASS
index 0d5b2b66f90d4f47f97b3cf88fec79ebb2ff4028..56297f0fd3884fde9d85cd305cd4b16b439053d2 100644 (file)
@@ -43,6 +43,7 @@ obj-$(CONFIG_RTC_DRV_DS1511)  += rtc-ds1511.o
 obj-$(CONFIG_RTC_DRV_DS1553)   += rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)   += rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)   += rtc-ds1742.o
+obj-$(CONFIG_RTC_DRV_DS2404)    += rtc-ds2404.o
 obj-$(CONFIG_RTC_DRV_DS3232)   += rtc-ds3232.o
 obj-$(CONFIG_RTC_DRV_DS3234)   += rtc-ds3234.o
 obj-$(CONFIG_RTC_DRV_EFI)      += rtc-efi.o
@@ -64,6 +65,7 @@ obj-$(CONFIG_RTC_DRV_M48T59)  += rtc-m48t59.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_MXC)      += rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
+obj-$(CONFIG_RTC_DRV_MAX8907)  += rtc-max8907.o
 obj-$(CONFIG_RTC_DRV_MAX8925)  += rtc-max8925.o
 obj-$(CONFIG_RTC_DRV_MAX8998)  += rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
@@ -85,6 +87,7 @@ obj-$(CONFIG_RTC_DRV_PS3)     += rtc-ps3.o
 obj-$(CONFIG_RTC_DRV_PUV3)     += rtc-puv3.o
 obj-$(CONFIG_RTC_DRV_PXA)      += rtc-pxa.o
 obj-$(CONFIG_RTC_DRV_R9701)    += rtc-r9701.o
+obj-$(CONFIG_RTC_DRV_RC5T583)  += rtc-rc5t583.o
 obj-$(CONFIG_RTC_DRV_RP5C01)   += rtc-rp5c01.o
 obj-$(CONFIG_RTC_DRV_RS5C313)  += rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_RS5C348)  += rtc-rs5c348.o
@@ -96,6 +99,7 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
 obj-$(CONFIG_RTC_DRV_S3C)      += rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_SA1100)   += rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
+obj-$(CONFIG_RTC_DRV_SNVS)     += rtc-snvs.o
 obj-$(CONFIG_RTC_DRV_SPEAR)    += rtc-spear.o
 obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
 obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
@@ -105,6 +109,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
 obj-$(CONFIG_RTC_DRV_TEST)     += rtc-test.o
 obj-$(CONFIG_RTC_DRV_TILE)     += rtc-tile.o
 obj-$(CONFIG_RTC_DRV_TWL4030)  += rtc-twl.o
+obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
 obj-$(CONFIG_RTC_DRV_TX4939)   += rtc-tx4939.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_VR41XX)   += rtc-vr41xx.o
index dc4c2748bbc38bfac593cc47a2ff7bac6a34c8fe..f8a0aab218cbcd2777ea93b9e74aa96494e729fe 100644 (file)
@@ -31,8 +31,12 @@ static void rtc_device_release(struct device *dev)
        kfree(rtc);
 }
 
-#if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
+#ifdef CONFIG_RTC_HCTOSYS_DEVICE
+/* Result of the last RTC to system clock attempt. */
+int rtc_hctosys_ret = -ENODEV;
+#endif
 
+#if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
 /*
  * On suspend(), measure the delta between one RTC and the
  * system's wall clock; restore it on resume().
@@ -84,6 +88,7 @@ static int rtc_resume(struct device *dev)
        struct timespec         new_system, new_rtc;
        struct timespec         sleep_time;
 
+       rtc_hctosys_ret = -ENODEV;
        if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
                return 0;
 
@@ -117,6 +122,7 @@ static int rtc_resume(struct device *dev)
 
        if (sleep_time.tv_sec >= 0)
                timekeeping_inject_sleeptime(&sleep_time);
+       rtc_hctosys_ret = 0;
        return 0;
 }
 
@@ -238,6 +244,7 @@ void rtc_device_unregister(struct rtc_device *rtc)
                rtc_proc_del_device(rtc);
                device_unregister(&rtc->dev);
                rtc->ops = NULL;
+               ida_simple_remove(&rtc_ida, rtc->id);
                mutex_unlock(&rtc->ops_lock);
                put_device(&rtc->dev);
        }
index bc90b091f1954faecf087f2094c6094e31606da2..4aa60d74004e41ffdd7be050728f9cf63a7fa48c 100644 (file)
@@ -22,8 +22,6 @@
  * the best guess is to add 0.5s.
  */
 
-int rtc_hctosys_ret = -ENODEV;
-
 static int __init rtc_hctosys(void)
 {
        int err = -ENODEV;
@@ -56,7 +54,7 @@ static int __init rtc_hctosys(void)
 
        rtc_tm_to_time(&tm, &tv.tv_sec);
 
-       do_settimeofday(&tv);
+       err = do_settimeofday(&tv);
 
        dev_info(rtc->dev.parent,
                "setting system clock to "
index feddefc42109b5fe891b82b0c1ed520a6b9e9613..de9e854b326ac9a06b0c2f3fea0c19b9bf78980e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
@@ -284,6 +285,28 @@ out:
 }
 #endif
 
+#ifdef CONFIG_OF
+static int __devinit pm860x_rtc_dt_init(struct platform_device *pdev,
+                                       struct pm860x_rtc_info *info)
+{
+       struct device_node *np = pdev->dev.parent->of_node;
+       int ret;
+       if (!np)
+               return -ENODEV;
+       np = of_find_node_by_name(np, "rtc");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find rtc node\n");
+               return -ENODEV;
+       }
+       ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc);
+       if (ret)
+               info->vrtc = 0;
+       return 0;
+}
+#else
+#define pm860x_rtc_dt_init(x, y)       (-1)
+#endif
+
 static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -294,8 +317,6 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
        int ret;
 
        pdata = pdev->dev.platform_data;
-       if (pdata == NULL)
-               dev_warn(&pdev->dev, "No platform data!\n");
 
        info = kzalloc(sizeof(struct pm860x_rtc_info), GFP_KERNEL);
        if (!info)
@@ -345,9 +366,11 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
                }
        }
        rtc_tm_to_time(&tm, &ticks);
-       if (pdata && pdata->sync) {
-               pdata->sync(ticks);
-               info->sync = pdata->sync;
+       if (pm860x_rtc_dt_init(pdev, info)) {
+               if (pdata && pdata->sync) {
+                       pdata->sync(ticks);
+                       info->sync = pdata->sync;
+               }
        }
 
        info->rtc_dev = rtc_device_register("88pm860x-rtc", &pdev->dev,
@@ -366,10 +389,12 @@ static int __devinit pm860x_rtc_probe(struct platform_device *pdev)
 
 #ifdef VRTC_CALIBRATION
        /* <00> -- 2.7V, <01> -- 2.9V, <10> -- 3.1V, <11> -- 3.3V */
-       if (pdata && pdata->vrtc)
-               info->vrtc = pdata->vrtc & 0x3;
-       else
-               info->vrtc = 1;
+       if (pm860x_rtc_dt_init(pdev, info)) {
+               if (pdata && pdata->vrtc)
+                       info->vrtc = pdata->vrtc & 0x3;
+               else
+                       info->vrtc = 1;
+       }
        pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, MEAS2_VRTC);
 
        /* calibrate VRTC */
index 1dd61f402b040441c99078214017f802050c8fa5..2dfe7a2fb99800d063c8010c57ce3ecaf464b800 100644 (file)
@@ -473,18 +473,7 @@ static struct platform_driver at91_rtc_driver = {
        },
 };
 
-static int __init at91_rtc_init(void)
-{
-       return platform_driver_register(&at91_rtc_driver);
-}
-module_init(at91_rtc_init);
-
-static void __exit at91_rtc_exit(void)
-{
-       platform_driver_unregister(&at91_rtc_driver);
-}
-module_exit(at91_rtc_exit);
-
+module_platform_driver(at91_rtc_driver);
 
 MODULE_AUTHOR("Michel Benoit");
 MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x");
index 76b2156d3c62252c80aec1eacce8fe0684950d75..c8115b83e5ab513d2360adbdb4911352c3cd3187 100644 (file)
@@ -276,8 +276,7 @@ static void coh901331_shutdown(struct platform_device *pdev)
 
        clk_enable(rtap->clk);
        writel(0, rtap->virtbase + COH901331_IRQ_MASK);
-       clk_disable(rtap->clk);
-       clk_unprepare(rtap->clk);
+       clk_disable_unprepare(rtap->clk);
 }
 
 static struct platform_driver coh901331_driver = {
index 7fa67d0df172ca37494ad11b41a5475a72c87d0a..45d65c0b3a85d07ed592b9cb0380e01fe1e2b27a 100644 (file)
@@ -37,8 +37,17 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        unsigned char buf[4];
 
        struct i2c_msg msgs[] = {
-               {client->addr, 0, 1, &addr},    /* setup read ptr */
-               {client->addr, I2C_M_RD, 4, buf},       /* read date */
+               {/* setup read ptr */
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = &addr
+               },
+               {/* read date */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 4,
+                       .buf = buf
+               },
        };
 
        /* read date registers */
@@ -99,8 +108,17 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
        unsigned char addr = DS1672_REG_CONTROL;
 
        struct i2c_msg msgs[] = {
-               {client->addr, 0, 1, &addr},    /* setup read ptr */
-               {client->addr, I2C_M_RD, 1, status},    /* read control */
+               {/* setup read ptr */
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = &addr
+               },
+               {/* read control */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = status
+               },
        };
 
        /* read control register */
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c
new file mode 100644 (file)
index 0000000..5ea9df7
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2012 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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/platform_device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+#include <linux/bcd.h>
+#include <linux/rtc-ds2404.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/io.h>
+
+#define DS2404_STATUS_REG 0x200
+#define DS2404_CONTROL_REG 0x201
+#define DS2404_RTC_REG 0x202
+
+#define DS2404_WRITE_SCRATCHPAD_CMD 0x0f
+#define DS2404_READ_SCRATCHPAD_CMD 0xaa
+#define DS2404_COPY_SCRATCHPAD_CMD 0x55
+#define DS2404_READ_MEMORY_CMD 0xf0
+
+struct ds2404;
+
+struct ds2404_chip_ops {
+       int (*map_io)(struct ds2404 *chip, struct platform_device *pdev,
+                     struct ds2404_platform_data *pdata);
+       void (*unmap_io)(struct ds2404 *chip);
+};
+
+#define DS2404_RST     0
+#define DS2404_CLK     1
+#define DS2404_DQ      2
+
+struct ds2404_gpio {
+       const char *name;
+       unsigned int gpio;
+};
+
+struct ds2404 {
+       struct ds2404_gpio *gpio;
+       struct ds2404_chip_ops *ops;
+       struct rtc_device *rtc;
+};
+
+static struct ds2404_gpio ds2404_gpio[] = {
+       { "RTC RST", 0 },
+       { "RTC CLK", 0 },
+       { "RTC DQ", 0 },
+};
+
+static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev,
+                         struct ds2404_platform_data *pdata)
+{
+       int i, err;
+
+       ds2404_gpio[DS2404_RST].gpio = pdata->gpio_rst;
+       ds2404_gpio[DS2404_CLK].gpio = pdata->gpio_clk;
+       ds2404_gpio[DS2404_DQ].gpio = pdata->gpio_dq;
+
+       for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) {
+               err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name);
+               if (err) {
+                       printk(KERN_ERR "error mapping gpio %s: %d\n",
+                               ds2404_gpio[i].name, err);
+                       goto err_request;
+               }
+               if (i != DS2404_DQ)
+                       gpio_direction_output(ds2404_gpio[i].gpio, 1);
+       }
+
+       chip->gpio = ds2404_gpio;
+       return 0;
+
+err_request:
+       while (--i >= 0)
+               gpio_free(ds2404_gpio[i].gpio);
+       return err;
+}
+
+static void ds2404_gpio_unmap(struct ds2404 *chip)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++)
+               gpio_free(ds2404_gpio[i].gpio);
+}
+
+static struct ds2404_chip_ops ds2404_gpio_ops = {
+       .map_io         = ds2404_gpio_map,
+       .unmap_io       = ds2404_gpio_unmap,
+};
+
+static void ds2404_reset(struct device *dev)
+{
+       gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 0);
+       udelay(1000);
+       gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 1);
+       gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
+       gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 0);
+       udelay(10);
+}
+
+static void ds2404_write_byte(struct device *dev, u8 byte)
+{
+       int i;
+
+       gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 1);
+       for (i = 0; i < 8; i++) {
+               gpio_set_value(ds2404_gpio[DS2404_DQ].gpio, byte & (1 << i));
+               udelay(10);
+               gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1);
+               udelay(10);
+               gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
+               udelay(10);
+       }
+}
+
+static u8 ds2404_read_byte(struct device *dev)
+{
+       int i;
+       u8 ret = 0;
+
+       gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio);
+
+       for (i = 0; i < 8; i++) {
+               gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0);
+               udelay(10);
+               if (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio))
+                       ret |= 1 << i;
+               gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1);
+               udelay(10);
+       }
+       return ret;
+}
+
+static void ds2404_read_memory(struct device *dev, u16 offset,
+                              int length, u8 *out)
+{
+       ds2404_reset(dev);
+       ds2404_write_byte(dev, DS2404_READ_MEMORY_CMD);
+       ds2404_write_byte(dev, offset & 0xff);
+       ds2404_write_byte(dev, (offset >> 8) & 0xff);
+       while (length--)
+               *out++ = ds2404_read_byte(dev);
+}
+
+static void ds2404_write_memory(struct device *dev, u16 offset,
+                               int length, u8 *out)
+{
+       int i;
+       u8 ta01, ta02, es;
+
+       ds2404_reset(dev);
+       ds2404_write_byte(dev, DS2404_WRITE_SCRATCHPAD_CMD);
+       ds2404_write_byte(dev, offset & 0xff);
+       ds2404_write_byte(dev, (offset >> 8) & 0xff);
+
+       for (i = 0; i < length; i++)
+               ds2404_write_byte(dev, out[i]);
+
+       ds2404_reset(dev);
+       ds2404_write_byte(dev, DS2404_READ_SCRATCHPAD_CMD);
+
+       ta01 = ds2404_read_byte(dev);
+       ta02 = ds2404_read_byte(dev);
+       es = ds2404_read_byte(dev);
+
+       for (i = 0; i < length; i++) {
+               if (out[i] != ds2404_read_byte(dev)) {
+                       printk(KERN_ERR "read invalid data\n");
+                       return;
+               }
+       }
+
+       ds2404_reset(dev);
+       ds2404_write_byte(dev, DS2404_COPY_SCRATCHPAD_CMD);
+       ds2404_write_byte(dev, ta01);
+       ds2404_write_byte(dev, ta02);
+       ds2404_write_byte(dev, es);
+
+       gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio);
+       while (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio))
+               ;
+}
+
+static void ds2404_enable_osc(struct device *dev)
+{
+       u8 in[1] = { 0x10 }; /* enable oscillator */
+       ds2404_write_memory(dev, 0x201, 1, in);
+}
+
+static int ds2404_read_time(struct device *dev, struct rtc_time *dt)
+{
+       unsigned long time = 0;
+
+       ds2404_read_memory(dev, 0x203, 4, (u8 *)&time);
+       time = le32_to_cpu(time);
+
+       rtc_time_to_tm(time, dt);
+       return rtc_valid_tm(dt);
+}
+
+static int ds2404_set_mmss(struct device *dev, unsigned long secs)
+{
+       u32 time = cpu_to_le32(secs);
+       ds2404_write_memory(dev, 0x203, 4, (u8 *)&time);
+       return 0;
+}
+
+static const struct rtc_class_ops ds2404_rtc_ops = {
+       .read_time      = ds2404_read_time,
+       .set_mmss       = ds2404_set_mmss,
+};
+
+static int rtc_probe(struct platform_device *pdev)
+{
+       struct ds2404_platform_data *pdata = pdev->dev.platform_data;
+       struct ds2404 *chip;
+       int retval = -EBUSY;
+
+       chip = kzalloc(sizeof(struct ds2404), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->ops = &ds2404_gpio_ops;
+
+       retval = chip->ops->map_io(chip, pdev, pdata);
+       if (retval)
+               goto err_chip;
+
+       dev_info(&pdev->dev, "using GPIOs RST:%d, CLK:%d, DQ:%d\n",
+                chip->gpio[DS2404_RST].gpio, chip->gpio[DS2404_CLK].gpio,
+                chip->gpio[DS2404_DQ].gpio);
+
+       platform_set_drvdata(pdev, chip);
+
+       chip->rtc = rtc_device_register("ds2404",
+                               &pdev->dev, &ds2404_rtc_ops, THIS_MODULE);
+       if (IS_ERR(chip->rtc)) {
+               retval = PTR_ERR(chip->rtc);
+               goto err_io;
+       }
+
+       ds2404_enable_osc(&pdev->dev);
+       return 0;
+
+err_io:
+       chip->ops->unmap_io(chip);
+err_chip:
+       kfree(chip);
+       return retval;
+}
+
+static int rtc_remove(struct platform_device *dev)
+{
+       struct ds2404 *chip = platform_get_drvdata(dev);
+       struct rtc_device *rtc = chip->rtc;
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       chip->ops->unmap_io(chip);
+       kfree(chip);
+
+       return 0;
+}
+
+static struct platform_driver rtc_device_driver = {
+       .probe  = rtc_probe,
+       .remove = rtc_remove,
+       .driver = {
+               .name   = "ds2404",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static __init int ds2404_init(void)
+{
+       return platform_driver_register(&rtc_device_driver);
+}
+
+static __exit void ds2404_exit(void)
+{
+       platform_driver_unregister(&rtc_device_driver);
+}
+
+module_init(ds2404_init);
+module_exit(ds2404_exit);
+
+MODULE_DESCRIPTION("DS2404 RTC");
+MODULE_AUTHOR("Sven Schnelle");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ds2404");
index 0104ea7ebe503e03899468c8482d834a5eabb277..f6c24ce35d3629226f80d055677a6f4097f06406 100644 (file)
@@ -49,8 +49,17 @@ static int em3027_get_time(struct device *dev, struct rtc_time *tm)
        unsigned char buf[7];
 
        struct i2c_msg msgs[] = {
-               {client->addr, 0, 1, &addr},            /* setup read addr */
-               {client->addr, I2C_M_RD, 7, buf},       /* read time/date */
+               {/* setup read addr */
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = &addr
+               },
+               {/* read time/date */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 7,
+                       .buf = buf
+               },
        };
 
        /* read time/date registers */
@@ -76,7 +85,9 @@ static int em3027_set_time(struct device *dev, struct rtc_time *tm)
        unsigned char buf[8];
 
        struct i2c_msg msg = {
-               client->addr, 0, 8, buf,        /* write time/date */
+               .addr = client->addr,
+               .len = 8,
+               .buf = buf,     /* write time/date */
        };
 
        buf[0] = EM3027_REG_WATCH_SEC;
index dd2aeee6c66a05a7df3644f612d9033e9add496b..26c81f233606ebe043360cf349196f5ed7557670 100644 (file)
@@ -68,9 +68,17 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
 {
        u8 reg_addr[1] = { reg };
        struct i2c_msg msgs[2] = {
-               {client->addr, 0, sizeof(reg_addr), reg_addr}
-               ,
-               {client->addr, I2C_M_RD, len, buf}
+               {
+                       .addr = client->addr,
+                       .len = sizeof(reg_addr),
+                       .buf = reg_addr
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = buf
+               }
        };
        int ret;
 
@@ -90,7 +98,11 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
 {
        u8 i2c_buf[ISL1208_REG_USR2 + 2];
        struct i2c_msg msgs[1] = {
-               {client->addr, 0, len + 1, i2c_buf}
+               {
+                       .addr = client->addr,
+                       .len = len + 1,
+                       .buf = i2c_buf
+               }
        };
        int ret;
 
@@ -697,6 +709,7 @@ isl1208_remove(struct i2c_client *client)
 
 static const struct i2c_device_id isl1208_id[] = {
        { "isl1208", 0 },
+       { "isl1218", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, isl1208_id);
index 05ab227eeff725aaa11761990fc520de9b71ce07..1224182d3eabb165892aeb3350c1914bf590c9a1 100644 (file)
@@ -42,7 +42,7 @@ struct jz4740_rtc {
 
        struct rtc_device *rtc;
 
-       unsigned int irq;
+       int irq;
 
        spinlock_t lock;
 };
index 4e0f84af99a720b336aa1a08b48d25259e9e5fb8..b885bcd08908a8f5c84edbc2baa8c19f7aa5c907 100644 (file)
@@ -213,163 +213,14 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
        return m41t80_set_datetime(to_i2c_client(dev), tm);
 }
 
-static int m41t80_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       int rc;
-
-       rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
-       if (rc < 0)
-               goto err;
-
-       if (enabled)
-               rc |= M41T80_ALMON_AFE;
-       else
-               rc &= ~M41T80_ALMON_AFE;
-
-       if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0)
-               goto err;
-
-       return 0;
-err:
-       return -EIO;
-}
-
-static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       u8 wbuf[1 + M41T80_ALARM_REG_SIZE];
-       u8 *buf = &wbuf[1];
-       u8 *reg = buf - M41T80_REG_ALARM_MON;
-       u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
-       struct i2c_msg msgs_in[] = {
-               {
-                       .addr   = client->addr,
-                       .flags  = 0,
-                       .len    = 1,
-                       .buf    = dt_addr,
-               },
-               {
-                       .addr   = client->addr,
-                       .flags  = I2C_M_RD,
-                       .len    = M41T80_ALARM_REG_SIZE,
-                       .buf    = buf,
-               },
-       };
-       struct i2c_msg msgs[] = {
-               {
-                       .addr   = client->addr,
-                       .flags  = 0,
-                       .len    = 1 + M41T80_ALARM_REG_SIZE,
-                       .buf    = wbuf,
-                },
-       };
-
-       if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
-               dev_err(&client->dev, "read error\n");
-               return -EIO;
-       }
-       reg[M41T80_REG_ALARM_MON] &= ~(0x1f | M41T80_ALMON_AFE);
-       reg[M41T80_REG_ALARM_DAY] = 0;
-       reg[M41T80_REG_ALARM_HOUR] &= ~(0x3f | 0x80);
-       reg[M41T80_REG_ALARM_MIN] = 0;
-       reg[M41T80_REG_ALARM_SEC] = 0;
-
-       wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
-       reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
-               bin2bcd(t->time.tm_sec) : 0x80;
-       reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
-               bin2bcd(t->time.tm_min) : 0x80;
-       reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
-               bin2bcd(t->time.tm_hour) : 0x80;
-       reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
-               bin2bcd(t->time.tm_mday) : 0x80;
-       if (t->time.tm_mon >= 0)
-               reg[M41T80_REG_ALARM_MON] |= bin2bcd(t->time.tm_mon + 1);
-       else
-               reg[M41T80_REG_ALARM_DAY] |= 0x40;
-
-       if (i2c_transfer(client->adapter, msgs, 1) != 1) {
-               dev_err(&client->dev, "write error\n");
-               return -EIO;
-       }
-
-       if (t->enabled) {
-               reg[M41T80_REG_ALARM_MON] |= M41T80_ALMON_AFE;
-               if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
-                                             reg[M41T80_REG_ALARM_MON]) < 0) {
-                       dev_err(&client->dev, "write error\n");
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */
-       u8 dt_addr[1] = { M41T80_REG_ALARM_MON };
-       u8 *reg = buf - M41T80_REG_ALARM_MON;
-       struct i2c_msg msgs[] = {
-               {
-                       .addr   = client->addr,
-                       .flags  = 0,
-                       .len    = 1,
-                       .buf    = dt_addr,
-               },
-               {
-                       .addr   = client->addr,
-                       .flags  = I2C_M_RD,
-                       .len    = M41T80_ALARM_REG_SIZE + 1,
-                       .buf    = buf,
-               },
-       };
-
-       if (i2c_transfer(client->adapter, msgs, 2) < 0) {
-               dev_err(&client->dev, "read error\n");
-               return -EIO;
-       }
-       t->time.tm_sec = -1;
-       t->time.tm_min = -1;
-       t->time.tm_hour = -1;
-       t->time.tm_mday = -1;
-       t->time.tm_mon = -1;
-       if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
-               t->time.tm_sec = bcd2bin(reg[M41T80_REG_ALARM_SEC] & 0x7f);
-       if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
-               t->time.tm_min = bcd2bin(reg[M41T80_REG_ALARM_MIN] & 0x7f);
-       if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
-               t->time.tm_hour = bcd2bin(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
-       if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
-               t->time.tm_mday = bcd2bin(reg[M41T80_REG_ALARM_DAY] & 0x3f);
-       if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
-               t->time.tm_mon = bcd2bin(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
-       t->time.tm_year = -1;
-       t->time.tm_wday = -1;
-       t->time.tm_yday = -1;
-       t->time.tm_isdst = -1;
-       t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
-       t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
-       return 0;
-}
-
+/*
+ * XXX - m41t80 alarm functionality is reported broken.
+ * until it is fixed, don't register alarm functions.
+ */
 static struct rtc_class_ops m41t80_rtc_ops = {
        .read_time = m41t80_rtc_read_time,
        .set_time = m41t80_rtc_set_time,
-       /*
-        * XXX - m41t80 alarm functionality is reported broken.
-        * until it is fixed, don't register alarm functions.
-        *
-       .read_alarm = m41t80_rtc_read_alarm,
-       .set_alarm = m41t80_rtc_set_alarm,
-       */
        .proc = m41t80_rtc_proc,
-       /*
-        * See above comment on broken alarm
-        *
-       .alarm_irq_enable = m41t80_rtc_alarm_irq_enable,
-       */
 };
 
 #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c
new file mode 100644 (file)
index 0000000..e094ffa
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * RTC driver for Maxim MAX8907
+ *
+ * Copyright (c) 2011-2012, NVIDIA Corporation.
+ *
+ * Based on drivers/rtc/rtc-max8925.c,
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *
+ * 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/bcd.h>
+#include <linux/i2c.h>
+#include <linux/mfd/max8907.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+enum {
+       RTC_SEC = 0,
+       RTC_MIN,
+       RTC_HOUR,
+       RTC_WEEKDAY,
+       RTC_DATE,
+       RTC_MONTH,
+       RTC_YEAR1,
+       RTC_YEAR2,
+};
+
+#define TIME_NUM                       8
+#define ALARM_1SEC                     (1 << 7)
+#define HOUR_12                                (1 << 7)
+#define HOUR_AM_PM                     (1 << 5)
+#define ALARM0_IRQ                     (1 << 3)
+#define ALARM1_IRQ                     (1 << 2)
+#define ALARM0_STATUS                  (1 << 2)
+#define ALARM1_STATUS                  (1 << 1)
+
+struct max8907_rtc {
+       struct max8907          *max8907;
+       struct regmap           *regmap;
+       struct rtc_device       *rtc_dev;
+       int                     irq;
+};
+
+static irqreturn_t max8907_irq_handler(int irq, void *data)
+{
+       struct max8907_rtc *rtc = data;
+
+       regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0);
+
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+       return IRQ_HANDLED;
+}
+
+static void regs_to_tm(u8 *regs, struct rtc_time *tm)
+{
+       tm->tm_year = bcd2bin(regs[RTC_YEAR2]) * 100 +
+               bcd2bin(regs[RTC_YEAR1]) - 1900;
+       tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1;
+       tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f);
+       tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07) - 1;
+       if (regs[RTC_HOUR] & HOUR_12) {
+               tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f);
+               if (tm->tm_hour == 12)
+                       tm->tm_hour = 0;
+               if (regs[RTC_HOUR] & HOUR_AM_PM)
+                       tm->tm_hour += 12;
+       } else {
+               tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x03f);
+       }
+       tm->tm_min = bcd2bin(regs[RTC_MIN] & 0x7f);
+       tm->tm_sec = bcd2bin(regs[RTC_SEC] & 0x7f);
+}
+
+static void tm_to_regs(struct rtc_time *tm, u8 *regs)
+{
+       u8 high, low;
+
+       high = (tm->tm_year + 1900) / 100;
+       low = tm->tm_year % 100;
+       regs[RTC_YEAR2] = bin2bcd(high);
+       regs[RTC_YEAR1] = bin2bcd(low);
+       regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
+       regs[RTC_DATE] = bin2bcd(tm->tm_mday);
+       regs[RTC_WEEKDAY] = tm->tm_wday + 1;
+       regs[RTC_HOUR] = bin2bcd(tm->tm_hour);
+       regs[RTC_MIN] = bin2bcd(tm->tm_min);
+       regs[RTC_SEC] = bin2bcd(tm->tm_sec);
+}
+
+static int max8907_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct max8907_rtc *rtc = dev_get_drvdata(dev);
+       u8 regs[TIME_NUM];
+       int ret;
+
+       ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_RTC_SEC, regs,
+                              TIME_NUM);
+       if (ret < 0)
+               return ret;
+
+       regs_to_tm(regs, tm);
+
+       return 0;
+}
+
+static int max8907_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct max8907_rtc *rtc = dev_get_drvdata(dev);
+       u8 regs[TIME_NUM];
+
+       tm_to_regs(tm, regs);
+
+       return regmap_bulk_write(rtc->regmap, MAX8907_REG_RTC_SEC, regs,
+                                TIME_NUM);
+}
+
+static int max8907_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct max8907_rtc *rtc = dev_get_drvdata(dev);
+       u8 regs[TIME_NUM];
+       unsigned int val;
+       int ret;
+
+       ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs,
+                              TIME_NUM);
+       if (ret < 0)
+               return ret;
+
+       regs_to_tm(regs, &alrm->time);
+
+       ret = regmap_read(rtc->regmap, MAX8907_REG_ALARM0_CNTL, &val);
+       if (ret < 0)
+               return ret;
+
+       alrm->enabled = !!(val & 0x7f);
+
+       return 0;
+}
+
+static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct max8907_rtc *rtc = dev_get_drvdata(dev);
+       u8 regs[TIME_NUM];
+       int ret;
+
+       tm_to_regs(&alrm->time, regs);
+
+       /* Disable alarm while we update the target time */
+       ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = regmap_bulk_write(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs,
+                               TIME_NUM);
+       if (ret < 0)
+               return ret;
+
+       if (alrm->enabled)
+               ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL,
+                                        0x7f, 0x7f);
+
+       return ret;
+}
+
+static const struct rtc_class_ops max8907_rtc_ops = {
+       .read_time      = max8907_rtc_read_time,
+       .set_time       = max8907_rtc_set_time,
+       .read_alarm     = max8907_rtc_read_alarm,
+       .set_alarm      = max8907_rtc_set_alarm,
+};
+
+static int __devinit max8907_rtc_probe(struct platform_device *pdev)
+{
+       struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
+       struct max8907_rtc *rtc;
+       int ret;
+
+       rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, rtc);
+
+       rtc->max8907 = max8907;
+       rtc->regmap = max8907->regmap_rtc;
+
+       rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev,
+                                       &max8907_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc_dev)) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+               return ret;
+       }
+
+       rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc,
+                                      MAX8907_IRQ_RTC_ALARM0);
+       if (rtc->irq < 0) {
+               ret = rtc->irq;
+               goto err_unregister;
+       }
+
+       ret = request_threaded_irq(rtc->irq, NULL, max8907_irq_handler,
+                                  IRQF_ONESHOT, "max8907-alarm0", rtc);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n",
+                       rtc->irq, ret);
+               goto err_unregister;
+       }
+
+       return 0;
+
+err_unregister:
+       rtc_device_unregister(rtc->rtc_dev);
+       return ret;
+}
+
+static int __devexit max8907_rtc_remove(struct platform_device *pdev)
+{
+       struct max8907_rtc *rtc = platform_get_drvdata(pdev);
+
+       free_irq(rtc->irq, rtc);
+       rtc_device_unregister(rtc->rtc_dev);
+
+       return 0;
+}
+
+static struct platform_driver max8907_rtc_driver = {
+       .driver = {
+               .name = "max8907-rtc",
+               .owner = THIS_MODULE,
+       },
+       .probe = max8907_rtc_probe,
+       .remove = __devexit_p(max8907_rtc_remove),
+};
+module_platform_driver(max8907_rtc_driver);
+
+MODULE_DESCRIPTION("Maxim MAX8907 RTC driver");
+MODULE_LICENSE("GPL v2");
index e3e50d69baf85e75966bdea6d7f7b95ae6d65af0..cd0106293a4903672f2de56c008ecc7f0534c2e7 100644 (file)
@@ -343,7 +343,7 @@ static struct rtc_class_ops mxc_rtc_ops = {
        .alarm_irq_enable       = mxc_rtc_alarm_irq_enable,
 };
 
-static int __init mxc_rtc_probe(struct platform_device *pdev)
+static int __devinit mxc_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct rtc_device *rtc;
@@ -367,14 +367,14 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
        pdata->ioaddr = devm_ioremap(&pdev->dev, res->start,
                                     resource_size(res));
 
-       pdata->clk = clk_get(&pdev->dev, "rtc");
+       pdata->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(pdata->clk)) {
                dev_err(&pdev->dev, "unable to get clock!\n");
                ret = PTR_ERR(pdata->clk);
                goto exit_free_pdata;
        }
 
-       clk_enable(pdata->clk);
+       clk_prepare_enable(pdata->clk);
        rate = clk_get_rate(pdata->clk);
 
        if (rate == 32768)
@@ -426,22 +426,20 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
 exit_clr_drvdata:
        platform_set_drvdata(pdev, NULL);
 exit_put_clk:
-       clk_disable(pdata->clk);
-       clk_put(pdata->clk);
+       clk_disable_unprepare(pdata->clk);
 
 exit_free_pdata:
 
        return ret;
 }
 
-static int __exit mxc_rtc_remove(struct platform_device *pdev)
+static int __devexit mxc_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
        rtc_device_unregister(pdata->rtc);
 
-       clk_disable(pdata->clk);
-       clk_put(pdata->clk);
+       clk_disable_unprepare(pdata->clk);
        platform_set_drvdata(pdev, NULL);
 
        return 0;
@@ -482,21 +480,11 @@ static struct platform_driver mxc_rtc_driver = {
 #endif
                   .owner       = THIS_MODULE,
        },
-       .remove         = __exit_p(mxc_rtc_remove),
+       .probe = mxc_rtc_probe,
+       .remove = __devexit_p(mxc_rtc_remove),
 };
 
-static int __init mxc_rtc_init(void)
-{
-       return platform_driver_probe(&mxc_rtc_driver, mxc_rtc_probe);
-}
-
-static void __exit mxc_rtc_exit(void)
-{
-       platform_driver_unregister(&mxc_rtc_driver);
-}
-
-module_init(mxc_rtc_init);
-module_exit(mxc_rtc_exit);
+module_platform_driver(mxc_rtc_driver)
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 MODULE_DESCRIPTION("RTC driver for Freescale MXC");
index c2fe426a6ef2d384e50835c1f6f05bc7e3418b9e..98e3a2b681e6f7957c830e5dca4292c4b5fe73b0 100644 (file)
@@ -78,8 +78,17 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        unsigned char buf[13] = { PCF8563_REG_ST1 };
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 1, buf },    /* setup read ptr */
-               { client->addr, I2C_M_RD, 13, buf },    /* read status + date */
+               {/* setup read ptr */
+                       .addr = client->addr,
+                       .len = 1,
+                       .buf = buf
+               },
+               {/* read status + date */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 13,
+                       .buf = buf
+               },
        };
 
        /* read registers */
index 0a59fda5c09d176c5fa0af1f90625c04a29232c4..e96236ac2e78a74cc9673f71ef8c07233343277f 100644 (file)
 
 #include "rtc-core.h"
 
+#define NAME_SIZE      10
+
+#if defined(CONFIG_RTC_HCTOSYS_DEVICE)
+static bool is_rtc_hctosys(struct rtc_device *rtc)
+{
+       int size;
+       char name[NAME_SIZE];
+
+       size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id);
+       if (size > NAME_SIZE)
+               return false;
+
+       return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE);
+}
+#else
+static bool is_rtc_hctosys(struct rtc_device *rtc)
+{
+       return (rtc->id == 0);
+}
+#endif
 
 static int rtc_proc_show(struct seq_file *seq, void *offset)
 {
@@ -117,12 +137,12 @@ static const struct file_operations rtc_proc_fops = {
 
 void rtc_proc_add_device(struct rtc_device *rtc)
 {
-       if (rtc->id == 0)
+       if (is_rtc_hctosys(rtc))
                proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc);
 }
 
 void rtc_proc_del_device(struct rtc_device *rtc)
 {
-       if (rtc->id == 0)
+       if (is_rtc_hctosys(rtc))
                remove_proc_entry("driver/rtc", NULL);
 }
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c
new file mode 100644 (file)
index 0000000..cdb140c
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Venu Byravarasu <vbyravarasu@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/rc5t583.h>
+
+struct rc5t583_rtc {
+       struct rtc_device       *rtc;
+       /* To store the list of enabled interrupts, during system suspend */
+       u32 irqen;
+};
+
+/* Total number of RTC registers needed to set time*/
+#define NUM_TIME_REGS  (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1)
+
+/* Total number of RTC registers needed to set Y-Alarm*/
+#define NUM_YAL_REGS   (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1)
+
+/* Set Y-Alarm interrupt */
+#define SET_YAL BIT(5)
+
+/* Get Y-Alarm interrupt status*/
+#define GET_YAL_STATUS BIT(3)
+
+static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       u8 val;
+
+       /* Set Y-Alarm, based on 'enabled' */
+       val = enabled ? SET_YAL : 0;
+
+       return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL,
+               val);
+}
+
+/*
+ * Gets current rc5t583 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ *  - Months are 1..12 vs Linux 0-11
+ *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       u8 rtc_data[NUM_TIME_REGS];
+       int ret;
+
+       ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
+               NUM_TIME_REGS);
+       if (ret < 0) {
+               dev_err(dev, "RTC read time failed with err:%d\n", ret);
+               return ret;
+       }
+
+       tm->tm_sec = bcd2bin(rtc_data[0]);
+       tm->tm_min = bcd2bin(rtc_data[1]);
+       tm->tm_hour = bcd2bin(rtc_data[2]);
+       tm->tm_wday = bcd2bin(rtc_data[3]);
+       tm->tm_mday = bcd2bin(rtc_data[4]);
+       tm->tm_mon = bcd2bin(rtc_data[5]) - 1;
+       tm->tm_year = bcd2bin(rtc_data[6]) + 100;
+
+       return ret;
+}
+
+static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       unsigned char rtc_data[NUM_TIME_REGS];
+       int ret;
+
+       rtc_data[0] = bin2bcd(tm->tm_sec);
+       rtc_data[1] = bin2bcd(tm->tm_min);
+       rtc_data[2] = bin2bcd(tm->tm_hour);
+       rtc_data[3] = bin2bcd(tm->tm_wday);
+       rtc_data[4] = bin2bcd(tm->tm_mday);
+       rtc_data[5] = bin2bcd(tm->tm_mon + 1);
+       rtc_data[6] = bin2bcd(tm->tm_year - 100);
+
+       ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data,
+               NUM_TIME_REGS);
+       if (ret < 0) {
+               dev_err(dev, "RTC set time failed with error %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       unsigned char alarm_data[NUM_YAL_REGS];
+       u32 interrupt_enable;
+       int ret;
+
+       ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
+               NUM_YAL_REGS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_alarm error %d\n", ret);
+               return ret;
+       }
+
+       alm->time.tm_min = bcd2bin(alarm_data[0]);
+       alm->time.tm_hour = bcd2bin(alarm_data[1]);
+       alm->time.tm_mday = bcd2bin(alarm_data[2]);
+       alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1;
+       alm->time.tm_year = bcd2bin(alarm_data[4]) + 100;
+
+       ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable);
+       if (ret < 0)
+               return ret;
+
+       /* check if YALE is set */
+       if (interrupt_enable & SET_YAL)
+               alm->enabled = 1;
+
+       return ret;
+}
+
+static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       unsigned char alarm_data[NUM_YAL_REGS];
+       int ret;
+
+       ret = rc5t583_rtc_alarm_irq_enable(dev, 0);
+       if (ret)
+               return ret;
+
+       alarm_data[0] = bin2bcd(alm->time.tm_min);
+       alarm_data[1] = bin2bcd(alm->time.tm_hour);
+       alarm_data[2] = bin2bcd(alm->time.tm_mday);
+       alarm_data[3] = bin2bcd(alm->time.tm_mon + 1);
+       alarm_data[4] = bin2bcd(alm->time.tm_year - 100);
+
+       ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data,
+               NUM_YAL_REGS);
+       if (ret) {
+               dev_err(dev, "rtc_set_alarm error %d\n", ret);
+               return ret;
+       }
+
+       if (alm->enabled)
+               ret = rc5t583_rtc_alarm_irq_enable(dev, 1);
+
+       return ret;
+}
+
+static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc)
+{
+       struct device *dev = rtc;
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
+       unsigned long events = 0;
+       int ret;
+       u32 rtc_reg;
+
+       ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg);
+       if (ret < 0)
+               return IRQ_NONE;
+
+       if (rtc_reg & GET_YAL_STATUS) {
+               events = RTC_IRQF | RTC_AF;
+               /* clear pending Y-alarm interrupt bit */
+               rtc_reg &= ~GET_YAL_STATUS;
+       }
+
+       ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg);
+       if (ret)
+               return IRQ_NONE;
+
+       /* Notify RTC core on event */
+       rtc_update_irq(rc5t583_rtc->rtc, 1, events);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops rc5t583_rtc_ops = {
+       .read_time      = rc5t583_rtc_read_time,
+       .set_time       = rc5t583_rtc_set_time,
+       .read_alarm     = rc5t583_rtc_read_alarm,
+       .set_alarm      = rc5t583_rtc_set_alarm,
+       .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable,
+};
+
+static int __devinit rc5t583_rtc_probe(struct platform_device *pdev)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+       struct rc5t583_rtc *ricoh_rtc;
+       struct rc5t583_platform_data *pmic_plat_data;
+       int ret;
+       int irq;
+
+       ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc),
+                       GFP_KERNEL);
+       if (!ricoh_rtc)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, ricoh_rtc);
+
+       /* Clear pending interrupts */
+       ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0);
+       if (ret < 0)
+               return ret;
+
+       /* clear RTC Adjust register */
+       ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to program rtc_adjust reg\n");
+               return -EBUSY;
+       }
+
+       pmic_plat_data = dev_get_platdata(rc5t583->dev);
+       irq = pmic_plat_data->irq_base;
+       if (irq <= 0) {
+               dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
+                       irq);
+               return ret;
+       }
+
+       irq += RC5T583_IRQ_YALE;
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+               rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW,
+               "rtc-rc5t583", &pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "IRQ is not free.\n");
+               return ret;
+       }
+       device_init_wakeup(&pdev->dev, 1);
+
+       ricoh_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+               &rc5t583_rtc_ops, THIS_MODULE);
+       if (IS_ERR(ricoh_rtc->rtc)) {
+               ret = PTR_ERR(ricoh_rtc->rtc);
+               dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Disable rc5t583 RTC interrupts.
+ * Sets status flag to free.
+ */
+static int __devexit rc5t583_rtc_remove(struct platform_device *pdev)
+{
+       struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev);
+
+       rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0);
+
+       rtc_device_unregister(rc5t583_rtc->rtc);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int rc5t583_rtc_suspend(struct device *dev)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
+       int ret;
+
+       /* Store current list of enabled interrupts*/
+       ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1,
+               &rc5t583_rtc->irqen);
+       return ret;
+}
+
+static int rc5t583_rtc_resume(struct device *dev)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent);
+       struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev);
+
+       /* Restore list of enabled interrupts before suspend */
+       return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1,
+               rc5t583_rtc->irqen);
+}
+
+static const struct dev_pm_ops rc5t583_rtc_pm_ops = {
+       .suspend        = rc5t583_rtc_suspend,
+       .resume         = rc5t583_rtc_resume,
+};
+
+#define DEV_PM_OPS     (&rc5t583_rtc_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+static struct platform_driver rc5t583_rtc_driver = {
+       .probe          = rc5t583_rtc_probe,
+       .remove         = __devexit_p(rc5t583_rtc_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "rtc-rc5t583",
+               .pm     = DEV_PM_OPS,
+       },
+};
+
+module_platform_driver(rc5t583_rtc_driver);
+MODULE_ALIAS("platform:rtc-rc5t583");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index fb4842c3544e40f9acedc852b58a912b02d8888f..76f565ae384d623d78acffbdf9b124149df67efe 100644 (file)
@@ -104,7 +104,12 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
 {
        struct i2c_client       *client = rs5c->client;
        struct i2c_msg          msgs[] = {
-               { client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(rs5c->buf),
+                       .buf = rs5c->buf
+               },
        };
 
        /* This implements the third reading method from the datasheet, using
index c9562ceedef39a68d0991fca892a4e337596bcda..8a092325188d07265e7c77f7935407d58c9e41e5 100644 (file)
@@ -19,6 +19,8 @@
 #define S35390A_CMD_STATUS1    0
 #define S35390A_CMD_STATUS2    1
 #define S35390A_CMD_TIME1      2
+#define S35390A_CMD_TIME2      3
+#define S35390A_CMD_INT2_REG1  5
 
 #define S35390A_BYTE_YEAR      0
 #define S35390A_BYTE_MONTH     1
 #define S35390A_BYTE_MINS      5
 #define S35390A_BYTE_SECS      6
 
+#define S35390A_ALRM_BYTE_WDAY 0
+#define S35390A_ALRM_BYTE_HOURS        1
+#define S35390A_ALRM_BYTE_MINS 2
+
 #define S35390A_FLAG_POC       0x01
 #define S35390A_FLAG_BLD       0x02
 #define S35390A_FLAG_24H       0x40
 #define S35390A_FLAG_RESET     0x80
 #define S35390A_FLAG_TEST      0x01
 
+#define S35390A_INT2_MODE_MASK         0xF0
+
+#define S35390A_INT2_MODE_NOINTR       0x00
+#define S35390A_INT2_MODE_FREQ         0x10
+#define S35390A_INT2_MODE_ALARM                0x40
+#define S35390A_INT2_MODE_PMIN_EDG     0x20
+
 static const struct i2c_device_id s35390a_id[] = {
        { "s35390a", 0 },
        { }
@@ -50,7 +63,11 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len)
 {
        struct i2c_client *client = s35390a->client[reg];
        struct i2c_msg msg[] = {
-               { client->addr, 0, len, buf },
+               {
+                       .addr = client->addr,
+                       .len = len,
+                       .buf = buf
+               },
        };
 
        if ((i2c_transfer(client->adapter, msg, 1)) != 1)
@@ -63,7 +80,12 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
 {
        struct i2c_client *client = s35390a->client[reg];
        struct i2c_msg msg[] = {
-               { client->addr, I2C_M_RD, len, buf },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = len,
+                       .buf = buf
+               },
        };
 
        if ((i2c_transfer(client->adapter, msg, 1)) != 1)
@@ -184,6 +206,104 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        return rtc_valid_tm(tm);
 }
 
+static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
+{
+       struct s35390a *s35390a = i2c_get_clientdata(client);
+       char buf[3], sts = 0;
+       int err, i;
+
+       dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\
+               "mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec,
+               alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
+               alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
+
+       /* disable interrupt */
+       err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
+       if (err < 0)
+               return err;
+
+       /* clear pending interrupt, if any */
+       err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
+       if (err < 0)
+               return err;
+
+       if (alm->enabled)
+               sts = S35390A_INT2_MODE_ALARM;
+       else
+               sts = S35390A_INT2_MODE_NOINTR;
+
+       /* This chip expects the bits of each byte to be in reverse order */
+       sts = bitrev8(sts);
+
+       /* set interupt mode*/
+       err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
+       if (err < 0)
+               return err;
+
+       if (alm->time.tm_wday != -1)
+               buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
+
+       buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
+                       alm->time.tm_hour) | 0x80;
+       buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80;
+
+       if (alm->time.tm_hour >= 12)
+               buf[S35390A_ALRM_BYTE_HOURS] |= 0x40;
+
+       for (i = 0; i < 3; ++i)
+               buf[i] = bitrev8(buf[i]);
+
+       err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf,
+                                                               sizeof(buf));
+
+       return err;
+}
+
+static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
+{
+       struct s35390a *s35390a = i2c_get_clientdata(client);
+       char buf[3], sts;
+       int i, err;
+
+       err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
+       if (err < 0)
+               return err;
+
+       if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
+               return -EINVAL;
+
+       err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
+       if (err < 0)
+               return err;
+
+       /* This chip returns the bits of each byte in reverse order */
+       for (i = 0; i < 3; ++i) {
+               buf[i] = bitrev8(buf[i]);
+               buf[i] &= ~0x80;
+       }
+
+       alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
+       alm->time.tm_hour = s35390a_reg2hr(s35390a,
+                                               buf[S35390A_ALRM_BYTE_HOURS]);
+       alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
+
+       dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
+                       __func__, alm->time.tm_min, alm->time.tm_hour,
+                       alm->time.tm_wday);
+
+       return 0;
+}
+
+static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       return s35390a_read_alarm(to_i2c_client(dev), alm);
+}
+
+static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       return s35390a_set_alarm(to_i2c_client(dev), alm);
+}
+
 static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        return s35390a_get_datetime(to_i2c_client(dev), tm);
@@ -197,6 +317,9 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static const struct rtc_class_ops s35390a_rtc_ops = {
        .read_time      = s35390a_rtc_read_time,
        .set_time       = s35390a_rtc_set_time,
+       .set_alarm      = s35390a_rtc_set_alarm,
+       .read_alarm     = s35390a_rtc_read_alarm,
+
 };
 
 static struct i2c_driver s35390a_driver;
@@ -261,6 +384,8 @@ static int s35390a_probe(struct i2c_client *client,
        if (s35390a_get_datetime(client, &tm) < 0)
                dev_warn(&client->dev, "clock needs to be set\n");
 
+       device_set_wakeup_capable(&client->dev, 1);
+
        s35390a->rtc = rtc_device_register(s35390a_driver.driver.name,
                                &client->dev, &s35390a_rtc_ops, THIS_MODULE);
 
index bfbd92c8d1c9d9cba042b494cfde450066320dea..77823d21d31488065b6ca8a12de02d1b5e9f013f 100644 (file)
@@ -476,13 +476,13 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
        s3c_rtc_tickno = platform_get_irq(pdev, 1);
        if (s3c_rtc_tickno < 0) {
                dev_err(&pdev->dev, "no irq for rtc tick\n");
-               return -ENOENT;
+               return s3c_rtc_tickno;
        }
 
        s3c_rtc_alarmno = platform_get_irq(pdev, 0);
        if (s3c_rtc_alarmno < 0) {
                dev_err(&pdev->dev, "no irq for alarm\n");
-               return -ENOENT;
+               return s3c_rtc_alarmno;
        }
 
        pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n",
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
new file mode 100644 (file)
index 0000000..3c0da33
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* These register offsets are relative to LP (Low Power) range */
+#define SNVS_LPCR              0x04
+#define SNVS_LPSR              0x18
+#define SNVS_LPSRTCMR          0x1c
+#define SNVS_LPSRTCLR          0x20
+#define SNVS_LPTAR             0x24
+#define SNVS_LPPGDR            0x30
+
+#define SNVS_LPCR_SRTC_ENV     (1 << 0)
+#define SNVS_LPCR_LPTA_EN      (1 << 1)
+#define SNVS_LPCR_LPWUI_EN     (1 << 3)
+#define SNVS_LPSR_LPTA         (1 << 0)
+
+#define SNVS_LPPGDR_INIT       0x41736166
+#define CNTR_TO_SECS_SH                15
+
+struct snvs_rtc_data {
+       struct rtc_device *rtc;
+       void __iomem *ioaddr;
+       int irq;
+       spinlock_t lock;
+};
+
+static u32 rtc_read_lp_counter(void __iomem *ioaddr)
+{
+       u64 read1, read2;
+
+       do {
+               read1 = readl(ioaddr + SNVS_LPSRTCMR);
+               read1 <<= 32;
+               read1 |= readl(ioaddr + SNVS_LPSRTCLR);
+
+               read2 = readl(ioaddr + SNVS_LPSRTCMR);
+               read2 <<= 32;
+               read2 |= readl(ioaddr + SNVS_LPSRTCLR);
+       } while (read1 != read2);
+
+       /* Convert 47-bit counter to 32-bit raw second count */
+       return (u32) (read1 >> CNTR_TO_SECS_SH);
+}
+
+static void rtc_write_sync_lp(void __iomem *ioaddr)
+{
+       u32 count1, count2, count3;
+       int i;
+
+       /* Wait for 3 CKIL cycles */
+       for (i = 0; i < 3; i++) {
+               do {
+                       count1 = readl(ioaddr + SNVS_LPSRTCLR);
+                       count2 = readl(ioaddr + SNVS_LPSRTCLR);
+               } while (count1 != count2);
+
+               /* Now wait until counter value changes */
+               do {
+                       do {
+                               count2 = readl(ioaddr + SNVS_LPSRTCLR);
+                               count3 = readl(ioaddr + SNVS_LPSRTCLR);
+                       } while (count2 != count3);
+               } while (count3 == count1);
+       }
+}
+
+static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
+{
+       unsigned long flags;
+       int timeout = 1000;
+       u32 lpcr;
+
+       spin_lock_irqsave(&data->lock, flags);
+
+       lpcr = readl(data->ioaddr + SNVS_LPCR);
+       if (enable)
+               lpcr |= SNVS_LPCR_SRTC_ENV;
+       else
+               lpcr &= ~SNVS_LPCR_SRTC_ENV;
+       writel(lpcr, data->ioaddr + SNVS_LPCR);
+
+       spin_unlock_irqrestore(&data->lock, flags);
+
+       while (--timeout) {
+               lpcr = readl(data->ioaddr + SNVS_LPCR);
+
+               if (enable) {
+                       if (lpcr & SNVS_LPCR_SRTC_ENV)
+                               break;
+               } else {
+                       if (!(lpcr & SNVS_LPCR_SRTC_ENV))
+                               break;
+               }
+       }
+
+       if (!timeout)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       unsigned long time = rtc_read_lp_counter(data->ioaddr);
+
+       rtc_time_to_tm(time, tm);
+
+       return 0;
+}
+
+static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       unsigned long time;
+
+       rtc_tm_to_time(tm, &time);
+
+       /* Disable RTC first */
+       snvs_rtc_enable(data, false);
+
+       /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
+       writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR);
+       writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR);
+
+       /* Enable RTC again */
+       snvs_rtc_enable(data, true);
+
+       return 0;
+}
+
+static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       u32 lptar, lpsr;
+
+       lptar = readl(data->ioaddr + SNVS_LPTAR);
+       rtc_time_to_tm(lptar, &alrm->time);
+
+       lpsr = readl(data->ioaddr + SNVS_LPSR);
+       alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
+
+       return 0;
+}
+
+static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       u32 lpcr;
+       unsigned long flags;
+
+       spin_lock_irqsave(&data->lock, flags);
+
+       lpcr = readl(data->ioaddr + SNVS_LPCR);
+       if (enable)
+               lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
+       else
+               lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
+       writel(lpcr, data->ioaddr + SNVS_LPCR);
+
+       spin_unlock_irqrestore(&data->lock, flags);
+
+       rtc_write_sync_lp(data->ioaddr);
+
+       return 0;
+}
+
+static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       struct rtc_time *alrm_tm = &alrm->time;
+       unsigned long time;
+       unsigned long flags;
+       u32 lpcr;
+
+       rtc_tm_to_time(alrm_tm, &time);
+
+       spin_lock_irqsave(&data->lock, flags);
+
+       /* Have to clear LPTA_EN before programming new alarm time in LPTAR */
+       lpcr = readl(data->ioaddr + SNVS_LPCR);
+       lpcr &= ~SNVS_LPCR_LPTA_EN;
+       writel(lpcr, data->ioaddr + SNVS_LPCR);
+
+       spin_unlock_irqrestore(&data->lock, flags);
+
+       writel(time, data->ioaddr + SNVS_LPTAR);
+
+       /* Clear alarm interrupt status bit */
+       writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR);
+
+       return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
+}
+
+static const struct rtc_class_ops snvs_rtc_ops = {
+       .read_time = snvs_rtc_read_time,
+       .set_time = snvs_rtc_set_time,
+       .read_alarm = snvs_rtc_read_alarm,
+       .set_alarm = snvs_rtc_set_alarm,
+       .alarm_irq_enable = snvs_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
+{
+       struct device *dev = dev_id;
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       u32 lpsr;
+       u32 events = 0;
+
+       lpsr = readl(data->ioaddr + SNVS_LPSR);
+
+       if (lpsr & SNVS_LPSR_LPTA) {
+               events |= (RTC_AF | RTC_IRQF);
+
+               /* RTC alarm should be one-shot */
+               snvs_rtc_alarm_irq_enable(dev, 0);
+
+               rtc_update_irq(data->rtc, 1, events);
+       }
+
+       /* clear interrupt status */
+       writel(lpsr, data->ioaddr + SNVS_LPSR);
+
+       return events ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int __devinit snvs_rtc_probe(struct platform_device *pdev)
+{
+       struct snvs_rtc_data *data;
+       struct resource *res;
+       int ret;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
+       if (!data->ioaddr)
+               return -EADDRNOTAVAIL;
+
+       data->irq = platform_get_irq(pdev, 0);
+       if (data->irq < 0)
+               return data->irq;
+
+       platform_set_drvdata(pdev, data);
+
+       spin_lock_init(&data->lock);
+
+       /* Initialize glitch detect */
+       writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR);
+
+       /* Clear interrupt status */
+       writel(0xffffffff, data->ioaddr + SNVS_LPSR);
+
+       /* Enable RTC */
+       snvs_rtc_enable(data, true);
+
+       device_init_wakeup(&pdev->dev, true);
+
+       ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler,
+                              IRQF_SHARED, "rtc alarm", &pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request irq %d: %d\n",
+                       data->irq, ret);
+               return ret;
+       }
+
+       data->rtc = rtc_device_register(pdev->name, &pdev->dev,
+                                       &snvs_rtc_ops, THIS_MODULE);
+       if (IS_ERR(data->rtc)) {
+               ret = PTR_ERR(data->rtc);
+               dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit snvs_rtc_remove(struct platform_device *pdev)
+{
+       struct snvs_rtc_data *data = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(data->rtc);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int snvs_rtc_suspend(struct device *dev)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(data->irq);
+
+       return 0;
+}
+
+static int snvs_rtc_resume(struct device *dev)
+{
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(data->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume);
+
+static const struct of_device_id __devinitconst snvs_dt_ids[] = {
+       { .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, snvs_dt_ids);
+
+static struct platform_driver snvs_rtc_driver = {
+       .driver = {
+               .name   = "snvs_rtc",
+               .owner  = THIS_MODULE,
+               .pm     = &snvs_rtc_pm_ops,
+               .of_match_table = snvs_dt_ids,
+       },
+       .probe          = snvs_rtc_probe,
+       .remove         = __devexit_p(snvs_rtc_remove),
+};
+module_platform_driver(snvs_rtc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Freescale SNVS RTC Driver");
+MODULE_LICENSE("GPL");
index e2785479113ca06648949d6c6a78adee92c78367..bb507d23f6cea09e3c2ab80fec144e1acbb1c4a9 100644 (file)
@@ -235,7 +235,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct spear_rtc_config *config = dev_get_drvdata(dev);
-       unsigned int time, date, err = 0;
+       unsigned int time, date;
 
        if (tm2bcd(tm) < 0)
                return -EINVAL;
@@ -247,11 +247,8 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
                (tm->tm_year << YEAR_SHIFT);
        writel(time, config->ioaddr + TIME_REG);
        writel(date, config->ioaddr + DATE_REG);
-       err = is_write_complete(config);
-       if (err < 0)
-               return err;
 
-       return 0;
+       return is_write_complete(config);
 }
 
 /*
@@ -295,7 +292,8 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
        struct spear_rtc_config *config = dev_get_drvdata(dev);
-       unsigned int time, date, err = 0;
+       unsigned int time, date;
+       int err;
 
        if (tm2bcd(&alm->time) < 0)
                return -EINVAL;
@@ -357,7 +355,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct spear_rtc_config *config;
-       unsigned int status = 0;
+       int status = 0;
        int irq;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 380083ca572fd480ba0f060c2f9ead3925d855a4..b70e2bb6364500fb7d02c2dffb6c01575e1771e4 100644 (file)
@@ -102,6 +102,12 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr,
        return n;
 }
 
+/**
+ * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
+ *
+ * Returns 1 if the system clock was set by this RTC at the last
+ * boot or resume event.
+ */
 static ssize_t
 rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr,
                char *buf)
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
new file mode 100644 (file)
index 0000000..7a82337
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * rtc-tps65910.c -- TPS65910 Real Time Clock interface
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Author: Venu Byravarasu <vbyravarasu@nvidia.com>
+ *
+ * Based on original TI driver rtc-twl.c
+ *   Copyright (C) 2007 MontaVista Software, Inc
+ *   Author: Alexandre Rusev <source@mvista.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/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tps65910.h>
+
+struct tps65910_rtc {
+       struct rtc_device       *rtc;
+       /* To store the list of enabled interrupts */
+       u32 irqstat;
+};
+
+/* Total number of RTC registers needed to set time*/
+#define NUM_TIME_REGS  (TPS65910_YEARS - TPS65910_SECONDS + 1)
+
+static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
+{
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       u8 val = 0;
+
+       if (enabled)
+               val = TPS65910_RTC_INTERRUPTS_IT_ALARM;
+
+       return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val);
+}
+
+/*
+ * Gets current tps65910 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ *  - Months are 1..12 vs Linux 0-11
+ *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       unsigned char rtc_data[NUM_TIME_REGS];
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       int ret;
+
+       /* Copy RTC counting registers to static registers or latches */
+       ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
+               TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME);
+       if (ret < 0) {
+               dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data,
+               NUM_TIME_REGS);
+       if (ret < 0) {
+               dev_err(dev, "reading from RTC failed with err:%d\n", ret);
+               return ret;
+       }
+
+       tm->tm_sec = bcd2bin(rtc_data[0]);
+       tm->tm_min = bcd2bin(rtc_data[1]);
+       tm->tm_hour = bcd2bin(rtc_data[2]);
+       tm->tm_mday = bcd2bin(rtc_data[3]);
+       tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
+       tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+
+       return ret;
+}
+
+static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       unsigned char rtc_data[NUM_TIME_REGS];
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       int ret;
+
+       rtc_data[0] = bin2bcd(tm->tm_sec);
+       rtc_data[1] = bin2bcd(tm->tm_min);
+       rtc_data[2] = bin2bcd(tm->tm_hour);
+       rtc_data[3] = bin2bcd(tm->tm_mday);
+       rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+       rtc_data[5] = bin2bcd(tm->tm_year - 100);
+
+       /* Stop RTC while updating the RTC time registers */
+       ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
+               TPS65910_RTC_CTRL_STOP_RTC, 0);
+       if (ret < 0) {
+               dev_err(dev, "RTC stop failed with err:%d\n", ret);
+               return ret;
+       }
+
+       /* update all the time registers in one shot */
+       ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data,
+               NUM_TIME_REGS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_set_time error %d\n", ret);
+               return ret;
+       }
+
+       /* Start back RTC */
+       ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL,
+               TPS65910_RTC_CTRL_STOP_RTC, 1);
+       if (ret < 0)
+               dev_err(dev, "RTC start failed with err:%d\n", ret);
+
+       return ret;
+}
+
+/*
+ * Gets current tps65910 RTC alarm time.
+ */
+static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       unsigned char alarm_data[NUM_TIME_REGS];
+       u32 int_val;
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       int ret;
+
+       ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data,
+               NUM_TIME_REGS);
+       if (ret < 0) {
+               dev_err(dev, "rtc_read_alarm error %d\n", ret);
+               return ret;
+       }
+
+       alm->time.tm_sec = bcd2bin(alarm_data[0]);
+       alm->time.tm_min = bcd2bin(alarm_data[1]);
+       alm->time.tm_hour = bcd2bin(alarm_data[2]);
+       alm->time.tm_mday = bcd2bin(alarm_data[3]);
+       alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
+       alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
+
+       ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val);
+       if (ret < 0)
+               return ret;
+
+       if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM)
+               alm->enabled = 1;
+
+       return ret;
+}
+
+static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       unsigned char alarm_data[NUM_TIME_REGS];
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       int ret;
+
+       ret = tps65910_rtc_alarm_irq_enable(dev, 0);
+       if (ret)
+               return ret;
+
+       alarm_data[0] = bin2bcd(alm->time.tm_sec);
+       alarm_data[1] = bin2bcd(alm->time.tm_min);
+       alarm_data[2] = bin2bcd(alm->time.tm_hour);
+       alarm_data[3] = bin2bcd(alm->time.tm_mday);
+       alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
+       alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
+
+       /* update all the alarm registers in one shot */
+       ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS,
+               alarm_data, NUM_TIME_REGS);
+       if (ret) {
+               dev_err(dev, "rtc_set_alarm error %d\n", ret);
+               return ret;
+       }
+
+       if (alm->enabled)
+               ret = tps65910_rtc_alarm_irq_enable(dev, 1);
+
+       return ret;
+}
+
+static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc)
+{
+       struct device *dev = rtc;
+       unsigned long events = 0;
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev);
+       int ret;
+       u32 rtc_reg;
+
+       ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg);
+       if (ret)
+               return IRQ_NONE;
+
+       if (rtc_reg & TPS65910_RTC_STATUS_ALARM)
+               events = RTC_IRQF | RTC_AF;
+
+       ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg);
+       if (ret)
+               return IRQ_NONE;
+
+       /* Notify RTC core on event */
+       rtc_update_irq(tps_rtc->rtc, 1, events);
+
+       return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops tps65910_rtc_ops = {
+       .read_time      = tps65910_rtc_read_time,
+       .set_time       = tps65910_rtc_set_time,
+       .read_alarm     = tps65910_rtc_read_alarm,
+       .set_alarm      = tps65910_rtc_set_alarm,
+       .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
+};
+
+static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
+{
+       struct tps65910 *tps65910 = NULL;
+       struct tps65910_rtc *tps_rtc = NULL;
+       int ret;
+       int irq;
+       u32 rtc_reg;
+
+       tps65910 = dev_get_drvdata(pdev->dev.parent);
+
+       tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc),
+                       GFP_KERNEL);
+       if (!tps_rtc)
+               return -ENOMEM;
+
+       /* Clear pending interrupts */
+       ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg);
+       if (ret < 0)
+               return ret;
+
+       ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n");
+       rtc_reg = TPS65910_RTC_CTRL_STOP_RTC;
+       ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg);
+       if (ret < 0)
+               return ret;
+
+       irq  = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n",
+                       irq);
+               return ret;
+       }
+
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+               tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
+               "rtc-tps65910", &pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "IRQ is not free.\n");
+               return ret;
+       }
+       device_init_wakeup(&pdev->dev, 1);
+
+       tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
+               &tps65910_rtc_ops, THIS_MODULE);
+       if (IS_ERR(tps_rtc->rtc)) {
+               ret = PTR_ERR(tps_rtc->rtc);
+               dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, tps_rtc);
+
+       return 0;
+}
+
+/*
+ * Disable tps65910 RTC interrupts.
+ * Sets status flag to free.
+ */
+static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
+{
+       /* leave rtc running, but disable irqs */
+       struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+       tps65910_rtc_alarm_irq_enable(&rtc->dev, 0);
+
+       rtc_device_unregister(rtc);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int tps65910_rtc_suspend(struct device *dev)
+{
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+       u8 alarm = TPS65910_RTC_INTERRUPTS_IT_ALARM;
+       int ret;
+
+       /* Store current list of enabled interrupts*/
+       ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS,
+               &tps->rtc->irqstat);
+       if (ret < 0)
+               return ret;
+
+       /* Enable RTC ALARM interrupt only */
+       return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, alarm);
+}
+
+static int tps65910_rtc_resume(struct device *dev)
+{
+       struct tps65910 *tps = dev_get_drvdata(dev->parent);
+
+       /* Restore list of enabled interrupts before suspend */
+       return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS,
+               tps->rtc->irqstat);
+}
+
+static const struct dev_pm_ops tps65910_rtc_pm_ops = {
+       .suspend        = tps65910_rtc_suspend,
+       .resume         = tps65910_rtc_resume,
+};
+
+#define DEV_PM_OPS     (&tps65910_rtc_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+static struct platform_driver tps65910_rtc_driver = {
+       .probe          = tps65910_rtc_probe,
+       .remove         = __devexit_p(tps65910_rtc_remove),
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "tps65910-rtc",
+               .pm     = DEV_PM_OPS,
+       },
+};
+
+module_platform_driver(tps65910_rtc_driver);
+MODULE_ALIAS("platform:rtc-tps65910");
+MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
+MODULE_LICENSE("GPL");
index 403b3d41d101cc97e4cad649f8b4f44955122c92..f36e59c6bc01fc0435c2719d8396261245bdc707 100644 (file)
@@ -97,8 +97,17 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
        int i;
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 2, dt_addr },        /* setup read ptr */
-               { client->addr, I2C_M_RD, 8, buf },     /* read date */
+               {/* setup read ptr */
+                       .addr = client->addr,
+                       .len = 2,
+                       .buf = dt_addr
+               },
+               {/* read date */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 8,
+                       .buf = buf
+               },
        };
 
        /* read date registers */
@@ -142,8 +151,17 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
        static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 2, sr_addr },        /* setup read ptr */
-               { client->addr, I2C_M_RD, 1, sr },      /* read status */
+               {     /* setup read ptr */
+                       .addr = client->addr,
+                       .len = 2,
+                       .buf = sr_addr
+               },
+               {    /* read status */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = sr
+               },
        };
 
        /* read status register */
@@ -279,8 +297,17 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
        static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 2, dtr_addr },       /* setup read ptr */
-               { client->addr, I2C_M_RD, 1, &dtr },    /* read dtr */
+               {       /* setup read ptr */
+                       .addr = client->addr,
+                       .len = 2,
+                       .buf = dtr_addr
+               },
+               {      /* read dtr */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = &dtr
+               },
        };
 
        /* read dtr register */
@@ -311,8 +338,17 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
        static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 2, atr_addr },       /* setup read ptr */
-               { client->addr, I2C_M_RD, 1, &atr },    /* read atr */
+               {/* setup read ptr */
+                       .addr = client->addr,
+                       .len = 2,
+                       .buf = atr_addr
+               },
+               {/* read atr */
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = &atr
+               },
        };
 
        /* read atr register */
@@ -381,8 +417,17 @@ static int x1205_validate_client(struct i2c_client *client)
                unsigned char addr[2] = { 0, probe_zero_pattern[i] };
 
                struct i2c_msg msgs[2] = {
-                       { client->addr, 0, 2, addr },
-                       { client->addr, I2C_M_RD, 1, &buf },
+                       {
+                               .addr = client->addr,
+                               .len = 2,
+                               .buf = addr
+                       },
+                       {
+                               .addr = client->addr,
+                               .flags = I2C_M_RD,
+                               .len = 1,
+                               .buf = &buf
+                       },
                };
 
                if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
@@ -409,8 +454,17 @@ static int x1205_validate_client(struct i2c_client *client)
                unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
 
                struct i2c_msg msgs[2] = {
-                       { client->addr, 0, 2, addr },
-                       { client->addr, I2C_M_RD, 1, &reg },
+                       {
+                               .addr = client->addr,
+                               .len = 2,
+                               .buf = addr
+                       },
+                       {
+                               .addr = client->addr,
+                               .flags = I2C_M_RD,
+                               .len = 1,
+                               .buf = &reg
+                       },
                };
 
                if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
@@ -444,8 +498,18 @@ static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        static unsigned char int_addr[2] = { 0, X1205_REG_INT };
        struct i2c_client *client = to_i2c_client(dev);
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 2, int_addr },        /* setup read ptr */
-               { client->addr, I2C_M_RD, 1, &intreg },  /* read INT register */
+               { /* setup read ptr */
+                       .addr = client->addr,
+                       .len = 2,
+                       .buf = int_addr
+               },
+               {/* read INT register */
+
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = &intreg
+               },
        };
 
        /* read interrupt register and status register */
index 47cccd52aae8d15b1f064fe016b9eacbd3f16203..7dabef624da394e6b90a2e04c787f74a4ffaa98d 100644 (file)
@@ -190,6 +190,9 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
        if (index >= kdev->desc->num_vq)
                return ERR_PTR(-ENOENT);
 
+       if (!name)
+               return NULL;
+
        config = kvm_vq_config(kdev->desc)+index;
 
        err = vmem_add_mapping(config->address,
@@ -198,7 +201,7 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
        if (err)
                goto out;
 
-       vq = vring_new_virtqueue(config->num, KVM_S390_VIRTIO_RING_ALIGN,
+       vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN,
                                 vdev, true, (void *) config->address,
                                 kvm_notify, callback, name);
        if (!vq) {
index 7199534cd07dba461f80d1dcde707ec4bda7fe4d..cb7f1582a6d158ebc41e1ca1e6dcb4b390d098ba 100644 (file)
@@ -93,7 +93,7 @@ static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
 #elif defined(__devinitconst)
 static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
 #else
-static const struct pci_device_id aac_pci_tbl[] __devinitdata = {
+static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
 #endif
        { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
        { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
index ff80552ead84ade04bddab69b162b714197a60d7..1c4120c3db41f622fc4277c6d7e549c71a3a18b5 100644 (file)
@@ -1012,7 +1012,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
        .lldd_ata_set_dmamode   = asd_set_dmamode,
 };
 
-static const struct pci_device_id aic94xx_pci_table[] __devinitdata = {
+static const struct pci_device_id aic94xx_pci_table[] __devinitconst = {
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1},
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1},
        {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1},
index 68ce08552f699b6752cecfaa2c8a9174e8c7c634..a540162ac59c1483bfd71c43a2384df4a1525529 100644 (file)
@@ -1173,7 +1173,16 @@ wait_io1:
        outw(val, tmport);
        outb(2, 0x80);
 TCM_SYNC:
-       udelay(0x800);
+       /*
+        * The funny division into multiple delays is to accomodate
+        * arches like ARM where udelay() multiplies its argument by
+        * a large number to initialize a loop counter.  To avoid
+        * overflow, the maximum supported udelay is 2000 microseconds.
+        *
+        * XXX it would be more polite to find a way to use msleep()
+        */
+       mdelay(2);
+       udelay(48);
        if ((inb(tmport) & 0x80) == 0x00) {     /* bsy ? */
                outw(0, tmport--);
                outb(0, tmport);
index e3f29f61cbc3910f7dec04e8fdc702b3077e1454..fe6029f4df164406e406fb8ca6b2c698461fd48a 100644 (file)
@@ -6373,14 +6373,14 @@ static struct ata_port_info sata_port_info = {
 
 #ifdef CONFIG_PPC_PSERIES
 static const u16 ipr_blocked_processors[] = {
-       PV_NORTHSTAR,
-       PV_PULSAR,
-       PV_POWER4,
-       PV_ICESTAR,
-       PV_SSTAR,
-       PV_POWER4p,
-       PV_630,
-       PV_630p
+       PVR_NORTHSTAR,
+       PVR_PULSAR,
+       PVR_POWER4,
+       PVR_ICESTAR,
+       PVR_SSTAR,
+       PVR_POWER4p,
+       PVR_630,
+       PVR_630p
 };
 
 /**
@@ -6400,7 +6400,7 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
 
        if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
                for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++) {
-                       if (__is_processor(ipr_blocked_processors[i]))
+                       if (pvr_version_is(ipr_blocked_processors[i]))
                                return 1;
                }
        }
index 9bd1c92ad96e89abe988dea3def8b37944643e30..dfb4b7f448c585e4a88b78a803e5d61e7d5bbe00 100644 (file)
@@ -37,8 +37,6 @@
 
 #include <linux/spi/spi.h>
 
-#include <plat/clock.h>
-
 #define OMAP1_SPI100K_MAX_FREQ          48000000
 
 #define ICR_SPITAS      (OMAP7XX_ICR_BASE + 0x12)
index 474e2174e08a5576d8ec432fd7a52e49b8baf782..3542fdc664b11abcaecd579b8743b52346453354 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <linux/spi/spi.h>
 
-#include <plat/clock.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #define OMAP2_MCSPI_MAX_FREQ           48000000
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 67789b8345d25cb7a5fad998863aab3c9d999689..efd81bb25e0157926ac8a03a556758f2ed124b1a 100644 (file)
@@ -78,7 +78,7 @@ again:
        else if (unlikely(err))
                return err;
 
-       *id = *id & MAX_ID_MASK;
+       *id = *id & MAX_IDR_MASK;
        return 0;
 }
 
index 4a652999380f691a359fc614f605cb18ede57ae9..a5dec1ca1b826bad18d9a1bf5c69eae17bfba423 100644 (file)
@@ -245,6 +245,20 @@ static void hvc_port_destruct(struct tty_port *port)
        kfree(hp);
 }
 
+static void hvc_check_console(int index)
+{
+       /* Already enabled, bail out */
+       if (hvc_console.flags & CON_ENABLED)
+               return;
+
+       /* If this index is what the user requested, then register
+        * now (setup won't fail at this point).  It's ok to just
+        * call register again if previously .setup failed.
+        */
+       if (index == hvc_console.index)
+               register_console(&hvc_console);
+}
+
 /*
  * hvc_instantiate() is an early console discovery method which locates
  * consoles * prior to the vio subsystem discovering them.  Hotplugged
@@ -275,12 +289,8 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
        if (last_hvc < index)
                last_hvc = index;
 
-       /* if this index is what the user requested, then register
-        * now (setup won't fail at this point).  It's ok to just
-        * call register again if previously .setup failed.
-        */
-       if (index == hvc_console.index)
-               register_console(&hvc_console);
+       /* check if we need to re-register the kernel console */
+       hvc_check_console(index);
 
        return 0;
 }
@@ -877,10 +887,15 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
                i = ++last_hvc;
 
        hp->index = i;
+       cons_ops[i] = ops;
+       vtermnos[i] = vtermno;
 
        list_add_tail(&(hp->next), &hvc_structs);
        spin_unlock(&hvc_structs_lock);
 
+       /* check if we need to re-register the kernel console */
+       hvc_check_console(i);
+
        return hp;
 }
 EXPORT_SYMBOL_GPL(hvc_alloc);
@@ -893,8 +908,12 @@ int hvc_remove(struct hvc_struct *hp)
        tty = tty_port_tty_get(&hp->port);
 
        spin_lock_irqsave(&hp->lock, flags);
-       if (hp->index < MAX_NR_HVC_CONSOLES)
+       if (hp->index < MAX_NR_HVC_CONSOLES) {
+               console_lock();
                vtermnos[hp->index] = -1;
+               cons_ops[hp->index] = NULL;
+               console_unlock();
+       }
 
        /* Don't whack hp->irq because tty_hangup() will need to free the irq. */
 
index ee307799271a4d3cd362cb131a58490d0d00f18b..070c0ee6864239c5d395f71d37d563edcbbee7be 100644 (file)
@@ -230,6 +230,69 @@ static const struct hv_ops hvterm_hvsi_ops = {
        .tiocmset = hvterm_hvsi_tiocmset,
 };
 
+static void udbg_hvc_putc(char c)
+{
+       int count = -1;
+
+       if (!hvterm_privs[0])
+               return;
+
+       if (c == '\n')
+               udbg_hvc_putc('\r');
+
+       do {
+               switch(hvterm_privs[0]->proto) {
+               case HV_PROTOCOL_RAW:
+                       count = hvterm_raw_put_chars(0, &c, 1);
+                       break;
+               case HV_PROTOCOL_HVSI:
+                       count = hvterm_hvsi_put_chars(0, &c, 1);
+                       break;
+               }
+       } while(count == 0);
+}
+
+static int udbg_hvc_getc_poll(void)
+{
+       int rc = 0;
+       char c;
+
+       if (!hvterm_privs[0])
+               return -1;
+
+       switch(hvterm_privs[0]->proto) {
+       case HV_PROTOCOL_RAW:
+               rc = hvterm_raw_get_chars(0, &c, 1);
+               break;
+       case HV_PROTOCOL_HVSI:
+               rc = hvterm_hvsi_get_chars(0, &c, 1);
+               break;
+       }
+       if (!rc)
+               return -1;
+       return c;
+}
+
+static int udbg_hvc_getc(void)
+{
+       int ch;
+
+       if (!hvterm_privs[0])
+               return -1;
+
+       for (;;) {
+               ch = udbg_hvc_getc_poll();
+               if (ch == -1) {
+                       /* This shouldn't be needed...but... */
+                       volatile unsigned long delay;
+                       for (delay=0; delay < 2000000; delay++)
+                               ;
+               } else {
+                       return ch;
+               }
+       }
+}
+
 static int __devinit hvc_vio_probe(struct vio_dev *vdev,
                                   const struct vio_device_id *id)
 {
@@ -289,6 +352,13 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
                return PTR_ERR(hp);
        dev_set_drvdata(&vdev->dev, hp);
 
+       /* register udbg if it's not there already for console 0 */
+       if (hp->index == 0 && !udbg_putc) {
+               udbg_putc = udbg_hvc_putc;
+               udbg_getc = udbg_hvc_getc;
+               udbg_getc_poll = udbg_hvc_getc_poll;
+       }
+
        return 0;
 }
 
@@ -331,59 +401,6 @@ static void __exit hvc_vio_exit(void)
 }
 module_exit(hvc_vio_exit);
 
-static void udbg_hvc_putc(char c)
-{
-       int count = -1;
-
-       if (c == '\n')
-               udbg_hvc_putc('\r');
-
-       do {
-               switch(hvterm_priv0.proto) {
-               case HV_PROTOCOL_RAW:
-                       count = hvterm_raw_put_chars(0, &c, 1);
-                       break;
-               case HV_PROTOCOL_HVSI:
-                       count = hvterm_hvsi_put_chars(0, &c, 1);
-                       break;
-               }
-       } while(count == 0);
-}
-
-static int udbg_hvc_getc_poll(void)
-{
-       int rc = 0;
-       char c;
-
-       switch(hvterm_priv0.proto) {
-       case HV_PROTOCOL_RAW:
-               rc = hvterm_raw_get_chars(0, &c, 1);
-               break;
-       case HV_PROTOCOL_HVSI:
-               rc = hvterm_hvsi_get_chars(0, &c, 1);
-               break;
-       }
-       if (!rc)
-               return -1;
-       return c;
-}
-
-static int udbg_hvc_getc(void)
-{
-       int ch;
-       for (;;) {
-               ch = udbg_hvc_getc_poll();
-               if (ch == -1) {
-                       /* This shouldn't be needed...but... */
-                       volatile unsigned long delay;
-                       for (delay=0; delay < 2000000; delay++)
-                               ;
-               } else {
-                       return ch;
-               }
-       }
-}
-
 void __init hvc_vio_init_early(void)
 {
        struct device_node *stdout_node;
index 747442d2c0f69a8207c4ab577ca6a27f21a3d037..0fefa84ed9aef06c8df664c289d42cbecc8dac76 100644 (file)
@@ -149,7 +149,7 @@ enum {
 };
 
 /* Must match above enum */
-static const char *r128_family[] __devinitdata = {
+static char * const r128_family[] __devinitconst = {
        "AGP",
        "PCI",
        "PRO AGP",
index f49181c7311390c471b0abc6caa6d8ca6ae4de91..b7ec34c57f46d7f3c0b345935c3e4857e3a0b104 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
@@ -31,57 +32,26 @@ struct pm860x_backlight_data {
        int     port;
        int     pwm;
        int     iset;
+       int     reg_duty_cycle;
+       int     reg_always_on;
+       int     reg_current;
 };
 
-static inline int wled_a(int port)
-{
-       int ret;
-
-       ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
-       return ret;
-}
-
-static inline int wled_b(int port)
-{
-       int ret;
-
-       ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
-       return ret;
-}
-
-/* WLED2 & WLED3 share the same IDC */
-static inline int wled_idc(int port)
-{
-       int ret;
-
-       switch (port) {
-       case PM8606_BACKLIGHT1:
-       case PM8606_BACKLIGHT2:
-               ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
-               break;
-       case PM8606_BACKLIGHT3:
-       default:
-               ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
-               break;
-       }
-       return ret;
-}
-
 static int backlight_power_set(struct pm860x_chip *chip, int port,
                int on)
 {
        int ret = -EINVAL;
 
        switch (port) {
-       case PM8606_BACKLIGHT1:
+       case 0:
                ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) :
                        pm8606_osc_disable(chip, WLED1_DUTY);
                break;
-       case PM8606_BACKLIGHT2:
+       case 1:
                ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) :
                        pm8606_osc_disable(chip, WLED2_DUTY);
                break;
-       case PM8606_BACKLIGHT3:
+       case 2:
                ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) :
                        pm8606_osc_disable(chip, WLED3_DUTY);
                break;
@@ -104,13 +74,13 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
        if (brightness)
                backlight_power_set(chip, data->port, 1);
 
-       ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
+       ret = pm860x_reg_write(data->i2c, data->reg_duty_cycle, value);
        if (ret < 0)
                goto out;
 
        if ((data->current_brightness == 0) && brightness) {
                if (data->iset) {
-                       ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
+                       ret = pm860x_set_bits(data->i2c, data->reg_current,
                                              CURRENT_BITMASK, data->iset);
                        if (ret < 0)
                                goto out;
@@ -123,17 +93,17 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
                }
                if (brightness == MAX_BRIGHTNESS) {
                        /* set WLED_ON bit as 100% */
-                       ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+                       ret = pm860x_set_bits(data->i2c, data->reg_always_on,
                                              PM8606_WLED_ON, PM8606_WLED_ON);
                }
        } else {
                if (brightness == MAX_BRIGHTNESS) {
                        /* set WLED_ON bit as 100% */
-                       ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+                       ret = pm860x_set_bits(data->i2c, data->reg_always_on,
                                              PM8606_WLED_ON, PM8606_WLED_ON);
                } else {
                        /* clear WLED_ON bit since it's not 100% */
-                       ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+                       ret = pm860x_set_bits(data->i2c, data->reg_always_on,
                                              PM8606_WLED_ON, 0);
                }
        }
@@ -174,7 +144,7 @@ static int pm860x_backlight_get_brightness(struct backlight_device *bl)
        struct pm860x_chip *chip = data->chip;
        int ret;
 
-       ret = pm860x_reg_read(data->i2c, wled_a(data->port));
+       ret = pm860x_reg_read(data->i2c, data->reg_duty_cycle);
        if (ret < 0)
                goto out;
        data->current_brightness = ret;
@@ -190,45 +160,85 @@ static const struct backlight_ops pm860x_backlight_ops = {
        .get_brightness = pm860x_backlight_get_brightness,
 };
 
+#ifdef CONFIG_OF
+static int pm860x_backlight_dt_init(struct platform_device *pdev,
+                                   struct pm860x_backlight_data *data,
+                                   char *name)
+{
+       struct device_node *nproot = pdev->dev.parent->of_node, *np;
+       int iset = 0;
+       if (!nproot)
+               return -ENODEV;
+       nproot = of_find_node_by_name(nproot, "backlights");
+       if (!nproot) {
+               dev_err(&pdev->dev, "failed to find backlights node\n");
+               return -ENODEV;
+       }
+       for_each_child_of_node(nproot, np) {
+               if (!of_node_cmp(np->name, name)) {
+                       of_property_read_u32(np, "marvell,88pm860x-iset",
+                                            &iset);
+                       data->iset = PM8606_WLED_CURRENT(iset);
+                       of_property_read_u32(np, "marvell,88pm860x-pwm",
+                                            &data->pwm);
+                       break;
+               }
+       }
+       return 0;
+}
+#else
+#define pm860x_backlight_dt_init(x, y, z)      (-1)
+#endif
+
 static int pm860x_backlight_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm860x_backlight_pdata *pdata = NULL;
+       struct pm860x_backlight_pdata *pdata = pdev->dev.platform_data;
        struct pm860x_backlight_data *data;
        struct backlight_device *bl;
        struct resource *res;
        struct backlight_properties props;
        char name[MFD_NAME_SIZE];
-       int ret;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource!\n");
-               return -EINVAL;
-       }
-
-       pdata = pdev->dev.platform_data;
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "platform data isn't assigned to "
-                       "backlight\n");
-               return -EINVAL;
-       }
+       int ret = 0;
 
        data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_backlight_data),
                            GFP_KERNEL);
        if (data == NULL)
                return -ENOMEM;
-       strncpy(name, res->name, MFD_NAME_SIZE);
+       res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle");
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for duty cycle\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_duty_cycle = res->start;
+       res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on");
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resorce for always on\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_always_on = res->start;
+       res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current");
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for current\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_current = res->start;
+
+       memset(name, 0, MFD_NAME_SIZE);
+       sprintf(name, "backlight-%d", pdev->id);
+       data->port = pdev->id;
        data->chip = chip;
        data->i2c = (chip->id == CHIP_PM8606) ? chip->client    \
                        : chip->companion;
        data->current_brightness = MAX_BRIGHTNESS;
-       data->pwm = pdata->pwm;
-       data->iset = pdata->iset;
-       data->port = pdata->flags;
-       if (data->port < 0) {
-               dev_err(&pdev->dev, "wrong platform data is assigned");
-               return -EINVAL;
+       if (pm860x_backlight_dt_init(pdev, data, name)) {
+               if (pdata) {
+                       data->pwm = pdata->pwm;
+                       data->iset = pdata->iset;
+               }
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
@@ -247,12 +257,14 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
        /* read current backlight */
        ret = pm860x_backlight_get_brightness(bl);
        if (ret < 0)
-               goto out;
+               goto out_brt;
 
        backlight_update_status(bl);
        return 0;
-out:
+out_brt:
        backlight_device_unregister(bl);
+out:
+       devm_kfree(&pdev->dev, data);
        return ret;
 }
 
index cf282763a8dc941ab96554ed1cae855d959199de..c101697a4ba708e06b2ea102ba6000d97eaa0ed8 100644 (file)
@@ -229,13 +229,6 @@ config BACKLIGHT_HP700
          If you have an HP Jornada 700 series,
          say Y to include backlight control driver.
 
-config BACKLIGHT_PROGEAR
-       tristate "Frontpath ProGear Backlight Driver"
-       depends on PCI && X86
-       help
-         If you have a Frontpath ProGear say Y to enable the
-         backlight driver.
-
 config BACKLIGHT_CARILLO_RANCH
        tristate "Intel Carillo Ranch Backlight Driver"
        depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578
@@ -352,6 +345,22 @@ config BACKLIGHT_AAT2870
          If you have a AnalogicTech AAT2870 say Y to enable the
          backlight driver.
 
+config BACKLIGHT_LM3630
+       tristate "Backlight Driver for LM3630"
+       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       select REGMAP_I2C
+       help
+         This supports TI LM3630 Backlight Driver
+
+config BACKLIGHT_LM3639
+       tristate "Backlight Driver for LM3639"
+       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       select REGMAP_I2C
+       select NEW_LEDS
+       select LEDS_CLASS
+       help
+         This supports TI LM3639 Backlight + 1.5A Flash LED Driver
+
 config BACKLIGHT_LP855X
        tristate "Backlight driver for TI LP855X"
        depends on BACKLIGHT_CLASS_DEVICE && I2C
@@ -373,6 +382,13 @@ config BACKLIGHT_PANDORA
          If you have a Pandora console, say Y to enable the
          backlight driver.
 
+config BACKLIGHT_TPS65217
+       tristate "TPS65217 Backlight"
+       depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
+       help
+         If you have a Texas Instruments TPS65217 say Y to enable the
+         backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
index a2ac9cfbaf6bf1869e1c2b020b597952d4a7633a..e7ce7291635d61c2ece68722fc2e27cf1ad52d7d 100644 (file)
@@ -23,10 +23,11 @@ obj-$(CONFIG_BACKLIGHT_HP700)       += jornada720_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)  += hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
+obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o
+obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o
 obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o
 obj-$(CONFIG_BACKLIGHT_OMAP1)  += omap1_bl.o
 obj-$(CONFIG_BACKLIGHT_PANDORA)        += pandora_bl.o
-obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)    += pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
@@ -43,3 +44,4 @@ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
index b628d68f516284ea69f9ab204532d183d5ce0dc8..ac196181fe45a88ae45965ac7d18cb91570b1eb3 100644 (file)
@@ -72,7 +72,7 @@ static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
        if (ret < 0)
                return ret;
 
-       msleep(10);
+       usleep_range(10000, 11000);
 
        if (wleds->brightness) {
                ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg],
@@ -129,7 +129,6 @@ static int da9052_backlight_probe(struct platform_device *pdev)
                                       &da9052_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "Failed to register backlight\n");
-               devm_kfree(&pdev->dev, wleds);
                return PTR_ERR(bl);
        }
 
@@ -149,7 +148,6 @@ static int da9052_backlight_remove(struct platform_device *pdev)
        wleds->state = DA9052_WLEDS_OFF;
        da9052_adjust_wled_brightness(wleds);
        backlight_device_unregister(bl);
-       devm_kfree(&pdev->dev, wleds);
 
        return 0;
 }
index 72dd5556a35bdbe825f4fb86033f82828f206bc3..6c5ed6b242cc06f87706fe7dd85a4700a743ca82 100644 (file)
@@ -34,9 +34,9 @@ static void kb3886_bl_set_intensity(int intensity)
        mutex_lock(&bl_mutex);
        intensity = intensity&0xff;
        outb(KB3886_ADC_DAC_PWM, KB3886_PARENT);
-       msleep(10);
+       usleep_range(10000, 11000);
        outb(KB3886_PWM0_WRITE, KB3886_IO);
-       msleep(10);
+       usleep_range(10000, 11000);
        outb(intensity, KB3886_IO);
        mutex_unlock(&bl_mutex);
 }
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
new file mode 100644 (file)
index 0000000..dc19144
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+* Simple driver for Texas Instruments LM3630 Backlight driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/platform_data/lm3630_bl.h>
+
+#define REG_CTRL       0x00
+#define REG_CONFIG     0x01
+#define REG_BRT_A      0x03
+#define REG_BRT_B      0x04
+#define REG_INT_STATUS 0x09
+#define REG_INT_EN     0x0A
+#define REG_FAULT      0x0B
+#define REG_PWM_OUTLOW 0x12
+#define REG_PWM_OUTHIGH        0x13
+#define REG_MAX                0x1F
+
+#define INT_DEBOUNCE_MSEC      10
+
+enum lm3630_leds {
+       BLED_ALL = 0,
+       BLED_1,
+       BLED_2
+};
+
+static const char *bled_name[] = {
+       [BLED_ALL] = "lm3630_bled",     /*Bank1 controls all string */
+       [BLED_1] = "lm3630_bled1",      /*Bank1 controls bled1 */
+       [BLED_2] = "lm3630_bled2",      /*Bank1 or 2 controls bled2 */
+};
+
+struct lm3630_chip_data {
+       struct device *dev;
+       struct delayed_work work;
+       int irq;
+       struct workqueue_struct *irqthread;
+       struct lm3630_platform_data *pdata;
+       struct backlight_device *bled1;
+       struct backlight_device *bled2;
+       struct regmap *regmap;
+};
+
+/* initialize chip */
+static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3630_platform_data *pdata = pchip->pdata;
+
+       /*pwm control */
+       reg_val = ((pdata->pwm_active & 0x01) << 2) | (pdata->pwm_ctrl & 0x03);
+       ret = regmap_update_bits(pchip->regmap, REG_CONFIG, 0x07, reg_val);
+       if (ret < 0)
+               goto out;
+
+       /* bank control */
+       reg_val = ((pdata->bank_b_ctrl & 0x01) << 1) |
+                       (pdata->bank_a_ctrl & 0x07);
+       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x07, reg_val);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+       if (ret < 0)
+               goto out;
+
+       /* set initial brightness */
+       if (pdata->bank_a_ctrl != BANK_A_CTRL_DISABLE) {
+               ret = regmap_write(pchip->regmap,
+                                  REG_BRT_A, pdata->init_brt_led1);
+               if (ret < 0)
+                       goto out;
+       }
+
+       if (pdata->bank_b_ctrl != BANK_B_CTRL_DISABLE) {
+               ret = regmap_write(pchip->regmap,
+                                  REG_BRT_B, pdata->init_brt_led2);
+               if (ret < 0)
+                       goto out;
+       }
+       return ret;
+
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return ret;
+}
+
+/* interrupt handling */
+static void lm3630_delayed_func(struct work_struct *work)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3630_chip_data *pchip;
+
+       pchip = container_of(work, struct lm3630_chip_data, work.work);
+
+       ret = regmap_read(pchip->regmap, REG_INT_STATUS, &reg_val);
+       if (ret < 0) {
+               dev_err(pchip->dev,
+                       "i2c failed to access REG_INT_STATUS Register\n");
+               return;
+       }
+
+       dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", reg_val);
+}
+
+static irqreturn_t lm3630_isr_func(int irq, void *chip)
+{
+       int ret;
+       struct lm3630_chip_data *pchip = chip;
+       unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
+
+       queue_delayed_work(pchip->irqthread, &pchip->work, delay);
+
+       ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+       if (ret < 0)
+               goto out;
+
+       return IRQ_HANDLED;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return IRQ_HANDLED;
+}
+
+static int lm3630_intr_config(struct lm3630_chip_data *pchip)
+{
+       INIT_DELAYED_WORK(&pchip->work, lm3630_delayed_func);
+       pchip->irqthread = create_singlethread_workqueue("lm3630-irqthd");
+       if (!pchip->irqthread) {
+               dev_err(pchip->dev, "create irq thread fail...\n");
+               return -1;
+       }
+       if (request_threaded_irq
+           (pchip->irq, NULL, lm3630_isr_func,
+            IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630_irq", pchip)) {
+               dev_err(pchip->dev, "request threaded irq fail..\n");
+               return -1;
+       }
+       return 0;
+}
+
+static bool
+set_intensity(struct backlight_device *bl, struct lm3630_chip_data *pchip)
+{
+       if (!pchip->pdata->pwm_set_intensity)
+               return false;
+       pchip->pdata->pwm_set_intensity(bl->props.brightness - 1,
+                                       pchip->pdata->pwm_period);
+       return true;
+}
+
+/* update and get brightness */
+static int lm3630_bank_a_update_status(struct backlight_device *bl)
+{
+       int ret;
+       struct lm3630_chip_data *pchip = bl_get_data(bl);
+       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       /* brightness 0 means disable */
+       if (!bl->props.brightness) {
+               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x04, 0x00);
+               if (ret < 0)
+                       goto out;
+               return bl->props.brightness;
+       }
+
+       /* pwm control */
+       if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) {
+               if (!set_intensity(bl, pchip))
+                       dev_err(pchip->dev, "No pwm control func. in plat-data\n");
+       } else {
+
+               /* i2c control */
+               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+               if (ret < 0)
+                       goto out;
+               mdelay(1);
+               ret = regmap_write(pchip->regmap,
+                                  REG_BRT_A, bl->props.brightness - 1);
+               if (ret < 0)
+                       goto out;
+       }
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access REG_CTRL\n");
+       return bl->props.brightness;
+}
+
+static int lm3630_bank_a_get_brightness(struct backlight_device *bl)
+{
+       unsigned int reg_val;
+       int brightness, ret;
+       struct lm3630_chip_data *pchip = bl_get_data(bl);
+       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) {
+               ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = reg_val & 0x01;
+               ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = ((brightness << 8) | reg_val) + 1;
+       } else {
+               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+               if (ret < 0)
+                       goto out;
+               mdelay(1);
+               ret = regmap_read(pchip->regmap, REG_BRT_A, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = reg_val + 1;
+       }
+       bl->props.brightness = brightness;
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return 0;
+}
+
+static const struct backlight_ops lm3630_bank_a_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = lm3630_bank_a_update_status,
+       .get_brightness = lm3630_bank_a_get_brightness,
+};
+
+static int lm3630_bank_b_update_status(struct backlight_device *bl)
+{
+       int ret;
+       struct lm3630_chip_data *pchip = bl_get_data(bl);
+       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) {
+               if (!set_intensity(bl, pchip))
+                       dev_err(pchip->dev,
+                               "no pwm control func. in plat-data\n");
+       } else {
+               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+               if (ret < 0)
+                       goto out;
+               mdelay(1);
+               ret = regmap_write(pchip->regmap,
+                                  REG_BRT_B, bl->props.brightness - 1);
+       }
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return bl->props.brightness;
+}
+
+static int lm3630_bank_b_get_brightness(struct backlight_device *bl)
+{
+       unsigned int reg_val;
+       int brightness, ret;
+       struct lm3630_chip_data *pchip = bl_get_data(bl);
+       enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
+
+       if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) {
+               ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = reg_val & 0x01;
+               ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = ((brightness << 8) | reg_val) + 1;
+       } else {
+               ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00);
+               if (ret < 0)
+                       goto out;
+               mdelay(1);
+               ret = regmap_read(pchip->regmap, REG_BRT_B, &reg_val);
+               if (ret < 0)
+                       goto out;
+               brightness = reg_val + 1;
+       }
+       bl->props.brightness = brightness;
+
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return bl->props.brightness;
+}
+
+static const struct backlight_ops lm3630_bank_b_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = lm3630_bank_b_update_status,
+       .get_brightness = lm3630_bank_b_get_brightness,
+};
+
+static int lm3630_backlight_register(struct lm3630_chip_data *pchip,
+                                    enum lm3630_leds ledno)
+{
+       const char *name = bled_name[ledno];
+       struct backlight_properties props;
+       struct lm3630_platform_data *pdata = pchip->pdata;
+
+       props.type = BACKLIGHT_RAW;
+       switch (ledno) {
+       case BLED_1:
+       case BLED_ALL:
+               props.brightness = pdata->init_brt_led1;
+               props.max_brightness = pdata->max_brt_led1;
+               pchip->bled1 =
+                   backlight_device_register(name, pchip->dev, pchip,
+                                             &lm3630_bank_a_ops, &props);
+               if (IS_ERR(pchip->bled1))
+                       return -EIO;
+               break;
+       case BLED_2:
+               props.brightness = pdata->init_brt_led2;
+               props.max_brightness = pdata->max_brt_led2;
+               pchip->bled2 =
+                   backlight_device_register(name, pchip->dev, pchip,
+                                             &lm3630_bank_b_ops, &props);
+               if (IS_ERR(pchip->bled2))
+                       return -EIO;
+               break;
+       }
+       return 0;
+}
+
+static void lm3630_backlight_unregister(struct lm3630_chip_data *pchip)
+{
+       if (pchip->bled1)
+               backlight_device_unregister(pchip->bled1);
+       if (pchip->bled2)
+               backlight_device_unregister(pchip->bled2);
+}
+
+static const struct regmap_config lm3630_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = REG_MAX,
+};
+
+static int __devinit lm3630_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lm3630_platform_data *pdata = client->dev.platform_data;
+       struct lm3630_chip_data *pchip;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "fail : i2c functionality check...\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "fail : no platform data.\n");
+               return -ENODATA;
+       }
+
+       pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630_chip_data),
+                            GFP_KERNEL);
+       if (!pchip)
+               return -ENOMEM;
+       pchip->pdata = pdata;
+       pchip->dev = &client->dev;
+
+       pchip->regmap = devm_regmap_init_i2c(client, &lm3630_regmap);
+       if (IS_ERR(pchip->regmap)) {
+               ret = PTR_ERR(pchip->regmap);
+               dev_err(&client->dev, "fail : allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, pchip);
+
+       /* chip initialize */
+       ret = lm3630_chip_init(pchip);
+       if (ret < 0) {
+               dev_err(&client->dev, "fail : init chip\n");
+               goto err_chip_init;
+       }
+
+       switch (pdata->bank_a_ctrl) {
+       case BANK_A_CTRL_ALL:
+               ret = lm3630_backlight_register(pchip, BLED_ALL);
+               pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE;
+               break;
+       case BANK_A_CTRL_LED1:
+               ret = lm3630_backlight_register(pchip, BLED_1);
+               break;
+       case BANK_A_CTRL_LED2:
+               ret = lm3630_backlight_register(pchip, BLED_2);
+               pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE;
+               break;
+       default:
+               break;
+       }
+
+       if (ret < 0)
+               goto err_bl_reg;
+
+       if (pdata->bank_b_ctrl && pchip->bled2 == NULL) {
+               ret = lm3630_backlight_register(pchip, BLED_2);
+               if (ret < 0)
+                       goto err_bl_reg;
+       }
+
+       /* interrupt enable  : irq 0 is not allowed for lm3630 */
+       pchip->irq = client->irq;
+       if (pchip->irq)
+               lm3630_intr_config(pchip);
+
+       dev_info(&client->dev, "LM3630 backlight register OK.\n");
+       return 0;
+
+err_bl_reg:
+       dev_err(&client->dev, "fail : backlight register.\n");
+       lm3630_backlight_unregister(pchip);
+err_chip_init:
+       return ret;
+}
+
+static int __devexit lm3630_remove(struct i2c_client *client)
+{
+       int ret;
+       struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
+
+       ret = regmap_write(pchip->regmap, REG_BRT_A, 0);
+       if (ret < 0)
+               dev_err(pchip->dev, "i2c failed to access register\n");
+
+       ret = regmap_write(pchip->regmap, REG_BRT_B, 0);
+       if (ret < 0)
+               dev_err(pchip->dev, "i2c failed to access register\n");
+
+       lm3630_backlight_unregister(pchip);
+       if (pchip->irq) {
+               free_irq(pchip->irq, pchip);
+               flush_workqueue(pchip->irqthread);
+               destroy_workqueue(pchip->irqthread);
+       }
+       return 0;
+}
+
+static const struct i2c_device_id lm3630_id[] = {
+       {LM3630_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3630_id);
+
+static struct i2c_driver lm3630_i2c_driver = {
+       .driver = {
+                  .name = LM3630_NAME,
+                  },
+       .probe = lm3630_probe,
+       .remove = __devexit_p(lm3630_remove),
+       .id_table = lm3630_id,
+};
+
+module_i2c_driver(lm3630_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
new file mode 100644 (file)
index 0000000..c6915c6
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+* Simple driver for Texas Instruments LM3639 Backlight + Flash LED driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/platform_data/lm3639_bl.h>
+
+#define REG_DEV_ID     0x00
+#define REG_CHECKSUM   0x01
+#define REG_BL_CONF_1  0x02
+#define REG_BL_CONF_2  0x03
+#define REG_BL_CONF_3  0x04
+#define REG_BL_CONF_4  0x05
+#define REG_FL_CONF_1  0x06
+#define REG_FL_CONF_2  0x07
+#define REG_FL_CONF_3  0x08
+#define REG_IO_CTRL    0x09
+#define REG_ENABLE     0x0A
+#define REG_FLAG       0x0B
+#define REG_MAX                REG_FLAG
+
+struct lm3639_chip_data {
+       struct device *dev;
+       struct lm3639_platform_data *pdata;
+
+       struct backlight_device *bled;
+       struct led_classdev cdev_flash;
+       struct led_classdev cdev_torch;
+       struct regmap *regmap;
+
+       unsigned int bled_mode;
+       unsigned int bled_map;
+       unsigned int last_flag;
+};
+
+/* initialize chip */
+static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3639_platform_data *pdata = pchip->pdata;
+
+       /* input pins config. */
+       ret =
+           regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x08,
+                              pdata->pin_pwm);
+       if (ret < 0)
+               goto out;
+
+       reg_val = (pdata->pin_pwm & 0x40) | pdata->pin_strobe | pdata->pin_tx;
+       ret = regmap_update_bits(pchip->regmap, REG_IO_CTRL, 0x7C, reg_val);
+       if (ret < 0)
+               goto out;
+
+       /* init brightness */
+       ret = regmap_write(pchip->regmap, REG_BL_CONF_4, pdata->init_brt_led);
+       if (ret < 0)
+               goto out;
+
+       ret = regmap_write(pchip->regmap, REG_BL_CONF_3, pdata->init_brt_led);
+       if (ret < 0)
+               goto out;
+
+       /* output pins config. */
+       if (!pdata->init_brt_led)
+               reg_val = pdata->fled_pins | pdata->bled_pins;
+       else
+               reg_val = pdata->fled_pins | pdata->bled_pins | 0x01;
+
+       ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val);
+       if (ret < 0)
+               goto out;
+
+       return ret;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return ret;
+}
+
+/* update and get brightness */
+static int lm3639_bled_update_status(struct backlight_device *bl)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3639_chip_data *pchip = bl_get_data(bl);
+       struct lm3639_platform_data *pdata = pchip->pdata;
+
+       ret = regmap_read(pchip->regmap, REG_FLAG, &reg_val);
+       if (ret < 0)
+               goto out;
+
+       if (reg_val != 0)
+               dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
+
+       /* pwm control */
+       if (pdata->pin_pwm) {
+               if (pdata->pwm_set_intensity)
+                       pdata->pwm_set_intensity(bl->props.brightness,
+                                                pdata->max_brt_led);
+               else
+                       dev_err(pchip->dev,
+                               "No pwm control func. in plat-data\n");
+               return bl->props.brightness;
+       }
+
+       /* i2c control and set brigtness */
+       ret = regmap_write(pchip->regmap, REG_BL_CONF_4, bl->props.brightness);
+       if (ret < 0)
+               goto out;
+       ret = regmap_write(pchip->regmap, REG_BL_CONF_3, bl->props.brightness);
+       if (ret < 0)
+               goto out;
+
+       if (!bl->props.brightness)
+               ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x00);
+       else
+               ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x01);
+       if (ret < 0)
+               goto out;
+
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access registers\n");
+       return bl->props.brightness;
+}
+
+static int lm3639_bled_get_brightness(struct backlight_device *bl)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3639_chip_data *pchip = bl_get_data(bl);
+       struct lm3639_platform_data *pdata = pchip->pdata;
+
+       if (pdata->pin_pwm) {
+               if (pdata->pwm_get_intensity)
+                       bl->props.brightness = pdata->pwm_get_intensity();
+               else
+                       dev_err(pchip->dev,
+                               "No pwm control func. in plat-data\n");
+               return bl->props.brightness;
+       }
+
+       ret = regmap_read(pchip->regmap, REG_BL_CONF_1, &reg_val);
+       if (ret < 0)
+               goto out;
+       if (reg_val & 0x10)
+               ret = regmap_read(pchip->regmap, REG_BL_CONF_4, &reg_val);
+       else
+               ret = regmap_read(pchip->regmap, REG_BL_CONF_3, &reg_val);
+       if (ret < 0)
+               goto out;
+       bl->props.brightness = reg_val;
+
+       return bl->props.brightness;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return bl->props.brightness;
+}
+
+static const struct backlight_ops lm3639_bled_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .update_status = lm3639_bled_update_status,
+       .get_brightness = lm3639_bled_get_brightness,
+};
+
+/* backlight mapping mode */
+static ssize_t lm3639_bled_mode_store(struct device *dev,
+                                     struct device_attribute *devAttr,
+                                     const char *buf, size_t size)
+{
+       ssize_t ret;
+       struct lm3639_chip_data *pchip = dev_get_drvdata(dev);
+       unsigned int state;
+
+       ret = kstrtouint(buf, 10, &state);
+       if (ret)
+               goto out_input;
+
+       if (!state)
+               ret =
+                   regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10,
+                                      0x00);
+       else
+               ret =
+                   regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10,
+                                      0x10);
+
+       if (ret < 0)
+               goto out;
+
+       return size;
+
+out:
+       dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__);
+       return size;
+
+out_input:
+       dev_err(pchip->dev, "%s:input conversion fail\n", __func__);
+       return size;
+
+}
+
+static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store);
+
+/* torch */
+static void lm3639_torch_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3639_chip_data *pchip;
+
+       pchip = container_of(cdev, struct lm3639_chip_data, cdev_torch);
+
+       ret = regmap_read(pchip->regmap, REG_FLAG, &reg_val);
+       if (ret < 0)
+               goto out;
+       if (reg_val != 0)
+               dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
+
+       /* brightness 0 means off state */
+       if (!brightness) {
+               ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00);
+               if (ret < 0)
+                       goto out;
+               return;
+       }
+
+       ret = regmap_update_bits(pchip->regmap,
+                                REG_FL_CONF_1, 0x70, (brightness - 1) << 4);
+       if (ret < 0)
+               goto out;
+       ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x02);
+       if (ret < 0)
+               goto out;
+
+       return;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return;
+}
+
+/* flash */
+static void lm3639_flash_brightness_set(struct led_classdev *cdev,
+                                       enum led_brightness brightness)
+{
+       int ret;
+       unsigned int reg_val;
+       struct lm3639_chip_data *pchip;
+
+       pchip = container_of(cdev, struct lm3639_chip_data, cdev_flash);
+
+       ret = regmap_read(pchip->regmap, REG_FLAG, &reg_val);
+       if (ret < 0)
+               goto out;
+       if (reg_val != 0)
+               dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
+
+       /* torch off before flash control */
+       ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00);
+       if (ret < 0)
+               goto out;
+
+       /* brightness 0 means off state */
+       if (!brightness)
+               return;
+
+       ret = regmap_update_bits(pchip->regmap,
+                                REG_FL_CONF_1, 0x0F, brightness - 1);
+       if (ret < 0)
+               goto out;
+       ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x06);
+       if (ret < 0)
+               goto out;
+
+       return;
+out:
+       dev_err(pchip->dev, "i2c failed to access register\n");
+       return;
+}
+
+static const struct regmap_config lm3639_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = REG_MAX,
+};
+
+static int __devinit lm3639_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       int ret;
+       struct lm3639_chip_data *pchip;
+       struct lm3639_platform_data *pdata = client->dev.platform_data;
+       struct backlight_properties props;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "i2c functionality check fail.\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "Needs Platform Data.\n");
+               return -ENODATA;
+       }
+
+       pchip = devm_kzalloc(&client->dev,
+                            sizeof(struct lm3639_chip_data), GFP_KERNEL);
+       if (!pchip)
+               return -ENOMEM;
+
+       pchip->pdata = pdata;
+       pchip->dev = &client->dev;
+
+       pchip->regmap = devm_regmap_init_i2c(client, &lm3639_regmap);
+       if (IS_ERR(pchip->regmap)) {
+               ret = PTR_ERR(pchip->regmap);
+               dev_err(&client->dev, "fail : allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, pchip);
+
+       /* chip initialize */
+       ret = lm3639_chip_init(pchip);
+       if (ret < 0) {
+               dev_err(&client->dev, "fail : chip init\n");
+               goto err_out;
+       }
+
+       /* backlight */
+       props.type = BACKLIGHT_RAW;
+       props.brightness = pdata->init_brt_led;
+       props.max_brightness = pdata->max_brt_led;
+       pchip->bled =
+           backlight_device_register("lm3639_bled", pchip->dev, pchip,
+                                     &lm3639_bled_ops, &props);
+       if (IS_ERR(pchip->bled)) {
+               dev_err(&client->dev, "fail : backlight register\n");
+               ret = -EIO;
+               goto err_out;
+       }
+
+       ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed : add sysfs entries\n");
+               ret = -EIO;
+               goto err_bled_mode;
+       }
+
+       /* flash */
+       pchip->cdev_flash.name = "lm3639_flash";
+       pchip->cdev_flash.max_brightness = 16;
+       pchip->cdev_flash.brightness_set = lm3639_flash_brightness_set;
+       ret = led_classdev_register((struct device *)
+                                   &client->dev, &pchip->cdev_flash);
+       if (ret < 0) {
+               dev_err(&client->dev, "fail : flash register\n");
+               ret = -EIO;
+               goto err_flash;
+       }
+
+       /* torch */
+       pchip->cdev_torch.name = "lm3639_torch";
+       pchip->cdev_torch.max_brightness = 8;
+       pchip->cdev_torch.brightness_set = lm3639_torch_brightness_set;
+       ret = led_classdev_register((struct device *)
+                                   &client->dev, &pchip->cdev_torch);
+       if (ret < 0) {
+               dev_err(&client->dev, "fail : torch register\n");
+               ret = -EIO;
+               goto err_torch;
+       }
+
+       return 0;
+
+err_torch:
+       led_classdev_unregister(&pchip->cdev_flash);
+err_flash:
+       device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode);
+err_bled_mode:
+       backlight_device_unregister(pchip->bled);
+err_out:
+       return ret;
+}
+
+static int __devexit lm3639_remove(struct i2c_client *client)
+{
+       struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
+
+       regmap_write(pchip->regmap, REG_ENABLE, 0x00);
+
+       if (&pchip->cdev_torch)
+               led_classdev_unregister(&pchip->cdev_torch);
+       if (&pchip->cdev_flash)
+               led_classdev_unregister(&pchip->cdev_flash);
+       if (pchip->bled) {
+               device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode);
+               backlight_device_unregister(pchip->bled);
+       }
+       return 0;
+}
+
+static const struct i2c_device_id lm3639_id[] = {
+       {LM3639_NAME, 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3639_id);
+static struct i2c_driver lm3639_i2c_driver = {
+       .driver = {
+                  .name = LM3639_NAME,
+                  },
+       .probe = lm3639_probe,
+       .remove = __devexit_p(lm3639_remove),
+       .id_table = lm3639_id,
+};
+
+module_i2c_driver(lm3639_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Backlight+Flash LED driver for LM3639");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
index 6c0f1ac0d32a93d9f278ad21155d2ca9d81b22d9..4066a5bbd826297928b2c01bba5e4b6587614968 100644 (file)
@@ -75,7 +75,7 @@ static int ltv350qv_power_on(struct ltv350qv *lcd)
        /* Power On Reset Display off State */
        if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000))
                goto err;
-       msleep(15);
+       usleep_range(15000, 16000);
 
        /* Power Setting Function 1 */
        if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE))
@@ -153,7 +153,7 @@ err_settings:
 err_power2:
 err_power1:
        ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000);
-       msleep(1);
+       usleep_range(1000, 1100);
 err:
        ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE);
        return -EIO;
@@ -175,7 +175,7 @@ static int ltv350qv_power_off(struct ltv350qv *lcd)
        ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000);
 
        /* Wait at least 1 ms */
-       msleep(1);
+       usleep_range(1000, 1100);
 
        /* Power down setting 2 */
        ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE);
index e833ac72e063b80f26f08e613014f750891377d4..f72ba54f364e36cc7c2c61ca8be4a11f7d4c4930 100644 (file)
@@ -27,7 +27,9 @@
 struct max8925_backlight_data {
        struct max8925_chip     *chip;
 
-       int             current_brightness;
+       int     current_brightness;
+       int     reg_mode_cntl;
+       int     reg_cntl;
 };
 
 static int max8925_backlight_set(struct backlight_device *bl, int brightness)
@@ -42,16 +44,16 @@ static int max8925_backlight_set(struct backlight_device *bl, int brightness)
        else
                value = brightness;
 
-       ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
+       ret = max8925_reg_write(chip->i2c, data->reg_cntl, value);
        if (ret < 0)
                goto out;
 
        if (!data->current_brightness && brightness)
                /* enable WLED output */
-               ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
+               ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 1, 1);
        else if (!brightness)
                /* disable WLED output */
-               ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
+               ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 1, 0);
        if (ret < 0)
                goto out;
        dev_dbg(chip->dev, "set brightness %d\n", value);
@@ -85,7 +87,7 @@ static int max8925_backlight_get_brightness(struct backlight_device *bl)
        struct max8925_chip *chip = data->chip;
        int ret;
 
-       ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
+       ret = max8925_reg_read(chip->i2c, data->reg_cntl);
        if (ret < 0)
                return -EINVAL;
        data->current_brightness = ret;
@@ -102,69 +104,70 @@ static const struct backlight_ops max8925_backlight_ops = {
 static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct max8925_platform_data *max8925_pdata;
-       struct max8925_backlight_pdata *pdata = NULL;
+       struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
        struct max8925_backlight_data *data;
        struct backlight_device *bl;
        struct backlight_properties props;
        struct resource *res;
-       char name[MAX8925_NAME_SIZE];
        unsigned char value;
-       int ret;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "No I/O resource!\n");
-               return -EINVAL;
-       }
-
-       if (pdev->dev.parent->platform_data) {
-               max8925_pdata = pdev->dev.parent->platform_data;
-               pdata = max8925_pdata->backlight;
-       }
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "platform data isn't assigned to "
-                       "backlight\n");
-               return -EINVAL;
-       }
+       int ret = 0;
 
        data = devm_kzalloc(&pdev->dev, sizeof(struct max8925_backlight_data),
                            GFP_KERNEL);
        if (data == NULL)
                return -ENOMEM;
-       strncpy(name, res->name, MAX8925_NAME_SIZE);
+
+       res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for mode control!\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_mode_cntl = res->start;
+       res = platform_get_resource(pdev, IORESOURCE_REG, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "No REG resource for control!\n");
+               ret = -ENXIO;
+               goto out;
+       }
+       data->reg_cntl = res->start;
+
        data->chip = chip;
        data->current_brightness = 0;
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = MAX_BRIGHTNESS;
-       bl = backlight_device_register(name, &pdev->dev, data,
+       bl = backlight_device_register("max8925-backlight", &pdev->dev, data,
                                        &max8925_backlight_ops, &props);
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
-               return PTR_ERR(bl);
+               ret = PTR_ERR(bl);
+               goto out;
        }
        bl->props.brightness = MAX_BRIGHTNESS;
 
        platform_set_drvdata(pdev, bl);
 
        value = 0;
-       if (pdata->lxw_scl)
-               value |= (1 << 7);
-       if (pdata->lxw_freq)
-               value |= (LWX_FREQ(pdata->lxw_freq) << 4);
-       if (pdata->dual_string)
-               value |= (1 << 1);
-       ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
+       if (pdata) {
+               if (pdata->lxw_scl)
+                       value |= (1 << 7);
+               if (pdata->lxw_freq)
+                       value |= (LWX_FREQ(pdata->lxw_freq) << 4);
+               if (pdata->dual_string)
+                       value |= (1 << 1);
+       }
+       ret = max8925_set_bits(chip->i2c, data->reg_mode_cntl, 0xfe, value);
        if (ret < 0)
-               goto out;
+               goto out_brt;
 
        backlight_update_status(bl);
        return 0;
-out:
+out_brt:
        backlight_device_unregister(bl);
+out:
+       devm_kfree(&pdev->dev, data);
        return ret;
 }
 
index b6672340d6c78b2cac69e7665beb38f59450d6df..ca4f5d70fe10aa1fbb45dc488d0cd406bb151f43 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/fb.h>
 #include <linux/backlight.h>
 #include <linux/lcd.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 #include <video/platform_lcd.h>
@@ -145,6 +146,14 @@ static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend,
                        platform_lcd_resume);
 #endif
 
+#ifdef CONFIG_OF
+static const struct of_device_id platform_lcd_of_match[] = {
+       { .compatible = "platform-lcd" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, platform_lcd_of_match);
+#endif
+
 static struct platform_driver platform_lcd_driver = {
        .driver         = {
                .name   = "platform-lcd",
@@ -152,6 +161,7 @@ static struct platform_driver platform_lcd_driver = {
 #ifdef CONFIG_PM
                .pm     = &platform_lcd_pm_ops,
 #endif
+               .of_match_table = of_match_ptr(platform_lcd_of_match),
        },
        .probe          = platform_lcd_probe,
        .remove         = __devexit_p(platform_lcd_remove),
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
deleted file mode 100644 (file)
index 69b35f0..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *  Backlight Driver for Frontpath ProGear HX1050+
- *
- *  Copyright (c) 2006 Marcin Juszkiewicz
- *
- *  Based on Progear LCD driver by M Schacht
- *  <mschacht at alumni dot washington dot edu>
- *
- *  Based on Sharp's Corgi Backlight Driver
- *  Based on Backlight Driver for HP Jornada 680
- *
- *  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.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/fb.h>
-#include <linux/backlight.h>
-#include <linux/pci.h>
-
-#define PMU_LPCR               0xB0
-#define SB_MPS1                0x61
-#define HW_LEVEL_MAX           0x77
-#define HW_LEVEL_MIN           0x4f
-
-static struct pci_dev *pmu_dev = NULL;
-static struct pci_dev *sb_dev = NULL;
-
-static int progearbl_set_intensity(struct backlight_device *bd)
-{
-       int intensity = bd->props.brightness;
-
-       if (bd->props.power != FB_BLANK_UNBLANK)
-               intensity = 0;
-       if (bd->props.fb_blank != FB_BLANK_UNBLANK)
-               intensity = 0;
-
-       pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN);
-
-       return 0;
-}
-
-static int progearbl_get_intensity(struct backlight_device *bd)
-{
-       u8 intensity;
-       pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity);
-
-       return intensity - HW_LEVEL_MIN;
-}
-
-static const struct backlight_ops progearbl_ops = {
-       .get_brightness = progearbl_get_intensity,
-       .update_status = progearbl_set_intensity,
-};
-
-static int progearbl_probe(struct platform_device *pdev)
-{
-       struct backlight_properties props;
-       u8 temp;
-       struct backlight_device *progear_backlight_device;
-       int ret;
-
-       pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
-       if (!pmu_dev) {
-               pr_err("ALI M7101 PMU not found.\n");
-               return -ENODEV;
-       }
-
-       sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-       if (!sb_dev) {
-               pr_err("ALI 1533 SB not found.\n");
-               ret = -ENODEV;
-               goto put_pmu;
-       }
-
-       /*     Set SB_MPS1 to enable brightness control. */
-       pci_read_config_byte(sb_dev, SB_MPS1, &temp);
-       pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
-
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_RAW;
-       props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
-       progear_backlight_device = backlight_device_register("progear-bl",
-                                                            &pdev->dev, NULL,
-                                                            &progearbl_ops,
-                                                            &props);
-       if (IS_ERR(progear_backlight_device)) {
-               ret = PTR_ERR(progear_backlight_device);
-               goto put_sb;
-       }
-
-       platform_set_drvdata(pdev, progear_backlight_device);
-
-       progear_backlight_device->props.power = FB_BLANK_UNBLANK;
-       progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
-       progearbl_set_intensity(progear_backlight_device);
-
-       return 0;
-put_sb:
-       pci_dev_put(sb_dev);
-put_pmu:
-       pci_dev_put(pmu_dev);
-       return ret;
-}
-
-static int progearbl_remove(struct platform_device *pdev)
-{
-       struct backlight_device *bd = platform_get_drvdata(pdev);
-       backlight_device_unregister(bd);
-
-       return 0;
-}
-
-static struct platform_driver progearbl_driver = {
-       .probe = progearbl_probe,
-       .remove = progearbl_remove,
-       .driver = {
-                  .name = "progear-bl",
-                  },
-};
-
-static struct platform_device *progearbl_device;
-
-static int __init progearbl_init(void)
-{
-       int ret = platform_driver_register(&progearbl_driver);
-
-       if (ret)
-               return ret;
-       progearbl_device = platform_device_register_simple("progear-bl", -1,
-                                                               NULL, 0);
-       if (IS_ERR(progearbl_device)) {
-               platform_driver_unregister(&progearbl_driver);
-               return PTR_ERR(progearbl_device);
-       }
-
-       return 0;
-}
-
-static void __exit progearbl_exit(void)
-{
-       pci_dev_put(pmu_dev);
-       pci_dev_put(sb_dev);
-
-       platform_device_unregister(progearbl_device);
-       platform_driver_unregister(&progearbl_driver);
-}
-
-module_init(progearbl_init);
-module_exit(progearbl_exit);
-
-MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
-MODULE_DESCRIPTION("ProGear Backlight Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
new file mode 100644 (file)
index 0000000..7088163
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * tps65217_bl.c
+ *
+ * TPS65217 backlight driver
+ *
+ * Copyright (C) 2012 Matthias Kaehlcke
+ * Author: Matthias Kaehlcke <matthias@kaehlcke.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/mfd/tps65217.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct tps65217_bl {
+       struct tps65217 *tps;
+       struct device *dev;
+       struct backlight_device *bl;
+       bool is_enabled;
+};
+
+static int tps65217_bl_enable(struct tps65217_bl *tps65217_bl)
+{
+       int rc;
+
+       rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+                       TPS65217_WLEDCTRL1_ISINK_ENABLE,
+                       TPS65217_WLEDCTRL1_ISINK_ENABLE, TPS65217_PROTECT_NONE);
+       if (rc) {
+               dev_err(tps65217_bl->dev,
+                       "failed to enable backlight: %d\n", rc);
+               return rc;
+       }
+
+       tps65217_bl->is_enabled = true;
+
+       dev_dbg(tps65217_bl->dev, "backlight enabled\n");
+
+       return 0;
+}
+
+static int tps65217_bl_disable(struct tps65217_bl *tps65217_bl)
+{
+       int rc;
+
+       rc = tps65217_clear_bits(tps65217_bl->tps,
+                               TPS65217_REG_WLEDCTRL1,
+                               TPS65217_WLEDCTRL1_ISINK_ENABLE,
+                               TPS65217_PROTECT_NONE);
+       if (rc) {
+               dev_err(tps65217_bl->dev,
+                       "failed to disable backlight: %d\n", rc);
+               return rc;
+       }
+
+       tps65217_bl->is_enabled = false;
+
+       dev_dbg(tps65217_bl->dev, "backlight disabled\n");
+
+       return 0;
+}
+
+static int tps65217_bl_update_status(struct backlight_device *bl)
+{
+       struct tps65217_bl *tps65217_bl = bl_get_data(bl);
+       int rc;
+       int brightness = bl->props.brightness;
+
+       if (bl->props.state & BL_CORE_SUSPENDED)
+               brightness = 0;
+
+       if ((bl->props.power != FB_BLANK_UNBLANK) ||
+               (bl->props.fb_blank != FB_BLANK_UNBLANK))
+               /* framebuffer in low power mode or blanking active */
+               brightness = 0;
+
+       if (brightness > 0) {
+               rc = tps65217_reg_write(tps65217_bl->tps,
+                                       TPS65217_REG_WLEDCTRL2,
+                                       brightness - 1,
+                                       TPS65217_PROTECT_NONE);
+               if (rc) {
+                       dev_err(tps65217_bl->dev,
+                               "failed to set brightness level: %d\n", rc);
+                       return rc;
+               }
+
+               dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
+
+               if (!tps65217_bl->is_enabled)
+                       rc = tps65217_bl_enable(tps65217_bl);
+       } else {
+               rc = tps65217_bl_disable(tps65217_bl);
+       }
+
+       return rc;
+}
+
+static int tps65217_bl_get_brightness(struct backlight_device *bl)
+{
+       return bl->props.brightness;
+}
+
+static const struct backlight_ops tps65217_bl_ops = {
+       .options        = BL_CORE_SUSPENDRESUME,
+       .update_status  = tps65217_bl_update_status,
+       .get_brightness = tps65217_bl_get_brightness
+};
+
+static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
+                       struct tps65217_bl_pdata *pdata)
+{
+       int rc;
+
+       rc = tps65217_bl_disable(tps65217_bl);
+       if (rc)
+               return rc;
+
+       switch (pdata->isel) {
+       case TPS65217_BL_ISET1:
+               /* select ISET_1 current level */
+               rc = tps65217_clear_bits(tps65217_bl->tps,
+                                       TPS65217_REG_WLEDCTRL1,
+                                       TPS65217_WLEDCTRL1_ISEL,
+                                       TPS65217_PROTECT_NONE);
+               if (rc) {
+                       dev_err(tps65217_bl->dev,
+                               "failed to select ISET1 current level: %d)\n",
+                               rc);
+                       return rc;
+               }
+
+               dev_dbg(tps65217_bl->dev, "selected ISET1 current level\n");
+
+               break;
+
+       case TPS65217_BL_ISET2:
+               /* select ISET2 current level */
+               rc = tps65217_set_bits(tps65217_bl->tps, TPS65217_REG_WLEDCTRL1,
+                               TPS65217_WLEDCTRL1_ISEL,
+                               TPS65217_WLEDCTRL1_ISEL, TPS65217_PROTECT_NONE);
+               if (rc) {
+                       dev_err(tps65217_bl->dev,
+                               "failed to select ISET2 current level: %d\n",
+                               rc);
+                       return rc;
+               }
+
+               dev_dbg(tps65217_bl->dev, "selected ISET2 current level\n");
+
+               break;
+
+       default:
+               dev_err(tps65217_bl->dev,
+                       "invalid value for current level: %d\n", pdata->isel);
+               return -EINVAL;
+       }
+
+       /* set PWM frequency */
+       rc = tps65217_set_bits(tps65217_bl->tps,
+                       TPS65217_REG_WLEDCTRL1,
+                       TPS65217_WLEDCTRL1_FDIM_MASK,
+                       pdata->fdim,
+                       TPS65217_PROTECT_NONE);
+       if (rc) {
+               dev_err(tps65217_bl->dev,
+                       "failed to select PWM dimming frequency: %d\n",
+                       rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static struct tps65217_bl_pdata *
+tps65217_bl_parse_dt(struct platform_device *pdev)
+{
+       struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct device_node *node = of_node_get(tps->dev->of_node);
+       struct tps65217_bl_pdata *pdata, *err;
+       u32 val;
+
+       node = of_find_node_by_name(node, "backlight");
+       if (!node)
+               return ERR_PTR(-ENODEV);
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "failed to allocate platform data\n");
+               err = ERR_PTR(-ENOMEM);
+               goto err;
+       }
+
+       pdata->isel = TPS65217_BL_ISET1;
+       if (!of_property_read_u32(node, "isel", &val)) {
+               if (val < TPS65217_BL_ISET1 ||
+                       val > TPS65217_BL_ISET2) {
+                       dev_err(&pdev->dev,
+                               "invalid 'isel' value in the device tree\n");
+                       err = ERR_PTR(-EINVAL);
+                       goto err;
+               }
+
+               pdata->isel = val;
+       }
+
+       pdata->fdim = TPS65217_BL_FDIM_200HZ;
+       if (!of_property_read_u32(node, "fdim", &val)) {
+               switch (val) {
+               case 100:
+                       pdata->fdim = TPS65217_BL_FDIM_100HZ;
+                       break;
+
+               case 200:
+                       pdata->fdim = TPS65217_BL_FDIM_200HZ;
+                       break;
+
+               case 500:
+                       pdata->fdim = TPS65217_BL_FDIM_500HZ;
+                       break;
+
+               case 1000:
+                       pdata->fdim = TPS65217_BL_FDIM_1000HZ;
+                       break;
+
+               default:
+                       dev_err(&pdev->dev,
+                               "invalid 'fdim' value in the device tree\n");
+                       err = ERR_PTR(-EINVAL);
+                       goto err;
+               }
+       }
+
+       of_node_put(node);
+
+       return pdata;
+
+err:
+       of_node_put(node);
+
+       return err;
+}
+#else
+static struct tps65217_bl_pdata *
+tps65217_bl_parse_dt(struct platform_device *pdev)
+{
+       return NULL;
+}
+#endif
+
+static int tps65217_bl_probe(struct platform_device *pdev)
+{
+       int rc;
+       struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct tps65217_bl *tps65217_bl;
+       struct tps65217_bl_pdata *pdata;
+       struct backlight_properties bl_props;
+
+       if (tps->dev->of_node) {
+               pdata = tps65217_bl_parse_dt(pdev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       } else {
+               if (!pdev->dev.platform_data) {
+                       dev_err(&pdev->dev, "no platform data provided\n");
+                       return -EINVAL;
+               }
+
+               pdata = pdev->dev.platform_data;
+       }
+
+       tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
+                               GFP_KERNEL);
+       if (tps65217_bl == NULL) {
+               dev_err(&pdev->dev, "allocation of struct tps65217_bl failed\n");
+               return -ENOMEM;
+       }
+
+       tps65217_bl->tps = tps;
+       tps65217_bl->dev = &pdev->dev;
+       tps65217_bl->is_enabled = false;
+
+       rc = tps65217_bl_hw_init(tps65217_bl, pdata);
+       if (rc)
+               return rc;
+
+       memset(&bl_props, 0, sizeof(struct backlight_properties));
+       bl_props.type = BACKLIGHT_RAW;
+       bl_props.max_brightness = 100;
+
+       tps65217_bl->bl = backlight_device_register(pdev->name,
+                                               tps65217_bl->dev, tps65217_bl,
+                                               &tps65217_bl_ops, &bl_props);
+       if (IS_ERR(tps65217_bl->bl)) {
+               dev_err(tps65217_bl->dev,
+                       "registration of backlight device failed: %d\n", rc);
+               return PTR_ERR(tps65217_bl->bl);
+       }
+
+       tps65217_bl->bl->props.brightness = 0;
+       platform_set_drvdata(pdev, tps65217_bl);
+
+       return 0;
+}
+
+static int tps65217_bl_remove(struct platform_device *pdev)
+{
+       struct tps65217_bl *tps65217_bl = platform_get_drvdata(pdev);
+
+       backlight_device_unregister(tps65217_bl->bl);
+
+       return 0;
+}
+
+static struct platform_driver tps65217_bl_driver = {
+       .probe          = tps65217_bl_probe,
+       .remove         = tps65217_bl_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = "tps65217-bl",
+       },
+};
+
+module_platform_driver(tps65217_bl_driver);
+
+MODULE_DESCRIPTION("TPS65217 Backlight driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Matthias Kaehlcke <matthias@kaehlcke.net>");
index 5a5d0928df33cf94355f39a73b803d4c1ab86522..265c5ed59adea8824f9a9fe225704cd877ec4924 100644 (file)
@@ -29,7 +29,7 @@ static int  crt_option = 1;
 static char panel_option[32] = "";
 
 /* Modes relevant to the GX1 (taken from modedb.c) */
-static const struct fb_videomode __devinitdata gx1_modedb[] = {
+static const struct fb_videomode __devinitconst gx1_modedb[] = {
        /* 640x480-60 VESA */
        { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
          0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
index 0fad23f810a32035faffd0fcd7e0256426947b58..0e9afa41d1630589402d7af902d33ce02ee85105 100644 (file)
@@ -156,7 +156,7 @@ struct gxt4500_par {
 static char *mode_option;
 
 /* default mode: 1280x1024 @ 60 Hz, 8 bpp */
-static const struct fb_videomode defaultmode __devinitdata = {
+static const struct fb_videomode defaultmode __devinitconst = {
        .refresh = 60,
        .xres = 1280,
        .yres = 1024,
@@ -581,7 +581,7 @@ static int gxt4500_blank(int blank, struct fb_info *info)
        return 0;
 }
 
-static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = {
+static const struct fb_fix_screeninfo gxt4500_fix __devinitconst = {
        .id = "IBM GXT4500P",
        .type = FB_TYPE_PACKED_PIXELS,
        .visual = FB_VISUAL_PSEUDOCOLOR,
index b83f36190cae41ff73609cc94695d42b34688d56..5c067816a81d82210177ae569768504ef2d3b8e5 100644 (file)
@@ -97,7 +97,7 @@ static int i810fb_blank      (int blank_mode, struct fb_info *info);
 static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
 
 /* PCI */
-static const char *i810_pci_list[] __devinitdata = {
+static const char * const i810_pci_list[] __devinitconst = {
        "Intel(R) 810 Framebuffer Device"                                 ,
        "Intel(R) 810-DC100 Framebuffer Device"                           ,
        "Intel(R) 810E Framebuffer Device"                                ,
index de366937c93362a68c73bcd6c18ba7e3f035241a..3c63fc24bb1f139c197e430d4889aa2b443be706 100644 (file)
@@ -136,7 +136,7 @@ struct jzfb {
        uint32_t pseudo_palette[16];
 };
 
-static const struct fb_fix_screeninfo jzfb_fix __devinitdata = {
+static const struct fb_fix_screeninfo jzfb_fix __devinitconst = {
        .id             = "JZ4740 FB",
        .type           = FB_TYPE_PACKED_PIXELS,
        .visual         = FB_VISUAL_TRUECOLOR,
index 213fbbcf613bdf0467eb97eec7c2c3e5649eb52d..4e292f29bf5dedb710085d291105c75f604e3e74 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 
-#include <asm/abs_addr.h>
 #include <asm/cell-regs.h>
 #include <asm/lv1call.h>
 #include <asm/ps3av.h>
@@ -1141,7 +1140,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
         */
        fb_start = ps3fb_videomemory.address + GPU_FB_START;
        info->screen_base = (char __force __iomem *)fb_start;
-       info->fix.smem_start = virt_to_abs(fb_start);
+       info->fix.smem_start = __pa(fb_start);
        info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
 
        info->pseudo_palette = par->pseudo_palette;
index f38b17a86c359a18240cd7e2c243474aa7d0934c..8d5bddb56cb1a65c02ceac34bb84705bec53bd1b 100644 (file)
@@ -1,11 +1,9 @@
-# Virtio always gets selected by whoever wants it.
 config VIRTIO
        tristate
-
-# Similarly the virtio ring implementation.
-config VIRTIO_RING
-       tristate
-       depends on VIRTIO
+       ---help---
+         This option is selected by any driver which implements the virtio
+         bus, such as CONFIG_VIRTIO_PCI, CONFIG_VIRTIO_MMIO, CONFIG_LGUEST,
+         CONFIG_RPMSG or CONFIG_S390_GUEST.
 
 menu "Virtio drivers"
 
@@ -13,7 +11,6 @@ config VIRTIO_PCI
        tristate "PCI driver for virtio devices (EXPERIMENTAL)"
        depends on PCI && EXPERIMENTAL
        select VIRTIO
-       select VIRTIO_RING
        ---help---
          This drivers provides support for virtio based paravirtual device
          drivers over PCI.  This requires that your VMM has appropriate PCI
@@ -26,9 +23,8 @@ config VIRTIO_PCI
          If unsure, say M.
 
 config VIRTIO_BALLOON
-       tristate "Virtio balloon driver (EXPERIMENTAL)"
-       select VIRTIO
-       select VIRTIO_RING
+       tristate "Virtio balloon driver"
+       depends on VIRTIO
        ---help---
         This driver supports increasing and decreasing the amount
         of memory within a KVM guest.
@@ -39,7 +35,6 @@ config VIRTIO_BALLOON
        tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
        depends on HAS_IOMEM && EXPERIMENTAL
        select VIRTIO
-       select VIRTIO_RING
        ---help---
         This drivers provides support for memory mapped virtio
         platform device driver.
index 5a4c63cfd3803308726ce5fb95fd73136ef5dae5..9076635697bb0fe4bd395f172eb67f9a0cf5ccfd 100644 (file)
@@ -1,5 +1,4 @@
-obj-$(CONFIG_VIRTIO) += virtio.o
-obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
+obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o
 obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
index c3b3f7f0d9d197ec0fd6e56aa99cd8b50e616cfa..1e8659ca27ef4228d55e97ec5cbafc99d861b22a 100644 (file)
@@ -159,7 +159,7 @@ static int virtio_dev_remove(struct device *_d)
        drv->remove(dev);
 
        /* Driver should have reset device. */
-       BUG_ON(dev->config->get_status(dev));
+       WARN_ON_ONCE(dev->config->get_status(dev));
 
        /* Acknowledge the device's existence again. */
        add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
index 453db0c403d807dbd0f2482f9d8dfc7c77f2f57e..6b1b7e1849396d8183c6ae326b0ab1dc4c66ead2 100644 (file)
@@ -131,9 +131,6 @@ struct virtio_mmio_vq_info {
        /* the number of entries in the queue */
        unsigned int num;
 
-       /* the index of the queue */
-       int queue_index;
-
        /* the virtual address of the ring queue */
        void *queue;
 
@@ -225,11 +222,10 @@ static void vm_reset(struct virtio_device *vdev)
 static void vm_notify(struct virtqueue *vq)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
-       struct virtio_mmio_vq_info *info = vq->priv;
 
        /* We write the queue's selector into the notification register to
         * signal the other end */
-       writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+       writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
 }
 
 /* Notify all virtqueues on an interrupt. */
@@ -270,6 +266,7 @@ static void vm_del_vq(struct virtqueue *vq)
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
        struct virtio_mmio_vq_info *info = vq->priv;
        unsigned long flags, size;
+       unsigned int index = virtqueue_get_queue_index(vq);
 
        spin_lock_irqsave(&vm_dev->lock, flags);
        list_del(&info->node);
@@ -278,7 +275,7 @@ static void vm_del_vq(struct virtqueue *vq)
        vring_del_virtqueue(vq);
 
        /* Select and deactivate the queue */
-       writel(info->queue_index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
+       writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
        writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
 
        size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
@@ -309,6 +306,9 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
        unsigned long flags, size;
        int err;
 
+       if (!name)
+               return NULL;
+
        /* Select the queue we're interested in */
        writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
 
@@ -324,7 +324,6 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
                err = -ENOMEM;
                goto error_kmalloc;
        }
-       info->queue_index = index;
 
        /* Allocate pages for the queue - start with a queue as big as
         * possible (limited by maximum size allowed by device), drop down
@@ -332,11 +331,21 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
         * and two rings (which makes it "alignment_size * 2")
         */
        info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
+
+       /* If the device reports a 0 entry queue, we won't be able to
+        * use it to perform I/O, and vring_new_virtqueue() can't create
+        * empty queues anyway, so don't bother to set up the device.
+        */
+       if (info->num == 0) {
+               err = -ENOENT;
+               goto error_alloc_pages;
+       }
+
        while (1) {
                size = PAGE_ALIGN(vring_size(info->num,
                                VIRTIO_MMIO_VRING_ALIGN));
-               /* Already smallest possible allocation? */
-               if (size <= VIRTIO_MMIO_VRING_ALIGN * 2) {
+               /* Did the last iter shrink the queue below minimum size? */
+               if (size < VIRTIO_MMIO_VRING_ALIGN * 2) {
                        err = -ENOMEM;
                        goto error_alloc_pages;
                }
@@ -356,7 +365,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
                        vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
 
        /* Create the vring */
-       vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN, vdev,
+       vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev,
                                 true, info->queue, vm_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
index 2e03d416b9af5c294803448ffbf5be33a4e5d571..c33aea36598aa2b6133147756956439f65a84f7f 100644 (file)
@@ -48,6 +48,7 @@ struct virtio_pci_device
        int msix_enabled;
        int intx_enabled;
        struct msix_entry *msix_entries;
+       cpumask_var_t *msix_affinity_masks;
        /* Name strings for interrupts. This size should be enough,
         * and I'm too lazy to allocate each name separately. */
        char (*msix_names)[256];
@@ -79,9 +80,6 @@ struct virtio_pci_vq_info
        /* the number of entries in the queue */
        int num;
 
-       /* the index of the queue */
-       int queue_index;
-
        /* the virtual address of the ring queue */
        void *queue;
 
@@ -202,11 +200,11 @@ static void vp_reset(struct virtio_device *vdev)
 static void vp_notify(struct virtqueue *vq)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
-       struct virtio_pci_vq_info *info = vq->priv;
 
        /* we write the queue's selector into the notification register to
         * signal the other end */
-       iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+       iowrite16(virtqueue_get_queue_index(vq),
+                 vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
 }
 
 /* Handle a configuration change: Tell driver if it wants to know. */
@@ -279,6 +277,10 @@ static void vp_free_vectors(struct virtio_device *vdev)
        for (i = 0; i < vp_dev->msix_used_vectors; ++i)
                free_irq(vp_dev->msix_entries[i].vector, vp_dev);
 
+       for (i = 0; i < vp_dev->msix_vectors; i++)
+               if (vp_dev->msix_affinity_masks[i])
+                       free_cpumask_var(vp_dev->msix_affinity_masks[i]);
+
        if (vp_dev->msix_enabled) {
                /* Disable the vector used for configuration */
                iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -296,6 +298,8 @@ static void vp_free_vectors(struct virtio_device *vdev)
        vp_dev->msix_names = NULL;
        kfree(vp_dev->msix_entries);
        vp_dev->msix_entries = NULL;
+       kfree(vp_dev->msix_affinity_masks);
+       vp_dev->msix_affinity_masks = NULL;
 }
 
 static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
@@ -314,6 +318,15 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
                                     GFP_KERNEL);
        if (!vp_dev->msix_names)
                goto error;
+       vp_dev->msix_affinity_masks
+               = kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks,
+                         GFP_KERNEL);
+       if (!vp_dev->msix_affinity_masks)
+               goto error;
+       for (i = 0; i < nvectors; ++i)
+               if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i],
+                                       GFP_KERNEL))
+                       goto error;
 
        for (i = 0; i < nvectors; ++i)
                vp_dev->msix_entries[i].entry = i;
@@ -402,7 +415,6 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index,
        if (!info)
                return ERR_PTR(-ENOMEM);
 
-       info->queue_index = index;
        info->num = num;
        info->msix_vector = msix_vec;
 
@@ -418,7 +430,7 @@ static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index,
                  vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
 
        /* create the vring */
-       vq = vring_new_virtqueue(info->num, VIRTIO_PCI_VRING_ALIGN, vdev,
+       vq = vring_new_virtqueue(index, info->num, VIRTIO_PCI_VRING_ALIGN, vdev,
                                 true, info->queue, vp_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
@@ -467,7 +479,8 @@ static void vp_del_vq(struct virtqueue *vq)
        list_del(&info->node);
        spin_unlock_irqrestore(&vp_dev->lock, flags);
 
-       iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+       iowrite16(virtqueue_get_queue_index(vq),
+               vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
        if (vp_dev->msix_enabled) {
                iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -542,7 +555,10 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs,
        vp_dev->per_vq_vectors = per_vq_vectors;
        allocated_vectors = vp_dev->msix_used_vectors;
        for (i = 0; i < nvqs; ++i) {
-               if (!callbacks[i] || !vp_dev->msix_enabled)
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               } else if (!callbacks[i] || !vp_dev->msix_enabled)
                        msix_vec = VIRTIO_MSI_NO_VECTOR;
                else if (vp_dev->per_vq_vectors)
                        msix_vec = allocated_vectors++;
@@ -609,6 +625,35 @@ static const char *vp_bus_name(struct virtio_device *vdev)
        return pci_name(vp_dev->pci_dev);
 }
 
+/* Setup the affinity for a virtqueue:
+ * - force the affinity for per vq vector
+ * - OR over all affinities for shared MSI
+ * - ignore the affinity request if we're using INTX
+ */
+static int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
+{
+       struct virtio_device *vdev = vq->vdev;
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+       struct virtio_pci_vq_info *info = vq->priv;
+       struct cpumask *mask;
+       unsigned int irq;
+
+       if (!vq->callback)
+               return -EINVAL;
+
+       if (vp_dev->msix_enabled) {
+               mask = vp_dev->msix_affinity_masks[info->msix_vector];
+               irq = vp_dev->msix_entries[info->msix_vector].vector;
+               if (cpu == -1)
+                       irq_set_affinity_hint(irq, NULL);
+               else {
+                       cpumask_set_cpu(cpu, mask);
+                       irq_set_affinity_hint(irq, mask);
+               }
+       }
+       return 0;
+}
+
 static struct virtio_config_ops virtio_pci_config_ops = {
        .get            = vp_get,
        .set            = vp_set,
@@ -620,6 +665,7 @@ static struct virtio_config_ops virtio_pci_config_ops = {
        .get_features   = vp_get_features,
        .finalize_features = vp_finalize_features,
        .bus_name       = vp_bus_name,
+       .set_vq_affinity = vp_set_vq_affinity,
 };
 
 static void virtio_pci_release_dev(struct device *_d)
@@ -673,8 +719,10 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
                goto out_enable_device;
 
        vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0);
-       if (vp_dev->ioaddr == NULL)
+       if (vp_dev->ioaddr == NULL) {
+               err = -ENOMEM;
                goto out_req_regions;
+       }
 
        pci_set_drvdata(pci_dev, vp_dev);
        pci_set_master(pci_dev);
index 5aa43c3392a2a061ed9fb35f3caa53605690e7fd..e639584b2dbd1c24e36017db1978009b73f8e33f 100644 (file)
@@ -106,6 +106,9 @@ struct vring_virtqueue
        /* How to notify other side. FIXME: commonalize hcalls! */
        void (*notify)(struct virtqueue *vq);
 
+       /* Index of the queue */
+       int queue_index;
+
 #ifdef DEBUG
        /* They're supposed to lock for us. */
        unsigned int in_use;
@@ -171,6 +174,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        return head;
 }
 
+int virtqueue_get_queue_index(struct virtqueue *_vq)
+{
+       struct vring_virtqueue *vq = to_vvq(_vq);
+       return vq->queue_index;
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
+
 /**
  * virtqueue_add_buf - expose buffer to other end
  * @vq: the struct virtqueue we're talking about.
@@ -616,7 +626,8 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
 }
 EXPORT_SYMBOL_GPL(vring_interrupt);
 
-struct virtqueue *vring_new_virtqueue(unsigned int num,
+struct virtqueue *vring_new_virtqueue(unsigned int index,
+                                     unsigned int num,
                                      unsigned int vring_align,
                                      struct virtio_device *vdev,
                                      bool weak_barriers,
@@ -647,6 +658,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
        vq->broken = false;
        vq->last_used_idx = 0;
        vq->num_added = 0;
+       vq->queue_index = index;
        list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
        vq->in_use = false;
index ceed39f26011a8aa0684e1768d919f38d119f93c..545d387de411bbd112a7be360f0c4efcd263c34c 100644 (file)
@@ -37,6 +37,7 @@
  *     document number TBD                   : DH89xxCC
  *     document number TBD                   : Panther Point
  *     document number TBD                   : Lynx Point
+ *     document number TBD                   : Lynx Point-LP
  */
 
 /*
index 663cad86c6333c29855a2a209fed47465437d238..173494a681e6faab613bcfda9a8c72a9fafda325 100644 (file)
@@ -46,17 +46,17 @@ static void wdt_enable(void)
        unsigned int gms0;
 
        /* preserve GPIO usage, if any */
-       gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
+       gms0 = __raw_readl(MCF_GPT_GMS0);
        if (gms0 & MCF_GPT_GMS_TMS_GPIO)
                gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK
                                                        | MCF_GPT_GMS_OD);
        else
                gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD;
-       __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(gms0, MCF_GPT_GMS0);
        __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) |
-                       MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0);
+                       MCF_GPT_GCIR_CNT(0xffff), MCF_GPT_GCIR0);
        gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE;
-       __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(gms0, MCF_GPT_GMS0);
 }
 
 static void wdt_disable(void)
@@ -64,18 +64,18 @@ static void wdt_disable(void)
        unsigned int gms0;
 
        /* disable watchdog */
-       gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
+       gms0 = __raw_readl(MCF_GPT_GMS0);
        gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE);
-       __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(gms0, MCF_GPT_GMS0);
 }
 
 static void wdt_keepalive(void)
 {
        unsigned int gms0;
 
-       gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0);
+       gms0 = __raw_readl(MCF_GPT_GMS0);
        gms0 |= MCF_GPT_GMS_OCPW(0xA5);
-       __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(gms0, MCF_GPT_GMS0);
 }
 
 static int m54xx_wdt_open(struct inode *inode, struct file *file)
@@ -195,8 +195,7 @@ static struct miscdevice m54xx_wdt_miscdev = {
 
 static int __init m54xx_wdt_init(void)
 {
-       if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4,
-                                               "Coldfire M54xx Watchdog")) {
+       if (!request_mem_region(MCF_GPT_GCIR0, 4, "Coldfire M54xx Watchdog")) {
                pr_warn("I/O region busy\n");
                return -EBUSY;
        }
@@ -208,7 +207,7 @@ static int __init m54xx_wdt_init(void)
 static void __exit m54xx_wdt_exit(void)
 {
        misc_deregister(&m54xx_wdt_miscdev);
-       release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4);
+       release_mem_region(MCF_GPT_GCIR0, 4);
 }
 
 module_init(m54xx_wdt_init);
index a4a3cab2f4596c4f1681a999bebf6353307d5084..0e86370354572ac7d4116eb70cf6e41d1a52cf35 100644 (file)
@@ -1,11 +1,19 @@
-obj-y  += grant-table.o features.o events.o manage.o balloon.o
+ifneq ($(CONFIG_ARM),y)
+obj-y  += manage.o balloon.o
+obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
+endif
+obj-y  += grant-table.o features.o events.o
 obj-y  += xenbus/
 
 nostackp := $(call cc-option, -fno-stack-protector)
 CFLAGS_features.o                      := $(nostackp)
 
+dom0-$(CONFIG_PCI) += pci.o
+dom0-$(CONFIG_USB_SUPPORT) += dbgp.o
+dom0-$(CONFIG_ACPI) += acpi.o
+dom0-$(CONFIG_X86) += pcpu.o
+obj-$(CONFIG_XEN_DOM0)                 += $(dom0-y)
 obj-$(CONFIG_BLOCK)                    += biomerge.o
-obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
 obj-$(CONFIG_XEN_XENCOMM)              += xencomm.o
 obj-$(CONFIG_XEN_BALLOON)              += xen-balloon.o
 obj-$(CONFIG_XEN_SELFBALLOONING)       += xen-selfballoon.o
@@ -17,8 +25,6 @@ obj-$(CONFIG_XEN_SYS_HYPERVISOR)      += sys-hypervisor.o
 obj-$(CONFIG_XEN_PVHVM)                        += platform-pci.o
 obj-$(CONFIG_XEN_TMEM)                 += tmem.o
 obj-$(CONFIG_SWIOTLB_XEN)              += swiotlb-xen.o
-obj-$(CONFIG_XEN_DOM0)                 += pcpu.o
-obj-$(CONFIG_XEN_DOM0)                 += pci.o dbgp.o acpi.o
 obj-$(CONFIG_XEN_MCE_LOG)              += mcelog.o
 obj-$(CONFIG_XEN_PCIDEV_BACKEND)       += xen-pciback/
 obj-$(CONFIG_XEN_PRIVCMD)              += xen-privcmd.o
index c60d1629c91601f366fef151a7d45f51736b1378..59e10a1286d53ff73aa3e0a6c91a5aed9033de9e 100644 (file)
 #include <linux/irqnr.h>
 #include <linux/pci.h>
 
+#ifdef CONFIG_X86
 #include <asm/desc.h>
 #include <asm/ptrace.h>
 #include <asm/irq.h>
 #include <asm/idle.h>
 #include <asm/io_apic.h>
-#include <asm/sync_bitops.h>
 #include <asm/xen/page.h>
 #include <asm/xen/pci.h>
+#endif
+#include <asm/sync_bitops.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
 
@@ -50,6 +52,9 @@
 #include <xen/interface/event_channel.h>
 #include <xen/interface/hvm/hvm_op.h>
 #include <xen/interface/hvm/params.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/sched.h>
+#include <asm/hw_irq.h>
 
 /*
  * This lock protects updates to the following mapping and reference-count
@@ -1386,7 +1391,9 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
+#ifdef CONFIG_X86
        exit_idle();
+#endif
        irq_enter();
 
        __xen_evtchn_do_upcall();
@@ -1797,7 +1804,7 @@ void xen_callback_vector(void) {}
 
 void __init xen_init_IRQ(void)
 {
-       int i, rc;
+       int i;
 
        evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
                                    GFP_KERNEL);
@@ -1813,6 +1820,7 @@ void __init xen_init_IRQ(void)
 
        pirq_needs_eoi = pirq_needs_eoi_flag;
 
+#ifdef CONFIG_X86
        if (xen_hvm_domain()) {
                xen_callback_vector();
                native_init_IRQ();
@@ -1820,6 +1828,7 @@ void __init xen_init_IRQ(void)
                 * __acpi_register_gsi can point at the right function */
                pci_xen_hvm_init();
        } else {
+               int rc;
                struct physdev_pirq_eoi_gmfn eoi_gmfn;
 
                irq_ctx_init(smp_processor_id());
@@ -1835,4 +1844,5 @@ void __init xen_init_IRQ(void)
                } else
                        pirq_needs_eoi = pirq_check_eoi_map;
        }
+#endif
 }
index 02257420274966b6f0085f20b148e1fe582bc865..0efd1524b9770844cf74899f067686073a1c730d 100644 (file)
@@ -164,3 +164,11 @@ config BINFMT_MISC
          You may say M here for module support and later load the module when
          you have use for it; the module is called binfmt_misc. If you
          don't know what to answer at this point, say Y.
+
+config COREDUMP
+       bool "Enable core dump support" if EXPERT
+       default y
+       help
+         This option enables support for performing core dumps. You almost
+         certainly want to say Y here. Not necessary on systems that never
+         need debugging or only ever run flawless code.
index 8938f8250320ecbde9ab3502141178ddd7492ad3..1d7af79288a04915ca0d1788bc84f32bd03793a0 100644 (file)
@@ -11,7 +11,7 @@ obj-y :=      open.o read_write.o file_table.o super.o \
                attr.o bad_inode.o file.o filesystems.o namespace.o \
                seq_file.o xattr.o libfs.o fs-writeback.o \
                pnode.o drop_caches.o splice.o sync.o utimes.o \
-               stack.o fs_struct.o statfs.o coredump.o
+               stack.o fs_struct.o statfs.o
 
 ifeq ($(CONFIG_BLOCK),y)
 obj-y +=       buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
@@ -48,6 +48,7 @@ obj-$(CONFIG_FS_MBCACHE)      += mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)     += posix_acl.o xattr_acl.o
 obj-$(CONFIG_NFS_COMMON)       += nfs_common/
 obj-$(CONFIG_GENERIC_ACL)      += generic_acl.o
+obj-$(CONFIG_COREDUMP)         += coredump.o
 
 obj-$(CONFIG_FHANDLE)          += fhandle.o
 
index d146e181d10df8611050c16745195b9efca62c93..0e7a6f81ae36c0d9b57b36550ea58705675bd9f1 100644 (file)
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
-static int aout_core_dump(struct coredump_params *cprm);
-
-static struct linux_binfmt aout_format = {
-       .module         = THIS_MODULE,
-       .load_binary    = load_aout_binary,
-       .load_shlib     = load_aout_library,
-       .core_dump      = aout_core_dump,
-       .min_coredump   = PAGE_SIZE
-};
-
-#define BAD_ADDR(x)    ((unsigned long)(x) >= TASK_SIZE)
-
-static int set_brk(unsigned long start, unsigned long end)
-{
-       start = PAGE_ALIGN(start);
-       end = PAGE_ALIGN(end);
-       if (end > start) {
-               unsigned long addr;
-               addr = vm_brk(start, end - start);
-               if (BAD_ADDR(addr))
-                       return addr;
-       }
-       return 0;
-}
 
+#ifdef CONFIG_COREDUMP
 /*
  * Routine writes a core dump image in the current directory.
  * Currently only a stub-function.
@@ -66,7 +43,6 @@ static int set_brk(unsigned long start, unsigned long end)
  * field, which also makes sure the core-dumps won't be recursive if the
  * dumping of the process results in another error..
  */
-
 static int aout_core_dump(struct coredump_params *cprm)
 {
        struct file *file = cprm->file;
@@ -89,7 +65,7 @@ static int aout_core_dump(struct coredump_params *cprm)
        current->flags |= PF_DUMPCORE;
                strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
        dump.u_ar0 = offsetof(struct user, regs);
-       dump.signal = cprm->signr;
+       dump.signal = cprm->siginfo->si_signo;
        aout_dump_thread(cprm->regs, &dump);
 
 /* If the size of the dump file exceeds the rlimit, then see what would happen
@@ -135,6 +111,32 @@ end_coredump:
        set_fs(fs);
        return has_dumped;
 }
+#else
+#define aout_core_dump NULL
+#endif
+
+static struct linux_binfmt aout_format = {
+       .module         = THIS_MODULE,
+       .load_binary    = load_aout_binary,
+       .load_shlib     = load_aout_library,
+       .core_dump      = aout_core_dump,
+       .min_coredump   = PAGE_SIZE
+};
+
+#define BAD_ADDR(x)    ((unsigned long)(x) >= TASK_SIZE)
+
+static int set_brk(unsigned long start, unsigned long end)
+{
+       start = PAGE_ALIGN(start);
+       end = PAGE_ALIGN(end);
+       if (end > start) {
+               unsigned long addr;
+               addr = vm_brk(start, end - start);
+               if (BAD_ADDR(addr))
+                       return addr;
+       }
+       return 0;
+}
 
 /*
  * create_aout_tables() parses the env- and arg-strings in new user
index 0225fddf49b7d9e25ae2a8361b631ba30c34a496..28a64e76952788146d24b4fe0e0069918c0b9584 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/compiler.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/vmalloc.h>
 #include <linux/security.h>
 #include <linux/random.h>
 #include <linux/elf.h>
 #include <asm/page.h>
 #include <asm/exec.h>
 
+#ifndef user_long_t
+#define user_long_t long
+#endif
+#ifndef user_siginfo_t
+#define user_siginfo_t siginfo_t
+#endif
+
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
 static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
@@ -881,7 +889,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        }
 
        if (elf_interpreter) {
-               unsigned long uninitialized_var(interp_map_addr);
+               unsigned long interp_map_addr = 0;
 
                elf_entry = load_elf_interp(&loc->interp_elf_ex,
                                            interpreter,
@@ -1372,6 +1380,103 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm)
        fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
 }
 
+static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
+               siginfo_t *siginfo)
+{
+       mm_segment_t old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
+       set_fs(old_fs);
+       fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
+}
+
+#define MAX_FILE_NOTE_SIZE (4*1024*1024)
+/*
+ * Format of NT_FILE note:
+ *
+ * long count     -- how many files are mapped
+ * long page_size -- units for file_ofs
+ * array of [COUNT] elements of
+ *   long start
+ *   long end
+ *   long file_ofs
+ * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
+ */
+static void fill_files_note(struct memelfnote *note)
+{
+       struct vm_area_struct *vma;
+       unsigned count, size, names_ofs, remaining, n;
+       user_long_t *data;
+       user_long_t *start_end_ofs;
+       char *name_base, *name_curpos;
+
+       /* *Estimated* file count and total data size needed */
+       count = current->mm->map_count;
+       size = count * 64;
+
+       names_ofs = (2 + 3 * count) * sizeof(data[0]);
+ alloc:
+       if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
+               goto err;
+       size = round_up(size, PAGE_SIZE);
+       data = vmalloc(size);
+       if (!data)
+               goto err;
+
+       start_end_ofs = data + 2;
+       name_base = name_curpos = ((char *)data) + names_ofs;
+       remaining = size - names_ofs;
+       count = 0;
+       for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+               struct file *file;
+               const char *filename;
+
+               file = vma->vm_file;
+               if (!file)
+                       continue;
+               filename = d_path(&file->f_path, name_curpos, remaining);
+               if (IS_ERR(filename)) {
+                       if (PTR_ERR(filename) == -ENAMETOOLONG) {
+                               vfree(data);
+                               size = size * 5 / 4;
+                               goto alloc;
+                       }
+                       continue;
+               }
+
+               /* d_path() fills at the end, move name down */
+               /* n = strlen(filename) + 1: */
+               n = (name_curpos + remaining) - filename;
+               remaining = filename - name_curpos;
+               memmove(name_curpos, filename, n);
+               name_curpos += n;
+
+               *start_end_ofs++ = vma->vm_start;
+               *start_end_ofs++ = vma->vm_end;
+               *start_end_ofs++ = vma->vm_pgoff;
+               count++;
+       }
+
+       /* Now we know exact count of files, can store it */
+       data[0] = count;
+       data[1] = PAGE_SIZE;
+       /*
+        * Count usually is less than current->mm->map_count,
+        * we need to move filenames down.
+        */
+       n = current->mm->map_count - count;
+       if (n != 0) {
+               unsigned shift_bytes = n * 3 * sizeof(data[0]);
+               memmove(name_base - shift_bytes, name_base,
+                       name_curpos - name_base);
+               name_curpos -= shift_bytes;
+       }
+
+       size = name_curpos - (char *)data;
+       fill_note(note, "CORE", NT_FILE, size, data);
+ err: ;
+}
+
 #ifdef CORE_DUMP_USE_REGSET
 #include <linux/regset.h>
 
@@ -1385,7 +1490,10 @@ struct elf_thread_core_info {
 struct elf_note_info {
        struct elf_thread_core_info *thread;
        struct memelfnote psinfo;
+       struct memelfnote signote;
        struct memelfnote auxv;
+       struct memelfnote files;
+       user_siginfo_t csigdata;
        size_t size;
        int thread_notes;
 };
@@ -1480,7 +1588,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
 
 static int fill_note_info(struct elfhdr *elf, int phdrs,
                          struct elf_note_info *info,
-                         long signr, struct pt_regs *regs)
+                         siginfo_t *siginfo, struct pt_regs *regs)
 {
        struct task_struct *dump_task = current;
        const struct user_regset_view *view = task_user_regset_view(dump_task);
@@ -1550,7 +1658,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
         * Now fill in each thread's information.
         */
        for (t = info->thread; t != NULL; t = t->next)
-               if (!fill_thread_core_info(t, view, signr, &info->size))
+               if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size))
                        return 0;
 
        /*
@@ -1559,9 +1667,15 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
        info->size += notesize(&info->psinfo);
 
+       fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
+       info->size += notesize(&info->signote);
+
        fill_auxv_note(&info->auxv, current->mm);
        info->size += notesize(&info->auxv);
 
+       fill_files_note(&info->files);
+       info->size += notesize(&info->files);
+
        return 1;
 }
 
@@ -1588,8 +1702,12 @@ static int write_note_info(struct elf_note_info *info,
 
                if (first && !writenote(&info->psinfo, file, foffset))
                        return 0;
+               if (first && !writenote(&info->signote, file, foffset))
+                       return 0;
                if (first && !writenote(&info->auxv, file, foffset))
                        return 0;
+               if (first && !writenote(&info->files, file, foffset))
+                       return 0;
 
                for (i = 1; i < info->thread_notes; ++i)
                        if (t->notes[i].data &&
@@ -1616,6 +1734,7 @@ static void free_note_info(struct elf_note_info *info)
                kfree(t);
        }
        kfree(info->psinfo.data);
+       vfree(info->files.data);
 }
 
 #else
@@ -1681,6 +1800,7 @@ struct elf_note_info {
 #ifdef ELF_CORE_COPY_XFPREGS
        elf_fpxregset_t *xfpu;
 #endif
+       user_siginfo_t csigdata;
        int thread_status_size;
        int numnote;
 };
@@ -1690,8 +1810,8 @@ static int elf_note_info_init(struct elf_note_info *info)
        memset(info, 0, sizeof(*info));
        INIT_LIST_HEAD(&info->thread_list);
 
-       /* Allocate space for six ELF notes */
-       info->notes = kmalloc(6 * sizeof(struct memelfnote), GFP_KERNEL);
+       /* Allocate space for ELF notes */
+       info->notes = kmalloc(8 * sizeof(struct memelfnote), GFP_KERNEL);
        if (!info->notes)
                return 0;
        info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
@@ -1713,14 +1833,14 @@ static int elf_note_info_init(struct elf_note_info *info)
 
 static int fill_note_info(struct elfhdr *elf, int phdrs,
                          struct elf_note_info *info,
-                         long signr, struct pt_regs *regs)
+                         siginfo_t *siginfo, struct pt_regs *regs)
 {
        struct list_head *t;
 
        if (!elf_note_info_init(info))
                return 0;
 
-       if (signr) {
+       if (siginfo->si_signo) {
                struct core_thread *ct;
                struct elf_thread_status *ets;
 
@@ -1738,13 +1858,13 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
                        int sz;
 
                        ets = list_entry(t, struct elf_thread_status, list);
-                       sz = elf_dump_thread_status(signr, ets);
+                       sz = elf_dump_thread_status(siginfo->si_signo, ets);
                        info->thread_status_size += sz;
                }
        }
        /* now collect the dump for the current */
        memset(info->prstatus, 0, sizeof(*info->prstatus));
-       fill_prstatus(info->prstatus, current, signr);
+       fill_prstatus(info->prstatus, current, siginfo->si_signo);
        elf_core_copy_regs(&info->prstatus->pr_reg, regs);
 
        /* Set up header */
@@ -1761,9 +1881,11 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        fill_note(info->notes + 1, "CORE", NT_PRPSINFO,
                  sizeof(*info->psinfo), info->psinfo);
 
-       info->numnote = 2;
+       fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo);
+       fill_auxv_note(info->notes + 3, current->mm);
+       fill_files_note(info->notes + 4);
 
-       fill_auxv_note(&info->notes[info->numnote++], current->mm);
+       info->numnote = 5;
 
        /* Try to dump the FPU. */
        info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs,
@@ -1825,6 +1947,9 @@ static void free_note_info(struct elf_note_info *info)
                kfree(list_entry(tmp, struct elf_thread_status, list));
        }
 
+       /* Free data allocated by fill_files_note(): */
+       vfree(info->notes[4].data);
+
        kfree(info->prstatus);
        kfree(info->psinfo);
        kfree(info->notes);
@@ -1951,7 +2076,7 @@ static int elf_core_dump(struct coredump_params *cprm)
         * Collect all the non-memory information about the process for the
         * notes.  This also sets up the file header.
         */
-       if (!fill_note_info(elf, e_phnum, &info, cprm->signr, cprm->regs))
+       if (!fill_note_info(elf, e_phnum, &info, cprm->siginfo, cprm->regs))
                goto cleanup;
 
        has_dumped = 1;
index 3d77cf81ba3c82c8dbe7d80531e34bea4355250c..08d812b3228262650473fc4ef0599a47cc898f65 100644 (file)
@@ -1642,7 +1642,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
                goto cleanup;
 #endif
 
-       if (cprm->signr) {
+       if (cprm->siginfo->si_signo) {
                struct core_thread *ct;
                struct elf_thread_status *tmp;
 
@@ -1661,13 +1661,13 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
                        int sz;
 
                        tmp = list_entry(t, struct elf_thread_status, list);
-                       sz = elf_dump_thread_status(cprm->signr, tmp);
+                       sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp);
                        thread_status_size += sz;
                }
        }
 
        /* now collect the dump for the current */
-       fill_prstatus(prstatus, current, cprm->signr);
+       fill_prstatus(prstatus, current, cprm->siginfo->si_signo);
        elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
 
        segs = current->mm->map_count;
index 178cb70acc26de80ec3db21a8455e88b7fc0360b..e280352b28f9e48adab2cc8d94963b0cbaf8b181 100644 (file)
@@ -107,7 +107,7 @@ static struct linux_binfmt flat_format = {
 static int flat_core_dump(struct coredump_params *cprm)
 {
        printk("Process %s:%d received signr %d and should have core dumped\n",
-                       current->comm, current->pid, (int) cprm->signr);
+                       current->comm, current->pid, (int) cprm->siginfo->si_signo);
        return(1);
 }
 
index 112e45a17e99717e1226f3b229c5ffe73c8193f3..a81147e2e4ef2eef2c2fb330a0f9ce464e2c67f6 100644 (file)
 #define elf_note       elf32_note
 #define elf_addr_t     Elf32_Addr
 
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t            compat_long_t
+#define user_siginfo_t         compat_siginfo_t
+#define copy_siginfo_to_user   copy_siginfo_to_user32
+
 /*
  * The machine-dependent core note format types are defined in elfcore-compat.h,
  * which requires asm/elf.h to define compat_elf_gregset_t et al.
index f045bbad682294330023e9a09020f16ccb9c241c..fd37facac8dc55f40281008ceb6799c667105588 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/key.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
+#include <linux/coredump.h>
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
 #include <linux/module.h>
@@ -39,6 +40,7 @@
 
 #include <trace/events/task.h>
 #include "internal.h"
+#include "coredump.h"
 
 #include <trace/events/sched.h>
 
@@ -147,7 +149,7 @@ put_exe_file:
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-static int format_corename(struct core_name *cn, long signr)
+static int format_corename(struct core_name *cn, struct coredump_params *cprm)
 {
        const struct cred *cred = current_cred();
        const char *pat_ptr = core_pattern;
@@ -192,9 +194,13 @@ static int format_corename(struct core_name *cn, long signr)
                        case 'g':
                                err = cn_printf(cn, "%d", cred->gid);
                                break;
+                       case 'd':
+                               err = cn_printf(cn, "%d",
+                                       __get_dumpable(cprm->mm_flags));
+                               break;
                        /* signal that caused the coredump */
                        case 's':
-                               err = cn_printf(cn, "%ld", signr);
+                               err = cn_printf(cn, "%ld", cprm->siginfo->si_signo);
                                break;
                        /* UNIX time of coredump */
                        case 't': {
@@ -451,7 +457,7 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
        return 0;
 }
 
-void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+void do_coredump(siginfo_t *siginfo, struct pt_regs *regs)
 {
        struct core_state core_state;
        struct core_name cn;
@@ -466,7 +472,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
        bool need_nonrelative = false;
        static atomic_t core_dump_count = ATOMIC_INIT(0);
        struct coredump_params cprm = {
-               .signr = signr,
+               .siginfo = siginfo,
                .regs = regs,
                .limit = rlimit(RLIMIT_CORE),
                /*
@@ -477,7 +483,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
                .mm_flags = mm->flags,
        };
 
-       audit_core_dumps(signr);
+       audit_core_dumps(siginfo->si_signo);
 
        binfmt = mm->binfmt;
        if (!binfmt || !binfmt->core_dump)
@@ -501,7 +507,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
                need_nonrelative = true;
        }
 
-       retval = coredump_wait(exit_code, &core_state);
+       retval = coredump_wait(siginfo->si_signo, &core_state);
        if (retval < 0)
                goto fail_creds;
 
@@ -513,7 +519,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
         */
        clear_thread_flag(TIF_SIGPENDING);
 
-       ispipe = format_corename(&cn, signr);
+       ispipe = format_corename(&cn, &cprm);
 
        if (ispipe) {
                int dump_count;
diff --git a/fs/coredump.h b/fs/coredump.h
new file mode 100644 (file)
index 0000000..e39ff07
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _FS_COREDUMP_H
+#define _FS_COREDUMP_H
+
+extern int __get_dumpable(unsigned long mm_flags);
+
+#endif
index cd96649bfe62da9e408dbd629f56f6452c139bc9..da72250ddc1cf2331336a23cbe8239bf880a10cf 100644 (file)
@@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-       return op != EPOLL_CTL_DEL;
+       return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -676,6 +676,34 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        return 0;
 }
 
+/*
+ * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
+ * had no event flags set, indicating that another thread may be currently
+ * handling that item's events (in the case that EPOLLONESHOT was being
+ * used). Otherwise a zero result indicates that the item has been disabled
+ * from receiving events. A disabled item may be re-enabled via
+ * EPOLL_CTL_MOD. Must be called with "mtx" held.
+ */
+static int ep_disable(struct eventpoll *ep, struct epitem *epi)
+{
+       int result = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ep->lock, flags);
+       if (epi->event.events & ~EP_PRIVATE_BITS) {
+               if (ep_is_linked(&epi->rdllink))
+                       list_del_init(&epi->rdllink);
+               /* Ensure ep_poll_callback will not add epi back onto ready
+                  list: */
+               epi->event.events &= EP_PRIVATE_BITS;
+               }
+       else
+               result = -EBUSY;
+       spin_unlock_irqrestore(&ep->lock, flags);
+
+       return result;
+}
+
 static void ep_free(struct eventpoll *ep)
 {
        struct rb_node *rbp;
@@ -1020,8 +1048,6 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
        rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
-
-
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1787,6 +1813,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                } else
                        error = -ENOENT;
                break;
+       case EPOLL_CTL_DISABLE:
+               if (epi)
+                       error = ep_disable(ep, epi);
+               else
+                       error = -ENOENT;
+               break;
        }
        mutex_unlock(&ep->mtx);
 
index 48fb26ef8a1b3daebb49a74c9ae09ba83c7f7a14..9824473a7ec1688737c2150ca8bd246587e7250b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -63,6 +63,7 @@
 
 #include <trace/events/task.h>
 #include "internal.h"
+#include "coredump.h"
 
 #include <trace/events/sched.h>
 
@@ -1096,7 +1097,7 @@ void setup_new_exec(struct linux_binprm * bprm)
        current->sas_ss_sp = current->sas_ss_size = 0;
 
        if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid()))
-               set_dumpable(current->mm, 1);
+               set_dumpable(current->mm, SUID_DUMPABLE_ENABLED);
        else
                set_dumpable(current->mm, suid_dumpable);
 
index e06190322c1c8af1544034c1476f3c779b165318..964b634f6667ca89a3427ee453a016285aec8cf8 100644 (file)
@@ -6,6 +6,6 @@ obj-$(CONFIG_FAT_FS) += fat.o
 obj-$(CONFIG_VFAT_FS) += vfat.o
 obj-$(CONFIG_MSDOS_FS) += msdos.o
 
-fat-y := cache.o dir.o fatent.o file.o inode.o misc.o
+fat-y := cache.o dir.o fatent.o file.o inode.o misc.o nfs.o
 vfat-y := namei_vfat.o
 msdos-y := namei_msdos.o
index 1cc7038e273de02bb404c91623bec8f65cd85288..91ad9e1c94417a813c1661af830bc2ecbc962033 100644 (file)
@@ -190,7 +190,8 @@ static void __fat_cache_inval_inode(struct inode *inode)
        struct fat_cache *cache;
 
        while (!list_empty(&i->cache_lru)) {
-               cache = list_entry(i->cache_lru.next, struct fat_cache, cache_list);
+               cache = list_entry(i->cache_lru.next,
+                                  struct fat_cache, cache_list);
                list_del_init(&cache->cache_list);
                i->nr_caches--;
                fat_cache_free(cache);
@@ -261,9 +262,10 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
                if (nr < 0)
                        goto out;
                else if (nr == FAT_ENT_FREE) {
-                       fat_fs_error_ratelimit(sb, "%s: invalid cluster chain"
-                                              " (i_pos %lld)", __func__,
-                                              MSDOS_I(inode)->i_pos);
+                       fat_fs_error_ratelimit(sb,
+                                      "%s: invalid cluster chain (i_pos %lld)",
+                                      __func__,
+                                      MSDOS_I(inode)->i_pos);
                        nr = -EIO;
                        goto out;
                } else if (nr == FAT_ENT_EOF) {
index dc49ed2cbffa66af9407f89886d8d84cf2dc9d0f..bca6d0a1255ecab0a1a8ec2b86032296a7a49e13 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/time.h>
 #include <linux/buffer_head.h>
 #include <linux/compat.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/kernel.h>
 #include "fat.h"
 
@@ -123,7 +123,8 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos,
 {
        /* Fast stuff first */
        if (*bh && *de &&
-           (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
+          (*de - (struct msdos_dir_entry *)(*bh)->b_data) <
+                               MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
                *pos += sizeof(struct msdos_dir_entry);
                (*de)++;
                return 0;
@@ -155,7 +156,8 @@ static int uni16_to_x8(struct super_block *sb, unsigned char *ascii,
 
        while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) {
                ec = *ip++;
-               if ((charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) {
+               charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE);
+               if (charlen > 0) {
                        op += charlen;
                        len -= charlen;
                } else {
@@ -172,12 +174,12 @@ static int uni16_to_x8(struct super_block *sb, unsigned char *ascii,
        }
 
        if (unlikely(*ip)) {
-               fat_msg(sb, KERN_WARNING, "filename was truncated while "
-                       "converting.");
+               fat_msg(sb, KERN_WARNING,
+                       "filename was truncated while converting.");
        }
 
        *op = 0;
-       return (op - ascii);
+       return op - ascii;
 }
 
 static inline int fat_uni_to_x8(struct super_block *sb, const wchar_t *uni,
@@ -205,7 +207,8 @@ fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 }
 
 static inline int
-fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
+fat_short2lower_uni(struct nls_table *t, unsigned char *c,
+                   int clen, wchar_t *uni)
 {
        int charlen;
        wchar_t wc;
@@ -220,7 +223,8 @@ fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *un
                if (!nc)
                        nc = *c;
 
-               if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {
+               charlen = t->char2uni(&nc, 1, uni);
+               if (charlen < 0) {
                        *uni = 0x003f;  /* a question mark */
                        charlen = 1;
                }
@@ -537,7 +541,6 @@ end_of_dir:
 
        return err;
 }
-
 EXPORT_SYMBOL_GPL(fat_search_long);
 
 struct fat_ioctl_filldir_callback {
@@ -574,7 +577,8 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
        /* Fake . and .. for the root directory. */
        if (inode->i_ino == MSDOS_ROOT_INO) {
                while (cpos < 2) {
-                       if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0)
+                       if (filldir(dirent, "..", cpos+1, cpos,
+                                   MSDOS_ROOT_INO, DT_DIR) < 0)
                                goto out;
                        cpos++;
                        filp->f_pos++;
@@ -872,25 +876,26 @@ static int fat_get_short_entry(struct inode *dir, loff_t *pos,
 }
 
 /*
- * The ".." entry can not provide the "struct fat_slot_info" informations
- * for inode. So, this function provide the some informations only.
+ * The ".." entry can not provide the "struct fat_slot_info" information
+ * for inode, nor a usable i_pos. So, this function provides some information
+ * only.
+ *
+ * Since this function walks through the on-disk inodes within a directory,
+ * callers are responsible for taking any locks necessary to prevent the
+ * directory from changing.
  */
 int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
-                        struct msdos_dir_entry **de, loff_t *i_pos)
+                        struct msdos_dir_entry **de)
 {
-       loff_t offset;
+       loff_t offset = 0;
 
-       offset = 0;
-       *bh = NULL;
+       *de = NULL;
        while (fat_get_short_entry(dir, &offset, bh, de) >= 0) {
-               if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) {
-                       *i_pos = fat_make_i_pos(dir->i_sb, *bh, *de);
+               if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME))
                        return 0;
-               }
        }
        return -ENOENT;
 }
-
 EXPORT_SYMBOL_GPL(fat_get_dotdot_entry);
 
 /* See if directory is empty */
@@ -913,7 +918,6 @@ int fat_dir_empty(struct inode *dir)
        brelse(bh);
        return result;
 }
-
 EXPORT_SYMBOL_GPL(fat_dir_empty);
 
 /*
@@ -959,7 +963,6 @@ int fat_scan(struct inode *dir, const unsigned char *name,
        }
        return -ENOENT;
 }
-
 EXPORT_SYMBOL_GPL(fat_scan);
 
 static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
@@ -1047,7 +1050,6 @@ int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
 
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(fat_remove_entries);
 
 static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
@@ -1141,10 +1143,8 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
                de[0].ctime_cs = de[1].ctime_cs = 0;
                de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;
        }
-       de[0].start = cpu_to_le16(cluster);
-       de[0].starthi = cpu_to_le16(cluster >> 16);
-       de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
-       de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16);
+       fat_set_start(&de[0], cluster);
+       fat_set_start(&de[1], MSDOS_I(dir)->i_logstart);
        de[0].size = de[1].size = 0;
        memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));
        set_buffer_uptodate(bhs[0]);
@@ -1161,7 +1161,6 @@ error_free:
 error:
        return err;
 }
-
 EXPORT_SYMBOL_GPL(fat_alloc_new_dir);
 
 static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,
@@ -1377,5 +1376,4 @@ error_remove:
                __fat_remove_entries(dir, pos, free_slots);
        return err;
 }
-
 EXPORT_SYMBOL_GPL(fat_add_entries);
index 7d8e0dcac5d5602fdd0c351047ef38980d0fb8b7..ca7e8f8bad7cd405f344f5983da364a7a2d0606f 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/string.h>
 #include <linux/nls.h>
 #include <linux/fs.h>
+#include <linux/hash.h>
 #include <linux/mutex.h>
 #include <linux/ratelimit.h>
 #include <linux/msdos_fs.h>
@@ -27,26 +28,27 @@ struct fat_mount_options {
        kgid_t fs_gid;
        unsigned short fs_fmask;
        unsigned short fs_dmask;
-       unsigned short codepage;  /* Codepage for shortname conversions */
-       char *iocharset;          /* Charset used for filename input/display */
-       unsigned short shortname; /* flags for shortname display/create rule */
-       unsigned char name_check; /* r = relaxed, n = normal, s = strict */
-       unsigned char errors;     /* On error: continue, panic, remount-ro */
+       unsigned short codepage;   /* Codepage for shortname conversions */
+       char *iocharset;           /* Charset used for filename input/display */
+       unsigned short shortname;  /* flags for shortname display/create rule */
+       unsigned char name_check;  /* r = relaxed, n = normal, s = strict */
+       unsigned char errors;      /* On error: continue, panic, remount-ro */
        unsigned short allow_utime;/* permission for setting the [am]time */
-       unsigned quiet:1,         /* set = fake successful chmods and chowns */
-                showexec:1,      /* set = only set x bit for com/exe/bat */
-                sys_immutable:1, /* set = system files are immutable */
-                dotsOK:1,        /* set = hidden and system files are named '.filename' */
-                isvfat:1,        /* 0=no vfat long filename support, 1=vfat support */
-                utf8:1,          /* Use of UTF-8 character set (Default) */
-                unicode_xlate:1, /* create escape sequences for unhandled Unicode */
-                numtail:1,       /* Does first alias have a numeric '~1' type tail? */
-                flush:1,         /* write things quickly */
-                nocase:1,        /* Does this need case conversion? 0=need case conversion*/
-                usefree:1,       /* Use free_clusters for FAT32 */
-                tz_utc:1,        /* Filesystem timestamps are in UTC */
-                rodir:1,         /* allow ATTR_RO for directory */
-                discard:1;       /* Issue discard requests on deletions */
+       unsigned quiet:1,          /* set = fake successful chmods and chowns */
+                showexec:1,       /* set = only set x bit for com/exe/bat */
+                sys_immutable:1,  /* set = system files are immutable */
+                dotsOK:1,         /* set = hidden and system files are named '.filename' */
+                isvfat:1,         /* 0=no vfat long filename support, 1=vfat support */
+                utf8:1,           /* Use of UTF-8 character set (Default) */
+                unicode_xlate:1,  /* create escape sequences for unhandled Unicode */
+                numtail:1,        /* Does first alias have a numeric '~1' type tail? */
+                flush:1,          /* write things quickly */
+                nocase:1,         /* Does this need case conversion? 0=need case conversion*/
+                usefree:1,        /* Use free_clusters for FAT32 */
+                tz_utc:1,         /* Filesystem timestamps are in UTC */
+                rodir:1,          /* allow ATTR_RO for directory */
+                discard:1,        /* Issue discard requests on deletions */
+                nfs:1;            /* Do extra work needed for NFS export */
 };
 
 #define FAT_HASH_BITS  8
@@ -56,28 +58,28 @@ struct fat_mount_options {
  * MS-DOS file system in-core superblock data
  */
 struct msdos_sb_info {
-       unsigned short sec_per_clus; /* sectors/cluster */
-       unsigned short cluster_bits; /* log2(cluster_size) */
-       unsigned int cluster_size;   /* cluster size */
-       unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
+       unsigned short sec_per_clus;  /* sectors/cluster */
+       unsigned short cluster_bits;  /* log2(cluster_size) */
+       unsigned int cluster_size;    /* cluster size */
+       unsigned char fats, fat_bits; /* number of FATs, FAT bits (12 or 16) */
        unsigned short fat_start;
-       unsigned long fat_length;    /* FAT start & length (sec.) */
+       unsigned long fat_length;     /* FAT start & length (sec.) */
        unsigned long dir_start;
-       unsigned short dir_entries;  /* root dir start & entries */
-       unsigned long data_start;    /* first data sector */
-       unsigned long max_cluster;   /* maximum cluster number */
-       unsigned long root_cluster;  /* first cluster of the root directory */
-       unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
+       unsigned short dir_entries;   /* root dir start & entries */
+       unsigned long data_start;     /* first data sector */
+       unsigned long max_cluster;    /* maximum cluster number */
+       unsigned long root_cluster;   /* first cluster of the root directory */
+       unsigned long fsinfo_sector;  /* sector number of FAT32 fsinfo */
        struct mutex fat_lock;
-       unsigned int prev_free;      /* previously allocated cluster number */
-       unsigned int free_clusters;  /* -1 if undefined */
+       unsigned int prev_free;       /* previously allocated cluster number */
+       unsigned int free_clusters;   /* -1 if undefined */
        unsigned int free_clus_valid; /* is free_clusters valid? */
        struct fat_mount_options options;
-       struct nls_table *nls_disk;  /* Codepage used on disk */
-       struct nls_table *nls_io;    /* Charset used for input and display */
-       const void *dir_ops;                 /* Opaque; default directory operations */
-       int dir_per_block;           /* dir entries per block */
-       int dir_per_block_bits;      /* log2(dir_per_block) */
+       struct nls_table *nls_disk;   /* Codepage used on disk */
+       struct nls_table *nls_io;     /* Charset used for input and display */
+       const void *dir_ops;          /* Opaque; default directory operations */
+       int dir_per_block;            /* dir entries per block */
+       int dir_per_block_bits;       /* log2(dir_per_block) */
 
        int fatent_shift;
        struct fatent_operations *fatent_ops;
@@ -88,6 +90,9 @@ struct msdos_sb_info {
 
        spinlock_t inode_hash_lock;
        struct hlist_head inode_hashtable[FAT_HASH_SIZE];
+
+       spinlock_t dir_hash_lock;
+       struct hlist_head dir_hashtable[FAT_HASH_SIZE];
 };
 
 #define FAT_CACHE_VALID        0       /* special case for valid cache */
@@ -110,6 +115,7 @@ struct msdos_inode_info {
        int i_attrs;            /* unused attribute bits */
        loff_t i_pos;           /* on-disk position of directory entry or 0 */
        struct hlist_node i_fat_hash;   /* hash by i_location */
+       struct hlist_node i_dir_hash;   /* hash by i_logstart */
        struct rw_semaphore truncate_lock; /* protect bmap against truncate */
        struct inode vfs_inode;
 };
@@ -262,7 +268,7 @@ extern int fat_subdirs(struct inode *dir);
 extern int fat_scan(struct inode *dir, const unsigned char *name,
                    struct fat_slot_info *sinfo);
 extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
-                               struct msdos_dir_entry **de, loff_t *i_pos);
+                               struct msdos_dir_entry **de);
 extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
 extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
                           struct fat_slot_info *sinfo);
@@ -322,7 +328,7 @@ extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
 extern const struct file_operations fat_file_operations;
 extern const struct inode_operations fat_file_inode_operations;
-extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
+extern int fat_setattr(struct dentry *dentry, struct iattr *attr);
 extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
                       struct kstat *stat);
@@ -340,7 +346,12 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent,
                          int isvfat, void (*setup)(struct super_block *));
 
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
-                           struct inode *i2);
+                           struct inode *i2);
+static inline unsigned long fat_dir_hash(int logstart)
+{
+       return hash_32(logstart, FAT_HASH_BITS);
+}
+
 /* fat/misc.c */
 extern __printf(3, 4) __cold
 void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...);
@@ -366,6 +377,14 @@ extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 int fat_cache_init(void);
 void fat_cache_destroy(void);
 
+/* fat/nfs.c */
+struct fid;
+extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
+                                      int fh_len, int fh_type);
+extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
+                                      int fh_len, int fh_type);
+extern struct dentry *fat_get_parent(struct dentry *child_dir);
+
 /* helper for printk */
 typedef unsigned long long     llu;
 
index 31f08ab62c562d1926a75183c802793642cd390c..260705c58062cc425b8c656434883de98e1b9e2a 100644 (file)
@@ -186,9 +186,6 @@ static void fat16_ent_put(struct fat_entry *fatent, int new)
 
 static void fat32_ent_put(struct fat_entry *fatent, int new)
 {
-       if (new == FAT_ENT_EOF)
-               new = EOF_FAT32;
-
        WARN_ON(new & 0xf0000000);
        new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
        *fatent->u.ent32_p = cpu_to_le32(new);
@@ -203,15 +200,18 @@ static int fat12_ent_next(struct fat_entry *fatent)
 
        fatent->entry++;
        if (fatent->nr_bhs == 1) {
-               WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 2)));
-               WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+               WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data +
+                                                       (bhs[0]->b_size - 2)));
+               WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data +
+                                                       (bhs[0]->b_size - 1)));
                if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {
                        ent12_p[0] = nextp - 1;
                        ent12_p[1] = nextp;
                        return 1;
                }
        } else {
-               WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+               WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data +
+                                                       (bhs[0]->b_size - 1)));
                WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);
                ent12_p[0] = nextp - 1;
                ent12_p[1] = nextp;
@@ -631,7 +631,6 @@ error:
 
        return err;
 }
-
 EXPORT_SYMBOL_GPL(fat_free_clusters);
 
 /* 128kb is the whole sectors for FAT12 and FAT16 */
index 4e5a6ac54ebd9deec1e8bfeb430eb3c7608dc78d..76f60c642c06399b1bf8696ff515be9a99ffc922 100644 (file)
@@ -281,15 +281,42 @@ static inline unsigned long fat_hash(loff_t i_pos)
        return hash_32(i_pos, FAT_HASH_BITS);
 }
 
+static void dir_hash_init(struct super_block *sb)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       int i;
+
+       spin_lock_init(&sbi->dir_hash_lock);
+       for (i = 0; i < FAT_HASH_SIZE; i++)
+               INIT_HLIST_HEAD(&sbi->dir_hashtable[i]);
+}
+
 void fat_attach(struct inode *inode, loff_t i_pos)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
-       struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
 
-       spin_lock(&sbi->inode_hash_lock);
-       MSDOS_I(inode)->i_pos = i_pos;
-       hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head);
-       spin_unlock(&sbi->inode_hash_lock);
+       if (inode->i_ino != MSDOS_ROOT_INO) {
+               struct hlist_head *head =   sbi->inode_hashtable
+                                         + fat_hash(i_pos);
+
+               spin_lock(&sbi->inode_hash_lock);
+               MSDOS_I(inode)->i_pos = i_pos;
+               hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head);
+               spin_unlock(&sbi->inode_hash_lock);
+       }
+
+       /* If NFS support is enabled, cache the mapping of start cluster
+        * to directory inode. This is used during reconnection of
+        * dentries to the filesystem root.
+        */
+       if (S_ISDIR(inode->i_mode) && sbi->options.nfs) {
+               struct hlist_head *d_head = sbi->dir_hashtable;
+               d_head += fat_dir_hash(MSDOS_I(inode)->i_logstart);
+
+               spin_lock(&sbi->dir_hash_lock);
+               hlist_add_head(&MSDOS_I(inode)->i_dir_hash, d_head);
+               spin_unlock(&sbi->dir_hash_lock);
+       }
 }
 EXPORT_SYMBOL_GPL(fat_attach);
 
@@ -300,6 +327,12 @@ void fat_detach(struct inode *inode)
        MSDOS_I(inode)->i_pos = 0;
        hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
        spin_unlock(&sbi->inode_hash_lock);
+
+       if (S_ISDIR(inode->i_mode) && sbi->options.nfs) {
+               spin_lock(&sbi->dir_hash_lock);
+               hlist_del_init(&MSDOS_I(inode)->i_dir_hash);
+               spin_unlock(&sbi->dir_hash_lock);
+       }
 }
 EXPORT_SYMBOL_GPL(fat_detach);
 
@@ -504,6 +537,7 @@ static void init_once(void *foo)
        ei->cache_valid_id = FAT_CACHE_VALID + 1;
        INIT_LIST_HEAD(&ei->cache_lru);
        INIT_HLIST_NODE(&ei->i_fat_hash);
+       INIT_HLIST_NODE(&ei->i_dir_hash);
        inode_init_once(&ei->vfs_inode);
 }
 
@@ -668,125 +702,9 @@ static const struct super_operations fat_sops = {
        .show_options   = fat_show_options,
 };
 
-/*
- * a FAT file handle with fhtype 3 is
- *  0/  i_ino - for fast, reliable lookup if still in the cache
- *  1/  i_generation - to see if i_ino is still valid
- *          bit 0 == 0 iff directory
- *  2/  i_pos(8-39) - if ino has changed, but still in cache
- *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
- *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
- *
- * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
- * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
- * of i_logstart is used to store the directory entry offset.
- */
-
-static struct dentry *fat_fh_to_dentry(struct super_block *sb,
-               struct fid *fid, int fh_len, int fh_type)
-{
-       struct inode *inode = NULL;
-       u32 *fh = fid->raw;
-
-       if (fh_len < 5 || fh_type != 3)
-               return NULL;
-
-       inode = ilookup(sb, fh[0]);
-       if (!inode || inode->i_generation != fh[1]) {
-               if (inode)
-                       iput(inode);
-               inode = NULL;
-       }
-       if (!inode) {
-               loff_t i_pos;
-               int i_logstart = fh[3] & 0x0fffffff;
-
-               i_pos = (loff_t)fh[2] << 8;
-               i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
-
-               /* try 2 - see if i_pos is in F-d-c
-                * require i_logstart to be the same
-                * Will fail if you truncate and then re-write
-                */
-
-               inode = fat_iget(sb, i_pos);
-               if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
-                       iput(inode);
-                       inode = NULL;
-               }
-       }
-
-       /*
-        * For now, do nothing if the inode is not found.
-        *
-        * What we could do is:
-        *
-        *      - follow the file starting at fh[4], and record the ".." entry,
-        *        and the name of the fh[2] entry.
-        *      - then follow the ".." file finding the next step up.
-        *
-        * This way we build a path to the root of the tree. If this works, we
-        * lookup the path and so get this inode into the cache.  Finally try
-        * the fat_iget lookup again.  If that fails, then we are totally out
-        * of luck.  But all that is for another day
-        */
-       return d_obtain_alias(inode);
-}
-
-static int
-fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent)
-{
-       int len = *lenp;
-       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
-       loff_t i_pos;
-
-       if (len < 5) {
-               *lenp = 5;
-               return 255; /* no room */
-       }
-
-       i_pos = fat_i_pos_read(sbi, inode);
-       *lenp = 5;
-       fh[0] = inode->i_ino;
-       fh[1] = inode->i_generation;
-       fh[2] = i_pos >> 8;
-       fh[3] = ((i_pos & 0xf0) << 24) | MSDOS_I(inode)->i_logstart;
-       fh[4] = (i_pos & 0x0f) << 28;
-       if (parent)
-               fh[4] |= MSDOS_I(parent)->i_logstart;
-       return 3;
-}
-
-static struct dentry *fat_get_parent(struct dentry *child)
-{
-       struct super_block *sb = child->d_sb;
-       struct buffer_head *bh;
-       struct msdos_dir_entry *de;
-       loff_t i_pos;
-       struct dentry *parent;
-       struct inode *inode;
-       int err;
-
-       lock_super(sb);
-
-       err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);
-       if (err) {
-               parent = ERR_PTR(err);
-               goto out;
-       }
-       inode = fat_build_inode(sb, de, i_pos);
-       brelse(bh);
-
-       parent = d_obtain_alias(inode);
-out:
-       unlock_super(sb);
-
-       return parent;
-}
-
 static const struct export_operations fat_export_ops = {
-       .encode_fh      = fat_encode_fh,
        .fh_to_dentry   = fat_fh_to_dentry,
+       .fh_to_parent   = fat_fh_to_parent,
        .get_parent     = fat_get_parent,
 };
 
@@ -836,6 +754,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
                seq_puts(m, ",usefree");
        if (opts->quiet)
                seq_puts(m, ",quiet");
+       if (opts->nfs)
+               seq_puts(m, ",nfs");
        if (opts->showexec)
                seq_puts(m, ",showexec");
        if (opts->sys_immutable)
@@ -880,7 +800,7 @@ enum {
        Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
        Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
        Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
-       Opt_err_panic, Opt_err_ro, Opt_discard, Opt_err,
+       Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -909,6 +829,7 @@ static const match_table_t fat_tokens = {
        {Opt_err_panic, "errors=panic"},
        {Opt_err_ro, "errors=remount-ro"},
        {Opt_discard, "discard"},
+       {Opt_nfs, "nfs"},
        {Opt_obsolete, "conv=binary"},
        {Opt_obsolete, "conv=text"},
        {Opt_obsolete, "conv=auto"},
@@ -989,6 +910,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
        opts->numtail = 1;
        opts->usefree = opts->nocase = 0;
        opts->tz_utc = 0;
+       opts->nfs = 0;
        opts->errors = FAT_ERRORS_RO;
        *debug = 0;
 
@@ -1153,6 +1075,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
                case Opt_discard:
                        opts->discard = 1;
                        break;
+               case Opt_nfs:
+                       opts->nfs = 1;
+                       break;
 
                /* obsolete mount options */
                case Opt_obsolete:
@@ -1443,6 +1368,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 
        /* set up enough so that it can read an inode */
        fat_hash_init(sb);
+       dir_hash_init(sb);
        fat_ent_access_init(sb);
 
        /*
@@ -1497,6 +1423,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        }
        error = -ENOMEM;
        insert_inode_hash(root_inode);
+       fat_attach(root_inode, 0);
        sb->s_root = d_make_root(root_inode);
        if (!sb->s_root) {
                fat_msg(sb, KERN_ERR, "get root inode failed");
@@ -1536,18 +1463,14 @@ static int writeback_inode(struct inode *inode)
 {
 
        int ret;
-       struct address_space *mapping = inode->i_mapping;
-       struct writeback_control wbc = {
-              .sync_mode = WB_SYNC_NONE,
-             .nr_to_write = 0,
-       };
-       /* if we used WB_SYNC_ALL, sync_inode waits for the io for the
-       * inode to finish.  So WB_SYNC_NONE is sent down to sync_inode
+
+       /* if we used wait=1, sync_inode_metadata waits for the io for the
+       * inode to finish.  So wait=0 is sent down to sync_inode_metadata
        * and filemap_fdatawrite is used for the data blocks
        */
-       ret = sync_inode(inode, &wbc);
+       ret = sync_inode_metadata(inode, 0);
        if (!ret)
-              ret = filemap_fdatawrite(mapping);
+               ret = filemap_fdatawrite(inode->i_mapping);
        return ret;
 }
 
index b0e12bf9f4a1c0fc32dc42facffaf84ff75fe880..c1055e778fff51a980105797ad82ce4c28005691 100644 (file)
@@ -407,7 +407,7 @@ out:
 static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
-       struct super_block *sb= inode->i_sb;
+       struct super_block *sb = inode->i_sb;
        struct fat_slot_info sinfo;
        int err;
 
@@ -440,7 +440,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
        struct inode *old_inode, *new_inode;
        struct fat_slot_info old_sinfo, sinfo;
        struct timespec ts;
-       loff_t dotdot_i_pos, new_i_pos;
+       loff_t new_i_pos;
        int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
 
        old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
@@ -456,8 +456,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
        is_dir = S_ISDIR(old_inode->i_mode);
        update_dotdot = (is_dir && old_dir != new_dir);
        if (update_dotdot) {
-               if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
-                                        &dotdot_i_pos) < 0) {
+               if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) {
                        err = -EIO;
                        goto out;
                }
index 6a6d8c0715a1c16daf2b1ac53e8d461eb2253810..e535dd75b986779f8910831c8bafba44ab2a5e71 100644 (file)
@@ -914,7 +914,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct inode *old_inode, *new_inode;
        struct fat_slot_info old_sinfo, sinfo;
        struct timespec ts;
-       loff_t dotdot_i_pos, new_i_pos;
+       loff_t new_i_pos;
        int err, is_dir, update_dotdot, corrupt = 0;
        struct super_block *sb = old_dir->i_sb;
 
@@ -929,8 +929,7 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        is_dir = S_ISDIR(old_inode->i_mode);
        update_dotdot = (is_dir && old_dir != new_dir);
        if (update_dotdot) {
-               if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
-                                        &dotdot_i_pos) < 0) {
+               if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) {
                        err = -EIO;
                        goto out;
                }
diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c
new file mode 100644 (file)
index 0000000..ef4b5fa
--- /dev/null
@@ -0,0 +1,101 @@
+/* fs/fat/nfs.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/exportfs.h>
+#include "fat.h"
+
+/**
+ * Look up a directory inode given its starting cluster.
+ */
+static struct inode *fat_dget(struct super_block *sb, int i_logstart)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       struct hlist_head *head;
+       struct hlist_node *_p;
+       struct msdos_inode_info *i;
+       struct inode *inode = NULL;
+
+       head = sbi->dir_hashtable + fat_dir_hash(i_logstart);
+       spin_lock(&sbi->dir_hash_lock);
+       hlist_for_each_entry(i, _p, head, i_dir_hash) {
+               BUG_ON(i->vfs_inode.i_sb != sb);
+               if (i->i_logstart != i_logstart)
+                       continue;
+               inode = igrab(&i->vfs_inode);
+               if (inode)
+                       break;
+       }
+       spin_unlock(&sbi->dir_hash_lock);
+       return inode;
+}
+
+static struct inode *fat_nfs_get_inode(struct super_block *sb,
+                                      u64 ino, u32 generation)
+{
+       struct inode *inode;
+
+       if ((ino < MSDOS_ROOT_INO) || (ino == MSDOS_FSINFO_INO))
+               return NULL;
+
+       inode = ilookup(sb, ino);
+       if (inode && generation && (inode->i_generation != generation)) {
+               iput(inode);
+               inode = NULL;
+       }
+
+       return inode;
+}
+
+/**
+ * Map a NFS file handle to a corresponding dentry.
+ * The dentry may or may not be connected to the filesystem root.
+ */
+struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
+                               int fh_len, int fh_type)
+{
+       return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+                                   fat_nfs_get_inode);
+}
+
+/*
+ * Find the parent for a file specified by NFS handle.
+ * This requires that the handle contain the i_ino of the parent.
+ */
+struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
+                               int fh_len, int fh_type)
+{
+       return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+                                   fat_nfs_get_inode);
+}
+
+/*
+ * Find the parent for a directory that is not currently connected to
+ * the filesystem root.
+ *
+ * On entry, the caller holds child_dir->d_inode->i_mutex.
+ */
+struct dentry *fat_get_parent(struct dentry *child_dir)
+{
+       struct super_block *sb = child_dir->d_sb;
+       struct buffer_head *bh = NULL;
+       struct msdos_dir_entry *de;
+       struct inode *parent_inode = NULL;
+
+       if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
+               int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
+               parent_inode = fat_dget(sb, parent_logstart);
+       }
+       brelse(bh);
+
+       return d_obtain_alias(parent_inode);
+}
index 4bae4a4a60b1936eba70d17d18e7d4a016ed54b9..2d5b254ad9e275352eae070e729a30b6af2f1a14 100644 (file)
@@ -102,7 +102,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                        return -1;
                }
                if (hpfs_alloc_if_possible(s, se = le32_to_cpu(btree->u.external[n].disk_secno) + le32_to_cpu(btree->u.external[n].length))) {
-                       btree->u.external[n].length = cpu_to_le32(le32_to_cpu(btree->u.external[n].length) + 1);
+                       le32_add_cpu(&btree->u.external[n].length, 1);
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        return se;
@@ -153,7 +153,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                btree = &anode->btree;
        }
        btree->n_free_nodes--; n = btree->n_used_nodes++;
-       btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 12);
+       le16_add_cpu(&btree->first_free, 12);
        btree->u.external[n].disk_secno = cpu_to_le32(se);
        btree->u.external[n].file_secno = cpu_to_le32(fs);
        btree->u.external[n].length = cpu_to_le32(1);
@@ -174,7 +174,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
                }
                if (btree->n_free_nodes) {
                        btree->n_free_nodes--; n = btree->n_used_nodes++;
-                       btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 8);
+                       le16_add_cpu(&btree->first_free, 8);
                        btree->u.internal[n].file_secno = cpu_to_le32(-1);
                        btree->u.internal[n].down = cpu_to_le32(na);
                        btree->u.internal[n-1].file_secno = cpu_to_le32(fs);
index 3228c524ebe56f948d8896cec23ca6b1284f6303..4364b2a02c5dba48c121c7e642afc0a9c56cf9c1 100644 (file)
@@ -145,10 +145,10 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno
                }
        }
        if (ptr) {
-               d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + 4);
+               le32_add_cpu(&d->first_free, 4);
                if (le32_to_cpu(d->first_free) > 2048) {
                        hpfs_error(s, "set_last_pointer: too long dnode %08x", le32_to_cpu(d->self));
-                       d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - 4);
+                       le32_add_cpu(&d->first_free, -4);
                        return;
                }
                de->length = cpu_to_le16(36);
@@ -184,7 +184,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
        de->not_8x3 = hpfs_is_name_long(name, namelen);
        de->namelen = namelen;
        memcpy(de->name, name, namelen);
-       d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + d_size);
+       le32_add_cpu(&d->first_free, d_size);
        return de;
 }
 
@@ -314,7 +314,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
        set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
        de = de_next_de(de);
        memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de);
-       nd->first_free = cpu_to_le32(le32_to_cpu(nd->first_free) - ((char *)de - (char *)nd - 20));
+       le32_add_cpu(&nd->first_free, -((char *)de - (char *)nd - 20));
        memcpy(d, nd, le32_to_cpu(nd->first_free));
        for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos);
        fix_up_ptrs(i->i_sb, ad);
@@ -474,8 +474,8 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
                        hpfs_brelse4(&qbh);
                        return 0;
                }
-               dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
-               de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
+               le32_add_cpu(&dnode->first_free, -4);
+               le16_add_cpu(&de->length, -4);
                de->down = 0;
                hpfs_mark_4buffers_dirty(&qbh);
                dno = up;
@@ -570,8 +570,8 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p);
                if (!down) {
                        de->down = 0;
-                       de->length = cpu_to_le16(le16_to_cpu(de->length) - 4);
-                       dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
+                       le16_add_cpu(&de->length, -4);
+                       le32_add_cpu(&dnode->first_free, -4);
                        memmove(de_next_de(de), (char *)de_next_de(de) + 4,
                                (char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de));
                } else {
@@ -647,14 +647,14 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                                        printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
                                        printk("HPFS: warning: goin'on\n");
                                }
-                               del->length = cpu_to_le16(le16_to_cpu(del->length) + 4);
+                               le16_add_cpu(&del->length, 4);
                                del->down = 1;
-                               d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) + 4);
+                               le32_add_cpu(&d1->first_free, 4);
                        }
                        if (dlp && !down) {
-                               del->length = cpu_to_le16(le16_to_cpu(del->length) - 4);
+                               le16_add_cpu(&del->length, -4);
                                del->down = 0;
-                               d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
+                               le32_add_cpu(&d1->first_free, -4);
                        } else if (down)
                                *(__le32 *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);
                } else goto endm;
@@ -668,9 +668,9 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
                memcpy(de_cp, de_prev, le16_to_cpu(de_prev->length));
                hpfs_delete_de(i->i_sb, dnode, de_prev);
                if (!de_prev->down) {
-                       de_prev->length = cpu_to_le16(le16_to_cpu(de_prev->length) + 4);
+                       le16_add_cpu(&de_prev->length, 4);
                        de_prev->down = 1;
-                       dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
+                       le32_add_cpu(&dnode->first_free, 4);
                }
                *(__le32 *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);
                hpfs_mark_4buffers_dirty(&qbh);
index 2c6d95257a4d5c7a61bf39b895c5ebbd647cc49b..77e3cb2962b46e58a982cce170e9716dfc8880df 100644 (file)
@@ -146,8 +146,7 @@ static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe,
                        be64_to_cpu(entry->e_blocks);
 
                if (omfs_allocate_block(inode->i_sb, new_block)) {
-                       entry->e_blocks =
-                               cpu_to_be64(be64_to_cpu(entry->e_blocks) + 1);
+                       be64_add_cpu(&entry->e_blocks, 1);
                        terminator->e_blocks = ~(cpu_to_be64(
                                be64_to_cpu(~terminator->e_blocks) + 1));
                        goto out;
@@ -177,7 +176,7 @@ static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe,
                be64_to_cpu(~terminator->e_blocks) + (u64) new_count));
 
        /* write in new entry */
-       oe->e_extent_count = cpu_to_be32(1 + be32_to_cpu(oe->e_extent_count));
+       be32_add_cpu(&oe->e_extent_count, 1);
 
 out:
        *ret_block = new_block;
index b3647fe6a60870e55f36710497fd9dff583963ee..0d80cef4cfb93ea5bbd423b6cf887039f15b093a 100644 (file)
@@ -427,7 +427,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
                if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
                        pde_get(de);
                        spin_unlock(&proc_subdir_lock);
-                       error = -EINVAL;
+                       error = -ENOMEM;
                        inode = proc_get_inode(dir->i_sb, de);
                        goto out_unlock;
                }
@@ -605,7 +605,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        unsigned int len;
 
        /* make sure name is valid */
-       if (!name || !strlen(name)) goto out;
+       if (!name || !strlen(name))
+               goto out;
 
        if (xlate_proc_name(name, parent, &fn) != 0)
                goto out;
@@ -616,20 +617,18 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
 
        len = strlen(fn);
 
-       ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
-       if (!ent) goto out;
+       ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+       if (!ent)
+               goto out;
 
-       memset(ent, 0, sizeof(struct proc_dir_entry));
        memcpy(ent->name, fn, len + 1);
        ent->namelen = len;
        ent->mode = mode;
        ent->nlink = nlink;
        atomic_set(&ent->count, 1);
-       ent->pde_users = 0;
        spin_lock_init(&ent->pde_unload_lock);
-       ent->pde_unload_completion = NULL;
        INIT_LIST_HEAD(&ent->pde_openers);
- out:
+out:
        return ent;
 }
 
index 7ac817b64a7193b71cf867f72fc0d94d68294c90..3b22bbdee9ec6e8bb9a8b6f19d19bc508e9d2879 100644 (file)
@@ -450,7 +450,6 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
                return NULL;
        if (inode->i_state & I_NEW) {
                inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-               PROC_I(inode)->fd = 0;
                PROC_I(inode)->pde = de;
 
                if (de->mode) {
index 67925a7bd8cb757f56db940efcff1fe9c7ef112a..cceaab07ad549caaa124b71e3db01f126052ef59 100644 (file)
@@ -103,7 +103,7 @@ static inline int task_dumpable(struct task_struct *task)
        if (mm)
                dumpable = get_dumpable(mm);
        task_unlock(task);
-       if(dumpable == 1)
+       if (dumpable == SUID_DUMPABLE_ENABLED)
                return 1;
        return 0;
 }
index eb7cc91b7258870f89b77a60de4172dd6f1502b6..dcd56f84db7ebcce37e884cae218c90d795109b0 100644 (file)
@@ -266,8 +266,7 @@ void sysctl_head_put(struct ctl_table_header *head)
 
 static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
 {
-       if (!head)
-               BUG();
+       BUG_ON(!head);
        spin_lock(&sysctl_lock);
        if (!use_table(head))
                head = ERR_PTR(-ENOENT);
index 9a2d9fd7cadd2acde77a4e00615f9bbafefc8d96..9889a92d2e01773113a5c7db29975cb47d7dcb1d 100644 (file)
@@ -61,7 +61,7 @@ static int proc_parse_options(char *options, struct pid_namespace *pid)
                if (!*p)
                        continue;
 
-               args[0].to = args[0].from = 0;
+               args[0].to = args[0].from = NULL;
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_gid:
index d39bb5cce88389809cf00a9010bb00bacb255e58..ca71db69da07a000814837c20cf76bac049b3ca1 100644 (file)
@@ -23,6 +23,7 @@ config PSTORE_FTRACE
        bool "Persistent function tracer"
        depends on PSTORE
        depends on FUNCTION_TRACER
+       depends on DEBUG_FS
        help
          With this option kernel traces function calls into a persistent
          ram buffer that can be decoded and dumped after reboot through
index a130d484b7d35ba7fe4463075e6c84f3811ad2eb..2d57e1ac0115ae12357e108c22ef8d783637ab87 100644 (file)
 #include <linux/percpu.h>
 #include <linux/smp.h>
 #include <linux/atomic.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/ftrace.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/cache.h>
 #include <asm/barrier.h>
 #include "internal.h"
 
-void notrace pstore_ftrace_call(unsigned long ip, unsigned long parent_ip)
+static void notrace pstore_ftrace_call(unsigned long ip,
+                                      unsigned long parent_ip)
 {
+       unsigned long flags;
        struct pstore_ftrace_record rec = {};
 
        if (unlikely(oops_in_progress))
                return;
 
+       local_irq_save(flags);
+
        rec.ip = ip;
        rec.parent_ip = parent_ip;
        pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
        psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec,
                          sizeof(rec), psinfo);
+
+       local_irq_restore(flags);
+}
+
+static struct ftrace_ops pstore_ftrace_ops __read_mostly = {
+       .func   = pstore_ftrace_call,
+};
+
+static DEFINE_MUTEX(pstore_ftrace_lock);
+static bool pstore_ftrace_enabled;
+
+static ssize_t pstore_ftrace_knob_write(struct file *f, const char __user *buf,
+                                       size_t count, loff_t *ppos)
+{
+       u8 on;
+       ssize_t ret;
+
+       ret = kstrtou8_from_user(buf, count, 2, &on);
+       if (ret)
+               return ret;
+
+       mutex_lock(&pstore_ftrace_lock);
+
+       if (!on ^ pstore_ftrace_enabled)
+               goto out;
+
+       if (on)
+               ret = register_ftrace_function(&pstore_ftrace_ops);
+       else
+               ret = unregister_ftrace_function(&pstore_ftrace_ops);
+       if (ret) {
+               pr_err("%s: unable to %sregister ftrace ops: %zd\n",
+                      __func__, on ? "" : "un", ret);
+               goto err;
+       }
+
+       pstore_ftrace_enabled = on;
+out:
+       ret = count;
+err:
+       mutex_unlock(&pstore_ftrace_lock);
+
+       return ret;
+}
+
+static ssize_t pstore_ftrace_knob_read(struct file *f, char __user *buf,
+                                      size_t count, loff_t *ppos)
+{
+       char val[] = { '0' + pstore_ftrace_enabled, '\n' };
+
+       return simple_read_from_buffer(buf, count, ppos, val, sizeof(val));
+}
+
+static const struct file_operations pstore_knob_fops = {
+       .open   = simple_open,
+       .read   = pstore_ftrace_knob_read,
+       .write  = pstore_ftrace_knob_write,
+};
+
+void pstore_register_ftrace(void)
+{
+       struct dentry *dir;
+       struct dentry *file;
+
+       if (!psinfo->write_buf)
+               return;
+
+       dir = debugfs_create_dir("pstore", NULL);
+       if (!dir) {
+               pr_err("%s: unable to create pstore directory\n", __func__);
+               return;
+       }
+
+       file = debugfs_create_file("record_ftrace", 0600, dir, NULL,
+                                  &pstore_knob_fops);
+       if (!file) {
+               pr_err("%s: unable to create record_ftrace file\n", __func__);
+               goto err_file;
+       }
+
+       return;
+err_file:
+       debugfs_remove(dir);
 }
index 0d0d3b7d5f12096f556e8ba104eac520de810e5c..4847f588b7d5079df974c42a2f7324615e477aca 100644 (file)
@@ -39,6 +39,12 @@ pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
 #endif
 }
 
+#ifdef CONFIG_PSTORE_FTRACE
+extern void pstore_register_ftrace(void);
+#else
+static inline void pstore_register_ftrace(void) {}
+#endif
+
 extern struct pstore_info *psinfo;
 
 extern void    pstore_set_kmsg_bytes(int);
index 29996e8793a7753139bdb7105bc00994bb411ba0..a40da07e93d68a88e670b5256a1c22c4badeb634 100644 (file)
@@ -164,7 +164,13 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 
                if (c > psinfo->bufsize)
                        c = psinfo->bufsize;
-               spin_lock_irqsave(&psinfo->buf_lock, flags);
+
+               if (oops_in_progress) {
+                       if (!spin_trylock_irqsave(&psinfo->buf_lock, flags))
+                               break;
+               } else {
+                       spin_lock_irqsave(&psinfo->buf_lock, flags);
+               }
                memcpy(psinfo->buf, s, c);
                psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
@@ -236,6 +242,7 @@ int pstore_register(struct pstore_info *psi)
 
        kmsg_dump_register(&pstore_dumper);
        pstore_register_console();
+       pstore_register_ftrace();
 
        if (pstore_update_ms >= 0) {
                pstore_timer.expires = jiffies +
index 0b311bc18916ab137c31d59aa2228c71a2a285c7..1a4f6da58eab4018878aab4275e1d3b6f3309b37 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/compiler.h>
 #include <linux/pstore_ram.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
@@ -181,12 +182,11 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
        return len;
 }
 
-
-static int ramoops_pstore_write_buf(enum pstore_type_id type,
-                                   enum kmsg_dump_reason reason,
-                                   u64 *id, unsigned int part,
-                                   const char *buf, size_t size,
-                                   struct pstore_info *psi)
+static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
+                                           enum kmsg_dump_reason reason,
+                                           u64 *id, unsigned int part,
+                                           const char *buf, size_t size,
+                                           struct pstore_info *psi)
 {
        struct ramoops_context *cxt = psi->data;
        struct persistent_ram_zone *prz = cxt->przs[cxt->dump_write_cnt];
@@ -406,7 +406,7 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
                goto fail_init_fprz;
 
        if (!cxt->przs && !cxt->cprz && !cxt->fprz) {
-               pr_err("memory size too small, minimum is %lu\n",
+               pr_err("memory size too small, minimum is %zu\n",
                        cxt->console_size + cxt->record_size +
                        cxt->ftrace_size);
                goto fail_cnt;
@@ -414,13 +414,14 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
 
        cxt->pstore.data = cxt;
        /*
-        * Console can handle any buffer size, so prefer dumps buffer
-        * size since usually it is smaller.
+        * Console can handle any buffer size, so prefer LOG_LINE_MAX. If we
+        * have to handle dumps, we must have at least record_size buffer. And
+        * for ftrace, bufsize is irrelevant (if bufsize is 0, buf will be
+        * ZERO_SIZE_PTR).
         */
-       if (cxt->przs)
-               cxt->pstore.bufsize = cxt->przs[0]->buffer_size;
-       else
-               cxt->pstore.bufsize = cxt->cprz->buffer_size;
+       if (cxt->console_size)
+               cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
+       cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
        cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
        spin_lock_init(&cxt->pstore.buf_lock);
        if (!cxt->pstore.buf) {
@@ -537,6 +538,7 @@ postcore_initcall(ramoops_init);
 static void __exit ramoops_exit(void)
 {
        platform_driver_unregister(&ramoops_driver);
+       platform_device_unregister(dummy);
        kfree(dummy_data);
 }
 module_exit(ramoops_exit);
index 5fdf7ff32c4e283e74373bbabe00f9e165d5aa41..a3bc935069d9d5c643657793602ea42201263ed4 100644 (file)
@@ -865,7 +865,7 @@ int get_anon_bdev(dev_t *p)
        else if (error)
                return -EAGAIN;
 
-       if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) {
+       if ((dev & MAX_IDR_MASK) == (1 << MINORBITS)) {
                spin_lock(&unnamed_dev_lock);
                ida_remove(&unnamed_dev_ida, dev);
                if (unnamed_dev_start > dev)
index f95c663a6a4169f6a7ae2258623aeebec6d661c9..61731543c00ea381fb8954c69b834b976260c0db 100644 (file)
@@ -54,6 +54,16 @@ static inline int test_bit_le(int nr, const void *addr)
        return test_bit(nr ^ BITOP_LE_SWIZZLE, addr);
 }
 
+static inline void set_bit_le(int nr, void *addr)
+{
+       set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+       clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
 static inline void __set_bit_le(int nr, void *addr)
 {
        __set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
index 3748ec92dcbcdb988bad96406e7d53b664118152..cf22fae8cae1a00ba47bac98ab99286390c3becc 100644 (file)
@@ -1,6 +1,3 @@
-#if !defined(_ASM_GENERIC_UNISTD_H) || defined(__SYSCALL)
-#define _ASM_GENERIC_UNISTD_H
-
 #include <asm/bitsperlong.h>
 
 /*
@@ -930,4 +927,3 @@ __SYSCALL(__NR_fork, sys_ni_syscall)
 #endif
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_GENERIC_UNISTD_H */
index e149e8be9065a27d3ca56fb2aad581c8465841bc..d114db9477f43468b85a692e034f00d18ec2d596 100644 (file)
@@ -21,18 +21,15 @@ header-y += usb/
 header-y += wimax/
 
 ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
-                 $(srctree)/include/asm-$(SRCARCH)/a.out.h \
-                 $(INSTALL_HDR_PATH)/include/asm-*/a.out.h),)
+                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),)
 header-y += a.out.h
 endif
 ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
-                 $(srctree)/include/asm-$(SRCARCH)/kvm.h \
-                 $(INSTALL_HDR_PATH)/include/asm-*/kvm.h),)
+                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),)
 header-y += kvm.h
 endif
 ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \
-                 $(srctree)/include/asm-$(SRCARCH)/kvm_para.h \
-                 $(INSTALL_HDR_PATH)/include/asm-*/kvm_para.h),)
+                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),)
 header-y += kvm_para.h
 endif
 
@@ -385,6 +382,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 e7c836d961ea3e442c6fcf1c63534f549a956e98..2c83e5f7edb12882330d2958f9c1db6b2d708c69 100644 (file)
@@ -527,9 +527,18 @@ static inline void audit_ptrace(struct task_struct *t)
 extern unsigned int audit_serial(void);
 extern int auditsc_get_stamp(struct audit_context *ctx,
                              struct timespec *t, unsigned int *serial);
-extern int  audit_set_loginuid(kuid_t loginuid);
-#define audit_get_loginuid(t) ((t)->loginuid)
-#define audit_get_sessionid(t) ((t)->sessionid)
+extern int audit_set_loginuid(kuid_t loginuid);
+
+static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
+{
+       return tsk->loginuid;
+}
+
+static inline int audit_get_sessionid(struct task_struct *tsk)
+{
+       return tsk->sessionid;
+}
+
 extern void audit_log_task_context(struct audit_buffer *ab);
 extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk);
 extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
@@ -626,38 +635,101 @@ static inline void audit_mmap_fd(int fd, int flags)
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
-#define audit_alloc(t) ({ 0; })
-#define audit_free(t) do { ; } while (0)
-#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(r) do { ; } while (0)
-#define audit_dummy_context() 1
-#define audit_getname(n) do { ; } while (0)
-#define audit_putname(n) do { ; } while (0)
-#define __audit_inode(n,d) do { ; } while (0)
-#define __audit_inode_child(i,p) do { ; } while (0)
-#define audit_inode(n,d) do { (void)(d); } while (0)
-#define audit_inode_child(i,p) do { ; } while (0)
-#define audit_core_dumps(i) do { ; } while (0)
-#define audit_seccomp(i,s,c) do { ; } while (0)
-#define auditsc_get_stamp(c,t,s) (0)
-#define audit_get_loginuid(t) (INVALID_UID)
-#define audit_get_sessionid(t) (-1)
-#define audit_log_task_context(b) do { ; } while (0)
-#define audit_log_task_info(b, t) do { ; } while (0)
-#define audit_ipc_obj(i) ((void)0)
-#define audit_ipc_set_perm(q,u,g,m) ((void)0)
-#define audit_bprm(p) ({ 0; })
-#define audit_socketcall(n,a) ((void)0)
-#define audit_fd_pair(n,a) ((void)0)
-#define audit_sockaddr(len, addr) ({ 0; })
-#define audit_mq_open(o,m,a) ((void)0)
-#define audit_mq_sendrecv(d,l,p,t) ((void)0)
-#define audit_mq_notify(d,n) ((void)0)
-#define audit_mq_getsetattr(d,s) ((void)0)
-#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
-#define audit_log_capset(pid, ncr, ocr) ((void)0)
-#define audit_mmap_fd(fd, flags) ((void)0)
-#define audit_ptrace(t) ((void)0)
+static inline int audit_alloc(struct task_struct *task)
+{
+       return 0;
+}
+static inline void audit_free(struct task_struct *task)
+{ }
+static inline void audit_syscall_entry(int arch, int major, unsigned long a0,
+                                      unsigned long a1, unsigned long a2,
+                                      unsigned long a3)
+{ }
+static inline void audit_syscall_exit(void *pt_regs)
+{ }
+static inline int audit_dummy_context(void)
+{
+       return 1;
+}
+static inline void audit_getname(const char *name)
+{ }
+static inline void audit_putname(const char *name)
+{ }
+static inline void __audit_inode(const char *name, const struct dentry *dentry)
+{ }
+static inline void __audit_inode_child(const struct dentry *dentry,
+                                       const struct inode *parent)
+{ }
+static inline void audit_inode(const char *name, const struct dentry *dentry)
+{ }
+static inline void audit_inode_child(const struct dentry *dentry,
+                                    const struct inode *parent)
+{ }
+static inline void audit_core_dumps(long signr)
+{ }
+static inline void __audit_seccomp(unsigned long syscall, long signr, int code)
+{ }
+static inline void audit_seccomp(unsigned long syscall, long signr, int code)
+{ }
+static inline int auditsc_get_stamp(struct audit_context *ctx,
+                             struct timespec *t, unsigned int *serial)
+{
+       return 0;
+}
+static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
+{
+       return INVALID_UID;
+}
+static inline int audit_get_sessionid(struct task_struct *tsk)
+{
+       return -1;
+}
+static inline void audit_log_task_context(struct audit_buffer *ab)
+{ }
+static inline void audit_log_task_info(struct audit_buffer *ab,
+                                      struct task_struct *tsk)
+{ }
+static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
+{ }
+static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
+                                       gid_t gid, umode_t mode)
+{ }
+static inline int audit_bprm(struct linux_binprm *bprm)
+{
+       return 0;
+}
+static inline void audit_socketcall(int nargs, unsigned long *args)
+{ }
+static inline void audit_fd_pair(int fd1, int fd2)
+{ }
+static inline int audit_sockaddr(int len, void *addr)
+{
+       return 0;
+}
+static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
+{ }
+static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len,
+                                    unsigned int msg_prio,
+                                    const struct timespec *abs_timeout)
+{ }
+static inline void audit_mq_notify(mqd_t mqdes,
+                                  const struct sigevent *notification)
+{ }
+static inline void audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{ }
+static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm,
+                                      const struct cred *new,
+                                      const struct cred *old)
+{
+       return 0;
+}
+static inline void audit_log_capset(pid_t pid, const struct cred *new,
+                                  const struct cred *old)
+{ }
+static inline void audit_mmap_fd(int fd, int flags)
+{ }
+static inline void audit_ptrace(struct task_struct *t)
+{ }
 #define audit_n_rules 0
 #define audit_signals 0
 #endif /* CONFIG_AUDITSYSCALL */
@@ -681,7 +753,6 @@ extern void             audit_log_n_hex(struct audit_buffer *ab,
 extern void                audit_log_n_string(struct audit_buffer *ab,
                                               const char *buf,
                                               size_t n);
-#define audit_log_string(a,b) audit_log_n_string(a, b, strlen(b));
 extern void                audit_log_n_untrustedstring(struct audit_buffer *ab,
                                                        const char *string,
                                                        size_t n);
@@ -698,7 +769,8 @@ extern void             audit_log_lost(const char *message);
 #ifdef CONFIG_SECURITY
 extern void                audit_log_secctx(struct audit_buffer *ab, u32 secid);
 #else
-#define audit_log_secctx(b,s) do { ; } while (0)
+static inline void         audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{ }
 #endif
 
 extern int                 audit_update_lsm_rules(void);
@@ -710,22 +782,50 @@ extern int  audit_receive_filter(int type, int pid, int seq,
                                void *data, size_t datasz, kuid_t loginuid,
                                u32 sessionid, u32 sid);
 extern int audit_enabled;
-#else
-#define audit_log(c,g,t,f,...) do { ; } while (0)
-#define audit_log_start(c,g,t) ({ NULL; })
-#define audit_log_vformat(b,f,a) do { ; } while (0)
-#define audit_log_format(b,f,...) do { ; } while (0)
-#define audit_log_end(b) do { ; } while (0)
-#define audit_log_n_hex(a,b,l) do { ; } while (0)
-#define audit_log_n_string(a,c,l) do { ; } while (0)
-#define audit_log_string(a,c) do { ; } while (0)
-#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
-#define audit_log_untrustedstring(a,s) do { ; } while (0)
-#define audit_log_d_path(b, p, d) do { ; } while (0)
-#define audit_log_key(b, k) do { ; } while (0)
-#define audit_log_link_denied(o, l) do { ; } while (0)
-#define audit_log_secctx(b,s) do { ; } while (0)
+#else /* CONFIG_AUDIT */
+static inline __printf(4, 5)
+void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
+              const char *fmt, ...)
+{ }
+static inline struct audit_buffer *audit_log_start(struct audit_context *ctx,
+                                                  gfp_t gfp_mask, int type)
+{
+       return NULL;
+}
+static inline __printf(2, 3)
+void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
+{ }
+static inline void audit_log_end(struct audit_buffer *ab)
+{ }
+static inline void audit_log_n_hex(struct audit_buffer *ab,
+                                  const unsigned char *buf, size_t len)
+{ }
+static inline void audit_log_n_string(struct audit_buffer *ab,
+                                     const char *buf, size_t n)
+{ }
+static inline void  audit_log_n_untrustedstring(struct audit_buffer *ab,
+                                               const char *string, size_t n)
+{ }
+static inline void audit_log_untrustedstring(struct audit_buffer *ab,
+                                            const char *string)
+{ }
+static inline void audit_log_d_path(struct audit_buffer *ab,
+                                   const char *prefix,
+                                   const struct path *path)
+{ }
+static inline void audit_log_key(struct audit_buffer *ab, char *key)
+{ }
+static inline void audit_log_link_denied(const char *string,
+                                        const struct path *link)
+{ }
+static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{ }
 #define audit_enabled 0
-#endif
+#endif /* CONFIG_AUDIT */
+static inline void audit_log_string(struct audit_buffer *ab, const char *buf)
+{
+       audit_log_n_string(ab, buf, strlen(buf));
+}
+
 #endif
 #endif
index 366422bc1633cecda39235276569f283faf0bf46..37935c2d2e8f1eb1a4b071a38e3af6fd14bb1296 100644 (file)
@@ -72,7 +72,7 @@ struct linux_binprm {
 
 /* Function parameter for binfmt->coredump */
 struct coredump_params {
-       long signr;
+       siginfo_t *siginfo;
        struct pt_regs *regs;
        struct file *file;
        unsigned long limit;
@@ -132,7 +132,6 @@ extern int copy_strings_kernel(int argc, const char *const *argv,
                               struct linux_binprm *bprm);
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
 extern void install_exec_creds(struct linux_binprm *bprm);
-extern void do_coredump(long signr, int exit_code, struct pt_regs *regs);
 extern void set_binfmt(struct linux_binfmt *new);
 extern void free_bprm(struct linux_binprm *);
 
index fd4e29956d1c1d8069a085553bf1474e7b99ff7f..3f53d002c7c5c88521874e2e0085f0a083f2e7d1 100644 (file)
@@ -160,11 +160,6 @@ struct compat_ustat {
        char                    f_fpack[6];
 };
 
-typedef union compat_sigval {
-       compat_int_t    sival_int;
-       compat_uptr_t   sival_ptr;
-} compat_sigval_t;
-
 #define COMPAT_SIGEV_PAD_SIZE  ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
 
 typedef struct compat_sigevent {
index ba4b85a6d9b8bc71853de37df2a36b865707b745..1775eb8acc03665d36bf8b094c440a41ba10764d 100644 (file)
  */
 extern int dump_write(struct file *file, const void *addr, int nr);
 extern int dump_seek(struct file *file, loff_t off);
+#ifdef CONFIG_COREDUMP
+extern void do_coredump(siginfo_t *siginfo, struct pt_regs *regs);
+#else
+static inline void do_coredump(siginfo_t *siginfo, struct pt_regs *regs) {}
+#endif
 
 #endif /* _LINUX_COREDUMP_H */
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 0a05051a8924df5e2d1e55562c1d66698702a7db..59ef40650e1ea19d107a62c76decec52c4d7797f 100644 (file)
@@ -372,6 +372,12 @@ typedef struct elf64_shdr {
 #define NT_PRPSINFO    3
 #define NT_TASKSTRUCT  4
 #define NT_AUXV                6
+/*
+ * Note to userspace developers: size of NT_SIGINFO note may increase
+ * in the future to accomodate more fields, don't assume it is fixed!
+ */
+#define NT_SIGINFO      0x53494749
+#define NT_FILE         0x46494c45
 #define NT_PRXFPREG     0x46e62b7f      /* copied from gdb5.1/include/elf/common.h */
 #define NT_PPC_VMX     0x100           /* PowerPC Altivec/VMX registers */
 #define NT_PPC_SPE     0x101           /* PowerPC SPE/EVR registers */
index f4bb378ccf6a355bbe49e79f56019f9ef386d1d4..41085d0f3955b3ff247b426de9452b731d00c19b 100644 (file)
@@ -25,6 +25,7 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
+#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
index 5e98eeb2af3b970220c7743016f9f85b0213ae8b..dd7c569aacad6283c396872625a985e0a42b4e91 100644 (file)
 
 #ifndef __GENALLOC_H__
 #define __GENALLOC_H__
+/**
+ * Allocation callback function type definition
+ * @map: Pointer to bitmap
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @data: optional additional data used by @genpool_algo_t
+ */
+typedef unsigned long (*genpool_algo_t)(unsigned long *map,
+                       unsigned long size,
+                       unsigned long start,
+                       unsigned int nr,
+                       void *data);
+
 /*
  *  General purpose special memory pool descriptor.
  */
@@ -36,6 +50,9 @@ struct gen_pool {
        spinlock_t lock;
        struct list_head chunks;        /* list of chunks in this pool */
        int min_alloc_order;            /* minimum allocation order */
+
+       genpool_algo_t algo;            /* allocation function */
+       void *data;
 };
 
 /*
@@ -78,4 +95,14 @@ extern void gen_pool_for_each_chunk(struct gen_pool *,
        void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
 extern size_t gen_pool_avail(struct gen_pool *);
 extern size_t gen_pool_size(struct gen_pool *);
+
+extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo,
+               void *data);
+
+extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
+               unsigned long start, unsigned int nr, void *data);
+
+extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
+               unsigned long start, unsigned int nr, void *data);
+
 #endif /* __GENALLOC_H__ */
index a12a38107c1aa3157d8ddb622c3f613aed28f850..1faa58f9b85edefe0d9e76c7372173baafa20f26 100644 (file)
@@ -188,6 +188,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
 
 int twl_get_type(void);
 int twl_get_version(void);
+int twl_get_hfclk_rate(void);
 
 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
 int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
index 255491cf522e1d08ea6d0066fc7872f32817c82c..87259a44c251472595598f0f6ed0852655171554 100644 (file)
 #define IDR_SIZE (1 << IDR_BITS)
 #define IDR_MASK ((1 << IDR_BITS)-1)
 
-#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
-#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
-#define MAX_ID_MASK (MAX_ID_BIT - 1)
+#define MAX_IDR_SHIFT (sizeof(int)*8 - 1)
+#define MAX_IDR_BIT (1U << MAX_IDR_SHIFT)
+#define MAX_IDR_MASK (MAX_IDR_BIT - 1)
 
 /* Leave the possibility of an incomplete final layer */
-#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
+#define MAX_IDR_LEVEL ((MAX_IDR_SHIFT + IDR_BITS - 1) / IDR_BITS)
 
 /* Number of id_layer structs to leave in free list */
-#define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
+#define MAX_IDR_FREE (MAX_IDR_LEVEL * 2)
 
 struct idr_layer {
        unsigned long            bitmap; /* A zero bit means "space here" */
index 5e664f671615d9615421ed40444aac1550d36fa2..e59041e21df32c279a3a732a70cb6a18b47b10d3 100644 (file)
    discard it in modules) */
 #define __init         __section(.init.text) __cold notrace
 #define __initdata     __section(.init.data)
-#define __initconst    __section(.init.rodata)
+#define __initconst    __constsection(.init.rodata)
 #define __exitdata     __section(.exit.data)
 #define __exit_call    __used __section(.exitcall.exit)
 
+/*
+ * Some architecture have tool chains which do not handle rodata attributes
+ * correctly. For those disable special sections for const, so that other
+ * architectures can annotate correctly.
+ */
+#ifdef CONFIG_BROKEN_RODATA
+#define __constsection(x)
+#else
+#define __constsection(x) __section(x)
+#endif
+
 /*
  * modpost check for section mismatches during the kernel build.
  * A section mismatch happens when there are references from a
@@ -66,7 +77,7 @@
  */
 #define __ref            __section(.ref.text) noinline
 #define __refdata        __section(.ref.data)
-#define __refconst       __section(.ref.rodata)
+#define __refconst       __constsection(.ref.rodata)
 
 /* compatibility defines */
 #define __init_refok     __ref
 /* Used for HOTPLUG */
 #define __devinit        __section(.devinit.text) __cold notrace
 #define __devinitdata    __section(.devinit.data)
-#define __devinitconst   __section(.devinit.rodata)
+#define __devinitconst   __constsection(.devinit.rodata)
 #define __devexit        __section(.devexit.text) __exitused __cold notrace
 #define __devexitdata    __section(.devexit.data)
-#define __devexitconst   __section(.devexit.rodata)
+#define __devexitconst   __constsection(.devexit.rodata)
 
 /* Used for HOTPLUG_CPU */
 #define __cpuinit        __section(.cpuinit.text) __cold notrace
 #define __cpuinitdata    __section(.cpuinit.data)
-#define __cpuinitconst   __section(.cpuinit.rodata)
+#define __cpuinitconst   __constsection(.cpuinit.rodata)
 #define __cpuexit        __section(.cpuexit.text) __exitused __cold notrace
 #define __cpuexitdata    __section(.cpuexit.data)
-#define __cpuexitconst   __section(.cpuexit.rodata)
+#define __cpuexitconst   __constsection(.cpuexit.rodata)
 
 /* Used for MEMORY_HOTPLUG */
 #define __meminit        __section(.meminit.text) __cold notrace
 #define __meminitdata    __section(.meminit.data)
-#define __meminitconst   __section(.meminit.rodata)
+#define __meminitconst   __constsection(.meminit.rodata)
 #define __memexit        __section(.memexit.text) __exitused __cold notrace
 #define __memexitdata    __section(.memexit.data)
-#define __memexitconst   __section(.memexit.rodata)
+#define __memexitconst   __constsection(.memexit.rodata)
 
 /* For assembly routines */
 #define __HEAD         .section        ".head.text","ax"
index 589e0e75efae2dc1146da2cc0f92e6c649f834ed..85ac9b9b72a24acc54ebab8241d279fe2332d4b6 100644 (file)
@@ -29,8 +29,9 @@ struct resource {
 #define IORESOURCE_BITS                0x000000ff      /* Bus-specific bits */
 
 #define IORESOURCE_TYPE_BITS   0x00001f00      /* Resource type */
-#define IORESOURCE_IO          0x00000100
+#define IORESOURCE_IO          0x00000100      /* PCI/ISA I/O ports */
 #define IORESOURCE_MEM         0x00000200
+#define IORESOURCE_REG         0x00000300      /* Register offsets */
 #define IORESOURCE_IRQ         0x00000400
 #define IORESOURCE_DMA         0x00000800
 #define IORESOURCE_BUS         0x00001000
index a0c3bf6c9edb5af29b4823b3903c458cb4d19702..4c0306c69b4e0efce9c8b10d84dafc08c9c1f836 100644 (file)
@@ -2,7 +2,7 @@
 #define _INCLUDE_LIBFDT_H_
 
 #include <linux/libfdt_env.h>
-#include <>
-#include <>
+#include "../../scripts/dtc/libfdt/fdt.h"
+#include "../../scripts/dtc/libfdt/libfdt.h"
 
 #endif /* _INCLUDE_LIBFDT_H_ */
index 7b24943779fa7258904f2b93dbd484856b8fe74d..cd97530205c22e995708ec7c4f96ca31aaf3841b 100644 (file)
@@ -34,27 +34,26 @@ enum {
        PM8606_ID_MAX,
 };
 
-enum {
-       PM8606_BACKLIGHT1 = 0,
-       PM8606_BACKLIGHT2,
-       PM8606_BACKLIGHT3,
-};
-
-enum {
-       PM8606_LED1_RED = 0,
-       PM8606_LED1_GREEN,
-       PM8606_LED1_BLUE,
-       PM8606_LED2_RED,
-       PM8606_LED2_GREEN,
-       PM8606_LED2_BLUE,
-       PM8607_LED_VIBRATOR,
-};
-
 
 /* 8606 Registers */
 #define PM8606_DCM_BOOST               (0x00)
 #define PM8606_PWM                     (0x01)
 
+#define PM8607_MISC2                   (0x42)
+
+/* Power Up Log Register */
+#define PM8607_POWER_UP_LOG            (0x3F)
+
+/* Charger Control Registers */
+#define PM8607_CCNT                    (0x47)
+#define PM8607_CHG_CTRL1               (0x48)
+#define PM8607_CHG_CTRL2               (0x49)
+#define PM8607_CHG_CTRL3               (0x4A)
+#define PM8607_CHG_CTRL4               (0x4B)
+#define PM8607_CHG_CTRL5               (0x4C)
+#define PM8607_CHG_CTRL6               (0x4D)
+#define PM8607_CHG_CTRL7               (0x4E)
+
 /* Backlight Registers */
 #define PM8606_WLED1A                  (0x02)
 #define PM8606_WLED1B                  (0x03)
@@ -205,6 +204,71 @@ enum {
 #define PM8607_PD_PREBIAS              (0x56)  /* prebias time */
 #define PM8607_GPADC_MISC1             (0x57)
 
+/* bit definitions of  MEAS_EN1*/
+#define PM8607_MEAS_EN1_VBAT           (1 << 0)
+#define PM8607_MEAS_EN1_VCHG           (1 << 1)
+#define PM8607_MEAS_EN1_VSYS           (1 << 2)
+#define PM8607_MEAS_EN1_TINT           (1 << 3)
+#define PM8607_MEAS_EN1_RFTMP          (1 << 4)
+#define PM8607_MEAS_EN1_TBAT           (1 << 5)
+#define PM8607_MEAS_EN1_GPADC2         (1 << 6)
+#define PM8607_MEAS_EN1_GPADC3         (1 << 7)
+
+/* Battery Monitor Registers */
+#define PM8607_GP_BIAS2                        (0x5A)
+#define PM8607_VBAT_LOWTH              (0x5B)
+#define PM8607_VCHG_LOWTH              (0x5C)
+#define PM8607_VSYS_LOWTH              (0x5D)
+#define PM8607_TINT_LOWTH              (0x5E)
+#define PM8607_GPADC0_LOWTH            (0x5F)
+#define PM8607_GPADC1_LOWTH            (0x60)
+#define PM8607_GPADC2_LOWTH            (0x61)
+#define PM8607_GPADC3_LOWTH            (0x62)
+#define PM8607_VBAT_HIGHTH             (0x63)
+#define PM8607_VCHG_HIGHTH             (0x64)
+#define PM8607_VSYS_HIGHTH             (0x65)
+#define PM8607_TINT_HIGHTH             (0x66)
+#define PM8607_GPADC0_HIGHTH           (0x67)
+#define PM8607_GPADC1_HIGHTH           (0x68)
+#define PM8607_GPADC2_HIGHTH           (0x69)
+#define PM8607_GPADC3_HIGHTH           (0x6A)
+#define PM8607_IBAT_MEAS1              (0x6B)
+#define PM8607_IBAT_MEAS2              (0x6C)
+#define PM8607_VBAT_MEAS1              (0x6D)
+#define PM8607_VBAT_MEAS2              (0x6E)
+#define PM8607_VCHG_MEAS1              (0x6F)
+#define PM8607_VCHG_MEAS2              (0x70)
+#define PM8607_VSYS_MEAS1              (0x71)
+#define PM8607_VSYS_MEAS2              (0x72)
+#define PM8607_TINT_MEAS1              (0x73)
+#define PM8607_TINT_MEAS2              (0x74)
+#define PM8607_GPADC0_MEAS1            (0x75)
+#define PM8607_GPADC0_MEAS2            (0x76)
+#define PM8607_GPADC1_MEAS1            (0x77)
+#define PM8607_GPADC1_MEAS2            (0x78)
+#define PM8607_GPADC2_MEAS1            (0x79)
+#define PM8607_GPADC2_MEAS2            (0x7A)
+#define PM8607_GPADC3_MEAS1            (0x7B)
+#define PM8607_GPADC3_MEAS2            (0x7C)
+#define PM8607_CCNT_MEAS1              (0x95)
+#define PM8607_CCNT_MEAS2              (0x96)
+#define PM8607_VBAT_AVG                        (0x97)
+#define PM8607_VCHG_AVG                        (0x98)
+#define PM8607_VSYS_AVG                        (0x99)
+#define PM8607_VBAT_MIN                        (0x9A)
+#define PM8607_VCHG_MIN                        (0x9B)
+#define PM8607_VSYS_MIN                        (0x9C)
+#define PM8607_VBAT_MAX                        (0x9D)
+#define PM8607_VCHG_MAX                        (0x9E)
+#define PM8607_VSYS_MAX                        (0x9F)
+
+#define PM8607_GPADC_MISC2             (0x59)
+#define PM8607_GPADC0_GP_BIAS_A0       (1 << 0)
+#define PM8607_GPADC1_GP_BIAS_A1       (1 << 1)
+#define PM8607_GPADC2_GP_BIAS_A2       (1 << 2)
+#define PM8607_GPADC3_GP_BIAS_A3       (1 << 3)
+#define PM8607_GPADC2_GP_BIAS_OUT2     (1 << 6)
+
 /* RTC Control Registers */
 #define PM8607_RTC1                    (0xA0)
 #define PM8607_RTC_COUNTER1            (0xA1)
@@ -322,7 +386,7 @@ struct pm860x_chip {
        struct regmap           *regmap_companion;
 
        int                     buck3_double;   /* DVC ramp slope double */
-       unsigned short          companion_addr;
+       int                     companion_addr;
        unsigned short          osc_vote;
        int                     id;
        int                     irq_mode;
@@ -340,16 +404,12 @@ enum {
 };
 
 struct pm860x_backlight_pdata {
-       int             id;
        int             pwm;
        int             iset;
-       unsigned long   flags;
 };
 
 struct pm860x_led_pdata {
-       int             id;
        int             iset;
-       unsigned long   flags;
 };
 
 struct pm860x_rtc_pdata {
@@ -370,7 +430,8 @@ struct pm860x_touch_pdata {
 };
 
 struct pm860x_power_pdata {
-       unsigned        fast_charge;    /* charge current */
+       int             max_capacity;
+       int             resistor;
 };
 
 struct pm860x_platform_data {
@@ -379,15 +440,30 @@ struct pm860x_platform_data {
        struct pm860x_rtc_pdata         *rtc;
        struct pm860x_touch_pdata       *touch;
        struct pm860x_power_pdata       *power;
-       struct regulator_init_data      *regulator;
-
-       unsigned short  companion_addr; /* I2C address of companion chip */
+       struct regulator_init_data      *buck1;
+       struct regulator_init_data      *buck2;
+       struct regulator_init_data      *buck3;
+       struct regulator_init_data      *ldo1;
+       struct regulator_init_data      *ldo2;
+       struct regulator_init_data      *ldo3;
+       struct regulator_init_data      *ldo4;
+       struct regulator_init_data      *ldo5;
+       struct regulator_init_data      *ldo6;
+       struct regulator_init_data      *ldo7;
+       struct regulator_init_data      *ldo8;
+       struct regulator_init_data      *ldo9;
+       struct regulator_init_data      *ldo10;
+       struct regulator_init_data      *ldo12;
+       struct regulator_init_data      *ldo_vibrator;
+       struct regulator_init_data      *ldo14;
+       struct charger_desc             *chg_desc;
+
+       int             companion_addr; /* I2C address of companion chip */
        int             i2c_port;       /* Controlled by GI2C or PI2C */
        int             irq_mode;       /* Clear interrupt by read/write(0/1) */
        int             irq_base;       /* IRQ base number of 88pm860x */
        int             num_leds;
        int             num_backlights;
-       int             num_regulators;
 };
 
 extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short);
@@ -408,8 +484,4 @@ extern int pm860x_page_bulk_write(struct i2c_client *, int, int,
 extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char,
                                unsigned char);
 
-extern int pm860x_device_init(struct pm860x_chip *chip,
-                             struct pm860x_platform_data *pdata) __devinit ;
-extern void pm860x_device_exit(struct pm860x_chip *chip) __devexit ;
-
 #endif /* __LINUX_MFD_88PM860X_H */
diff --git a/include/linux/mfd/ab3100.h b/include/linux/mfd/ab3100.h
new file mode 100644 (file)
index 0000000..afd3080
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * AB3100 core access functions
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ */
+
+#include <linux/regulator/machine.h>
+
+struct device;
+
+#ifndef MFD_AB3100_H
+#define MFD_AB3100_H
+
+
+#define AB3100_P1A     0xc0
+#define AB3100_P1B     0xc1
+#define AB3100_P1C     0xc2
+#define AB3100_P1D     0xc3
+#define AB3100_P1E     0xc4
+#define AB3100_P1F     0xc5
+#define AB3100_P1G     0xc6
+#define AB3100_R2A     0xc7
+#define AB3100_R2B     0xc8
+
+/*
+ * AB3100, EVENTA1, A2 and A3 event register flags
+ * these are catenated into a single 32-bit flag in the code
+ * for event notification broadcasts.
+ */
+#define AB3100_EVENTA1_ONSWA                           (0x01<<16)
+#define AB3100_EVENTA1_ONSWB                           (0x02<<16)
+#define AB3100_EVENTA1_ONSWC                           (0x04<<16)
+#define AB3100_EVENTA1_DCIO                            (0x08<<16)
+#define AB3100_EVENTA1_OVER_TEMP                       (0x10<<16)
+#define AB3100_EVENTA1_SIM_OFF                         (0x20<<16)
+#define AB3100_EVENTA1_VBUS                            (0x40<<16)
+#define AB3100_EVENTA1_VSET_USB                                (0x80<<16)
+
+#define AB3100_EVENTA2_READY_TX                                (0x01<<8)
+#define AB3100_EVENTA2_READY_RX                                (0x02<<8)
+#define AB3100_EVENTA2_OVERRUN_ERROR                   (0x04<<8)
+#define AB3100_EVENTA2_FRAMING_ERROR                   (0x08<<8)
+#define AB3100_EVENTA2_CHARG_OVERCURRENT               (0x10<<8)
+#define AB3100_EVENTA2_MIDR                            (0x20<<8)
+#define AB3100_EVENTA2_BATTERY_REM                     (0x40<<8)
+#define AB3100_EVENTA2_ALARM                           (0x80<<8)
+
+#define AB3100_EVENTA3_ADC_TRIG5                       (0x01)
+#define AB3100_EVENTA3_ADC_TRIG4                       (0x02)
+#define AB3100_EVENTA3_ADC_TRIG3                       (0x04)
+#define AB3100_EVENTA3_ADC_TRIG2                       (0x08)
+#define AB3100_EVENTA3_ADC_TRIGVBAT                    (0x10)
+#define AB3100_EVENTA3_ADC_TRIGVTX                     (0x20)
+#define AB3100_EVENTA3_ADC_TRIG1                       (0x40)
+#define AB3100_EVENTA3_ADC_TRIG0                       (0x80)
+
+/* AB3100, STR register flags */
+#define AB3100_STR_ONSWA                               (0x01)
+#define AB3100_STR_ONSWB                               (0x02)
+#define AB3100_STR_ONSWC                               (0x04)
+#define AB3100_STR_DCIO                                        (0x08)
+#define AB3100_STR_BOOT_MODE                           (0x10)
+#define AB3100_STR_SIM_OFF                             (0x20)
+#define AB3100_STR_BATT_REMOVAL                                (0x40)
+#define AB3100_STR_VBUS                                        (0x80)
+
+/*
+ * AB3100 contains 8 regulators, one external regulator controller
+ * and a buck converter, further the LDO E and buck converter can
+ * have separate settings if they are in sleep mode, this is
+ * modeled as a separate regulator.
+ */
+#define AB3100_NUM_REGULATORS                          10
+
+/**
+ * struct ab3100
+ * @access_mutex: lock out concurrent accesses to the AB3100 registers
+ * @dev: pointer to the containing device
+ * @i2c_client: I2C client for this chip
+ * @testreg_client: secondary client for test registers
+ * @chip_name: name of this chip variant
+ * @chip_id: 8 bit chip ID for this chip variant
+ * @event_subscribers: event subscribers are listed here
+ * @startup_events: a copy of the first reading of the event registers
+ * @startup_events_read: whether the first events have been read
+ *
+ * This struct is PRIVATE and devices using it should NOT
+ * access ANY fields. It is used as a token for calling the
+ * AB3100 functions.
+ */
+struct ab3100 {
+       struct mutex access_mutex;
+       struct device *dev;
+       struct i2c_client *i2c_client;
+       struct i2c_client *testreg_client;
+       char chip_name[32];
+       u8 chip_id;
+       struct blocking_notifier_head event_subscribers;
+       u8 startup_events[3];
+       bool startup_events_read;
+};
+
+/**
+ * struct ab3100_platform_data
+ * Data supplied to initialize board connections to the AB3100
+ * @reg_constraints: regulator constraints for target board
+ *     the order of these constraints are: LDO A, C, D, E,
+ *     F, G, H, K, EXT and BUCK.
+ * @reg_initvals: initial values for the regulator registers
+ *     plus two sleep settings for LDO E and the BUCK converter.
+ *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
+ *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
+ *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
+ * @external_voltage: voltage level of the external regulator.
+ */
+struct ab3100_platform_data {
+       struct regulator_init_data reg_constraints[AB3100_NUM_REGULATORS];
+       u8 reg_initvals[AB3100_NUM_REGULATORS+2];
+       int external_voltage;
+};
+
+int ab3100_event_register(struct ab3100 *ab3100,
+                         struct notifier_block *nb);
+int ab3100_event_unregister(struct ab3100 *ab3100,
+                           struct notifier_block *nb);
+
+#endif /*  MFD_AB3100_H */
index 1318ca6226338679d16544411a52c6fbd8741f47..5d5298d56026e6a8681769c68b0f4927b2f60930 100644 (file)
@@ -1,12 +1,9 @@
 /*
  * Copyright (C) 2007-2009 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
- * AB3100 core access functions
- * Author: Linus Walleij <linus.walleij@stericsson.com>
  *
  * ABX500 core access functions.
- * The abx500 interface is used for the Analog Baseband chip
- * ab3100 and ab8500.
+ * The abx500 interface is used for the Analog Baseband chips.
  *
  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
@@ -21,118 +18,6 @@ struct device;
 #ifndef MFD_ABX500_H
 #define MFD_ABX500_H
 
-#define AB3100_P1A     0xc0
-#define AB3100_P1B     0xc1
-#define AB3100_P1C     0xc2
-#define AB3100_P1D     0xc3
-#define AB3100_P1E     0xc4
-#define AB3100_P1F     0xc5
-#define AB3100_P1G     0xc6
-#define AB3100_R2A     0xc7
-#define AB3100_R2B     0xc8
-
-/*
- * AB3100, EVENTA1, A2 and A3 event register flags
- * these are catenated into a single 32-bit flag in the code
- * for event notification broadcasts.
- */
-#define AB3100_EVENTA1_ONSWA                           (0x01<<16)
-#define AB3100_EVENTA1_ONSWB                           (0x02<<16)
-#define AB3100_EVENTA1_ONSWC                           (0x04<<16)
-#define AB3100_EVENTA1_DCIO                            (0x08<<16)
-#define AB3100_EVENTA1_OVER_TEMP                       (0x10<<16)
-#define AB3100_EVENTA1_SIM_OFF                         (0x20<<16)
-#define AB3100_EVENTA1_VBUS                            (0x40<<16)
-#define AB3100_EVENTA1_VSET_USB                                (0x80<<16)
-
-#define AB3100_EVENTA2_READY_TX                                (0x01<<8)
-#define AB3100_EVENTA2_READY_RX                                (0x02<<8)
-#define AB3100_EVENTA2_OVERRUN_ERROR                   (0x04<<8)
-#define AB3100_EVENTA2_FRAMING_ERROR                   (0x08<<8)
-#define AB3100_EVENTA2_CHARG_OVERCURRENT               (0x10<<8)
-#define AB3100_EVENTA2_MIDR                            (0x20<<8)
-#define AB3100_EVENTA2_BATTERY_REM                     (0x40<<8)
-#define AB3100_EVENTA2_ALARM                           (0x80<<8)
-
-#define AB3100_EVENTA3_ADC_TRIG5                       (0x01)
-#define AB3100_EVENTA3_ADC_TRIG4                       (0x02)
-#define AB3100_EVENTA3_ADC_TRIG3                       (0x04)
-#define AB3100_EVENTA3_ADC_TRIG2                       (0x08)
-#define AB3100_EVENTA3_ADC_TRIGVBAT                    (0x10)
-#define AB3100_EVENTA3_ADC_TRIGVTX                     (0x20)
-#define AB3100_EVENTA3_ADC_TRIG1                       (0x40)
-#define AB3100_EVENTA3_ADC_TRIG0                       (0x80)
-
-/* AB3100, STR register flags */
-#define AB3100_STR_ONSWA                               (0x01)
-#define AB3100_STR_ONSWB                               (0x02)
-#define AB3100_STR_ONSWC                               (0x04)
-#define AB3100_STR_DCIO                                        (0x08)
-#define AB3100_STR_BOOT_MODE                           (0x10)
-#define AB3100_STR_SIM_OFF                             (0x20)
-#define AB3100_STR_BATT_REMOVAL                                (0x40)
-#define AB3100_STR_VBUS                                        (0x80)
-
-/*
- * AB3100 contains 8 regulators, one external regulator controller
- * and a buck converter, further the LDO E and buck converter can
- * have separate settings if they are in sleep mode, this is
- * modeled as a separate regulator.
- */
-#define AB3100_NUM_REGULATORS                          10
-
-/**
- * struct ab3100
- * @access_mutex: lock out concurrent accesses to the AB3100 registers
- * @dev: pointer to the containing device
- * @i2c_client: I2C client for this chip
- * @testreg_client: secondary client for test registers
- * @chip_name: name of this chip variant
- * @chip_id: 8 bit chip ID for this chip variant
- * @event_subscribers: event subscribers are listed here
- * @startup_events: a copy of the first reading of the event registers
- * @startup_events_read: whether the first events have been read
- *
- * This struct is PRIVATE and devices using it should NOT
- * access ANY fields. It is used as a token for calling the
- * AB3100 functions.
- */
-struct ab3100 {
-       struct mutex access_mutex;
-       struct device *dev;
-       struct i2c_client *i2c_client;
-       struct i2c_client *testreg_client;
-       char chip_name[32];
-       u8 chip_id;
-       struct blocking_notifier_head event_subscribers;
-       u8 startup_events[3];
-       bool startup_events_read;
-};
-
-/**
- * struct ab3100_platform_data
- * Data supplied to initialize board connections to the AB3100
- * @reg_constraints: regulator constraints for target board
- *     the order of these constraints are: LDO A, C, D, E,
- *     F, G, H, K, EXT and BUCK.
- * @reg_initvals: initial values for the regulator registers
- *     plus two sleep settings for LDO E and the BUCK converter.
- *     exactly AB3100_NUM_REGULATORS+2 values must be sent in.
- *     Order: LDO A, C, E, E sleep, F, G, H, K, EXT, BUCK,
- *     BUCK sleep, LDO D. (LDO D need to be initialized last.)
- * @external_voltage: voltage level of the external regulator.
- */
-struct ab3100_platform_data {
-       struct regulator_init_data reg_constraints[AB3100_NUM_REGULATORS];
-       u8 reg_initvals[AB3100_NUM_REGULATORS+2];
-       int external_voltage;
-};
-
-int ab3100_event_register(struct ab3100 *ab3100,
-                         struct notifier_block *nb);
-int ab3100_event_unregister(struct ab3100 *ab3100,
-                           struct notifier_block *nb);
-
 /**
  * struct abx500_init_setting
  * Initial value of the registers for driver to use during setup.
index 3764cb6759e31e05a39c8eb99034f48d323462b4..1491044efa10b25bcc17d69f25c6e77768dbf509 100644 (file)
@@ -341,6 +341,4 @@ static inline int is_ab8500_2p0(struct ab8500 *ab)
        return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0));
 }
 
-int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq);
-
 #endif /* MFD_AB8500_H */
diff --git a/include/linux/mfd/anatop.h b/include/linux/mfd/anatop.h
deleted file mode 100644 (file)
index 7f92acf..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * anatop.h - Anatop MFD driver
- *
- *  Copyright (C) 2012 Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
- *  Copyright (C) 2012 Linaro
- *
- * 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
- */
-
-#ifndef __LINUX_MFD_ANATOP_H
-#define __LINUX_MFD_ANATOP_H
-
-#include <linux/spinlock.h>
-
-/**
- * anatop - MFD data
- * @ioreg: ioremap register
- * @reglock: spinlock for register read/write
- */
-struct anatop {
-       void *ioreg;
-       spinlock_t reglock;
-};
-
-extern u32 anatop_read_reg(struct anatop *, u32);
-extern void anatop_write_reg(struct anatop *, u32, u32, u32);
-
-#endif /*  __LINUX_MFD_ANATOP_H */
diff --git a/include/linux/mfd/da9055/core.h b/include/linux/mfd/da9055/core.h
new file mode 100644 (file)
index 0000000..c96ad68
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * da9055 declarations for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __DA9055_CORE_H
+#define __DA9055_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+
+/*
+ * PMIC IRQ
+ */
+#define DA9055_IRQ_ALARM       0x01
+#define DA9055_IRQ_TICK                0x02
+#define DA9055_IRQ_NONKEY      0x00
+#define DA9055_IRQ_REGULATOR   0x0B
+#define DA9055_IRQ_HWMON       0x03
+
+struct da9055_pdata;
+
+struct da9055 {
+       struct regmap *regmap;
+       struct regmap_irq_chip_data *irq_data;
+       struct device *dev;
+       struct i2c_client *i2c_client;
+
+       int irq_base;
+       int chip_irq;
+};
+
+/* Device I/O */
+static inline int da9055_reg_read(struct da9055 *da9055, unsigned char reg)
+{
+       int val, ret;
+
+       ret = regmap_read(da9055->regmap, reg, &val);
+       if (ret < 0)
+               return ret;
+
+       return val;
+}
+
+static inline int da9055_reg_write(struct da9055 *da9055, unsigned char reg,
+                                   unsigned char val)
+{
+       return regmap_write(da9055->regmap, reg, val);
+}
+
+static inline int da9055_group_read(struct da9055 *da9055, unsigned char reg,
+                                    unsigned reg_cnt, unsigned char *val)
+{
+       return regmap_bulk_read(da9055->regmap, reg, val, reg_cnt);
+}
+
+static inline int da9055_group_write(struct da9055 *da9055, unsigned char reg,
+                                     unsigned reg_cnt, unsigned char *val)
+{
+       return regmap_raw_write(da9055->regmap, reg, val, reg_cnt);
+}
+
+static inline int da9055_reg_update(struct da9055 *da9055, unsigned char reg,
+                                    unsigned char bit_mask,
+                                    unsigned char reg_val)
+{
+       return regmap_update_bits(da9055->regmap, reg, bit_mask, reg_val);
+}
+
+/* Generic Device API */
+int da9055_device_init(struct da9055 *da9055);
+void da9055_device_exit(struct da9055 *da9055);
+
+extern struct regmap_config da9055_regmap_config;
+
+#endif /* __DA9055_CORE_H */
diff --git a/include/linux/mfd/da9055/pdata.h b/include/linux/mfd/da9055/pdata.h
new file mode 100644 (file)
index 0000000..147293b
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (C) 2012 Dialog Semiconductor 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 __DA9055_PDATA_H
+#define __DA9055_PDATA_H
+
+#define DA9055_MAX_REGULATORS  8
+
+struct da9055;
+
+enum gpio_select {
+       NO_GPIO = 0,
+       GPIO_1,
+       GPIO_2
+};
+
+struct da9055_pdata {
+       int (*init) (struct da9055 *da9055);
+       int irq_base;
+       int gpio_base;
+
+       struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
+       bool reset_enable;              /* Enable RTC in RESET Mode */
+       enum gpio_select *gpio_rsel;    /* Select regulator set thru GPIO 1/2 */
+       enum gpio_select *gpio_ren;     /* Enable regulator thru GPIO 1/2 */
+};
+#endif /* __DA9055_PDATA_H */
diff --git a/include/linux/mfd/da9055/reg.h b/include/linux/mfd/da9055/reg.h
new file mode 100644 (file)
index 0000000..df237ee
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * DA9055 declarations for DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __DA9055_REG_H
+#define __DA9055_REG_H
+
+/*
+ * PMIC registers
+ */
+ /* PAGE0 */
+#define        DA9055_REG_PAGE_CON             0x00
+
+/* System Control and Event Registers */
+#define        DA9055_REG_STATUS_A             0x01
+#define        DA9055_REG_STATUS_B             0x02
+#define        DA9055_REG_FAULT_LOG            0x03
+#define        DA9055_REG_EVENT_A              0x04
+#define        DA9055_REG_EVENT_B              0x05
+#define        DA9055_REG_EVENT_C              0x06
+#define        DA9055_REG_IRQ_MASK_A           0x07
+#define        DA9055_REG_IRQ_MASK_B           0x08
+#define        DA9055_REG_IRQ_MASK_C           0x09
+#define        DA9055_REG_CONTROL_A            0x0A
+#define        DA9055_REG_CONTROL_B            0x0B
+#define        DA9055_REG_CONTROL_C            0x0C
+#define        DA9055_REG_CONTROL_D            0x0D
+#define        DA9055_REG_CONTROL_E            0x0E
+#define        DA9055_REG_PD_DIS               0x0F
+
+/* GPIO Control Registers */
+#define        DA9055_REG_GPIO0_1              0x10
+#define        DA9055_REG_GPIO2                0x11
+#define        DA9055_REG_GPIO_MODE0_2         0x12
+
+/* Regulator Control Registers */
+#define        DA9055_REG_BCORE_CONT           0x13
+#define        DA9055_REG_BMEM_CONT            0x14
+#define        DA9055_REG_LDO1_CONT            0x15
+#define        DA9055_REG_LDO2_CONT            0x16
+#define        DA9055_REG_LDO3_CONT            0x17
+#define        DA9055_REG_LDO4_CONT            0x18
+#define        DA9055_REG_LDO5_CONT            0x19
+#define        DA9055_REG_LDO6_CONT            0x1A
+
+/* GP-ADC Control Registers */
+#define        DA9055_REG_ADC_MAN              0x1B
+#define        DA9055_REG_ADC_CONT             0x1C
+#define        DA9055_REG_VSYS_MON             0x1D
+#define        DA9055_REG_ADC_RES_L            0x1E
+#define        DA9055_REG_ADC_RES_H            0x1F
+#define        DA9055_REG_VSYS_RES             0x20
+#define        DA9055_REG_ADCIN1_RES           0x21
+#define        DA9055_REG_ADCIN2_RES           0x22
+#define        DA9055_REG_ADCIN3_RES           0x23
+
+/* Sequencer Control Registers */
+#define        DA9055_REG_EN_32K               0x35
+
+/* Regulator Setting Registers */
+#define        DA9055_REG_BUCK_LIM             0x37
+#define        DA9055_REG_BCORE_MODE           0x38
+#define        DA9055_REG_VBCORE_A             0x39
+#define        DA9055_REG_VBMEM_A              0x3A
+#define        DA9055_REG_VLDO1_A              0x3B
+#define        DA9055_REG_VLDO2_A              0x3C
+#define        DA9055_REG_VLDO3_A              0x3D
+#define        DA9055_REG_VLDO4_A              0x3E
+#define        DA9055_REG_VLDO5_A              0x3F
+#define        DA9055_REG_VLDO6_A              0x40
+#define        DA9055_REG_VBCORE_B             0x41
+#define        DA9055_REG_VBMEM_B              0x42
+#define        DA9055_REG_VLDO1_B              0x43
+#define        DA9055_REG_VLDO2_B              0x44
+#define        DA9055_REG_VLDO3_B              0x45
+#define        DA9055_REG_VLDO4_B              0x46
+#define        DA9055_REG_VLDO5_B              0x47
+#define        DA9055_REG_VLDO6_B              0x48
+
+/* GP-ADC Threshold Registers */
+#define        DA9055_REG_AUTO1_HIGH           0x49
+#define        DA9055_REG_AUTO1_LOW            0x4A
+#define        DA9055_REG_AUTO2_HIGH           0x4B
+#define        DA9055_REG_AUTO2_LOW            0x4C
+#define        DA9055_REG_AUTO3_HIGH           0x4D
+#define        DA9055_REG_AUTO3_LOW            0x4E
+
+/* OTP */
+#define        DA9055_REG_OPT_COUNT            0x50
+#define        DA9055_REG_OPT_ADDR             0x51
+#define        DA9055_REG_OPT_DATA             0x52
+
+/* RTC Calendar and Alarm Registers */
+#define        DA9055_REG_COUNT_S              0x53
+#define        DA9055_REG_COUNT_MI             0x54
+#define        DA9055_REG_COUNT_H              0x55
+#define        DA9055_REG_COUNT_D              0x56
+#define        DA9055_REG_COUNT_MO             0x57
+#define        DA9055_REG_COUNT_Y              0x58
+#define        DA9055_REG_ALARM_MI             0x59
+#define        DA9055_REG_ALARM_H              0x5A
+#define        DA9055_REG_ALARM_D              0x5B
+#define        DA9055_REG_ALARM_MO             0x5C
+#define        DA9055_REG_ALARM_Y              0x5D
+#define        DA9055_REG_SECOND_A             0x5E
+#define        DA9055_REG_SECOND_B             0x5F
+#define        DA9055_REG_SECOND_C             0x60
+#define        DA9055_REG_SECOND_D             0x61
+
+/* Customer Trim and Configuration */
+#define        DA9055_REG_T_OFFSET             0x63
+#define        DA9055_REG_INTERFACE            0x64
+#define        DA9055_REG_CONFIG_A             0x65
+#define        DA9055_REG_CONFIG_B             0x66
+#define        DA9055_REG_CONFIG_C             0x67
+#define        DA9055_REG_CONFIG_D             0x68
+#define        DA9055_REG_CONFIG_E             0x69
+#define        DA9055_REG_TRIM_CLDR            0x6F
+
+/* General Purpose Registers */
+#define        DA9055_REG_GP_ID_0              0x70
+#define        DA9055_REG_GP_ID_1              0x71
+#define        DA9055_REG_GP_ID_2              0x72
+#define        DA9055_REG_GP_ID_3              0x73
+#define        DA9055_REG_GP_ID_4              0x74
+#define        DA9055_REG_GP_ID_5              0x75
+#define        DA9055_REG_GP_ID_6              0x76
+#define        DA9055_REG_GP_ID_7              0x77
+#define        DA9055_REG_GP_ID_8              0x78
+#define        DA9055_REG_GP_ID_9              0x79
+#define        DA9055_REG_GP_ID_10             0x7A
+#define        DA9055_REG_GP_ID_11             0x7B
+#define        DA9055_REG_GP_ID_12             0x7C
+#define        DA9055_REG_GP_ID_13             0x7D
+#define        DA9055_REG_GP_ID_14             0x7E
+#define        DA9055_REG_GP_ID_15             0x7F
+#define        DA9055_REG_GP_ID_16             0x80
+#define        DA9055_REG_GP_ID_17             0x81
+#define        DA9055_REG_GP_ID_18             0x82
+#define        DA9055_REG_GP_ID_19             0x83
+
+#define DA9055_MAX_REGISTER_CNT                DA9055_REG_GP_ID_19
+
+/*
+ * PMIC registers bits
+ */
+
+/* DA9055_REG_PAGE_CON (addr=0x00) */
+#define        DA9055_PAGE_WRITE_MODE          (0<<6)
+#define        DA9055_REPEAT_WRITE_MODE        (1<<6)
+
+/* DA9055_REG_STATUS_A (addr=0x01) */
+#define        DA9055_NOKEY_STS                0x01
+#define        DA9055_WAKE_STS                 0x02
+#define        DA9055_DVC_BUSY_STS             0x04
+#define        DA9055_COMP1V2_STS              0x08
+#define        DA9055_NJIG_STS                 0x10
+#define        DA9055_LDO5_LIM_STS             0x20
+#define        DA9055_LDO6_LIM_STS             0x40
+
+/* DA9055_REG_STATUS_B (addr=0x02) */
+#define        DA9055_GPI0_STS                 0x01
+#define        DA9055_GPI1_STS                 0x02
+#define        DA9055_GPI2_STS                 0x04
+
+/* DA9055_REG_FAULT_LOG (addr=0x03) */
+#define        DA9055_TWD_ERROR_FLG            0x01
+#define        DA9055_POR_FLG                  0x02
+#define        DA9055_VDD_FAULT_FLG            0x04
+#define        DA9055_VDD_START_FLG            0x08
+#define        DA9055_TEMP_CRIT_FLG            0x10
+#define        DA9055_KEY_RESET_FLG            0x20
+#define        DA9055_WAIT_SHUT_FLG            0x80
+
+/* DA9055_REG_EVENT_A (addr=0x04) */
+#define        DA9055_NOKEY_EINT               0x01
+#define        DA9055_ALARM_EINT               0x02
+#define        DA9055_TICK_EINT                0x04
+#define        DA9055_ADC_RDY_EINT             0x08
+#define        DA9055_SEQ_RDY_EINT             0x10
+#define        DA9055_EVENTS_B_EINT            0x20
+#define        DA9055_EVENTS_C_EINT            0x40
+
+/* DA9055_REG_EVENT_B (addr=0x05) */
+#define        DA9055_E_WAKE_EINT              0x01
+#define        DA9055_E_TEMP_EINT              0x02
+#define        DA9055_E_COMP1V2_EINT           0x04
+#define        DA9055_E_LDO_LIM_EINT           0x08
+#define        DA9055_E_NJIG_EINT              0x20
+#define        DA9055_E_VDD_MON_EINT           0x40
+#define        DA9055_E_VDD_WARN_EINT          0x80
+
+/* DA9055_REG_EVENT_C (addr=0x06) */
+#define        DA9055_E_GPI0_EINT              0x01
+#define        DA9055_E_GPI1_EINT              0x02
+#define        DA9055_E_GPI2_EINT              0x04
+
+/* DA9055_REG_IRQ_MASK_A (addr=0x07) */
+#define        DA9055_M_NONKEY_EINT            0x01
+#define        DA9055_M_ALARM_EINT             0x02
+#define        DA9055_M_TICK_EINT              0x04
+#define        DA9055_M_ADC_RDY_EINT           0x08
+#define        DA9055_M_SEQ_RDY_EINT           0x10
+
+/* DA9055_REG_IRQ_MASK_B (addr=0x08) */
+#define        DA9055_M_WAKE_EINT              0x01
+#define        DA9055_M_TEMP_EINT              0x02
+#define        DA9055_M_COMP_1V2_EINT          0x04
+#define        DA9055_M_LDO_LIM_EINT           0x08
+#define        DA9055_M_NJIG_EINT              0x20
+#define        DA9055_M_VDD_MON_EINT           0x40
+#define        DA9055_M_VDD_WARN_EINT          0x80
+
+/* DA9055_REG_IRQ_MASK_C (addr=0x09) */
+#define        DA9055_M_GPI0_EINT              0x01
+#define        DA9055_M_GPI1_EINT              0x02
+#define        DA9055_M_GPI2_EINT              0x04
+
+/* DA9055_REG_CONTROL_A (addr=0xA) */
+#define        DA9055_DEBOUNCING_SHIFT         0x00
+#define        DA9055_DEBOUNCING_MASK          0x07
+#define        DA9055_NRES_MODE_SHIFT          0x03
+#define        DA9055_NRES_MODE_MASK           0x08
+#define        DA9055_SLEW_RATE_SHIFT          0x04
+#define        DA9055_SLEW_RATE_MASK           0x30
+#define        DA9055_NOKEY_LOCK_SHIFT         0x06
+#define        DA9055_NOKEY_LOCK_MASK          0x40
+
+/* DA9055_REG_CONTROL_B (addr=0xB) */
+#define        DA9055_RTC_MODE_PD              0x01
+#define        DA9055_RTC_MODE_SD_SHIFT        0x01
+#define        DA9055_RTC_MODE_SD              0x02
+#define        DA9055_RTC_EN                   0x04
+#define        DA9055_ECO_MODE_SHIFT           0x03
+#define        DA9055_ECO_MODE_MASK            0x08
+#define        DA9055_TWDSCALE_SHIFT           4
+#define        DA9055_TWDSCALE_MASK            0x70
+#define        DA9055_V_LOCK_SHIFT             0x07
+#define        DA9055_V_LOCK_MASK              0x80
+
+/* DA9055_REG_CONTROL_C (addr=0xC) */
+#define        DA9055_SYSTEM_EN_SHIFT          0x00
+#define        DA9055_SYSTEM_EN_MASK           0x01
+#define        DA9055_POWERN_EN_SHIFT          0x01
+#define        DA9055_POWERN_EN_MASK           0x02
+#define        DA9055_POWER1_EN_SHIFT          0x02
+#define        DA9055_POWER1_EN_MASK           0x04
+
+/* DA9055_REG_CONTROL_D (addr=0xD) */
+#define        DA9055_STANDBY_SHIFT            0x02
+#define        DA9055_STANDBY_MASK             0x08
+#define        DA9055_AUTO_BOOT_SHIFT          0x03
+#define        DA9055_AUTO_BOOT_MASK           0x04
+
+/* DA9055_REG_CONTROL_E (addr=0xE) */
+#define        DA9055_WATCHDOG_SHIFT           0x00
+#define        DA9055_WATCHDOG_MASK            0x01
+#define        DA9055_SHUTDOWN_SHIFT           0x01
+#define        DA9055_SHUTDOWN_MASK            0x02
+#define        DA9055_WAKE_UP_SHIFT            0x02
+#define        DA9055_WAKE_UP_MASK             0x04
+
+/* DA9055_REG_GPIO (addr=0x10/0x11) */
+#define        DA9055_GPIO0_PIN_SHIFT          0x00
+#define        DA9055_GPIO0_PIN_MASK           0x03
+#define        DA9055_GPIO0_TYPE_SHIFT         0x02
+#define        DA9055_GPIO0_TYPE_MASK          0x04
+#define        DA9055_GPIO0_WEN_SHIFT          0x03
+#define        DA9055_GPIO0_WEN_MASK           0x08
+#define        DA9055_GPIO1_PIN_SHIFT          0x04
+#define        DA9055_GPIO1_PIN_MASK           0x30
+#define        DA9055_GPIO1_TYPE_SHIFT         0x06
+#define        DA9055_GPIO1_TYPE_MASK          0x40
+#define        DA9055_GPIO1_WEN_SHIFT          0x07
+#define        DA9055_GPIO1_WEN_MASK           0x80
+#define        DA9055_GPIO2_PIN_SHIFT          0x00
+#define        DA9055_GPIO2_PIN_MASK           0x30
+#define        DA9055_GPIO2_TYPE_SHIFT         0x02
+#define        DA9055_GPIO2_TYPE_MASK          0x04
+#define        DA9055_GPIO2_WEN_SHIFT          0x03
+#define        DA9055_GPIO2_WEN_MASK           0x08
+
+/* DA9055_REG_GPIO_MODE (addr=0x12) */
+#define        DA9055_GPIO0_MODE_SHIFT         0x00
+#define        DA9055_GPIO0_MODE_MASK          0x01
+#define        DA9055_GPIO1_MODE_SHIFT         0x01
+#define        DA9055_GPIO1_MODE_MASK          0x02
+#define        DA9055_GPIO2_MODE_SHIFT         0x02
+#define        DA9055_GPIO2_MODE_MASK          0x04
+
+/* DA9055_REG_BCORE_CONT (addr=0x13) */
+#define        DA9055_BCORE_EN_SHIFT           0x00
+#define        DA9055_BCORE_EN_MASK            0x01
+#define        DA9055_BCORE_GPI_SHIFT          0x01
+#define        DA9055_BCORE_GPI_MASK           0x02
+#define        DA9055_BCORE_PD_DIS_SHIFT       0x03
+#define        DA9055_BCORE_PD_DIS_MASK        0x04
+#define        DA9055_VBCORE_SEL_SHIFT         0x04
+#define        DA9055_SEL_REG_A                0x0
+#define        DA9055_SEL_REG_B                0x10
+#define        DA9055_VBCORE_SEL_MASK          0x10
+#define DA9055_V_GPI_MASK              0x60
+#define DA9055_V_GPI_SHIFT             0x05
+#define DA9055_E_GPI_MASK              0x06
+#define DA9055_E_GPI_SHIFT             0x01
+#define        DA9055_VBCORE_GPI_SHIFT         0x05
+#define        DA9055_VBCORE_GPI_MASK          0x60
+#define        DA9055_BCORE_CONF_SHIFT         0x07
+#define        DA9055_BCORE_CONF_MASK          0x80
+
+/* DA9055_REG_BMEM_CONT (addr=0x14) */
+#define        DA9055_BMEM_EN_SHIFT            0x00
+#define        DA9055_BMEM_EN_MASK             0x01
+#define        DA9055_BMEM_GPI_SHIFT           0x01
+#define        DA9055_BMEM_GPI_MASK            0x06
+#define        DA9055_BMEM_PD_DIS_SHIFT        0x03
+#define        DA9055_BMEM_PD_DIS_MASK         0x08
+#define        DA9055_VBMEM_SEL_SHIT           0x04
+#define        DA9055_VBMEM_SEL_VBMEM_A        (0<<4)
+#define        DA9055_VBMEM_SEL_VBMEM_B        (1<<4)
+#define        DA9055_VBMEM_SEL_MASK           0x10
+#define        DA9055_VBMEM_GPI_SHIFT          0x05
+#define        DA9055_VBMEM_GPI_MASK           0x60
+#define        DA9055_BMEM_CONF_SHIFT          0x07
+#define        DA9055_BMEM_CONF_MASK           0x80
+
+/* DA9055_REG_LDO_CONT (addr=0x15-0x1A) */
+#define        DA9055_LDO_EN_SHIFT             0x00
+#define        DA9055_LDO_EN_MASK              0x01
+#define        DA9055_LDO_GPI_SHIFT            0x01
+#define        DA9055_LDO_GPI_MASK             0x06
+#define        DA9055_LDO_PD_DIS_SHIFT         0x03
+#define        DA9055_LDO_PD_DIS_MASK          0x08
+#define        DA9055_VLDO_SEL_SHIFT           0x04
+#define        DA9055_VLDO_SEL_MASK            0x10
+#define        DA9055_VLDO_SEL_VLDO_A          0x00
+#define        DA9055_VLDO_SEL_VLDO_B          0x01
+#define        DA9055_VLDO_GPI_SHIFT           0x05
+#define        DA9055_VLDO_GPI_MASK            0x60
+#define        DA9055_LDO_CONF_SHIFT           0x07
+#define        DA9055_LDO_CONF_MASK            0x80
+#define        DA9055_REGUALTOR_SET_A          0x00
+#define        DA9055_REGUALTOR_SET_B          0x10
+
+/* DA9055_REG_ADC_MAN (addr=0x1B) */
+#define        DA9055_ADC_MUX_SHIFT            0
+#define        DA9055_ADC_MUX_MASK             0xF
+#define        DA9055_ADC_MUX_VSYS             0x0
+#define        DA9055_ADC_MUX_ADCIN1           0x01
+#define        DA9055_ADC_MUX_ADCIN2           0x02
+#define        DA9055_ADC_MUX_ADCIN3           0x03
+#define        DA9055_ADC_MUX_T_SENSE          0x04
+#define        DA9055_ADC_MAN_SHIFT            0x04
+#define        DA9055_ADC_MAN_CONV             0x10
+#define DA9055_ADC_LSB_MASK            0X03
+#define DA9055_ADC_MODE_MASK           0x20
+#define        DA9055_ADC_MODE_SHIFT           5
+#define        DA9055_ADC_MODE_1MS             (1<<5)
+#define        DA9055_COMP1V2_EN_SHIFT         7
+
+/* DA9055_REG_ADC_CONT (addr=0x1C) */
+#define        DA9055_ADC_AUTO_VSYS_EN_SHIFT   0
+#define        DA9055_ADC_AUTO_AD1_EN_SHIFT    1
+#define        DA9055_ADC_AUTO_AD2_EN_SHIFT    2
+#define        DA9055_ADC_AUTO_AD3_EN_SHIFT    3
+#define        DA9055_ADC_ISRC_EN_SHIFT        4
+#define        DA9055_ADC_ADCIN1_DEB_SHIFT     5
+#define        DA9055_ADC_ADCIN2_DEB_SHIFT     6
+#define        DA9055_ADC_ADCIN3_DEB_SHIFT     7
+#define DA9055_AD1_ISRC_MASK           0x10
+#define DA9055_AD1_ISRC_SHIFT          4
+
+/* DA9055_REG_VSYS_MON (addr=0x1D) */
+#define        DA9055_VSYS_VAL_SHIFT           0
+#define        DA9055_VSYS_VAL_MASK            0xFF
+#define        DA9055_VSYS_VAL_BASE            0x00
+#define        DA9055_VSYS_VAL_MAX             DA9055_VSYS_VAL_MASK
+#define        DA9055_VSYS_VOLT_BASE           2500
+#define        DA9055_VSYS_VOLT_INC            10
+#define        DA9055_VSYS_STEPS               255
+#define        DA9055_VSYS_VOLT_MIN            2500
+
+/* DA9044_REG_XXX_RES (addr=0x20-0x23) */
+#define        DA9055_ADC_VAL_SHIFT            0
+#define        DA9055_ADC_VAL_MASK             0xFF
+#define        DA9055_ADC_VAL_BASE             0x00
+#define        DA9055_ADC_VAL_MAX              DA9055_ADC_VAL_MASK
+#define        DA9055_ADC_VOLT_BASE            0
+#define        DA9055_ADC_VSYS_VOLT_BASE       2500
+#define        DA9055_ADC_VOLT_INC             10
+#define        DA9055_ADC_VSYS_VOLT_INC        12
+#define        DA9055_ADC_STEPS                255
+
+/* DA9055_REG_EN_32K  (addr=0x35)*/
+#define        DA9055_STARTUP_TIME_MASK        0x07
+#define        DA9055_STARTUP_TIME_0S          0x0
+#define        DA9055_STARTUP_TIME_0_52S       0x1
+#define        DA9055_STARTUP_TIME_1S          0x2
+#define        DA9055_CRYSTAL_EN               0x08
+#define        DA9055_DELAY_MODE_EN            0x10
+#define        DA9055_OUT_CLCK_GATED           0x20
+#define        DA9055_RTC_CLOCK_GATED          0x40
+#define        DA9055_EN_32KOUT_BUF            0x80
+
+/* DA9055_REG_RESET (addr=0x36) */
+/* Timer up to 31.744 ms */
+#define        DA9055_RESET_TIMER_VAL_SHIFT    0
+#define        DA9055_RESET_LOW_VAL_MASK       0x3F
+#define        DA9055_RESET_LOW_VAL_BASE       0
+#define        DA9055_RESET_LOW_VAL_MAX        DA9055_RESET_LOW_VAL_MASK
+#define        DA9055_RESET_US_LOW_BASE        1024 /* min val in units of us */
+#define        DA9055_RESET_US_LOW_INC         1024 /* inc val in units of us */
+#define        DA9055_RESET_US_LOW_STEP        30
+
+/* Timer up to 1048.576ms */
+#define        DA9055_RESET_HIGH_VAL_MASK      0x3F
+#define        DA9055_RESET_HIGH_VAL_BASE      0
+#define        DA9055_RESET_HIGH_VAL_MAX       DA9055_RESET_HIGH_VAL_MASK
+#define        DA9055_RESET_US_HIGH_BASE       32768 /* min val in units of us */
+#define        DA9055_RESET_US_HIGH_INC        32768 /* inv val in units of us */
+#define        DA9055_RESET_US_HIGH_STEP       31
+
+/* DA9055_REG_BUCK_ILIM (addr=0x37)*/
+#define        DA9055_BMEM_ILIM_SHIFT          0
+#define        DA9055_ILIM_MASK                0x3
+#define        DA9055_ILIM_500MA               0x0
+#define        DA9055_ILIM_600MA               0x1
+#define        DA9055_ILIM_700MA               0x2
+#define        DA9055_ILIM_800MA               0x3
+#define        DA9055_BCORE_ILIM_SHIFT         2
+
+/* DA9055_REG_BCORE_MODE (addr=0x38) */
+#define        DA9055_BMEM_MODE_SHIFT          0
+#define        DA9055_MODE_MASK                0x3
+#define        DA9055_MODE_AB                  0x0
+#define        DA9055_MODE_SLEEP               0x1
+#define        DA9055_MODE_SYNCHRO             0x2
+#define        DA9055_MODE_AUTO                0x3
+#define        DA9055_BCORE_MODE_SHIFT         2
+
+/* DA9055_REG_VBCORE_A/B (addr=0x39/0x41)*/
+#define        DA9055_VBCORE_VAL_SHIFT         0
+#define        DA9055_VBCORE_VAL_MASK          0x3F
+#define        DA9055_VBCORE_VAL_BASE          0x09
+#define        DA9055_VBCORE_VAL_MAX           DA9055_VBCORE_VAL_MASK
+#define        DA9055_VBCORE_VOLT_BASE         750
+#define        DA9055_VBCORE_VOLT_INC          25
+#define        DA9055_VBCORE_STEPS             53
+#define        DA9055_VBCORE_VOLT_MIN          DA9055_VBCORE_VOLT_BASE
+#define        DA9055_BCORE_SL_SYNCHRO         (0<<7)
+#define        DA9055_BCORE_SL_SLEEP           (1<<7)
+
+/* DA9055_REG_VBMEM_A/B (addr=0x3A/0x42)*/
+#define        DA9055_VBMEM_VAL_SHIFT          0
+#define        DA9055_VBMEM_VAL_MASK           0x3F
+#define        DA9055_VBMEM_VAL_BASE           0x00
+#define        DA9055_VBMEM_VAL_MAX            DA9055_VBMEM_VAL_MASK
+#define        DA9055_VBMEM_VOLT_BASE          925
+#define        DA9055_VBMEM_VOLT_INC           25
+#define        DA9055_VBMEM_STEPS              63
+#define        DA9055_VBMEM_VOLT_MIN           DA9055_VBMEM_VOLT_BASE
+#define        DA9055_BCMEM_SL_SYNCHRO         (0<<7)
+#define        DA9055_BCMEM_SL_SLEEP           (1<<7)
+
+
+/* DA9055_REG_VLDO (addr=0x3B-0x40/0x43-0x48)*/
+#define        DA9055_VLDO_VAL_SHIFT           0
+#define        DA9055_VLDO_VAL_MASK            0x3F
+#define        DA9055_VLDO6_VAL_MASK           0x7F
+#define        DA9055_VLDO_VAL_BASE            0x02
+#define        DA9055_VLDO2_VAL_BASE           0x03
+#define        DA9055_VLDO6_VAL_BASE           0x00
+#define        DA9055_VLDO_VAL_MAX             DA9055_VLDO_VAL_MASK
+#define        DA9055_VLDO6_VAL_MAX            DA9055_VLDO6_VAL_MASK
+#define        DA9055_VLDO_VOLT_BASE           900
+#define        DA9055_VLDO_VOLT_INC            50
+#define        DA9055_VLDO6_VOLT_INC           20
+#define        DA9055_VLDO_STEPS               48
+#define        DA9055_VLDO5_STEPS              37
+#define        DA9055_VLDO6_STEPS              120
+#define        DA9055_VLDO_VOLT_MIN            DA9055_VLDO_VOLT_BASE
+#define        DA9055_LDO_MODE_SHIFT           7
+#define        DA9055_LDO_SL_NORMAL            0
+#define        DA9055_LDO_SL_SLEEP             1
+
+/* DA9055_REG_OTP_CONT (addr=0x50) */
+#define        DA9055_OTP_TIM_NORMAL           (0<<0)
+#define        DA9055_OTP_TIM_MARGINAL         (1<<0)
+#define        DA9055_OTP_GP_RD_SHIFT          1
+#define        DA9055_OTP_APPS_RD_SHIFT        2
+#define        DA9055_PC_DONE_SHIFT            3
+#define        DA9055_OTP_GP_LOCK_SHIFT        4
+#define        DA9055_OTP_APPS_LOCK_SHIFT      5
+#define        DA9055_OTP_CONF_LOCK_SHIFT      6
+#define        DA9055_OTP_WRITE_DIS_SHIFT      7
+
+/* DA9055_REG_COUNT_S (addr=0x53) */
+#define        DA9055_RTC_SEC                  0x3F
+#define        DA9055_RTC_MONITOR_EN           0x40
+#define        DA9055_RTC_READ                 0x80
+
+/* DA9055_REG_COUNT_MI (addr=0x54) */
+#define        DA9055_RTC_MIN                  0x3F
+
+/* DA9055_REG_COUNT_H (addr=0x55) */
+#define        DA9055_RTC_HOUR                 0x1F
+
+/* DA9055_REG_COUNT_D (addr=0x56) */
+#define        DA9055_RTC_DAY                  0x1F
+
+/* DA9055_REG_COUNT_MO (addr=0x57) */
+#define        DA9055_RTC_MONTH                0x0F
+
+/* DA9055_REG_COUNT_Y (addr=0x58) */
+#define        DA9055_RTC_YEAR                 0x3F
+#define        DA9055_RTC_YEAR_BASE            2000
+
+/* DA9055_REG_ALARM_MI (addr=0x59) */
+#define        DA9055_RTC_ALM_MIN              0x3F
+#define        DA9055_ALARM_STATUS_SHIFT       6
+#define        DA9055_ALARM_STATUS_MASK        0x3
+#define        DA9055_ALARM_STATUS_NO_ALARM    0x0
+#define        DA9055_ALARM_STATUS_TICK        0x1
+#define        DA9055_ALARM_STATUS_TIMER_ALARM 0x2
+#define        DA9055_ALARM_STATUS_BOTH        0x3
+
+/* DA9055_REG_ALARM_H (addr=0x5A) */
+#define        DA9055_RTC_ALM_HOUR             0x1F
+
+/* DA9055_REG_ALARM_D (addr=0x5B) */
+#define        DA9055_RTC_ALM_DAY              0x1F
+
+/* DA9055_REG_ALARM_MO (addr=0x5C) */
+#define        DA9055_RTC_ALM_MONTH            0x0F
+#define        DA9055_RTC_TICK_WAKE_MASK       0x20
+#define        DA9055_RTC_TICK_WAKE_SHIFT      5
+#define        DA9055_RTC_TICK_TYPE            0x10
+#define        DA9055_RTC_TICK_TYPE_SHIFT      0x4
+#define        DA9055_RTC_TICK_SEC             0x0
+#define        DA9055_RTC_TICK_MIN             0x1
+#define        DA9055_ALARAM_TICK_WAKE         0x20
+
+/* DA9055_REG_ALARM_Y (addr=0x5D) */
+#define        DA9055_RTC_TICK_EN              0x80
+#define        DA9055_RTC_ALM_EN               0x40
+#define        DA9055_RTC_TICK_ALM_MASK        0xC0
+#define        DA9055_RTC_ALM_YEAR             0x3F
+
+/* DA9055_REG_TRIM_CLDR (addr=0x62) */
+#define        DA9055_TRIM_32K_SHIFT           0
+#define        DA9055_TRIM_32K_MASK            0x7F
+#define        DA9055_TRIM_DECREMENT           (1<<7)
+#define        DA9055_TRIM_INCREMENT           (0<<7)
+#define        DA9055_TRIM_VAL_BASE            0x0
+#define        DA9055_TRIM_PPM_BASE            0x0 /* min val in units of 0.1PPM */
+#define        DA9055_TRIM_PPM_INC             19 /* min inc in units of 0.1PPM */
+#define        DA9055_TRIM_STEPS               127
+
+/* DA9055_REG_CONFIG_A (addr=0x65) */
+#define        DA9055_PM_I_V_VDDCORE           (0<<0)
+#define        DA9055_PM_I_V_VDD_IO            (1<<0)
+#define        DA9055_VDD_FAULT_TYPE_ACT_LOW   (0<<1)
+#define        DA9055_VDD_FAULT_TYPE_ACT_HIGH  (1<<1)
+#define        DA9055_PM_O_TYPE_PUSH_PULL      (0<<2)
+#define        DA9055_PM_O_TYPE_OPEN_DRAIN     (1<<2)
+#define        DA9055_IRQ_TYPE_ACT_LOW         (0<<3)
+#define        DA9055_IRQ_TYPE_ACT_HIGH        (1<<3)
+#define        DA9055_NIRQ_MODE_IMM            (0<<4)
+#define        DA9055_NIRQ_MODE_ACTIVE         (1<<4)
+#define        DA9055_GPI_V_VDDCORE            (0<<5)
+#define        DA9055_GPI_V_VDD_IO             (1<<5)
+#define        DA9055_PM_IF_V_VDDCORE          (0<<6)
+#define        DA9055_PM_IF_V_VDD_IO           (1<<6)
+
+/* DA9055_REG_CONFIG_B (addr=0x66) */
+#define        DA9055_VDD_FAULT_VAL_SHIFT      0
+#define        DA9055_VDD_FAULT_VAL_MASK       0xF
+#define        DA9055_VDD_FAULT_VAL_BASE       0x0
+#define        DA9055_VDD_FAULT_VAL_MAX        DA9055_VDD_FAULT_VAL_MASK
+#define        DA9055_VDD_FAULT_VOLT_BASE      2500
+#define        DA9055_VDD_FAULT_VOLT_INC       50
+#define        DA9055_VDD_FAULT_STEPS          15
+
+#define        DA9055_VDD_HYST_VAL_SHIFT       4
+#define        DA9055_VDD_HYST_VAL_MASK        0x7
+#define        DA9055_VDD_HYST_VAL_BASE        0x0
+#define        DA9055_VDD_HYST_VAL_MAX         DA9055_VDD_HYST_VAL_MASK
+#define        DA9055_VDD_HYST_VOLT_BASE       100
+#define        DA9055_VDD_HYST_VOLT_INC        50
+#define        DA9055_VDD_HYST_STEPS           7
+#define        DA9055_VDD_HYST_VOLT_MIN        DA9055_VDD_HYST_VOLT_BASE
+
+#define        DA9055_VDD_FAULT_EN_SHIFT       7
+
+/* DA9055_REG_CONFIG_C (addr=0x67) */
+#define        DA9055_BCORE_CLK_INV_SHIFT      0
+#define        DA9055_BMEM_CLK_INV_SHIFT       1
+#define        DA9055_NFAULT_CONF_SHIFT        2
+#define        DA9055_LDO_SD_SHIFT             4
+#define        DA9055_LDO5_BYP_SHIFT           6
+#define        DA9055_LDO6_BYP_SHIFT           7
+
+/* DA9055_REG_CONFIG_D (addr=0x68) */
+#define        DA9055_NONKEY_PIN_SHIFT         0
+#define        DA9055_NONKEY_PIN_MASK          0x3
+#define        DA9055_NONKEY_PIN_PORT_MODE     0x0
+#define        DA9055_NONKEY_PIN_KEY_MODE      0x1
+#define        DA9055_NONKEY_PIN_MULTI_FUNC    0x2
+#define        DA9055_NONKEY_PIN_DEDICT        0x3
+#define        DA9055_NONKEY_SD_SHIFT          2
+#define        DA9055_KEY_DELAY_SHIFT          3
+#define        DA9055_KEY_DELAY_MASK           0x3
+#define        DA9055_KEY_DELAY_4S             0x0
+#define        DA9055_KEY_DELAY_6S             0x1
+#define        DA9055_KEY_DELAY_8S             0x2
+#define        DA9055_KEY_DELAY_10S            0x3
+
+/* DA9055_REG_CONFIG_E (addr=0x69) */
+#define        DA9055_GPIO_PUPD_PULL_UP        0x0
+#define        DA9055_GPIO_PUPD_OPEN_DRAIN     0x1
+#define        DA9055_GPIO0_PUPD_SHIFT         0
+#define        DA9055_GPIO1_PUPD_SHIFT         1
+#define        DA9055_GPIO2_PUPD_SHIFT         2
+#define        DA9055_UVOV_DELAY_SHIFT         4
+#define        DA9055_UVOV_DELAY_MASK          0x3
+#define        DA9055_RESET_DURATION_SHIFT     6
+#define        DA9055_RESET_DURATION_MASK      0x3
+#define        DA9055_RESET_DURATION_0MS       0x0
+#define        DA9055_RESET_DURATION_100MS     0x1
+#define        DA9055_RESET_DURATION_500MS     0x2
+#define        DA9055_RESET_DURATION_1000MS    0x3
+
+/* DA9055_REG_MON_REG_1 (addr=0x6A) */
+#define        DA9055_MON_THRES_SHIFT          0
+#define        DA9055_MON_THRES_MASK           0x3
+#define        DA9055_MON_RES_SHIFT            2
+#define        DA9055_MON_DEB_SHIFT            3
+#define        DA9055_MON_MODE_SHIFT           4
+#define        DA9055_MON_MODE_MASK            0x3
+#define        DA9055_START_MAX_SHIFT          6
+#define        DA9055_START_MAX_MASK           0x3
+
+/* DA9055_REG_MON_REG_2 (addr=0x6B) */
+#define        DA9055_LDO1_MON_EN_SHIFT        0
+#define        DA9055_LDO2_MON_EN_SHIFT        1
+#define        DA9055_LDO3_MON_EN_SHIFT        2
+#define        DA9055_LDO4_MON_EN_SHIFT        3
+#define        DA9055_LDO5_MON_EN_SHIFT        4
+#define        DA9055_LDO6_MON_EN_SHIFT        5
+#define        DA9055_BCORE_MON_EN_SHIFT       6
+#define        DA9055_BMEM_MON_EN_SHIFT        7
+
+/* DA9055_REG_CONFIG_F (addr=0x6C) */
+#define        DA9055_LDO1_DEF_SHIFT           0
+#define        DA9055_LDO2_DEF_SHIFT           1
+#define        DA9055_LDO3_DEF_SHIFT           2
+#define        DA9055_LDO4_DEF_SHIFT           3
+#define        DA9055_LDO5_DEF_SHIFT           4
+#define        DA9055_LDO6_DEF_SHIFT           5
+#define        DA9055_BCORE_DEF_SHIFT          6
+#define        DA9055_BMEM_DEF_SHIFT           7
+
+/* DA9055_REG_MON_REG_4 (addr=0x6D) */
+#define        DA9055_MON_A8_IDX_SHIFT         0
+#define        DA9055_MON_A89_IDX_MASK         0x3
+#define        DA9055_MON_A89_IDX_NONE         0x0
+#define        DA9055_MON_A89_IDX_BUCKCORE     0x1
+#define        DA9055_MON_A89_IDX_LDO3         0x2
+#define        DA9055_MON_A9_IDX_SHIFT         5
+
+/* DA9055_REG_MON_REG_5 (addr=0x6E) */
+#define        DA9055_MON_A10_IDX_SHIFT        0
+#define        DA9055_MON_A10_IDX_MASK         0x3
+#define        DA9055_MON_A10_IDX_NONE         0x0
+#define        DA9055_MON_A10_IDX_LDO1         0x1
+#define        DA9055_MON_A10_IDX_LDO2         0x2
+#define        DA9055_MON_A10_IDX_LDO5         0x3
+#define        DA9055_MON_A10_IDX_LDO6         0x4
+
+#endif /* __DA9055_REG_H */
diff --git a/include/linux/mfd/lp8788-isink.h b/include/linux/mfd/lp8788-isink.h
new file mode 100644 (file)
index 0000000..f38262d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * TI LP8788 MFD - common definitions for current sinks
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.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 __ISINK_LP8788_H__
+#define __ISINK_LP8788_H__
+
+/* register address */
+#define LP8788_ISINK_CTRL              0x99
+#define LP8788_ISINK12_IOUT            0x9A
+#define LP8788_ISINK3_IOUT             0x9B
+#define LP8788_ISINK1_PWM              0x9C
+#define LP8788_ISINK2_PWM              0x9D
+#define LP8788_ISINK3_PWM              0x9E
+
+/* mask bits */
+#define LP8788_ISINK1_IOUT_M           0x0F    /* Addr 9Ah */
+#define LP8788_ISINK2_IOUT_M           0xF0
+#define LP8788_ISINK3_IOUT_M           0x0F    /* Addr 9Bh */
+
+/* 6 bits used for PWM code : Addr 9C ~ 9Eh */
+#define LP8788_ISINK_MAX_PWM           63
+#define LP8788_ISINK_SCALE_OFFSET      3
+
+static const u8 lp8788_iout_addr[] = {
+       LP8788_ISINK12_IOUT,
+       LP8788_ISINK12_IOUT,
+       LP8788_ISINK3_IOUT,
+};
+
+static const u8 lp8788_iout_mask[] = {
+       LP8788_ISINK1_IOUT_M,
+       LP8788_ISINK2_IOUT_M,
+       LP8788_ISINK3_IOUT_M,
+};
+
+static const u8 lp8788_pwm_addr[] = {
+       LP8788_ISINK1_PWM,
+       LP8788_ISINK2_PWM,
+       LP8788_ISINK3_PWM,
+};
+
+#endif
diff --git a/include/linux/mfd/lp8788.h b/include/linux/mfd/lp8788.h
new file mode 100644 (file)
index 0000000..cec364b
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * TI LP8788 MFD Device
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.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 __MFD_LP8788_H__
+#define __MFD_LP8788_H__
+
+#include <linux/gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+#define LP8788_DEV_BUCK                "lp8788-buck"
+#define LP8788_DEV_DLDO                "lp8788-dldo"
+#define LP8788_DEV_ALDO                "lp8788-aldo"
+#define LP8788_DEV_CHARGER     "lp8788-charger"
+#define LP8788_DEV_RTC         "lp8788-rtc"
+#define LP8788_DEV_BACKLIGHT   "lp8788-backlight"
+#define LP8788_DEV_VIBRATOR    "lp8788-vibrator"
+#define LP8788_DEV_KEYLED      "lp8788-keyled"
+#define LP8788_DEV_ADC         "lp8788-adc"
+
+#define LP8788_NUM_BUCKS       4
+#define LP8788_NUM_DLDOS       12
+#define LP8788_NUM_ALDOS       10
+#define LP8788_NUM_BUCK2_DVS   2
+
+#define LP8788_CHG_IRQ         "CHG_IRQ"
+#define LP8788_PRSW_IRQ                "PRSW_IRQ"
+#define LP8788_BATT_IRQ                "BATT_IRQ"
+#define LP8788_ALM_IRQ         "ALARM_IRQ"
+
+enum lp8788_int_id {
+       /* interrup register 1 : Addr 00h */
+       LP8788_INT_TSDL,
+       LP8788_INT_TSDH,
+       LP8788_INT_UVLO,
+       LP8788_INT_FLAGMON,
+       LP8788_INT_PWRON_TIME,
+       LP8788_INT_PWRON,
+       LP8788_INT_COMP1,
+       LP8788_INT_COMP2,
+
+       /* interrupt register 2 : Addr 01h */
+       LP8788_INT_CHG_INPUT_STATE,
+       LP8788_INT_CHG_STATE,
+       LP8788_INT_EOC,
+       LP8788_INT_CHG_RESTART,
+       LP8788_INT_RESTART_TIMEOUT,
+       LP8788_INT_FULLCHG_TIMEOUT,
+       LP8788_INT_PRECHG_TIMEOUT,
+
+       /* interrupt register 3 : Addr 02h */
+       LP8788_INT_RTC_ALARM1 = 17,
+       LP8788_INT_RTC_ALARM2,
+       LP8788_INT_ENTER_SYS_SUPPORT,
+       LP8788_INT_EXIT_SYS_SUPPORT,
+       LP8788_INT_BATT_LOW,
+       LP8788_INT_NO_BATT,
+
+       LP8788_INT_MAX = 24,
+};
+
+enum lp8788_dvs_sel {
+       DVS_SEL_V0,
+       DVS_SEL_V1,
+       DVS_SEL_V2,
+       DVS_SEL_V3,
+};
+
+enum lp8788_ext_ldo_en_id {
+       EN_ALDO1,
+       EN_ALDO234,
+       EN_ALDO5,
+       EN_ALDO7,
+       EN_DLDO7,
+       EN_DLDO911,
+       EN_LDOS_MAX,
+};
+
+enum lp8788_charger_event {
+       NO_CHARGER,
+       CHARGER_DETECTED,
+};
+
+enum lp8788_bl_ctrl_mode {
+       LP8788_BL_REGISTER_ONLY,
+       LP8788_BL_COMB_PWM_BASED,       /* PWM + I2C, changed by PWM input */
+       LP8788_BL_COMB_REGISTER_BASED,  /* PWM + I2C, changed by I2C */
+};
+
+enum lp8788_bl_dim_mode {
+       LP8788_DIM_EXPONENTIAL,
+       LP8788_DIM_LINEAR,
+};
+
+enum lp8788_bl_full_scale_current {
+       LP8788_FULLSCALE_5000uA,
+       LP8788_FULLSCALE_8500uA,
+       LP8788_FULLSCALE_1200uA,
+       LP8788_FULLSCALE_1550uA,
+       LP8788_FULLSCALE_1900uA,
+       LP8788_FULLSCALE_2250uA,
+       LP8788_FULLSCALE_2600uA,
+       LP8788_FULLSCALE_2950uA,
+};
+
+enum lp8788_bl_ramp_step {
+       LP8788_RAMP_8us,
+       LP8788_RAMP_1024us,
+       LP8788_RAMP_2048us,
+       LP8788_RAMP_4096us,
+       LP8788_RAMP_8192us,
+       LP8788_RAMP_16384us,
+       LP8788_RAMP_32768us,
+       LP8788_RAMP_65538us,
+};
+
+enum lp8788_bl_pwm_polarity {
+       LP8788_PWM_ACTIVE_HIGH,
+       LP8788_PWM_ACTIVE_LOW,
+};
+
+enum lp8788_isink_scale {
+       LP8788_ISINK_SCALE_100mA,
+       LP8788_ISINK_SCALE_120mA,
+};
+
+enum lp8788_isink_number {
+       LP8788_ISINK_1,
+       LP8788_ISINK_2,
+       LP8788_ISINK_3,
+};
+
+enum lp8788_alarm_sel {
+       LP8788_ALARM_1,
+       LP8788_ALARM_2,
+       LP8788_ALARM_MAX,
+};
+
+enum lp8788_adc_id {
+       LPADC_VBATT_5P5,
+       LPADC_VIN_CHG,
+       LPADC_IBATT,
+       LPADC_IC_TEMP,
+       LPADC_VBATT_6P0,
+       LPADC_VBATT_5P0,
+       LPADC_ADC1,
+       LPADC_ADC2,
+       LPADC_VDD,
+       LPADC_VCOIN,
+       LPADC_VDD_LDO,
+       LPADC_ADC3,
+       LPADC_ADC4,
+       LPADC_MAX,
+};
+
+struct lp8788;
+
+/*
+ * lp8788_buck1_dvs
+ * @gpio         : gpio pin number for dvs control
+ * @vsel         : dvs selector for buck v1 register
+ */
+struct lp8788_buck1_dvs {
+       int gpio;
+       enum lp8788_dvs_sel vsel;
+};
+
+/*
+ * lp8788_buck2_dvs
+ * @gpio         : two gpio pin numbers are used for dvs
+ * @vsel         : dvs selector for buck v2 register
+ */
+struct lp8788_buck2_dvs {
+       int gpio[LP8788_NUM_BUCK2_DVS];
+       enum lp8788_dvs_sel vsel;
+};
+
+/*
+ * struct lp8788_ldo_enable_pin
+ *
+ *   Basically, all LDOs are enabled through the I2C commands.
+ *   But ALDO 1 ~ 5, 7, DLDO 7, 9, 11 can be enabled by external gpio pins.
+ *
+ * @gpio         : gpio number which is used for enabling ldos
+ * @init_state   : initial gpio state (ex. GPIOF_OUT_INIT_LOW)
+ */
+struct lp8788_ldo_enable_pin {
+       int gpio;
+       int init_state;
+};
+
+/*
+ * struct lp8788_chg_param
+ * @addr         : charging control register address (range : 0x11 ~ 0x1C)
+ * @val          : charging parameter value
+ */
+struct lp8788_chg_param {
+       u8 addr;
+       u8 val;
+};
+
+/*
+ * struct lp8788_charger_platform_data
+ * @vbatt_adc         : adc selection id for battery voltage
+ * @batt_temp_adc     : adc selection id for battery temperature
+ * @max_vbatt_mv      : used for calculating battery capacity
+ * @chg_params        : initial charging parameters
+ * @num_chg_params    : numbers of charging parameters
+ * @charger_event     : the charger event can be reported to the platform side
+ */
+struct lp8788_charger_platform_data {
+       enum lp8788_adc_id vbatt_adc;
+       enum lp8788_adc_id batt_temp_adc;
+       unsigned int max_vbatt_mv;
+       struct lp8788_chg_param *chg_params;
+       int num_chg_params;
+       void (*charger_event) (struct lp8788 *lp,
+                               enum lp8788_charger_event event);
+};
+
+/*
+ * struct lp8788_bl_pwm_data
+ * @pwm_set_intensity     : set duty of pwm
+ * @pwm_get_intensity     : get current duty of pwm
+ */
+struct lp8788_bl_pwm_data {
+       void (*pwm_set_intensity) (int brightness, int max_brightness);
+       int (*pwm_get_intensity) (int max_brightness);
+};
+
+/*
+ * struct lp8788_backlight_platform_data
+ * @name                  : backlight driver name. (default: "lcd-backlight")
+ * @initial_brightness    : initial value of backlight brightness
+ * @bl_mode               : brightness control by pwm or lp8788 register
+ * @dim_mode              : dimming mode selection
+ * @full_scale            : full scale current setting
+ * @rise_time             : brightness ramp up step time
+ * @fall_time             : brightness ramp down step time
+ * @pwm_pol               : pwm polarity setting when bl_mode is pwm based
+ * @pwm_data              : platform specific pwm generation functions
+ *                          only valid when bl_mode is pwm based
+ */
+struct lp8788_backlight_platform_data {
+       char *name;
+       int initial_brightness;
+       enum lp8788_bl_ctrl_mode bl_mode;
+       enum lp8788_bl_dim_mode dim_mode;
+       enum lp8788_bl_full_scale_current full_scale;
+       enum lp8788_bl_ramp_step rise_time;
+       enum lp8788_bl_ramp_step fall_time;
+       enum lp8788_bl_pwm_polarity pwm_pol;
+       struct lp8788_bl_pwm_data pwm_data;
+};
+
+/*
+ * struct lp8788_led_platform_data
+ * @name         : led driver name. (default: "keyboard-backlight")
+ * @scale        : current scale
+ * @num          : current sink number
+ * @iout_code    : current output value (Addr 9Ah ~ 9Bh)
+ */
+struct lp8788_led_platform_data {
+       char *name;
+       enum lp8788_isink_scale scale;
+       enum lp8788_isink_number num;
+       int iout_code;
+};
+
+/*
+ * struct lp8788_vib_platform_data
+ * @name         : vibrator driver name
+ * @scale        : current scale
+ * @num          : current sink number
+ * @iout_code    : current output value (Addr 9Ah ~ 9Bh)
+ * @pwm_code     : PWM code value (Addr 9Ch ~ 9Eh)
+ */
+struct lp8788_vib_platform_data {
+       char *name;
+       enum lp8788_isink_scale scale;
+       enum lp8788_isink_number num;
+       int iout_code;
+       int pwm_code;
+};
+
+/*
+ * struct lp8788_platform_data
+ * @init_func    : used for initializing registers
+ *                 before mfd driver is registered
+ * @buck_data    : regulator initial data for buck
+ * @dldo_data    : regulator initial data for digital ldo
+ * @aldo_data    : regulator initial data for analog ldo
+ * @buck1_dvs    : gpio configurations for buck1 dvs
+ * @buck2_dvs    : gpio configurations for buck2 dvs
+ * @ldo_pin      : gpio configurations for enabling LDOs
+ * @chg_pdata    : platform data for charger driver
+ * @alarm_sel    : rtc alarm selection (1 or 2)
+ * @bl_pdata     : configurable data for backlight driver
+ * @led_pdata    : configurable data for led driver
+ * @vib_pdata    : configurable data for vibrator driver
+ * @adc_pdata    : iio map data for adc driver
+ */
+struct lp8788_platform_data {
+       /* general system information */
+       int (*init_func) (struct lp8788 *lp);
+
+       /* regulators */
+       struct regulator_init_data *buck_data[LP8788_NUM_BUCKS];
+       struct regulator_init_data *dldo_data[LP8788_NUM_DLDOS];
+       struct regulator_init_data *aldo_data[LP8788_NUM_ALDOS];
+       struct lp8788_buck1_dvs *buck1_dvs;
+       struct lp8788_buck2_dvs *buck2_dvs;
+       struct lp8788_ldo_enable_pin *ldo_pin[EN_LDOS_MAX];
+
+       /* charger */
+       struct lp8788_charger_platform_data *chg_pdata;
+
+       /* rtc alarm */
+       enum lp8788_alarm_sel alarm_sel;
+
+       /* backlight */
+       struct lp8788_backlight_platform_data *bl_pdata;
+
+       /* current sinks */
+       struct lp8788_led_platform_data *led_pdata;
+       struct lp8788_vib_platform_data *vib_pdata;
+
+       /* adc iio map data */
+       struct iio_map *adc_pdata;
+};
+
+/*
+ * struct lp8788
+ * @dev          : parent device pointer
+ * @regmap       : used for i2c communcation on accessing registers
+ * @irqdm        : interrupt domain for handling nested interrupt
+ * @irq          : pin number of IRQ_N
+ * @pdata        : lp8788 platform specific data
+ */
+struct lp8788 {
+       struct device *dev;
+       struct regmap *regmap;
+       struct irq_domain *irqdm;
+       int irq;
+       struct lp8788_platform_data *pdata;
+};
+
+int lp8788_irq_init(struct lp8788 *lp, int chip_irq);
+void lp8788_irq_exit(struct lp8788 *lp);
+int lp8788_read_byte(struct lp8788 *lp, u8 reg, u8 *data);
+int lp8788_read_multi_bytes(struct lp8788 *lp, u8 reg, u8 *data, size_t count);
+int lp8788_write_byte(struct lp8788 *lp, u8 reg, u8 data);
+int lp8788_update_bits(struct lp8788 *lp, u8 reg, u8 mask, u8 data);
+#endif
index fec5256c3f5d47a68239c60a051c1225640a6b20..3e1df644c407ed6d6965dc62908cb620421ca70a 100644 (file)
@@ -43,6 +43,7 @@ struct lpc_ich_info {
        char name[32];
        unsigned int iTCO_version;
        unsigned int gpio_version;
+       u8 use_gpio;
 };
 
 #endif
diff --git a/include/linux/mfd/max8907.h b/include/linux/mfd/max8907.h
new file mode 100644 (file)
index 0000000..b06f7a6
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Functions to access MAX8907 power management chip.
+ *
+ * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
+ * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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 __LINUX_MFD_MAX8907_H
+#define __LINUX_MFD_MAX8907_H
+
+#include <linux/mutex.h>
+#include <linux/pm.h>
+
+#define MAX8907_GEN_I2C_ADDR           (0x78 >> 1)
+#define MAX8907_ADC_I2C_ADDR           (0x8e >> 1)
+#define MAX8907_RTC_I2C_ADDR           (0xd0 >> 1)
+
+/* MAX8907 register map */
+#define MAX8907_REG_SYSENSEL           0x00
+#define MAX8907_REG_ON_OFF_IRQ1                0x01
+#define MAX8907_REG_ON_OFF_IRQ1_MASK   0x02
+#define MAX8907_REG_ON_OFF_STAT                0x03
+#define MAX8907_REG_SDCTL1             0x04
+#define MAX8907_REG_SDSEQCNT1          0x05
+#define MAX8907_REG_SDV1               0x06
+#define MAX8907_REG_SDCTL2             0x07
+#define MAX8907_REG_SDSEQCNT2          0x08
+#define MAX8907_REG_SDV2               0x09
+#define MAX8907_REG_SDCTL3             0x0A
+#define MAX8907_REG_SDSEQCNT3          0x0B
+#define MAX8907_REG_SDV3               0x0C
+#define MAX8907_REG_ON_OFF_IRQ2                0x0D
+#define MAX8907_REG_ON_OFF_IRQ2_MASK   0x0E
+#define MAX8907_REG_RESET_CNFG         0x0F
+#define MAX8907_REG_LDOCTL16           0x10
+#define MAX8907_REG_LDOSEQCNT16                0x11
+#define MAX8907_REG_LDO16VOUT          0x12
+#define MAX8907_REG_SDBYSEQCNT         0x13
+#define MAX8907_REG_LDOCTL17           0x14
+#define MAX8907_REG_LDOSEQCNT17                0x15
+#define MAX8907_REG_LDO17VOUT          0x16
+#define MAX8907_REG_LDOCTL1            0x18
+#define MAX8907_REG_LDOSEQCNT1         0x19
+#define MAX8907_REG_LDO1VOUT           0x1A
+#define MAX8907_REG_LDOCTL2            0x1C
+#define MAX8907_REG_LDOSEQCNT2         0x1D
+#define MAX8907_REG_LDO2VOUT           0x1E
+#define MAX8907_REG_LDOCTL3            0x20
+#define MAX8907_REG_LDOSEQCNT3         0x21
+#define MAX8907_REG_LDO3VOUT           0x22
+#define MAX8907_REG_LDOCTL4            0x24
+#define MAX8907_REG_LDOSEQCNT4         0x25
+#define MAX8907_REG_LDO4VOUT           0x26
+#define MAX8907_REG_LDOCTL5            0x28
+#define MAX8907_REG_LDOSEQCNT5         0x29
+#define MAX8907_REG_LDO5VOUT           0x2A
+#define MAX8907_REG_LDOCTL6            0x2C
+#define MAX8907_REG_LDOSEQCNT6         0x2D
+#define MAX8907_REG_LDO6VOUT           0x2E
+#define MAX8907_REG_LDOCTL7            0x30
+#define MAX8907_REG_LDOSEQCNT7         0x31
+#define MAX8907_REG_LDO7VOUT           0x32
+#define MAX8907_REG_LDOCTL8            0x34
+#define MAX8907_REG_LDOSEQCNT8         0x35
+#define MAX8907_REG_LDO8VOUT           0x36
+#define MAX8907_REG_LDOCTL9            0x38
+#define MAX8907_REG_LDOSEQCNT9         0x39
+#define MAX8907_REG_LDO9VOUT           0x3A
+#define MAX8907_REG_LDOCTL10           0x3C
+#define MAX8907_REG_LDOSEQCNT10                0x3D
+#define MAX8907_REG_LDO10VOUT          0x3E
+#define MAX8907_REG_LDOCTL11           0x40
+#define MAX8907_REG_LDOSEQCNT11                0x41
+#define MAX8907_REG_LDO11VOUT          0x42
+#define MAX8907_REG_LDOCTL12           0x44
+#define MAX8907_REG_LDOSEQCNT12                0x45
+#define MAX8907_REG_LDO12VOUT          0x46
+#define MAX8907_REG_LDOCTL13           0x48
+#define MAX8907_REG_LDOSEQCNT13                0x49
+#define MAX8907_REG_LDO13VOUT          0x4A
+#define MAX8907_REG_LDOCTL14           0x4C
+#define MAX8907_REG_LDOSEQCNT14                0x4D
+#define MAX8907_REG_LDO14VOUT          0x4E
+#define MAX8907_REG_LDOCTL15           0x50
+#define MAX8907_REG_LDOSEQCNT15                0x51
+#define MAX8907_REG_LDO15VOUT          0x52
+#define MAX8907_REG_OUT5VEN            0x54
+#define MAX8907_REG_OUT5VSEQ           0x55
+#define MAX8907_REG_OUT33VEN           0x58
+#define MAX8907_REG_OUT33VSEQ          0x59
+#define MAX8907_REG_LDOCTL19           0x5C
+#define MAX8907_REG_LDOSEQCNT19                0x5D
+#define MAX8907_REG_LDO19VOUT          0x5E
+#define MAX8907_REG_LBCNFG             0x60
+#define MAX8907_REG_SEQ1CNFG           0x64
+#define MAX8907_REG_SEQ2CNFG           0x65
+#define MAX8907_REG_SEQ3CNFG           0x66
+#define MAX8907_REG_SEQ4CNFG           0x67
+#define MAX8907_REG_SEQ5CNFG           0x68
+#define MAX8907_REG_SEQ6CNFG           0x69
+#define MAX8907_REG_SEQ7CNFG           0x6A
+#define MAX8907_REG_LDOCTL18           0x72
+#define MAX8907_REG_LDOSEQCNT18                0x73
+#define MAX8907_REG_LDO18VOUT          0x74
+#define MAX8907_REG_BBAT_CNFG          0x78
+#define MAX8907_REG_CHG_CNTL1          0x7C
+#define MAX8907_REG_CHG_CNTL2          0x7D
+#define MAX8907_REG_CHG_IRQ1           0x7E
+#define MAX8907_REG_CHG_IRQ2           0x7F
+#define MAX8907_REG_CHG_IRQ1_MASK      0x80
+#define MAX8907_REG_CHG_IRQ2_MASK      0x81
+#define MAX8907_REG_CHG_STAT           0x82
+#define MAX8907_REG_WLED_MODE_CNTL     0x84
+#define MAX8907_REG_ILED_CNTL          0x84
+#define MAX8907_REG_II1RR              0x8E
+#define MAX8907_REG_II2RR              0x8F
+#define MAX8907_REG_LDOCTL20           0x9C
+#define MAX8907_REG_LDOSEQCNT20                0x9D
+#define MAX8907_REG_LDO20VOUT          0x9E
+
+/* RTC register map */
+#define MAX8907_REG_RTC_SEC            0x00
+#define MAX8907_REG_RTC_MIN            0x01
+#define MAX8907_REG_RTC_HOURS          0x02
+#define MAX8907_REG_RTC_WEEKDAY                0x03
+#define MAX8907_REG_RTC_DATE           0x04
+#define MAX8907_REG_RTC_MONTH          0x05
+#define MAX8907_REG_RTC_YEAR1          0x06
+#define MAX8907_REG_RTC_YEAR2          0x07
+#define MAX8907_REG_ALARM0_SEC         0x08
+#define MAX8907_REG_ALARM0_MIN         0x09
+#define MAX8907_REG_ALARM0_HOURS       0x0A
+#define MAX8907_REG_ALARM0_WEEKDAY     0x0B
+#define MAX8907_REG_ALARM0_DATE                0x0C
+#define MAX8907_REG_ALARM0_MONTH       0x0D
+#define MAX8907_REG_ALARM0_YEAR1       0x0E
+#define MAX8907_REG_ALARM0_YEAR2       0x0F
+#define MAX8907_REG_ALARM1_SEC         0x10
+#define MAX8907_REG_ALARM1_MIN         0x11
+#define MAX8907_REG_ALARM1_HOURS       0x12
+#define MAX8907_REG_ALARM1_WEEKDAY     0x13
+#define MAX8907_REG_ALARM1_DATE                0x14
+#define MAX8907_REG_ALARM1_MONTH       0x15
+#define MAX8907_REG_ALARM1_YEAR1       0x16
+#define MAX8907_REG_ALARM1_YEAR2       0x17
+#define MAX8907_REG_ALARM0_CNTL                0x18
+#define MAX8907_REG_ALARM1_CNTL                0x19
+#define MAX8907_REG_RTC_STATUS         0x1A
+#define MAX8907_REG_RTC_CNTL           0x1B
+#define MAX8907_REG_RTC_IRQ            0x1C
+#define MAX8907_REG_RTC_IRQ_MASK       0x1D
+#define MAX8907_REG_MPL_CNTL           0x1E
+
+/* ADC and Touch Screen Controller register map */
+#define MAX8907_CTL                    0
+#define MAX8907_SEQCNT                 1
+#define MAX8907_VOUT                   2
+
+/* mask bit fields */
+#define MAX8907_MASK_LDO_SEQ           0x1C
+#define MAX8907_MASK_LDO_EN            0x01
+#define MAX8907_MASK_VBBATTCV          0x03
+#define MAX8907_MASK_OUT5V_VINEN       0x10
+#define MAX8907_MASK_OUT5V_ENSRC       0x0E
+#define MAX8907_MASK_OUT5V_EN          0x01
+#define MAX8907_MASK_POWER_OFF         0x40
+
+/* Regulator IDs */
+#define MAX8907_MBATT  0
+#define MAX8907_SD1    1
+#define MAX8907_SD2    2
+#define MAX8907_SD3    3
+#define MAX8907_LDO1   4
+#define MAX8907_LDO2   5
+#define MAX8907_LDO3   6
+#define MAX8907_LDO4   7
+#define MAX8907_LDO5   8
+#define MAX8907_LDO6   9
+#define MAX8907_LDO7   10
+#define MAX8907_LDO8   11
+#define MAX8907_LDO9   12
+#define MAX8907_LDO10  13
+#define MAX8907_LDO11  14
+#define MAX8907_LDO12  15
+#define MAX8907_LDO13  16
+#define MAX8907_LDO14  17
+#define MAX8907_LDO15  18
+#define MAX8907_LDO16  19
+#define MAX8907_LDO17  20
+#define MAX8907_LDO18  21
+#define MAX8907_LDO19  22
+#define MAX8907_LDO20  23
+#define MAX8907_OUT5V  24
+#define MAX8907_OUT33V 25
+#define MAX8907_BBAT   26
+#define MAX8907_SDBY   27
+#define MAX8907_VRTC   28
+#define MAX8907_NUM_REGULATORS (MAX8907_VRTC + 1)
+
+/* IRQ definitions */
+enum {
+       MAX8907_IRQ_VCHG_DC_OVP = 0,
+       MAX8907_IRQ_VCHG_DC_F,
+       MAX8907_IRQ_VCHG_DC_R,
+       MAX8907_IRQ_VCHG_THM_OK_R,
+       MAX8907_IRQ_VCHG_THM_OK_F,
+       MAX8907_IRQ_VCHG_MBATTLOW_F,
+       MAX8907_IRQ_VCHG_MBATTLOW_R,
+       MAX8907_IRQ_VCHG_RST,
+       MAX8907_IRQ_VCHG_DONE,
+       MAX8907_IRQ_VCHG_TOPOFF,
+       MAX8907_IRQ_VCHG_TMR_FAULT,
+
+       MAX8907_IRQ_GPM_RSTIN = 0,
+       MAX8907_IRQ_GPM_MPL,
+       MAX8907_IRQ_GPM_SW_3SEC,
+       MAX8907_IRQ_GPM_EXTON_F,
+       MAX8907_IRQ_GPM_EXTON_R,
+       MAX8907_IRQ_GPM_SW_1SEC,
+       MAX8907_IRQ_GPM_SW_F,
+       MAX8907_IRQ_GPM_SW_R,
+       MAX8907_IRQ_GPM_SYSCKEN_F,
+       MAX8907_IRQ_GPM_SYSCKEN_R,
+
+       MAX8907_IRQ_RTC_ALARM1 = 0,
+       MAX8907_IRQ_RTC_ALARM0,
+};
+
+struct max8907_platform_data {
+       struct regulator_init_data *init_data[MAX8907_NUM_REGULATORS];
+       bool pm_off;
+};
+
+struct regmap_irq_chips_data;
+
+struct max8907 {
+       struct device                   *dev;
+       struct mutex                    irq_lock;
+       struct i2c_client               *i2c_gen;
+       struct i2c_client               *i2c_rtc;
+       struct regmap                   *regmap_gen;
+       struct regmap                   *regmap_rtc;
+       struct regmap_irq_chip_data     *irqc_chg;
+       struct regmap_irq_chip_data     *irqc_on_off;
+       struct regmap_irq_chip_data     *irqc_rtc;
+};
+
+#endif
index 15b2392a56fbe4419c1caeb3986138249b2bc07b..74d8e2969630de5689957cff6ec0b5fc1e459ffd 100644 (file)
@@ -158,8 +158,6 @@ enum {
 #define TSC_IRQ_MASK                   (0x03)
 #define RTC_IRQ_MASK                   (0x0c)
 
-#define MAX8925_MAX_REGULATOR          (23)
-
 #define MAX8925_NAME_SIZE              (32)
 
 /* IRQ definitions */
@@ -236,7 +234,29 @@ struct max8925_platform_data {
        struct max8925_backlight_pdata  *backlight;
        struct max8925_touch_pdata      *touch;
        struct max8925_power_pdata      *power;
-       struct regulator_init_data      *regulator[MAX8925_MAX_REGULATOR];
+       struct regulator_init_data      *sd1;
+       struct regulator_init_data      *sd2;
+       struct regulator_init_data      *sd3;
+       struct regulator_init_data      *ldo1;
+       struct regulator_init_data      *ldo2;
+       struct regulator_init_data      *ldo3;
+       struct regulator_init_data      *ldo4;
+       struct regulator_init_data      *ldo5;
+       struct regulator_init_data      *ldo6;
+       struct regulator_init_data      *ldo7;
+       struct regulator_init_data      *ldo8;
+       struct regulator_init_data      *ldo9;
+       struct regulator_init_data      *ldo10;
+       struct regulator_init_data      *ldo11;
+       struct regulator_init_data      *ldo12;
+       struct regulator_init_data      *ldo13;
+       struct regulator_init_data      *ldo14;
+       struct regulator_init_data      *ldo15;
+       struct regulator_init_data      *ldo16;
+       struct regulator_init_data      *ldo17;
+       struct regulator_init_data      *ldo18;
+       struct regulator_init_data      *ldo19;
+       struct regulator_init_data      *ldo20;
 
        int             irq_base;
        int             tsc_irq;
index 9cbc642d40ad4efd809f42e2b0a8ce43c8f090bb..29f6616e12f07605379c6b21aa9bad1ff9152df3 100644 (file)
@@ -23,6 +23,9 @@
 #define PALMAS_NUM_CLIENTS             3
 
 struct palmas_pmic;
+struct palmas_gpadc;
+struct palmas_resource;
+struct palmas_usb;
 
 struct palmas {
        struct device *dev;
@@ -41,6 +44,9 @@ struct palmas {
 
        /* Child Devices */
        struct palmas_pmic *pmic;
+       struct palmas_gpadc *gpadc;
+       struct palmas_resource *resource;
+       struct palmas_usb *usb;
 
        /* GPIO MUXing */
        u8 gpio_muxed;
@@ -48,6 +54,23 @@ struct palmas {
        u8 pwm_muxed;
 };
 
+struct palmas_gpadc_platform_data {
+       /* Channel 3 current source is only enabled during conversion */
+       int ch3_current;
+
+       /* Channel 0 current source can be used for battery detection.
+        * If used for battery detection this will cause a permanent current
+        * consumption depending on current level set here.
+        */
+       int ch0_current;
+
+       /* default BAT_REMOVAL_DAT setting on device probe */
+       int bat_removal;
+
+       /* Sets the START_POLARITY bit in the RT_CTRL register */
+       int start_polarity;
+};
+
 struct palmas_reg_init {
        /* warm_rest controls the voltage levels after a warm reset
         *
@@ -107,21 +130,94 @@ struct palmas_reg_init {
 
 };
 
+enum palmas_regulators {
+       /* SMPS regulators */
+       PALMAS_REG_SMPS12,
+       PALMAS_REG_SMPS123,
+       PALMAS_REG_SMPS3,
+       PALMAS_REG_SMPS45,
+       PALMAS_REG_SMPS457,
+       PALMAS_REG_SMPS6,
+       PALMAS_REG_SMPS7,
+       PALMAS_REG_SMPS8,
+       PALMAS_REG_SMPS9,
+       PALMAS_REG_SMPS10,
+       /* LDO regulators */
+       PALMAS_REG_LDO1,
+       PALMAS_REG_LDO2,
+       PALMAS_REG_LDO3,
+       PALMAS_REG_LDO4,
+       PALMAS_REG_LDO5,
+       PALMAS_REG_LDO6,
+       PALMAS_REG_LDO7,
+       PALMAS_REG_LDO8,
+       PALMAS_REG_LDO9,
+       PALMAS_REG_LDOLN,
+       PALMAS_REG_LDOUSB,
+       /* Total number of regulators */
+       PALMAS_NUM_REGS,
+};
+
 struct palmas_pmic_platform_data {
        /* An array of pointers to regulator init data indexed by regulator
         * ID
         */
-       struct regulator_init_data **reg_data;
+       struct regulator_init_data *reg_data[PALMAS_NUM_REGS];
 
        /* An array of pointers to structures containing sleep mode and DVS
         * configuration for regulators indexed by ID
         */
-       struct palmas_reg_init **reg_init;
+       struct palmas_reg_init *reg_init[PALMAS_NUM_REGS];
 
        /* use LDO6 for vibrator control */
        int ldo6_vibrator;
+};
 
+struct palmas_usb_platform_data {
+       /* Set this if platform wishes its own vbus control */
+       int no_control_vbus;
 
+       /* Do we enable the wakeup comparator on probe */
+       int wakeup;
+};
+
+struct palmas_resource_platform_data {
+       int regen1_mode_sleep;
+       int regen2_mode_sleep;
+       int sysen1_mode_sleep;
+       int sysen2_mode_sleep;
+
+       /* bitfield to be loaded to NSLEEP_RES_ASSIGN */
+       u8 nsleep_res;
+       /* bitfield to be loaded to NSLEEP_SMPS_ASSIGN */
+       u8 nsleep_smps;
+       /* bitfield to be loaded to NSLEEP_LDO_ASSIGN1 */
+       u8 nsleep_ldo1;
+       /* bitfield to be loaded to NSLEEP_LDO_ASSIGN2 */
+       u8 nsleep_ldo2;
+
+       /* bitfield to be loaded to ENABLE1_RES_ASSIGN */
+       u8 enable1_res;
+       /* bitfield to be loaded to ENABLE1_SMPS_ASSIGN */
+       u8 enable1_smps;
+       /* bitfield to be loaded to ENABLE1_LDO_ASSIGN1 */
+       u8 enable1_ldo1;
+       /* bitfield to be loaded to ENABLE1_LDO_ASSIGN2 */
+       u8 enable1_ldo2;
+
+       /* bitfield to be loaded to ENABLE2_RES_ASSIGN */
+       u8 enable2_res;
+       /* bitfield to be loaded to ENABLE2_SMPS_ASSIGN */
+       u8 enable2_smps;
+       /* bitfield to be loaded to ENABLE2_LDO_ASSIGN1 */
+       u8 enable2_ldo1;
+       /* bitfield to be loaded to ENABLE2_LDO_ASSIGN2 */
+       u8 enable2_ldo2;
+};
+
+struct palmas_clk_platform_data {
+       int clk32kg_mode_sleep;
+       int clk32kgaudio_mode_sleep;
 };
 
 struct palmas_platform_data {
@@ -138,8 +234,49 @@ struct palmas_platform_data {
        u8 pad1, pad2;
 
        struct palmas_pmic_platform_data *pmic_pdata;
+       struct palmas_gpadc_platform_data *gpadc_pdata;
+       struct palmas_usb_platform_data *usb_pdata;
+       struct palmas_resource_platform_data *resource_pdata;
+       struct palmas_clk_platform_data *clk_pdata;
+};
+
+struct palmas_gpadc_calibration {
+       s32 gain;
+       s32 gain_error;
+       s32 offset_error;
 };
 
+struct palmas_gpadc {
+       struct device *dev;
+       struct palmas *palmas;
+
+       int ch3_current;
+       int ch0_current;
+
+       int gpadc_force;
+
+       int bat_removal;
+
+       struct mutex reading_lock;
+       struct completion irq_complete;
+
+       int eoc_sw_irq;
+
+       struct palmas_gpadc_calibration *palmas_cal_tbl;
+
+       int conv0_channel;
+       int conv1_channel;
+       int rt_channel;
+};
+
+struct palmas_gpadc_result {
+       s32 raw_code;
+       s32 corrected_code;
+       s32 result;
+};
+
+#define PALMAS_MAX_CHANNELS 16
+
 /* Define the palmas IRQ numbers */
 enum palmas_irqs {
        /* INT1 registers */
@@ -182,34 +319,6 @@ enum palmas_irqs {
        PALMAS_NUM_IRQ,
 };
 
-enum palmas_regulators {
-       /* SMPS regulators */
-       PALMAS_REG_SMPS12,
-       PALMAS_REG_SMPS123,
-       PALMAS_REG_SMPS3,
-       PALMAS_REG_SMPS45,
-       PALMAS_REG_SMPS457,
-       PALMAS_REG_SMPS6,
-       PALMAS_REG_SMPS7,
-       PALMAS_REG_SMPS8,
-       PALMAS_REG_SMPS9,
-       PALMAS_REG_SMPS10,
-       /* LDO regulators */
-       PALMAS_REG_LDO1,
-       PALMAS_REG_LDO2,
-       PALMAS_REG_LDO3,
-       PALMAS_REG_LDO4,
-       PALMAS_REG_LDO5,
-       PALMAS_REG_LDO6,
-       PALMAS_REG_LDO7,
-       PALMAS_REG_LDO8,
-       PALMAS_REG_LDO9,
-       PALMAS_REG_LDOLN,
-       PALMAS_REG_LDOUSB,
-       /* Total number of regulators */
-       PALMAS_NUM_REGS,
-};
-
 struct palmas_pmic {
        struct palmas *palmas;
        struct device *dev;
@@ -223,6 +332,69 @@ struct palmas_pmic {
        int range[PALMAS_REG_SMPS10];
 };
 
+struct palmas_resource {
+       struct palmas *palmas;
+       struct device *dev;
+};
+
+struct palmas_usb {
+       struct palmas *palmas;
+       struct device *dev;
+
+       /* for vbus reporting with irqs disabled */
+       spinlock_t lock;
+
+       struct regulator *vbus_reg;
+
+       /* used to set vbus, in atomic path */
+       struct work_struct set_vbus_work;
+
+       int irq1;
+       int irq2;
+       int irq3;
+       int irq4;
+
+       int vbus_enable;
+
+       u8 linkstat;
+};
+
+#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
+
+enum usb_irq_events {
+       /* Wakeup events from INT3 */
+       PALMAS_USB_ID_WAKEPUP,
+       PALMAS_USB_VBUS_WAKEUP,
+
+       /* ID_OTG_EVENTS */
+       PALMAS_USB_ID_GND,
+       N_PALMAS_USB_ID_GND,
+       PALMAS_USB_ID_C,
+       N_PALMAS_USB_ID_C,
+       PALMAS_USB_ID_B,
+       N_PALMAS_USB_ID_B,
+       PALMAS_USB_ID_A,
+       N_PALMAS_USB_ID_A,
+       PALMAS_USB_ID_FLOAT,
+       N_PALMAS_USB_ID_FLOAT,
+
+       /* VBUS_OTG_EVENTS */
+       PALMAS_USB_VB_SESS_END,
+       N_PALMAS_USB_VB_SESS_END,
+       PALMAS_USB_VB_SESS_VLD,
+       N_PALMAS_USB_VB_SESS_VLD,
+       PALMAS_USB_VA_SESS_VLD,
+       N_PALMAS_USB_VA_SESS_VLD,
+       PALMAS_USB_VA_VBUS_VLD,
+       N_PALMAS_USB_VA_VBUS_VLD,
+       PALMAS_USB_VADP_SNS,
+       N_PALMAS_USB_VADP_SNS,
+       PALMAS_USB_VADP_PRB,
+       N_PALMAS_USB_VADP_PRB,
+       PALMAS_USB_VOTG_SESS_VLD,
+       N_PALMAS_USB_VOTG_SESS_VLD,
+};
+
 /* defines so we can store the mux settings */
 #define PALMAS_GPIO_0_MUXED                                    (1 << 0)
 #define PALMAS_GPIO_1_MUXED                                    (1 << 1)
index 3661c59aa1e9f52149e166032bba6d9f50eaa6f7..36c242e52ef17826d3e0e44ce053a62b77a88987 100644 (file)
 #define RC5T583_GPIO_MON_IOIN  0xAB
 #define RC5T583_GPIO_GPOFUNC   0xAC
 
+/* RTC registers */
+#define RC5T583_RTC_SEC                0xE0
+#define RC5T583_RTC_MIN                0xE1
+#define RC5T583_RTC_HOUR       0xE2
+#define RC5T583_RTC_WDAY       0xE3
+#define RC5T583_RTC_DAY                0xE4
+#define RC5T583_RTC_MONTH      0xE5
+#define RC5T583_RTC_YEAR       0xE6
+#define RC5T583_RTC_ADJ                0xE7
+#define RC5T583_RTC_AW_MIN     0xE8
+#define RC5T583_RTC_AW_HOUR    0xE9
+#define RC5T583_RTC_AW_WEEK    0xEA
+#define RC5T583_RTC_AD_MIN     0xEB
+#define RC5T583_RTC_AD_HOUR    0xEC
+#define RC5T583_RTC_CTL1       0xED
+#define RC5T583_RTC_CTL2       0xEE
+#define RC5T583_RTC_AY_MIN     0xF0
+#define RC5T583_RTC_AY_HOUR    0xF1
+#define RC5T583_RTC_AY_DAY     0xF2
+#define RC5T583_RTC_AY_MONTH 0xF3
+#define RC5T583_RTC_AY_YEAR    0xF4
+
 /* RICOH_RC5T583 IRQ definitions */
 enum {
        RC5T583_IRQ_ONKEY,
diff --git a/include/linux/mfd/smsc.h b/include/linux/mfd/smsc.h
new file mode 100644 (file)
index 0000000..9747b29
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * SMSC ECE1099
+ *
+ * Copyright 2012 Texas Instruments Inc.
+ *
+ * Author: Sourav Poddar <sourav.poddar@ti.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.
+ *
+ */
+
+#ifndef __LINUX_MFD_SMSC_H
+#define __LINUX_MFD_SMSC_H
+
+#include <linux/regmap.h>
+
+#define SMSC_ID_ECE1099                        1
+#define SMSC_NUM_CLIENTS               2
+
+#define SMSC_BASE_ADDR                 0x38
+#define OMAP_GPIO_SMSC_IRQ             151
+
+#define SMSC_MAXGPIO         32
+#define SMSC_BANK(offs)      ((offs) >> 3)
+#define SMSC_BIT(offs)       (1u << ((offs) & 0x7))
+
+struct smsc {
+       struct device *dev;
+       struct i2c_client *i2c_clients[SMSC_NUM_CLIENTS];
+       struct regmap *regmap;
+       int clk;
+       /* Stored chip id */
+       int id;
+};
+
+struct smsc_gpio;
+struct smsc_keypad;
+
+static inline int smsc_read(struct device *child, unsigned int reg,
+       unsigned int *dest)
+{
+       struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+       return regmap_read(smsc->regmap, reg, dest);
+}
+
+static inline int smsc_write(struct device *child, unsigned int reg,
+       unsigned int value)
+{
+       struct smsc     *smsc = dev_get_drvdata(child->parent);
+
+       return regmap_write(smsc->regmap, reg, value);
+}
+
+/* Registers for SMSC */
+#define SMSC_RESET                                             0xF5
+#define SMSC_GRP_INT                                           0xF9
+#define SMSC_CLK_CTRL                                          0xFA
+#define SMSC_WKUP_CTRL                                         0xFB
+#define SMSC_DEV_ID                                            0xFC
+#define SMSC_DEV_REV                                           0xFD
+#define SMSC_VEN_ID_L                                          0xFE
+#define SMSC_VEN_ID_H                                          0xFF
+
+/* CLK VALUE */
+#define SMSC_CLK_VALUE                                         0x13
+
+/* Registers for function GPIO INPUT */
+#define SMSC_GPIO_DATA_IN_START                                        0x00
+
+/* Registers for function GPIO OUPUT */
+#define SMSC_GPIO_DATA_OUT_START                                       0x05
+
+/* Definitions for SMSC GPIO CONFIGURATION REGISTER*/
+#define SMSC_GPIO_INPUT_LOW                                    0x01
+#define SMSC_GPIO_INPUT_RISING                                 0x09
+#define SMSC_GPIO_INPUT_FALLING                                        0x11
+#define SMSC_GPIO_INPUT_BOTH_EDGE                              0x19
+#define SMSC_GPIO_OUTPUT_PP                                    0x21
+#define SMSC_GPIO_OUTPUT_OP                                    0x31
+
+#define GRP_INT_STAT                                           0xf9
+#define        SMSC_GPI_INT                                            0x0f
+#define SMSC_CFG_START                                         0x0A
+
+/* Registers for SMSC GPIO INTERRUPT STATUS REGISTER*/
+#define SMSC_GPIO_INT_STAT_START                                  0x32
+
+/* Registers for SMSC GPIO INTERRUPT MASK REGISTER*/
+#define SMSC_GPIO_INT_MASK_START                               0x37
+
+/* Registers for SMSC function KEYPAD*/
+#define SMSC_KP_OUT                                            0x40
+#define SMSC_KP_IN                                             0x41
+#define SMSC_KP_INT_STAT                                       0x42
+#define SMSC_KP_INT_MASK                                       0x43
+
+/* Definitions for keypad */
+#define SMSC_KP_KSO           0x70
+#define SMSC_KP_KSI           0x51
+#define SMSC_KSO_ALL_LOW        0x20
+#define SMSC_KP_SET_LOW_PWR        0x0B
+#define SMSC_KP_SET_HIGH           0xFF
+#define SMSC_KSO_EVAL           0x00
+
+#endif /*  __LINUX_MFD_SMSC_H */
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
new file mode 100644 (file)
index 0000000..6aeb6b8
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * System Control Driver
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.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.
+ */
+
+#ifndef __LINUX_MFD_SYSCON_H__
+#define __LINUX_MFD_SYSCON_H__
+
+extern struct regmap *syscon_node_to_regmap(struct device_node *np);
+extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
+extern struct regmap *syscon_regmap_lookup_by_phandle(
+                                       struct device_node *np,
+                                       const char *property);
+#endif /* __LINUX_MFD_SYSCON_H__ */
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
new file mode 100644 (file)
index 0000000..dab34a1
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, 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.
+ */
+
+#ifndef __LINUX_IMX6Q_IOMUXC_GPR_H
+#define __LINUX_IMX6Q_IOMUXC_GPR_H
+
+#include <linux/bitops.h>
+
+#define IOMUXC_GPR0    0x00
+#define IOMUXC_GPR1    0x04
+#define IOMUXC_GPR2    0x08
+#define IOMUXC_GPR3    0x0c
+#define IOMUXC_GPR4    0x10
+#define IOMUXC_GPR5    0x14
+#define IOMUXC_GPR6    0x18
+#define IOMUXC_GPR7    0x1c
+#define IOMUXC_GPR8    0x20
+#define IOMUXC_GPR9    0x24
+#define IOMUXC_GPR10   0x28
+#define IOMUXC_GPR11   0x2c
+#define IOMUXC_GPR12   0x30
+#define IOMUXC_GPR13   0x34
+
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_MASK                (0x3 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7_MUXED       (0x0 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7     (0x1 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_SSI_SRCK       (0x2 << 30)
+#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_RX_BIT_CLK     (0x3 << 30)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_MASK                (0x3 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR_MUXED    (0x0 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR  (0x1 << 28)
+#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_DO_SCKR   (0x2 << 28)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_MASK                (0x3 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7_MUXED       (0x0 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7     (0x1 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_SSI_STCK       (0x2 << 26)
+#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_TX_BIT_CLK     (0x3 << 26)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_MASK                (0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7_MUXED       (0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7     (0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_SSI_SRCK       (0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_RX_BIT_CLK     (0x3 << 24)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_MASK                (0x3 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2_MUXED       (0x0 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2     (0x1 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_SSI_STCK       (0x2 << 22)
+#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_TX_BIT_CLK     (0x3 << 22)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_MASK                (0x3 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2_MUXED       (0x0 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2     (0x1 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_SSI_SRCK       (0x2 << 20)
+#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_RX_BIT_CLK     (0x3 << 20)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_MASK                (0x3 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1_MUXED       (0x0 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1     (0x1 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_STCK       (0x2 << 18)
+#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_TX_BIT_CLK (0x3 << 18)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_MASK                (0x3 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1_MUXED       (0x0 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1     (0x1 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_SRCK       (0x2 << 16)
+#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_RX_BIT_CLK (0x3 << 16)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_MASK                (0x3 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK1  (0x0 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK2  (0x1 << 14)
+#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK3  (0x2 << 14)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_MASK                BIT(7)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_SPDIF       0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_IOMUX       BIT(7)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_MASK                BIT(6)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_ESAI                0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_I2C3                BIT(6)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_MASK                BIT(5)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_ECSPI4      0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_EPIT2       BIT(5)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_MASK                BIT(4)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_ECSPI4      0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_I2C1                BIT(4)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_MASK                BIT(3)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_ECSPI2      0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_I2C1                BIT(3)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_MASK                BIT(2)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_ECSPI1      0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_I2C2                BIT(2)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_MASK                BIT(1)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_ECSPI1      0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_I2C3                BIT(1)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_MASK                BIT(0)
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IPU1                0x0
+#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IOMUX       BIT(0)
+
+#define IMX6Q_GPR1_PCIE_REQ_MASK               (0x3 << 30)
+#define IMX6Q_GPR1_PCIE_EXIT_L1                        BIT(28)
+#define IMX6Q_GPR1_PCIE_RDY_L23                        BIT(27)
+#define IMX6Q_GPR1_PCIE_ENTER_L1               BIT(26)
+#define IMX6Q_GPR1_MIPI_COLOR_SW               BIT(25)
+#define IMX6Q_GPR1_DPI_OFF                     BIT(24)
+#define IMX6Q_GPR1_EXC_MON_MASK                        BIT(22)
+#define IMX6Q_GPR1_EXC_MON_OKAY                        0x0
+#define IMX6Q_GPR1_EXC_MON_SLVE                        BIT(22)
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_MASK          BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_GASKET                0x0
+#define IMX6Q_GPR1_MIPI_IPU2_SEL_IOMUX         BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK          BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET                0x0
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX         BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK          BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_GASKET                0x0
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX         BIT(19)
+#define IMX6Q_GPR1_PCIE_TEST_PD                        BIT(18)
+#define IMX6Q_GPR1_IPU_VPU_MUX_MASK            BIT(17)
+#define IMX6Q_GPR1_IPU_VPU_MUX_IPU1            0x0
+#define IMX6Q_GPR1_IPU_VPU_MUX_IPU2            BIT(17)
+#define IMX6Q_GPR1_PCIE_REF_CLK_EN             BIT(16)
+#define IMX6Q_GPR1_USB_EXP_MODE                        BIT(15)
+#define IMX6Q_GPR1_PCIE_INT                    BIT(14)
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_MASK         BIT(13)
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_ENET_RX_ER   0x0
+#define IMX6Q_GPR1_USB_OTG_ID_SEL_GPIO_1       BIT(13)
+#define IMX6Q_GPR1_GINT                                BIT(12)
+#define IMX6Q_GPR1_ADDRS3_MASK                 (0x3 << 10)
+#define IMX6Q_GPR1_ADDRS3_32MB                 (0x0 << 10)
+#define IMX6Q_GPR1_ADDRS3_64MB                 (0x1 << 10)
+#define IMX6Q_GPR1_ADDRS3_128MB                        (0x2 << 10)
+#define IMX6Q_GPR1_ACT_CS3                     BIT(9)
+#define IMX6Q_GPR1_ADDRS2_MASK                 (0x3 << 7)
+#define IMX6Q_GPR1_ACT_CS2                     BIT(6)
+#define IMX6Q_GPR1_ADDRS1_MASK                 (0x3 << 4)
+#define IMX6Q_GPR1_ACT_CS1                     BIT(3)
+#define IMX6Q_GPR1_ADDRS0_MASK                 (0x3 << 1)
+#define IMX6Q_GPR1_ACT_CS0                     BIT(0)
+
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_MASK      (0x3 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_5         (0x0 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_3         (0x1 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_4         (0x2 << 20)
+#define IMX6Q_GPR2_COUNTER_RESET_VAL_6         (0x3 << 20)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_MASK         (0x7 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_0            (0x0 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_1            (0x1 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_2            (0x2 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_3            (0x3 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_4            (0x4 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_5            (0x5 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_6            (0x6 << 16)
+#define IMX6Q_GPR2_LVDS_CLK_SHIFT_7            (0x7 << 16)
+#define IMX6Q_GPR2_BGREF_RRMODE_MASK           BIT(15)
+#define IMX6Q_GPR2_BGREF_RRMODE_EXT_RESISTOR   0x0
+#define IMX6Q_GPR2_BGREF_RRMODE_INT_RESISTOR   BIT(15)
+#define IMX6Q_GPR2_DI1_VS_POLARITY_MASK                BIT(10)
+#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_H    0x0
+#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_L    BIT(10)
+#define IMX6Q_GPR2_DI0_VS_POLARITY_MASK                BIT(9)
+#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_H    0x0
+#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_L    BIT(9)
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_MASK                BIT(8)
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_SPWG                0x0
+#define IMX6Q_GPR2_BIT_MAPPING_CH1_JEIDA       BIT(8)
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_MASK         BIT(7)
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_18BIT                0x0
+#define IMX6Q_GPR2_DATA_WIDTH_CH1_24BIT                BIT(7)
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_MASK                BIT(6)
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_SPWG                0x0
+#define IMX6Q_GPR2_BIT_MAPPING_CH0_JEIDA       BIT(6)
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_MASK         BIT(5)
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_18BIT                0x0
+#define IMX6Q_GPR2_DATA_WIDTH_CH0_24BIT                BIT(5)
+#define IMX6Q_GPR2_SPLIT_MODE_EN               BIT(4)
+#define IMX6Q_GPR2_CH1_MODE_MASK               (0x3 << 2)
+#define IMX6Q_GPR2_CH1_MODE_DISABLE            (0x0 << 2)
+#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI0       (0x1 << 2)
+#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI1       (0x3 << 2)
+#define IMX6Q_GPR2_CH0_MODE_MASK               (0x3 << 0)
+#define IMX6Q_GPR2_CH0_MODE_DISABLE            (0x0 << 0)
+#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI0       (0x1 << 0)
+#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI1       (0x3 << 0)
+
+#define IMX6Q_GPR3_GPU_DBG_MASK                        (0x3 << 29)
+#define IMX6Q_GPR3_GPU_DBG_GPU3D               (0x0 << 29)
+#define IMX6Q_GPR3_GPU_DBG_GPU2D               (0x1 << 29)
+#define IMX6Q_GPR3_GPU_DBG_OPENVG              (0x2 << 29)
+#define IMX6Q_GPR3_BCH_WR_CACHE_CTL            BIT(28)
+#define IMX6Q_GPR3_BCH_RD_CACHE_CTL            BIT(27)
+#define IMX6Q_GPR3_USDHCX_WR_CACHE_CTL         BIT(26)
+#define IMX6Q_GPR3_USDHCX_RD_CACHE_CTL         BIT(25)
+#define IMX6Q_GPR3_OCRAM_CTL_MASK              (0xf << 21)
+#define IMX6Q_GPR3_OCRAM_STATUS_MASK           (0xf << 17)
+#define IMX6Q_GPR3_CORE3_DBG_ACK_EN            BIT(16)
+#define IMX6Q_GPR3_CORE2_DBG_ACK_EN            BIT(15)
+#define IMX6Q_GPR3_CORE1_DBG_ACK_EN            BIT(14)
+#define IMX6Q_GPR3_CORE0_DBG_ACK_EN            BIT(13)
+#define IMX6Q_GPR3_TZASC2_BOOT_LOCK            BIT(12)
+#define IMX6Q_GPR3_TZASC1_BOOT_LOCK            BIT(11)
+#define IMX6Q_GPR3_IPU_DIAG_MASK               BIT(10)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_MASK          (0x3 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI0      (0x0 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI1      (0x1 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI0      (0x2 << 8)
+#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI1      (0x3 << 8)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_MASK          (0x3 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI0      (0x0 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1      (0x1 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0      (0x2 << 6)
+#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1      (0x3 << 6)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_MASK           (0x3 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI0       (0x0 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1       (0x1 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI0       (0x2 << 4)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI1       (0x3 << 4)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_MASK           (0x3 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI0       (0x0 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI1       (0x1 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI0       (0x2 << 2)
+#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI1       (0x3 << 2)
+
+#define IMX6Q_GPR4_VDOA_WR_CACHE_SEL           BIT(31)
+#define IMX6Q_GPR4_VDOA_RD_CACHE_SEL           BIT(30)
+#define IMX6Q_GPR4_VDOA_WR_CACHE_VAL           BIT(29)
+#define IMX6Q_GPR4_VDOA_RD_CACHE_VAL           BIT(28)
+#define IMX6Q_GPR4_PCIE_WR_CACHE_SEL           BIT(27)
+#define IMX6Q_GPR4_PCIE_RD_CACHE_SEL           BIT(26)
+#define IMX6Q_GPR4_PCIE_WR_CACHE_VAL           BIT(25)
+#define IMX6Q_GPR4_PCIE_RD_CACHE_VAL           BIT(24)
+#define IMX6Q_GPR4_SDMA_STOP_ACK               BIT(19)
+#define IMX6Q_GPR4_CAN2_STOP_ACK               BIT(18)
+#define IMX6Q_GPR4_CAN1_STOP_ACK               BIT(17)
+#define IMX6Q_GPR4_ENET_STOP_ACK               BIT(16)
+#define IMX6Q_GPR4_SOC_VERSION_MASK            (0xff << 8)
+#define IMX6Q_GPR4_SOC_VERSION_OFF             0x8
+#define IMX6Q_GPR4_VPU_WR_CACHE_SEL            BIT(7)
+#define IMX6Q_GPR4_VPU_RD_CACHE_SEL            BIT(6)
+#define IMX6Q_GPR4_VPU_P_WR_CACHE_VAL          BIT(3)
+#define IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK     BIT(2)
+#define IMX6Q_GPR4_IPU_WR_CACHE_CTL            BIT(1)
+#define IMX6Q_GPR4_IPU_RD_CACHE_CTL            BIT(0)
+
+#define IMX6Q_GPR5_L2_CLK_STOP                 BIT(8)
+
+#define IMX6Q_GPR9_TZASC2_BYP                  BIT(1)
+#define IMX6Q_GPR9_TZASC1_BYP                  BIT(0)
+
+#define IMX6Q_GPR10_LOCK_DBG_EN                        BIT(29)
+#define IMX6Q_GPR10_LOCK_DBG_CLK_EN            BIT(28)
+#define IMX6Q_GPR10_LOCK_SEC_ERR_RESP          BIT(27)
+#define IMX6Q_GPR10_LOCK_OCRAM_TZ_ADDR         (0x3f << 21)
+#define IMX6Q_GPR10_LOCK_OCRAM_TZ_EN           BIT(20)
+#define IMX6Q_GPR10_LOCK_DCIC2_MUX_MASK                (0x3 << 18)
+#define IMX6Q_GPR10_LOCK_DCIC1_MUX_MASK                (0x3 << 16)
+#define IMX6Q_GPR10_DBG_EN                     BIT(13)
+#define IMX6Q_GPR10_DBG_CLK_EN                 BIT(12)
+#define IMX6Q_GPR10_SEC_ERR_RESP_MASK          BIT(11)
+#define IMX6Q_GPR10_SEC_ERR_RESP_OKEY          0x0
+#define IMX6Q_GPR10_SEC_ERR_RESP_SLVE          BIT(11)
+#define IMX6Q_GPR10_OCRAM_TZ_ADDR_MASK         (0x3f << 5)
+#define IMX6Q_GPR10_OCRAM_TZ_EN_MASK           BIT(4)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_MASK         (0x3 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI0     (0x0 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1     (0x1 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI0     (0x2 << 2)
+#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI1     (0x3 << 2)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_MASK         (0x3 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI0     (0x0 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI1     (0x1 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI0     (0x2 << 0)
+#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI1     (0x3 << 0)
+
+#define IMX6Q_GPR12_ARMP_IPG_CLK_EN            BIT(27)
+#define IMX6Q_GPR12_ARMP_AHB_CLK_EN            BIT(26)
+#define IMX6Q_GPR12_ARMP_ATB_CLK_EN            BIT(25)
+#define IMX6Q_GPR12_ARMP_APB_CLK_EN            BIT(24)
+#define IMX6Q_GPR12_PCIE_CTL_2                 BIT(10)
+
+#define IMX6Q_GPR13_SDMA_STOP_REQ              BIT(30)
+#define IMX6Q_GPR13_CAN2_STOP_REQ              BIT(29)
+#define IMX6Q_GPR13_CAN1_STOP_REQ              BIT(28)
+#define IMX6Q_GPR13_ENET_STOP_REQ              BIT(27)
+#define IMX6Q_GPR13_SATA_PHY_8_MASK            (0x7 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_0_5_DB          (0x0 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_1_0_DB          (0x1 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_1_5_DB          (0x2 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_2_0_DB          (0x3 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_2_5_DB          (0x4 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_3_0_DB          (0x5 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_3_5_DB          (0x6 << 24)
+#define IMX6Q_GPR13_SATA_PHY_8_4_0_DB          (0x7 << 24)
+#define IMX6Q_GPR13_SATA_PHY_7_MASK            (0x1f << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1I          (0x10 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1M          (0x10 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA1X          (0x1a << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2I          (0x12 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2M          (0x12 << 19)
+#define IMX6Q_GPR13_SATA_PHY_7_SATA2X          (0x1a << 19)
+#define IMX6Q_GPR13_SATA_PHY_6_MASK            (0x7 << 16)
+#define IMX6Q_GPR13_SATA_SPEED_MASK            BIT(15)
+#define IMX6Q_GPR13_SATA_SPEED_1P5G            0x0
+#define IMX6Q_GPR13_SATA_SPEED_3P0G            BIT(15)
+#define IMX6Q_GPR13_SATA_PHY_5                 BIT(14)
+#define IMX6Q_GPR13_SATA_PHY_4_MASK            (0x7 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_16_16           (0x0 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_14_16           (0x1 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_12_16           (0x2 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_10_16           (0x3 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_9_16            (0x4 << 11)
+#define IMX6Q_GPR13_SATA_PHY_4_8_16            (0x5 << 11)
+#define IMX6Q_GPR13_SATA_PHY_3_MASK            (0xf << 7)
+#define IMX6Q_GPR13_SATA_PHY_3_OFF             0x7
+#define IMX6Q_GPR13_SATA_PHY_2_MASK            (0x1f << 2)
+#define IMX6Q_GPR13_SATA_PHY_2_OFF             0x2
+#define IMX6Q_GPR13_SATA_PHY_1_MASK            (0x3 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_FAST            (0x0 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_MED             (0x1 << 0)
+#define IMX6Q_GPR13_SATA_PHY_1_SLOW            (0x2 << 0)
+
+#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
index 3acb3a8e3af589cbf9b237290bb18d0216d57a8d..6b8e1ff4672b0a39aeef85604a106e93c5984730 100644 (file)
@@ -117,6 +117,7 @@ struct tc3589x {
        struct mutex lock;
        struct device *dev;
        struct i2c_client *i2c;
+       struct irq_domain *domain;
 
        int irq_base;
        int num_gpio;
index 7cd83d826ed82285099c55cc7008dc558feddcb2..290762f939304706ebdd27c6181e0fa34afd365c 100644 (file)
@@ -213,6 +213,23 @@ enum tps65217_regulator_id {
 /* Number of total regulators available */
 #define TPS65217_NUM_REGULATOR         (TPS65217_NUM_DCDC + TPS65217_NUM_LDO)
 
+enum tps65217_bl_isel {
+       TPS65217_BL_ISET1 = 1,
+       TPS65217_BL_ISET2,
+};
+
+enum tps65217_bl_fdim {
+       TPS65217_BL_FDIM_100HZ,
+       TPS65217_BL_FDIM_200HZ,
+       TPS65217_BL_FDIM_500HZ,
+       TPS65217_BL_FDIM_1000HZ,
+};
+
+struct tps65217_bl_pdata {
+       enum tps65217_bl_isel isel;
+       enum tps65217_bl_fdim fdim;
+};
+
 /**
  * struct tps65217_board - packages regulator init data
  * @tps65217_regulator_data: regulator initialization values
@@ -222,6 +239,7 @@ enum tps65217_regulator_id {
 struct tps65217_board {
        struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR];
        struct device_node *of_node[TPS65217_NUM_REGULATOR];
+       struct tps65217_bl_pdata *bl_pdata;
 };
 
 /**
index 94514710a03f721b999a9a09f49ac2845ccf5a85..2dd123194958afe1551c63d30cc16dc200410f1e 100644 (file)
@@ -78,6 +78,7 @@ struct tps6586x_platform_data {
 
        int gpio_base;
        int irq_base;
+       bool pm_off;
 };
 
 /*
index 9bf8767818b450003dface8acf7585d4ce809059..02e894f3ff45cee8ebdc244bcdf6dc714b86a309 100644 (file)
  *
  */
 
+/* RTC_CTRL_REG bitfields */
+#define TPS65910_RTC_CTRL_STOP_RTC                     0x01 /*0=stop, 1=run */
+#define TPS65910_RTC_CTRL_GET_TIME                     0x40
+
+/* RTC_STATUS_REG bitfields */
+#define TPS65910_RTC_STATUS_ALARM               0x40
+
+/* RTC_INTERRUPTS_REG bitfields */
+#define TPS65910_RTC_INTERRUPTS_EVERY           0x03
+#define TPS65910_RTC_INTERRUPTS_IT_ALARM        0x08
 
 /*Register BCK1  (0x80) register.RegisterDescription */
 #define BCK1_BCKUP_MASK                                        0xFF
 
 
 /*Register DEVCTRL  (0x80) register.RegisterDescription */
+#define DEVCTRL_PWR_OFF_MASK                           0x80
+#define DEVCTRL_PWR_OFF_SHIFT                          7
 #define DEVCTRL_RTC_PWDN_MASK                          0x40
 #define DEVCTRL_RTC_PWDN_SHIFT                         6
 #define DEVCTRL_CK32K_CTRL_MASK                                0x20
@@ -809,6 +821,7 @@ struct tps65910_board {
        int vmbch2_threshold;
        bool en_ck32k_xtal;
        bool en_dev_slp;
+       bool pm_off;
        struct tps65910_sleep_keepon_data *slp_keepon;
        bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
        unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
index ba43d4806b833e48fe7d67df559e6849c1253817..a8eff4ad9be5f63197435653c05690cfe3e38186 100644 (file)
 
 #define TWL6040_GPO1                   0x01
 #define TWL6040_GPO2                   0x02
-#define TWL6040_GPO3                   0x03
+#define TWL6040_GPO3                   0x04
 
 /* ACCCTL (0x2D) fields */
 
 #define TWL6040_VIBROCDET              0x20
 #define TWL6040_TSHUTDET                0x40
 
-#define TWL6040_CELLS                  2
+#define TWL6040_CELLS                  3
 
 #define TWL6040_REV_ES1_0              0x00
 #define TWL6040_REV_ES1_1              0x01 /* Rev ES1.1 and ES1.2 */
 #define TWL6040_SYSCLK_SEL_LPPLL       0
 #define TWL6040_SYSCLK_SEL_HPPLL       1
 
+#define TWL6040_GPO_MAX        3
+
 struct twl6040_codec_data {
        u16 hs_left_step;
        u16 hs_right_step;
@@ -192,11 +194,16 @@ struct twl6040_vibra_data {
        int vddvibr_uV;                 /* VDDVIBR volt, set 0 for fixed reg */
 };
 
+struct twl6040_gpo_data {
+       int gpio_base;
+};
+
 struct twl6040_platform_data {
        int audpwron_gpio;      /* audio power-on gpio */
 
        struct twl6040_codec_data *codec;
        struct twl6040_vibra_data *vibra;
+       struct twl6040_gpo_data *gpo;
 };
 
 struct regmap;
index d146ca10c0f52449dd528e9fec61be47e0c85221..5c86e2b33e2db55644ccdaa360c49e9ce394856a 100644 (file)
 #define NBD_SET_SIZE_BLOCKS    _IO( 0xab, 7 )
 #define NBD_DISCONNECT  _IO( 0xab, 8 )
 #define NBD_SET_TIMEOUT _IO( 0xab, 9 )
+#define NBD_SET_FLAGS   _IO( 0xab, 10)
 
 enum {
        NBD_CMD_READ = 0,
        NBD_CMD_WRITE = 1,
-       NBD_CMD_DISC = 2
+       NBD_CMD_DISC = 2,
+       /* there is a gap here to match userspace */
+       NBD_CMD_TRIM = 4
 };
 
+/* values for flags field */
+#define NBD_FLAG_HAS_FLAGS    (1 << 0) /* nbd-server supports flags */
+#define NBD_FLAG_READ_ONLY    (1 << 1) /* device is read-only */
+/* there is a gap here to match userspace */
+#define NBD_FLAG_SEND_TRIM    (1 << 5) /* send trim/discard */
+
 #define nbd_cmd(req) ((req)->cmd[0])
 
 /* userspace doesn't need the nbd_device structure */
@@ -42,10 +51,6 @@ enum {
 #include <linux/wait.h>
 #include <linux/mutex.h>
 
-/* values for flags field */
-#define NBD_READ_ONLY 0x0001
-#define NBD_WRITE_NOCHK 0x0002
-
 struct request;
 
 struct nbd_device {
index f594c528842fece04fc6931d627f0b34bf6ca931..72843b72a2b2619a5343be071d1ad104a9cb75af 100644 (file)
@@ -317,6 +317,12 @@ static inline const char* of_node_full_name(struct device_node *np)
        return "<no-node>";
 }
 
+static inline struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name)
+{
+       return NULL;
+}
+
 static inline bool of_have_populated_dt(void)
 {
        return false;
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 2b9f82c037c9279a6e26e8ea7e063ca3131b61b6..cc88172c7d9a827f919592eba81275c052f9046b 100644 (file)
@@ -107,7 +107,7 @@ enum pcpu_fc {
 
        PCPU_FC_NR,
 };
-extern const char *pcpu_fc_names[PCPU_FC_NR];
+extern const char * const pcpu_fc_names[PCPU_FC_NR];
 
 extern enum pcpu_fc pcpu_chosen_fc;
 
diff --git a/include/linux/platform_data/lm3630_bl.h b/include/linux/platform_data/lm3630_bl.h
new file mode 100644 (file)
index 0000000..9176dd3
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+* Simple driver for Texas Instruments LM3630 LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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 __LINUX_LM3630_H
+#define __LINUX_LM3630_H
+
+#define LM3630_NAME "lm3630_bl"
+
+enum lm3630_pwm_ctrl {
+       PWM_CTRL_DISABLE = 0,
+       PWM_CTRL_BANK_A,
+       PWM_CTRL_BANK_B,
+       PWM_CTRL_BANK_ALL,
+};
+
+enum lm3630_pwm_active {
+       PWM_ACTIVE_HIGH = 0,
+       PWM_ACTIVE_LOW,
+};
+
+enum lm3630_bank_a_ctrl {
+       BANK_A_CTRL_DISABLE = 0x0,
+       BANK_A_CTRL_LED1 = 0x4,
+       BANK_A_CTRL_LED2 = 0x1,
+       BANK_A_CTRL_ALL = 0x5,
+};
+
+enum lm3630_bank_b_ctrl {
+       BANK_B_CTRL_DISABLE = 0,
+       BANK_B_CTRL_LED2,
+};
+
+struct lm3630_platform_data {
+
+       /* maximum brightness */
+       int max_brt_led1;
+       int max_brt_led2;
+
+       /* initial on brightness */
+       int init_brt_led1;
+       int init_brt_led2;
+       enum lm3630_pwm_ctrl pwm_ctrl;
+       enum lm3630_pwm_active pwm_active;
+       enum lm3630_bank_a_ctrl bank_a_ctrl;
+       enum lm3630_bank_b_ctrl bank_b_ctrl;
+       unsigned int pwm_period;
+       void (*pwm_set_intensity) (int brightness, int max_brightness);
+};
+
+#endif /* __LINUX_LM3630_H */
diff --git a/include/linux/platform_data/lm3639_bl.h b/include/linux/platform_data/lm3639_bl.h
new file mode 100644 (file)
index 0000000..5234cd5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+* Simple driver for Texas Instruments LM3630 LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* 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 __LINUX_LM3639_H
+#define __LINUX_LM3639_H
+
+#define LM3639_NAME "lm3639_bl"
+
+enum lm3639_pwm {
+       LM3639_PWM_DISABLE = 0x00,
+       LM3639_PWM_EN_ACTLOW = 0x48,
+       LM3639_PWM_EN_ACTHIGH = 0x40,
+};
+
+enum lm3639_strobe {
+       LM3639_STROBE_DISABLE = 0x00,
+       LM3639_STROBE_EN_ACTLOW = 0x10,
+       LM3639_STROBE_EN_ACTHIGH = 0x30,
+};
+
+enum lm3639_txpin {
+       LM3639_TXPIN_DISABLE = 0x00,
+       LM3639_TXPIN_EN_ACTLOW = 0x04,
+       LM3639_TXPIN_EN_ACTHIGH = 0x0C,
+};
+
+enum lm3639_fleds {
+       LM3639_FLED_DIASBLE_ALL = 0x00,
+       LM3639_FLED_EN_1 = 0x40,
+       LM3639_FLED_EN_2 = 0x20,
+       LM3639_FLED_EN_ALL = 0x60,
+};
+
+enum lm3639_bleds {
+       LM3639_BLED_DIASBLE_ALL = 0x00,
+       LM3639_BLED_EN_1 = 0x10,
+       LM3639_BLED_EN_2 = 0x08,
+       LM3639_BLED_EN_ALL = 0x18,
+};
+enum lm3639_bled_mode {
+       LM3639_BLED_MODE_EXPONETIAL = 0x00,
+       LM3639_BLED_MODE_LINEAR = 0x10,
+};
+
+struct lm3639_platform_data {
+       unsigned int max_brt_led;
+       unsigned int init_brt_led;
+
+       /* input pins */
+       enum lm3639_pwm pin_pwm;
+       enum lm3639_strobe pin_strobe;
+       enum lm3639_txpin pin_tx;
+
+       /* output pins */
+       enum lm3639_fleds fled_pins;
+       enum lm3639_bleds bled_pins;
+       enum lm3639_bled_mode bled_mode;
+
+       void (*pwm_set_intensity) (int brightness, int max_brightness);
+       int (*pwm_get_intensity) (void);
+};
+#endif /* __LINUX_LM3639_H */
index cc76f1f18f18fc88b2c8cceb94901eb3976733ae..761f31752367c46bc61b1715ecb019e963663043 100644 (file)
@@ -46,6 +46,8 @@
 #define LP8556_I2C_CONFIG      ((ENABLE_BL << BL_CTL_SHFT) | \
                                (LP8556_I2C_ONLY << BRT_MODE_SHFT))
 #define LP8556_COMB2_CONFIG    (LP8556_COMBINED2 << BRT_MODE_SHFT)
+#define LP8556_FAST_CONFIG     BIT(7) /* use it if EPROMs should be maintained
+                                         when exiting the low power mode */
 
 enum lp855x_chip_id {
        LP8550,
index ea98c6133d32c694b57641906a146163f50a2af0..47128a50e04ecae182d9085b1af3d3084094194a 100644 (file)
 #define _LP8727_H
 
 enum lp8727_eoc_level {
-       EOC_5P,
-       EOC_10P,
-       EOC_16P,
-       EOC_20P,
-       EOC_25P,
-       EOC_33P,
-       EOC_50P,
+       LP8727_EOC_5P,
+       LP8727_EOC_10P,
+       LP8727_EOC_16P,
+       LP8727_EOC_20P,
+       LP8727_EOC_25P,
+       LP8727_EOC_33P,
+       LP8727_EOC_50P,
 };
 
 enum lp8727_ichg {
-       ICHG_90mA,
-       ICHG_100mA,
-       ICHG_400mA,
-       ICHG_450mA,
-       ICHG_500mA,
-       ICHG_600mA,
-       ICHG_700mA,
-       ICHG_800mA,
-       ICHG_900mA,
-       ICHG_1000mA,
+       LP8727_ICHG_90mA,
+       LP8727_ICHG_100mA,
+       LP8727_ICHG_400mA,
+       LP8727_ICHG_450mA,
+       LP8727_ICHG_500mA,
+       LP8727_ICHG_600mA,
+       LP8727_ICHG_700mA,
+       LP8727_ICHG_800mA,
+       LP8727_ICHG_900mA,
+       LP8727_ICHG_1000mA,
 };
 
 /**
  * struct lp8727_chg_param
  * @eoc_level : end of charge level setting
- * @ichg : charging current
+ * @ichg      : charging current
  */
 struct lp8727_chg_param {
        enum lp8727_eoc_level eoc_level;
@@ -47,19 +47,22 @@ struct lp8727_chg_param {
 
 /**
  * struct lp8727_platform_data
- * @get_batt_present : check battery status - exists or not
- * @get_batt_level : get battery voltage (mV)
+ * @get_batt_present  : check battery status - exists or not
+ * @get_batt_level    : get battery voltage (mV)
  * @get_batt_capacity : get battery capacity (%)
- * @get_batt_temp : get battery temperature
- * @ac, @usb : charging parameters each charger type
+ * @get_batt_temp     : get battery temperature
+ * @ac                : charging parameters for AC type charger
+ * @usb               : charging parameters for USB type charger
+ * @debounce_msec     : interrupt debounce time
  */
 struct lp8727_platform_data {
        u8 (*get_batt_present)(void);
        u16 (*get_batt_level)(void);
        u8 (*get_batt_capacity)(void);
        u8 (*get_batt_temp)(void);
-       struct lp8727_chg_param ac;
-       struct lp8727_chg_param usb;
+       struct lp8727_chg_param *ac;
+       struct lp8727_chg_param *usb;
+       unsigned int debounce_msec;
 };
 
 #endif
index cd22029e32aaf5adbd1b8136a3f48982705adbba..0e86840eb603186728d6af5d14a3c277f3f4382b 100644 (file)
@@ -109,24 +109,43 @@ struct charger_cable {
  * struct charger_regulator
  * @regulator_name: the name of regulator for using charger.
  * @consumer: the regulator consumer for the charger.
+ * @externally_control:
+ *     Set if the charger-manager cannot control charger,
+ *     the charger will be maintained with disabled state.
  * @cables:
  *     the array of charger cables to enable/disable charger
  *     and set current limit according to constratint data of
  *     struct charger_cable if only charger cable included
  *     in the array of charger cables is attached/detached.
  * @num_cables: the number of charger cables.
+ * @attr_g: Attribute group for the charger(regulator)
+ * @attr_name: "name" sysfs entry
+ * @attr_state: "state" sysfs entry
+ * @attr_externally_control: "externally_control" sysfs entry
+ * @attrs: Arrays pointing to attr_name/state/externally_control for attr_g
  */
 struct charger_regulator {
        /* The name of regulator for charging */
        const char *regulator_name;
        struct regulator *consumer;
 
+       /* charger never on when system is on */
+       int externally_control;
+
        /*
         * Store constraint information related to current limit,
         * each cable have different condition for charging.
         */
        struct charger_cable *cables;
        int num_cables;
+
+       struct attribute_group attr_g;
+       struct device_attribute attr_name;
+       struct device_attribute attr_state;
+       struct device_attribute attr_externally_control;
+       struct attribute *attrs[4];
+
+       struct charger_manager *cm;
 };
 
 /**
@@ -140,7 +159,11 @@ struct charger_regulator {
  *     If it has dropped more than fullbatt_vchkdrop_uV after
  *     fullbatt_vchkdrop_ms, CM will restart charging.
  * @fullbatt_uV: voltage in microvolt
- *     If it is not being charged and VBATT >= fullbatt_uV,
+ *     If VBATT >= fullbatt_uV, it is assumed to be full.
+ * @fullbatt_soc: state of Charge in %
+ *     If state of Charge >= fullbatt_soc, it is assumed to be full.
+ * @fullbatt_full_capacity: full capacity measure
+ *     If full capacity of battery >= fullbatt_full_capacity,
  *     it is assumed to be full.
  * @polling_interval_ms: interval in millisecond at which
  *     charger manager will monitor battery health
@@ -148,7 +171,7 @@ struct charger_regulator {
  *     Specify where information for existance of battery can be obtained
  * @psy_charger_stat: the names of power-supply for chargers
  * @num_charger_regulator: the number of entries in charger_regulators
- * @charger_regulators: array of regulator_bulk_data for chargers
+ * @charger_regulators: array of charger regulators
  * @psy_fuel_gauge: the name of power-supply for fuel gauge
  * @temperature_out_of_range:
  *     Determine whether the status is overheat or cold or normal.
@@ -158,6 +181,13 @@ struct charger_regulator {
  * @measure_battery_temp:
  *     true: measure battery temperature
  *     false: measure ambient temperature
+ * @charging_max_duration_ms: Maximum possible duration for charging
+ *     If whole charging duration exceed 'charging_max_duration_ms',
+ *     cm stop charging.
+ * @discharging_max_duration_ms:
+ *     Maximum possible duration for discharging with charger cable
+ *     after full-batt. If discharging duration exceed 'discharging
+ *     max_duration_ms', cm start charging.
  */
 struct charger_desc {
        char *psy_name;
@@ -168,6 +198,8 @@ struct charger_desc {
        unsigned int fullbatt_vchkdrop_ms;
        unsigned int fullbatt_vchkdrop_uV;
        unsigned int fullbatt_uV;
+       unsigned int fullbatt_soc;
+       unsigned int fullbatt_full_capacity;
 
        enum data_source battery_present;
 
@@ -180,6 +212,9 @@ struct charger_desc {
 
        int (*temperature_out_of_range)(int *mC);
        bool measure_battery_temp;
+
+       u64 charging_max_duration_ms;
+       u64 discharging_max_duration_ms;
 };
 
 #define PSY_NAME_MAX   30
@@ -194,8 +229,6 @@ struct charger_desc {
  * @charger_enabled: the state of charger
  * @fullbatt_vchk_jiffies_at:
  *     jiffies at the time full battery check will occur.
- * @fullbatt_vchk_uV: voltage in microvolt
- *     criteria for full battery
  * @fullbatt_vchk_work: work queue for full battery check
  * @emergency_stop:
  *     When setting true, stop charging
@@ -206,6 +239,8 @@ struct charger_desc {
  *     saved status of external power before entering suspend-to-RAM
  * @status_save_batt:
  *     saved status of battery before entering suspend-to-RAM
+ * @charging_start_time: saved start time of enabling charging
+ * @charging_end_time: saved end time of disabling charging
  */
 struct charger_manager {
        struct list_head entry;
@@ -218,7 +253,6 @@ struct charger_manager {
        bool charger_enabled;
 
        unsigned long fullbatt_vchk_jiffies_at;
-       unsigned int fullbatt_vchk_uV;
        struct delayed_work fullbatt_vchk_work;
 
        int emergency_stop;
@@ -229,6 +263,9 @@ struct charger_manager {
 
        bool status_save_ext_pwr_inserted;
        bool status_save_batt;
+
+       u64 charging_start_time;
+       u64 charging_end_time;
 };
 
 #ifdef CONFIG_CHARGER_MANAGER
index 0bafbb15f29cf55fb76672972bdc4b947bb2fa2c..e5ef45834c3c415e05af46d66b0d38599c12ec85 100644 (file)
@@ -88,6 +88,7 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_HEALTH,
        POWER_SUPPLY_PROP_PRESENT,
        POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_AUTHENTIC,
        POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MAX,
@@ -110,7 +111,9 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_CHARGE_AVG,
        POWER_SUPPLY_PROP_CHARGE_COUNTER,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
        POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
        POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -248,6 +251,7 @@ static inline bool power_supply_is_amp_property(enum power_supply_property psp)
        case POWER_SUPPLY_PROP_CHARGE_AVG:
        case POWER_SUPPLY_PROP_CHARGE_COUNTER:
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
        case POWER_SUPPLY_PROP_CURRENT_MAX:
        case POWER_SUPPLY_PROP_CURRENT_NOW:
        case POWER_SUPPLY_PROP_CURRENT_AVG:
@@ -276,6 +280,7 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp)
        case POWER_SUPPLY_PROP_VOLTAGE_AVG:
        case POWER_SUPPLY_PROP_VOLTAGE_OCV:
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
        case POWER_SUPPLY_PROP_POWER_NOW:
                return 1;
        default:
index c892587d9b81f87dbdacefee4c6acd485debae32..ee3034a408847153c664b20051874066d2150b05 100644 (file)
@@ -64,14 +64,6 @@ struct pstore_info {
        void            *data;
 };
 
-
-#ifdef CONFIG_PSTORE_FTRACE
-extern void pstore_ftrace_call(unsigned long ip, unsigned long parent_ip);
-#else
-static inline void pstore_ftrace_call(unsigned long ip, unsigned long parent_ip)
-{ }
-#endif
-
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 #else
index a90ebadd9da055bb5130782246872a0ef53d8438..d2dff22cf681bf6a0eee8789a5448cb5a17459e5 100644 (file)
@@ -30,6 +30,7 @@
 #define RIO_MAX_MPORTS         8
 #define RIO_MAX_MPORT_RESOURCES        16
 #define RIO_MAX_DEV_RESOURCES  16
+#define RIO_MAX_MPORT_NAME     40
 
 #define RIO_GLOBAL_TABLE       0xff    /* Indicates access of a switch's
                                           global routing table if it
@@ -235,6 +236,7 @@ enum rio_phy_type {
  * @phys_efptr: RIO port extended features pointer
  * @name: Port name string
  * @priv: Master port private data
+ * @dma: DMA device associated with mport
  */
 struct rio_mport {
        struct list_head dbells;        /* list of doorbell events */
@@ -255,13 +257,21 @@ struct rio_mport {
                                 */
        enum rio_phy_type phy_type;     /* RapidIO phy type */
        u32 phys_efptr;
-       unsigned char name[40];
+       unsigned char name[RIO_MAX_MPORT_NAME];
        void *priv;             /* Master port private data */
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
        struct dma_device       dma;
 #endif
 };
 
+struct rio_id_table {
+       u16 start;      /* logical minimal id */
+       u16 next;       /* hint for find */
+       u32 max;        /* max number of IDs in table */
+       spinlock_t lock;
+       unsigned long *table;
+};
+
 /**
  * struct rio_net - RIO network info
  * @node: Node in global list of RIO networks
@@ -273,9 +283,11 @@ struct rio_mport {
 struct rio_net {
        struct list_head node;  /* node in list of networks */
        struct list_head devices;       /* list of devices in this net */
+       struct list_head switches;      /* list of switches in this net */
        struct list_head mports;        /* list of ports accessing net */
        struct rio_mport *hport;        /* primary port for accessing net */
        unsigned char id;       /* RIO network ID */
+       struct rio_id_table destid_table;  /* destID allocation table */
 };
 
 /* Definitions used by switch sysfs initialization callback */
@@ -299,6 +311,8 @@ struct rio_net {
  * @add_outb_message: Callback to add a message to an outbound mailbox queue.
  * @add_inb_buffer: Callback to        add a buffer to an inbound mailbox queue.
  * @get_inb_message: Callback to get a message from an inbound mailbox queue.
+ * @map_inb: Callback to map RapidIO address region into local memory space.
+ * @unmap_inb: Callback to unmap RapidIO address region mapped with map_inb().
  */
 struct rio_ops {
        int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len,
@@ -321,6 +335,9 @@ struct rio_ops {
                                 int mbox, void *buffer, size_t len);
        int (*add_inb_buffer)(struct rio_mport *mport, int mbox, void *buf);
        void *(*get_inb_message)(struct rio_mport *mport, int mbox);
+       int (*map_inb)(struct rio_mport *mport, dma_addr_t lstart,
+                       u64 rstart, u32 size, u32 flags);
+       void (*unmap_inb)(struct rio_mport *mport, dma_addr_t lstart);
 };
 
 #define RIO_RESOURCE_MEM       0x00000100
@@ -403,7 +420,7 @@ union rio_pw_msg {
 
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 
-/**
+/*
  * enum rio_write_type - RIO write transaction types used in DMA transfers
  *
  * Note: RapidIO specification defines write (NWRITE) and
index 31ad146be3168bd127bdd083a0288f940f1b154b..b75c05920ab58f976cb73223ce7a7da97a4b146d 100644 (file)
@@ -365,6 +365,11 @@ void rio_release_regions(struct rio_dev *);
 int rio_request_region(struct rio_dev *, int, char *);
 void rio_release_region(struct rio_dev *, int);
 
+/* Memory mapping functions */
+extern int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local,
+                       u64 rbase, u32 size, u32 rflags);
+extern void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart);
+
 /* Port-Write management */
 extern int rio_request_inb_pwrite(struct rio_dev *,
                        int (*)(struct rio_dev *, union rio_pw_msg*, int));
diff --git a/include/linux/rtc-ds2404.h b/include/linux/rtc-ds2404.h
new file mode 100644 (file)
index 0000000..22c5382
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * ds2404.h - platform data structure for the DS2404 RTC.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 Sven Schnelle <svens@stackframe.org>
+ */
+
+#ifndef __LINUX_DS2404_H
+#define __LINUX_DS2404_H
+
+struct ds2404_platform_data {
+
+       unsigned int gpio_rst;
+       unsigned int gpio_clk;
+       unsigned int gpio_dq;
+};
+#endif
index f071b3922c67f7a253c0b5f978b4bec1b7a690df..20ec4d3bed733d3818f4bb7f899b0322b253372e 100644 (file)
@@ -276,7 +276,7 @@ static inline bool is_leap_year(unsigned int year)
        return (!(year % 4) && (year % 100)) || !(year % 400);
 }
 
-#ifdef CONFIG_RTC_HCTOSYS
+#ifdef CONFIG_RTC_HCTOSYS_DEVICE
 extern int rtc_hctosys_ret;
 #else
 #define rtc_hctosys_ret -ENODEV
index 9d51e260bde03536c75b3fc66f034a38ea420993..9c5612f0374b3b419b70066dd61599b32d6b0b9d 100644 (file)
@@ -405,7 +405,6 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
 
 extern void set_dumpable(struct mm_struct *mm, int value);
 extern int get_dumpable(struct mm_struct *mm);
-extern int __get_dumpable(unsigned long mm_flags);
 
 /* get/set_dumpable() values */
 #define SUID_DUMPABLE_DISABLED 0
index 0dd2dfa7becadd196849e0d9ff003a7dcd7f9b45..83d1a1454b7edea3bc32e91fc4b03b58e52af474 100644 (file)
@@ -321,7 +321,8 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
  * request comes from.
  */
 #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \
-       (defined(CONFIG_SLAB) && defined(CONFIG_TRACING))
+       (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \
+       (defined(CONFIG_SLOB) && defined(CONFIG_TRACING))
 extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long);
 #define kmalloc_track_caller(size, flags) \
        __kmalloc_track_caller(size, flags, _RET_IP_)
@@ -340,7 +341,8 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long);
  * allocation request comes from.
  */
 #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \
-       (defined(CONFIG_SLAB) && defined(CONFIG_TRACING))
+       (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \
+       (defined(CONFIG_SLOB) && defined(CONFIG_TRACING))
 extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long);
 #define kmalloc_node_track_caller(size, flags, node) \
        __kmalloc_node_track_caller(size, flags, node, \
index 0c634fa376c94b213bc295fb6372d60448623d83..cc290f0bdb346efe82dbe0e87985e6d015ad58e1 100644 (file)
@@ -45,7 +45,6 @@ struct kmem_cache {
        unsigned int colour_off;        /* colour offset */
        struct kmem_cache *slabp_cache;
        unsigned int slab_size;
-       unsigned int dflags;            /* dynamic flags */
 
        /* constructor func */
        void (*ctor)(void *obj);
@@ -112,19 +111,13 @@ void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
 void *__kmalloc(size_t size, gfp_t flags);
 
 #ifdef CONFIG_TRACING
-extern void *kmem_cache_alloc_trace(size_t size,
-                                   struct kmem_cache *cachep, gfp_t flags);
-extern size_t slab_buffer_size(struct kmem_cache *cachep);
+extern void *kmem_cache_alloc_trace(struct kmem_cache *, gfp_t, size_t);
 #else
 static __always_inline void *
-kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags)
+kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size)
 {
        return kmem_cache_alloc(cachep, flags);
 }
-static inline size_t slab_buffer_size(struct kmem_cache *cachep)
-{
-       return 0;
-}
 #endif
 
 static __always_inline void *kmalloc(size_t size, gfp_t flags)
@@ -154,7 +147,7 @@ found:
 #endif
                        cachep = malloc_sizes[i].cs_cachep;
 
-               ret = kmem_cache_alloc_trace(size, cachep, flags);
+               ret = kmem_cache_alloc_trace(cachep, flags, size);
 
                return ret;
        }
@@ -166,16 +159,16 @@ extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
 extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 #ifdef CONFIG_TRACING
-extern void *kmem_cache_alloc_node_trace(size_t size,
-                                        struct kmem_cache *cachep,
+extern void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep,
                                         gfp_t flags,
-                                        int nodeid);
+                                        int nodeid,
+                                        size_t size);
 #else
 static __always_inline void *
-kmem_cache_alloc_node_trace(size_t size,
-                           struct kmem_cache *cachep,
+kmem_cache_alloc_node_trace(struct kmem_cache *cachep,
                            gfp_t flags,
-                           int nodeid)
+                           int nodeid,
+                           size_t size)
 {
        return kmem_cache_alloc_node(cachep, flags, nodeid);
 }
@@ -207,7 +200,7 @@ found:
 #endif
                        cachep = malloc_sizes[i].cs_cachep;
 
-               return kmem_cache_alloc_node_trace(size, cachep, flags, node);
+               return kmem_cache_alloc_node_trace(cachep, flags, node, size);
        }
        return __kmalloc_node(size, flags, node);
 }
index 0ec00b39d006471e585a11e74759ff832f6f028b..f28e14a12e3fc44b4fb6599cf6b0100b84258fee 100644 (file)
@@ -1,12 +1,14 @@
 #ifndef __LINUX_SLOB_DEF_H
 #define __LINUX_SLOB_DEF_H
 
+#include <linux/numa.h>
+
 void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
 
 static __always_inline void *kmem_cache_alloc(struct kmem_cache *cachep,
                                              gfp_t flags)
 {
-       return kmem_cache_alloc_node(cachep, flags, -1);
+       return kmem_cache_alloc_node(cachep, flags, NUMA_NO_NODE);
 }
 
 void *__kmalloc_node(size_t size, gfp_t flags, int node);
@@ -26,7 +28,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
  */
 static __always_inline void *kmalloc(size_t size, gfp_t flags)
 {
-       return __kmalloc_node(size, flags, -1);
+       return __kmalloc_node(size, flags, NUMA_NO_NODE);
 }
 
 static __always_inline void *__kmalloc(size_t size, gfp_t flags)
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..421d24c
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ *  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)
+
+#endif
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..61395ef85a003a55ff8ce390bf52b582e4454db3 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.. */
@@ -1188,7 +1191,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 +1215,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 +1246,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 +1301,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 a1ba8bbd9fbeb70e94b8890203a03bff17501657..533b1157f22e675cf858c40d6e4b4a5ed17ee5ec 100644 (file)
@@ -50,6 +50,8 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
+int virtqueue_get_queue_index(struct virtqueue *vq);
+
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
index fc457f452f648722a1dc2850bc681e78576403d3..e2850a7ea2762ef01351c05b38bc31c6db721ab4 100644 (file)
@@ -84,7 +84,9 @@
  *     nvqs: the number of virtqueues to find
  *     vqs: on success, includes new virtqueues
  *     callbacks: array of callbacks, for each virtqueue
+ *             include a NULL entry for vqs that do not need a callback
  *     names: array of virtqueue names (mainly for debugging)
+ *             include a NULL entry for vqs unused by driver
  *     Returns 0 on success or error status
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
  *     vdev: the virtio_device
  *      This returns a pointer to the bus name a la pci_name from which
  *      the caller can then copy.
+ * @set_vq_affinity: set the affinity for a virtqueue.
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -116,6 +119,7 @@ struct virtio_config_ops {
        u32 (*get_features)(struct virtio_device *vdev);
        void (*finalize_features)(struct virtio_device *vdev);
        const char *(*bus_name)(struct virtio_device *vdev);
+       int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
@@ -190,5 +194,24 @@ const char *virtio_bus_name(struct virtio_device *vdev)
        return vdev->config->bus_name(vdev);
 }
 
+/**
+ * virtqueue_set_affinity - setting affinity for a virtqueue
+ * @vq: the virtqueue
+ * @cpu: the cpu no.
+ *
+ * Pay attention the function are best-effort: the affinity hint may not be set
+ * due to config support, irq type and sharing.
+ *
+ */
+static inline
+int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
+{
+       struct virtio_device *vdev = vq->vdev;
+       if (vdev->config->set_vq_affinity)
+               return vdev->config->set_vq_affinity(vq, cpu);
+       return 0;
+}
+
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_VIRTIO_CONFIG_H */
index e338730c2660f9e6efb593858bc672c486c8f996..c2d793a06ad701ddf2f74e38aff7abee5cdebec0 100644 (file)
@@ -165,7 +165,8 @@ static inline int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
 struct virtio_device;
 struct virtqueue;
 
-struct virtqueue *vring_new_virtqueue(unsigned int num,
+struct virtqueue *vring_new_virtqueue(unsigned int index,
+                                     unsigned int num,
                                      unsigned int vring_align,
                                      struct virtio_device *vdev,
                                      bool weak_barriers,
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
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..801adb466bd25cdde14eac5e7314ed4061f52707 100644 (file)
@@ -384,14 +384,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 +525,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 +560,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..2ecd7377153bb9bf7dbf5f5706466c6bf42bfdbf 100644 (file)
@@ -120,7 +120,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 +194,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);
 };
@@ -286,7 +286,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,
@@ -476,6 +476,8 @@ 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,
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 926142ed8d7aa67a55e560242c94c903611a8372..9497be1ad4c0c5cdf4fe2df49b79fa5f66a255f8 100644 (file)
@@ -102,6 +102,7 @@ struct fib_info {
        unsigned char           fib_dead;
        unsigned char           fib_protocol;
        unsigned char           fib_scope;
+       unsigned char           fib_type;
        __be32                  fib_prefsrc;
        u32                     fib_priority;
        u32                     *fib_metrics;
index 4faf6612ecacc05d2b00877691e440338ebb0144..95e646641184a3cdd2b32255822490683ea4f819 100644 (file)
@@ -257,10 +257,12 @@ static inline struct net *read_pnet(struct net * const *pnet)
 #define __net_init
 #define __net_exit
 #define __net_initdata
+#define __net_initconst
 #else
 #define __net_init     __init
 #define __net_exit     __exit_refok
 #define __net_initdata __initdata
+#define __net_initconst        __initconst
 #endif
 
 struct pernet_operations {
index 0fef00f5d3ce1fe65e2e6483ba1502f69615597b..64158aa1bb5f604aad0a68b172c2a1a674acca38 100644 (file)
@@ -1068,7 +1068,7 @@ void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
 void sctp_outq_teardown(struct sctp_outq *);
 void sctp_outq_free(struct sctp_outq*);
 int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
-int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
+int sctp_outq_sack(struct sctp_outq *, struct sctp_chunk *);
 int sctp_outq_is_empty(const struct sctp_outq *);
 void sctp_outq_restart(struct sctp_outq *);
 
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 04399b28e821bf694a58d706e0b6c9f66e9c7d9f..c6bfe01acf6b4f4952f42ea171b68947c87ff16f 100644 (file)
@@ -109,4 +109,6 @@ int xen_irq_from_gsi(unsigned gsi);
 /* Determine whether to ignore this IRQ if it is passed to a guest. */
 int xen_test_irq_shared(int irq);
 
+/* initialize Xen IRQ subsystem */
+void xen_init_IRQ(void);
 #endif /* _XEN_EVENTS_H */
index b6ca39a069d80c984962db4659e2f9bbe3256573..131a6ccdba25693e6899b7813d99a6934e846ce4 100644 (file)
@@ -50,6 +50,9 @@
 /* x86: pirq can be used by HVM guests */
 #define XENFEAT_hvm_pirqs           10
 
+/* operation as Dom0 is supported */
+#define XENFEAT_dom0                      11
+
 #define XENFEAT_NR_SUBMAPS 1
 
 #endif /* __XEN_PUBLIC_FEATURES_H__ */
index 01fc8ae5f0b06f9d96ed76852152a5ef64cf5d63..0eafaf254fff0e282e4fe340ede1950a5d9e86cb 100644 (file)
@@ -5,6 +5,7 @@
 #define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
 #define XEN_IO_PROTO_ABI_IA64       "ia64-abi"
 #define XEN_IO_PROTO_ABI_POWERPC64  "powerpc64-abi"
+#define XEN_IO_PROTO_ABI_ARM        "arm-abi"
 
 #if defined(__i386__)
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
@@ -14,6 +15,8 @@
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
 #elif defined(__powerpc64__)
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
+#elif defined(__arm__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
 #else
 # error arch fixup needed here
 #endif
index d8e33a93ea4d4483d69ea256c5abb99b16862a8c..b66d04ce6957549a1097c532bc483e5ee6ab38d8 100644 (file)
@@ -34,7 +34,7 @@ struct xen_memory_reservation {
     GUEST_HANDLE(xen_pfn_t) extent_start;
 
     /* Number of extents, and size/alignment of each (2^extent_order pages). */
-    unsigned long  nr_extents;
+    xen_ulong_t  nr_extents;
     unsigned int   extent_order;
 
     /*
@@ -92,7 +92,7 @@ struct xen_memory_exchange {
      *     command will be non-zero.
      *  5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
      */
-    unsigned long nr_exchanged;
+    xen_ulong_t nr_exchanged;
 };
 
 DEFINE_GUEST_HANDLE_STRUCT(xen_memory_exchange);
@@ -148,8 +148,8 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
  */
 #define XENMEM_machphys_mapping     12
 struct xen_machphys_mapping {
-    unsigned long v_start, v_end; /* Start and end virtual addresses.   */
-    unsigned long max_mfn;        /* Maximum MFN that can be looked up. */
+    xen_ulong_t v_start, v_end; /* Start and end virtual addresses.   */
+    xen_ulong_t max_mfn;        /* Maximum MFN that can be looked up. */
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
 
@@ -172,7 +172,7 @@ struct xen_add_to_physmap {
     unsigned int space;
 
     /* Index into source mapping space. */
-    unsigned long idx;
+    xen_ulong_t idx;
 
     /* GPFN where the source mapping page should appear. */
     xen_pfn_t gpfn;
@@ -189,7 +189,7 @@ struct xen_translate_gpfn_list {
     domid_t domid;
 
     /* Length of list. */
-    unsigned long nr_gpfns;
+    xen_ulong_t nr_gpfns;
 
     /* List of GPFNs to translate. */
     GUEST_HANDLE(ulong) gpfn_list;
index bfa1d50fe15bed0c5d2b37d392454ce5e6d56d02..1844d31f45520fef57c93be90ba7e247e1a0b042 100644 (file)
@@ -56,7 +56,7 @@ struct physdev_eoi {
 #define PHYSDEVOP_pirq_eoi_gmfn_v2       28
 struct physdev_pirq_eoi_gmfn {
     /* IN */
-    unsigned long gmfn;
+    xen_ulong_t gmfn;
 };
 
 /*
index 5f5e551cf546548a034e7423387a1a2e8e2f09db..7ff6498679a371e218137b3b5d2e6f1691304795 100644 (file)
@@ -45,7 +45,7 @@ struct xen_changeset_info {
 
 #define XENVER_platform_parameters 5
 struct xen_platform_parameters {
-    unsigned long virt_start;
+    xen_ulong_t virt_start;
 };
 
 #define XENVER_get_features 6
index a16402418d314710cf8281a28b5023cc06be94a1..a74d4362c4f84aca7a7218162a6cdba7df385fff 100644 (file)
@@ -23,8 +23,8 @@ extern enum xen_domain_type xen_domain_type;
 #include <xen/interface/xen.h>
 #include <asm/xen/hypervisor.h>
 
-#define xen_initial_domain()   (xen_pv_domain() && \
-                                xen_start_info->flags & SIF_INITDOMAIN)
+#define xen_initial_domain()   (xen_domain() && \
+                                xen_start_info && xen_start_info->flags & SIF_INITDOMAIN)
 #else  /* !CONFIG_XEN_DOM0 */
 #define xen_initial_domain()   (0)
 #endif /* CONFIG_XEN_DOM0 */
index cb003a3c9122e5be10ec0628049f954a4e3310a9..ed6334dd5e718cb874e4b4d272b652fadb101a8d 100644 (file)
@@ -1199,6 +1199,7 @@ config BUG
           Just say Y.
 
 config ELF_CORE
+       depends on COREDUMP
        default y
        bool "Enable ELF core dumps" if EXPERT
        help
@@ -1581,4 +1582,10 @@ config PADATA
        depends on SMP
        bool
 
+# Can be selected by architectures with broken toolchains
+# that get confused by correct const<->read_only section
+# mappings
+config BROKEN_RODATA
+       bool
+
 source "kernel/Kconfig.locks"
index 0668d58d6413e8eeb8736b234be6d8d7378a4bea..5e4bd7864c5dedf836a7c85cc1ed8e3c4e31e6cb 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/hardirq.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
-#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/numa.h>
 #include <linux/suspend.h>
index 34d45886ee8429acc7197c8ceaca18ef215fb2ae..73f35d4b30b9d22e727265f9ff06cd6250a88a36 100644 (file)
@@ -763,6 +763,7 @@ static void __init __reserve_region_with_split(struct resource *root,
        struct resource *parent = root;
        struct resource *conflict;
        struct resource *res = kzalloc(sizeof(*res), GFP_ATOMIC);
+       struct resource *next_res = NULL;
 
        if (!res)
                return;
@@ -772,21 +773,46 @@ static void __init __reserve_region_with_split(struct resource *root,
        res->end = end;
        res->flags = IORESOURCE_BUSY;
 
-       conflict = __request_resource(parent, res);
-       if (!conflict)
-               return;
+       while (1) {
 
-       /* failed, split and try again */
-       kfree(res);
+               conflict = __request_resource(parent, res);
+               if (!conflict) {
+                       if (!next_res)
+                               break;
+                       res = next_res;
+                       next_res = NULL;
+                       continue;
+               }
 
-       /* conflict covered whole area */
-       if (conflict->start <= start && conflict->end >= end)
-               return;
+               /* conflict covered whole area */
+               if (conflict->start <= res->start &&
+                               conflict->end >= res->end) {
+                       kfree(res);
+                       WARN_ON(next_res);
+                       break;
+               }
+
+               /* failed, split and try again */
+               if (conflict->start > res->start) {
+                       end = res->end;
+                       res->end = conflict->start - 1;
+                       if (conflict->end < end) {
+                               next_res = kzalloc(sizeof(*next_res),
+                                               GFP_ATOMIC);
+                               if (!next_res) {
+                                       kfree(res);
+                                       break;
+                               }
+                               next_res->name = name;
+                               next_res->start = conflict->end + 1;
+                               next_res->end = end;
+                               next_res->flags = IORESOURCE_BUSY;
+                       }
+               } else {
+                       res->start = conflict->end + 1;
+               }
+       }
 
-       if (conflict->start > start)
-               __reserve_region_with_split(root, start, conflict->start-1, name);
-       if (conflict->end < end)
-               __reserve_region_with_split(root, conflict->end+1, end, name);
 }
 
 void __init reserve_region_with_split(struct resource *root,
index 2c681f11b7d24b9deab0e7b4a7c1498f11a23b16..0af8868525d6d1853acfa77eb9f224566ccfb313 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/coredump.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
@@ -2359,7 +2360,7 @@ relock:
                         * first and our do_group_exit call below will use
                         * that value and ignore the one we pass it.
                         */
-                       do_coredump(info->si_signo, info->si_signo, regs);
+                       do_coredump(info, regs);
                }
 
                /*
index f9492284e5d23b76862dd87dcf458fc80a7072bb..c5cb5b99cb8152808f569f6b993010a33e646bce 100644 (file)
@@ -368,6 +368,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
 void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
+       disable_nonboot_cpus();
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
        else
@@ -2204,7 +2205,7 @@ static int __orderly_poweroff(void)
                return -ENOMEM;
        }
 
-       ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT,
+       ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC,
                                      NULL, argv_cleanup, NULL);
        if (ret == -ENOMEM)
                argv_free(argv);
index 84c76a34e41c7a01f3464506c5352cf00cf1f8ca..c2a2f8084bad0c95fbfc77ec08b2ee806d338097 100644 (file)
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int max_threads;
-extern int core_uses_pid;
 extern int suid_dumpable;
+#ifdef CONFIG_COREDUMP
+extern int core_uses_pid;
 extern char core_pattern[];
 extern unsigned int core_pipe_limit;
+#endif
 extern int pid_max;
 extern int min_free_kbytes;
 extern int pid_max_min, pid_max_max;
@@ -177,8 +179,10 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
 
 static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp, loff_t *ppos);
+#ifdef CONFIG_COREDUMP
 static int proc_dostring_coredump(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
 
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses it's own private copy */
@@ -404,6 +408,7 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+#ifdef CONFIG_COREDUMP
        {
                .procname       = "core_uses_pid",
                .data           = &core_uses_pid,
@@ -425,6 +430,7 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+#endif
 #ifdef CONFIG_PROC_SYSCTL
        {
                .procname       = "tainted",
@@ -2036,12 +2042,14 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
 
 static void validate_coredump_safety(void)
 {
+#ifdef CONFIG_COREDUMP
        if (suid_dumpable == SUID_DUMPABLE_SAFE &&
            core_pattern[0] != '/' && core_pattern[0] != '|') {
                printk(KERN_WARNING "Unsafe core_pattern used with "\
                        "suid_dumpable=2. Pipe handler or fully qualified "\
                        "core dump path required.\n");
        }
+#endif
 }
 
 static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
@@ -2053,6 +2061,7 @@ static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
        return error;
 }
 
+#ifdef CONFIG_COREDUMP
 static int proc_dostring_coredump(struct ctl_table *table, int write,
                  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2061,6 +2070,7 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
                validate_coredump_safety();
        return error;
 }
+#endif
 
 static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
                                     void __user *buffer,
index 610f0838d555393a08de2ac740d31fa05d8bafa9..145bb4d3bd4d9569fb38b33d9afe3496325a6a57 100644 (file)
@@ -445,6 +445,7 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
        na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
                                sizeof(struct cgroupstats));
        if (na == NULL) {
+               nlmsg_free(rep_skb);
                rc = -EMSGSIZE;
                goto err;
        }
index cdcb59450b491c2af7acf64bda54a82eaf0c16ab..31e4f55773f1c4e1959feffca13f6eb121b24e5f 100644 (file)
@@ -4200,12 +4200,6 @@ static void buffer_pipe_buf_release(struct pipe_inode_info *pipe,
        buf->private = 0;
 }
 
-static int buffer_pipe_buf_steal(struct pipe_inode_info *pipe,
-                                struct pipe_buffer *buf)
-{
-       return 1;
-}
-
 static void buffer_pipe_buf_get(struct pipe_inode_info *pipe,
                                struct pipe_buffer *buf)
 {
@@ -4221,7 +4215,7 @@ static const struct pipe_buf_operations buffer_pipe_buf_ops = {
        .unmap                  = generic_pipe_buf_unmap,
        .confirm                = generic_pipe_buf_confirm,
        .release                = buffer_pipe_buf_release,
-       .steal                  = buffer_pipe_buf_steal,
+       .steal                  = generic_pipe_buf_steal,
        .get                    = buffer_pipe_buf_get,
 };
 
index 483162a9f9080258fa08b76247e40103d8e5a6c5..507a7a9630bf06a8f69c5e4dbe1224716574acd3 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
-#include <linux/pstore.h>
 #include <linux/fs.h>
 
 #include "trace.h"
@@ -76,10 +75,9 @@ function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip,
        preempt_enable_notrace();
 }
 
-/* Our two options */
+/* Our option */
 enum {
        TRACE_FUNC_OPT_STACK    = 0x1,
-       TRACE_FUNC_OPT_PSTORE   = 0x2,
 };
 
 static struct tracer_flags func_flags;
@@ -109,12 +107,6 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
        disabled = atomic_inc_return(&data->disabled);
 
        if (likely(disabled == 1)) {
-               /*
-                * So far tracing doesn't support multiple buffers, so
-                * we make an explicit call for now.
-                */
-               if (unlikely(func_flags.val & TRACE_FUNC_OPT_PSTORE))
-                       pstore_ftrace_call(ip, parent_ip);
                pc = preempt_count();
                trace_function(tr, ip, parent_ip, flags, pc);
        }
@@ -180,9 +172,6 @@ static struct ftrace_ops trace_stack_ops __read_mostly =
 static struct tracer_opt func_opts[] = {
 #ifdef CONFIG_STACKTRACE
        { TRACER_OPT(func_stack_trace, TRACE_FUNC_OPT_STACK) },
-#endif
-#ifdef CONFIG_PSTORE_FTRACE
-       { TRACER_OPT(func_pstore, TRACE_FUNC_OPT_PSTORE) },
 #endif
        { } /* Always set a last empty entry */
 };
@@ -235,8 +224,6 @@ static int func_set_flag(u32 old_flags, u32 bit, int set)
                        register_ftrace_function(&trace_ops);
                }
 
-               break;
-       case TRACE_FUNC_OPT_PSTORE:
                break;
        default:
                return -EINVAL;
index 35c4565ee8fa26d5ce1ca1147ac6ccbdf47cf386..7fba3a98967fc826d76db8aac691a5a5e80911b8 100644 (file)
@@ -196,12 +196,13 @@ config LOCKUP_DETECTOR
          thresholds can be controlled through the sysctl watchdog_thresh.
 
 config HARDLOCKUP_DETECTOR
-       def_bool LOCKUP_DETECTOR && PERF_EVENTS && HAVE_PERF_EVENTS_NMI && \
-                !HAVE_NMI_WATCHDOG
+       def_bool y
+       depends on LOCKUP_DETECTOR && !HAVE_NMI_WATCHDOG
+       depends on PERF_EVENTS && HAVE_PERF_EVENTS_NMI
 
 config BOOTPARAM_HARDLOCKUP_PANIC
        bool "Panic (Reboot) On Hard Lockups"
-       depends on LOCKUP_DETECTOR
+       depends on HARDLOCKUP_DETECTOR
        help
          Say Y here to enable the kernel to panic on "hard lockups",
          which are bugs that cause the kernel to loop in kernel
@@ -212,7 +213,7 @@ config BOOTPARAM_HARDLOCKUP_PANIC
 
 config BOOTPARAM_HARDLOCKUP_PANIC_VALUE
        int
-       depends on LOCKUP_DETECTOR
+       depends on HARDLOCKUP_DETECTOR
        range 0 1
        default 0 if !BOOTPARAM_HARDLOCKUP_PANIC
        default 1 if BOOTPARAM_HARDLOCKUP_PANIC
index 61774b8db4de6911453ccd383df7d38dd2f2b42f..072fbd8234d56f531a25dbf4a6dcb53f6463eb7d 100644 (file)
@@ -188,11 +188,13 @@ u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len)
 #else
 u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
 {
-       return crc32_le_generic(crc, p, len, crc32table_le, CRCPOLY_LE);
+       return crc32_le_generic(crc, p, len,
+                       (const u32 (*)[256])crc32table_le, CRCPOLY_LE);
 }
 u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len)
 {
-       return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE);
+       return crc32_le_generic(crc, p, len,
+                       (const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE);
 }
 #endif
 EXPORT_SYMBOL(crc32_le);
@@ -253,7 +255,8 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
 #else
 u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
 {
-       return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE);
+       return crc32_be_generic(crc, p, len,
+                       (const u32 (*)[256])crc32table_be, CRCPOLY_BE);
 }
 #endif
 EXPORT_SYMBOL(crc32_be);
index 3d766b7f60aba915b9957be45e089e699f164c3e..31a8042772820d695b85dc15edfb33f57666b0db 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/init.h>
 
 #ifndef CONFIG_DECOMPRESS_GZIP
 # define gunzip NULL
 # define unlzo NULL
 #endif
 
-static const struct compress_format {
+struct compress_format {
        unsigned char magic[2];
        const char *name;
        decompress_fn decompressor;
-} compressed_formats[] = {
+};
+
+static const struct compress_format compressed_formats[] __initdata = {
        { {037, 0213}, "gzip", gunzip },
        { {037, 0236}, "gzip", gunzip },
        { {0x42, 0x5a}, "bzip2", bunzip2 },
@@ -45,7 +48,7 @@ static const struct compress_format {
        { {0, 0}, NULL, NULL }
 };
 
-decompress_fn decompress_method(const unsigned char *inbuf, int len,
+decompress_fn __init decompress_method(const unsigned char *inbuf, int len,
                                const char **name)
 {
        const struct compress_format *cf;
index cce4f3cd14b36f1511b7372a5c8a8106b9495437..3657f129d7b8c5db0bee11a94a97d5d4bf251b52 100644 (file)
--- a/lib/gcd.c
+++ b/lib/gcd.c
@@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b)
 
        if (a < b)
                swap(a, b);
+
+       if (!b)
+               return a;
        while ((r = a % b) != 0) {
                a = b;
                b = r;
index 8f8d5439e2d9c59d373f01e9bb507f3f41433ef0..71fcfcd964104f732c0e9c3ac0af45620fd438b7 100644 (file)
@@ -109,7 +109,7 @@ int main(int argc, char** argv)
 
        if (CRC_LE_BITS > 1) {
                crc32init_le();
-               printf("static const u32 __cacheline_aligned "
+               printf("static u32 __cacheline_aligned "
                       "crc32table_le[%d][%d] = {",
                       LE_TABLE_ROWS, LE_TABLE_SIZE);
                output_table(crc32table_le, LE_TABLE_ROWS,
@@ -119,7 +119,7 @@ int main(int argc, char** argv)
 
        if (CRC_BE_BITS > 1) {
                crc32init_be();
-               printf("static const u32 __cacheline_aligned "
+               printf("static u32 __cacheline_aligned "
                       "crc32table_be[%d][%d] = {",
                       BE_TABLE_ROWS, BE_TABLE_SIZE);
                output_table(crc32table_be, LE_TABLE_ROWS,
@@ -128,7 +128,7 @@ int main(int argc, char** argv)
        }
        if (CRC_LE_BITS > 1) {
                crc32cinit_le();
-               printf("static const u32 __cacheline_aligned "
+               printf("static u32 __cacheline_aligned "
                       "crc32ctable_le[%d][%d] = {",
                       LE_TABLE_ROWS, LE_TABLE_SIZE);
                output_table(crc32ctable_le, LE_TABLE_ROWS,
index 6bc04aab6ec717ea3144303e4a0294f528b83cf9..ca208a92628c1b49a6f5c1fece1a81592a65ecaa 100644 (file)
@@ -152,6 +152,8 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
                spin_lock_init(&pool->lock);
                INIT_LIST_HEAD(&pool->chunks);
                pool->min_alloc_order = min_alloc_order;
+               pool->algo = gen_pool_first_fit;
+               pool->data = NULL;
        }
        return pool;
 }
@@ -255,8 +257,9 @@ EXPORT_SYMBOL(gen_pool_destroy);
  * @size: number of bytes to allocate from the pool
  *
  * Allocate the requested number of bytes from the specified pool.
- * Uses a first-fit algorithm. Can not be used in NMI handler on
- * architectures without NMI-safe cmpxchg implementation.
+ * Uses the pool allocation function (with first-fit algorithm by default).
+ * Can not be used in NMI handler on architectures without
+ * NMI-safe cmpxchg implementation.
  */
 unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
 {
@@ -280,8 +283,8 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
 
                end_bit = (chunk->end_addr - chunk->start_addr) >> order;
 retry:
-               start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit,
-                                                      start_bit, nbits, 0);
+               start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits,
+                               pool->data);
                if (start_bit >= end_bit)
                        continue;
                remain = bitmap_set_ll(chunk->bits, start_bit, nbits);
@@ -400,3 +403,80 @@ size_t gen_pool_size(struct gen_pool *pool)
        return size;
 }
 EXPORT_SYMBOL_GPL(gen_pool_size);
+
+/**
+ * gen_pool_set_algo - set the allocation algorithm
+ * @pool: pool to change allocation algorithm
+ * @algo: custom algorithm function
+ * @data: additional data used by @algo
+ *
+ * Call @algo for each memory allocation in the pool.
+ * If @algo is NULL use gen_pool_first_fit as default
+ * memory allocation function.
+ */
+void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, void *data)
+{
+       rcu_read_lock();
+
+       pool->algo = algo;
+       if (!pool->algo)
+               pool->algo = gen_pool_first_fit;
+
+       pool->data = data;
+
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL(gen_pool_set_algo);
+
+/**
+ * gen_pool_first_fit - find the first available region
+ * of memory matching the size requirement (no alignment constraint)
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @data: additional data - unused
+ */
+unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
+               unsigned long start, unsigned int nr, void *data)
+{
+       return bitmap_find_next_zero_area(map, size, start, nr, 0);
+}
+EXPORT_SYMBOL(gen_pool_first_fit);
+
+/**
+ * gen_pool_best_fit - find the best fitting region of memory
+ * macthing the size requirement (no alignment constraint)
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @data: additional data - unused
+ *
+ * Iterate over the bitmap to find the smallest free region
+ * which we can allocate the memory.
+ */
+unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
+               unsigned long start, unsigned int nr, void *data)
+{
+       unsigned long start_bit = size;
+       unsigned long len = size + 1;
+       unsigned long index;
+
+       index = bitmap_find_next_zero_area(map, size, start, nr, 0);
+
+       while (index < size) {
+               int next_bit = find_next_bit(map, size, index + nr);
+               if ((next_bit - index) < len) {
+                       len = next_bit - index;
+                       start_bit = index;
+                       if (len == nr)
+                               return start_bit;
+               }
+               index = bitmap_find_next_zero_area(map, size,
+                                                  next_bit + 1, nr, 0);
+       }
+
+       return start_bit;
+}
+EXPORT_SYMBOL(gen_pool_best_fit);
index 4046e29c0a997bb38fd3892adeb55a4cf4914e31..648239079dd21329f0329ddaf12552677149d846 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -20,7 +20,7 @@
  * that id to this code and it returns your pointer.
 
  * You can release ids at any time. When all ids are released, most of
- * the memory is returned (we keep IDR_FREE_MAX) in a local pool so we
+ * the memory is returned (we keep MAX_IDR_FREE) in a local pool so we
  * don't need to go to the memory "store" during an id allocate, just
  * so you don't need to be too concerned about locking and conflicts
  * with the slab allocator.
@@ -122,7 +122,7 @@ static void idr_mark_full(struct idr_layer **pa, int id)
  */
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
-       while (idp->id_free_cnt < IDR_FREE_MAX) {
+       while (idp->id_free_cnt < MAX_IDR_FREE) {
                struct idr_layer *new;
                new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
                if (new == NULL)
@@ -179,7 +179,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
                        sh = IDR_BITS*l;
                        id = ((id >> sh) ^ n ^ m) << sh;
                }
-               if ((id >= MAX_ID_BIT) || (id < 0))
+               if ((id >= MAX_IDR_BIT) || (id < 0))
                        return IDR_NOMORE_SPACE;
                if (l == 0)
                        break;
@@ -223,7 +223,7 @@ build_up:
         * Add a new layer to the top of the tree if the requested
         * id is larger than the currently allocated space.
         */
-       while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
+       while ((layers < (MAX_IDR_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
                layers++;
                if (!p->count) {
                        /* special case: if the tree is currently empty,
@@ -265,7 +265,7 @@ build_up:
 
 static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
 {
-       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer *pa[MAX_IDR_LEVEL];
        int id;
 
        id = idr_get_empty_slot(idp, starting_id, pa);
@@ -357,7 +357,7 @@ static void idr_remove_warning(int id)
 static void sub_remove(struct idr *idp, int shift, int id)
 {
        struct idr_layer *p = idp->top;
-       struct idr_layer **pa[MAX_LEVEL];
+       struct idr_layer **pa[MAX_IDR_LEVEL];
        struct idr_layer ***paa = &pa[0];
        struct idr_layer *to_free;
        int n;
@@ -402,7 +402,7 @@ void idr_remove(struct idr *idp, int id)
        struct idr_layer *to_free;
 
        /* Mask off upper bits we don't use for the search. */
-       id &= MAX_ID_MASK;
+       id &= MAX_IDR_MASK;
 
        sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
        if (idp->top && idp->top->count == 1 && (idp->layers > 1) &&
@@ -420,7 +420,7 @@ void idr_remove(struct idr *idp, int id)
                to_free->bitmap = to_free->count = 0;
                free_layer(to_free);
        }
-       while (idp->id_free_cnt >= IDR_FREE_MAX) {
+       while (idp->id_free_cnt >= MAX_IDR_FREE) {
                p = get_from_free_list(idp);
                /*
                 * Note: we don't call the rcu callback here, since the only
@@ -451,7 +451,7 @@ void idr_remove_all(struct idr *idp)
        int n, id, max;
        int bt_mask;
        struct idr_layer *p;
-       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer *pa[MAX_IDR_LEVEL];
        struct idr_layer **paa = &pa[0];
 
        n = idp->layers * IDR_BITS;
@@ -517,7 +517,7 @@ void *idr_find(struct idr *idp, int id)
        n = (p->layer+1) * IDR_BITS;
 
        /* Mask off upper bits we don't use for the search. */
-       id &= MAX_ID_MASK;
+       id &= MAX_IDR_MASK;
 
        if (id >= (1 << n))
                return NULL;
@@ -555,7 +555,7 @@ int idr_for_each(struct idr *idp,
 {
        int n, id, max, error = 0;
        struct idr_layer *p;
-       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer *pa[MAX_IDR_LEVEL];
        struct idr_layer **paa = &pa[0];
 
        n = idp->layers * IDR_BITS;
@@ -601,7 +601,7 @@ EXPORT_SYMBOL(idr_for_each);
  */
 void *idr_get_next(struct idr *idp, int *nextidp)
 {
-       struct idr_layer *p, *pa[MAX_LEVEL];
+       struct idr_layer *p, *pa[MAX_IDR_LEVEL];
        struct idr_layer **paa = &pa[0];
        int id = *nextidp;
        int n, max;
@@ -659,7 +659,7 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
 
        n = (p->layer+1) * IDR_BITS;
 
-       id &= MAX_ID_MASK;
+       id &= MAX_IDR_MASK;
 
        if (id >= (1 << n))
                return ERR_PTR(-EINVAL);
@@ -780,7 +780,7 @@ EXPORT_SYMBOL(ida_pre_get);
  */
 int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
 {
-       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer *pa[MAX_IDR_LEVEL];
        struct ida_bitmap *bitmap;
        unsigned long flags;
        int idr_id = starting_id / IDA_BITMAP_BITS;
@@ -793,7 +793,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
        if (t < 0)
                return _idr_rc_to_errno(t);
 
-       if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
+       if (t * IDA_BITMAP_BITS >= MAX_IDR_BIT)
                return -ENOSPC;
 
        if (t != idr_id)
@@ -827,7 +827,7 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
        }
 
        id = idr_id * IDA_BITMAP_BITS + t;
-       if (id >= MAX_ID_BIT)
+       if (id >= MAX_IDR_BIT)
                return -ENOSPC;
 
        __set_bit(t, bitmap->bitmap);
index c43410084838725c18c3542cdd6e48794116d382..52cfa69f73dfe514b7424f0edf1c236a5e0edb59 100644 (file)
@@ -122,13 +122,14 @@ int match_token(char *s, const match_table_t table, substring_t args[])
  *
  * Description: Given a &substring_t and a base, attempts to parse the substring
  * as a number in that base. On success, sets @result to the integer represented
- * by the string and returns 0. Returns either -ENOMEM or -EINVAL on failure.
+ * by the string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure.
  */
 static int match_number(substring_t *s, int *result, int base)
 {
        char *endp;
        char *buf;
        int ret;
+       long val;
        size_t len = s->to - s->from;
 
        buf = kmalloc(len + 1, GFP_KERNEL);
@@ -136,10 +137,15 @@ static int match_number(substring_t *s, int *result, int base)
                return -ENOMEM;
        memcpy(buf, s->from, len);
        buf[len] = '\0';
-       *result = simple_strtol(buf, &endp, base);
+
        ret = 0;
+       val = simple_strtol(buf, &endp, base);
        if (endp == buf)
                ret = -EINVAL;
+       else if (val < (long)INT_MIN || val > (long)INT_MAX)
+               ret = -ERANGE;
+       else
+               *result = (int) val;
        kfree(buf);
        return ret;
 }
index 6ab0e521c48b93593c141a999e16b93937a993c0..1ebc95f7a46f40bb36cb04e180f9a07696185bc8 100644 (file)
@@ -175,7 +175,7 @@ static int  __init plist_test(void)
        int nr_expect = 0, i, loop;
        unsigned int r = local_clock();
 
-       printk(KERN_INFO "start plist test\n");
+       pr_debug("start plist test\n");
        plist_head_init(&test_head);
        for (i = 0; i < ARRAY_SIZE(test_node); i++)
                plist_node_init(test_node + i, 0);
@@ -203,7 +203,7 @@ static int  __init plist_test(void)
                plist_test_check(nr_expect);
        }
 
-       printk(KERN_INFO "end plist test\n");
+       pr_debug("end plist test\n");
        return 0;
 }
 
index fadae774a20cc6abb0226ee4c3bfbc6cb4cd4eeb..e76d85cf31755c6de5b9ca5898756254e0525845 100644 (file)
@@ -404,14 +404,13 @@ EXPORT_SYMBOL(sg_miter_start);
  * @miter: sg mapping iter to proceed
  *
  * Description:
- *   Proceeds @miter@ to the next mapping.  @miter@ should have been
- *   started using sg_miter_start().  On successful return,
- *   @miter@->page, @miter@->addr and @miter@->length point to the
- *   current mapping.
+ *   Proceeds @miter to the next mapping.  @miter should have been started
+ *   using sg_miter_start().  On successful return, @miter->page,
+ *   @miter->addr and @miter->length point to the current mapping.
  *
  * Context:
- *   IRQ disabled if SG_MITER_ATOMIC.  IRQ must stay disabled till
- *   @miter@ is stopped.  May sleep if !SG_MITER_ATOMIC.
+ *   Preemption disabled if SG_MITER_ATOMIC.  Preemption must stay disabled
+ *   till @miter is stopped.  May sleep if !SG_MITER_ATOMIC.
  *
  * Returns:
  *   true if @miter contains the next mapping.  false if end of sg
@@ -465,7 +464,8 @@ EXPORT_SYMBOL(sg_miter_next);
  *   resources (kmap) need to be released during iteration.
  *
  * Context:
- *   IRQ disabled if the SG_MITER_ATOMIC is set.  Don't care otherwise.
+ *   Preemption disabled if the SG_MITER_ATOMIC is set.  Don't care
+ *   otherwise.
  */
 void sg_miter_stop(struct sg_mapping_iter *miter)
 {
@@ -479,7 +479,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
                        flush_kernel_dcache_page(miter->page);
 
                if (miter->__flags & SG_MITER_ATOMIC) {
-                       WARN_ON(!irqs_disabled());
+                       WARN_ON_ONCE(preemptible());
                        kunmap_atomic(miter->addr);
                } else
                        kunmap(miter->page);
index eb10578ae055947d2cd39c9e4c8e9f7c1c76477e..0374a596cffac8439d36875ba2bd248753caf886 100644 (file)
@@ -107,23 +107,27 @@ static void __spin_lock_debug(raw_spinlock_t *lock)
 {
        u64 i;
        u64 loops = loops_per_jiffy * HZ;
-       int print_once = 1;
 
-       for (;;) {
-               for (i = 0; i < loops; i++) {
-                       if (arch_spin_trylock(&lock->raw_lock))
-                               return;
-                       __delay(1);
-               }
-               /* lockup suspected: */
-               if (print_once) {
-                       print_once = 0;
-                       spin_dump(lock, "lockup suspected");
+       for (i = 0; i < loops; i++) {
+               if (arch_spin_trylock(&lock->raw_lock))
+                       return;
+               __delay(1);
+       }
+       /* lockup suspected: */
+       spin_dump(lock, "lockup suspected");
 #ifdef CONFIG_SMP
-                       trigger_all_cpu_backtrace();
+       trigger_all_cpu_backtrace();
 #endif
-               }
-       }
+
+       /*
+        * The trylock above was causing a livelock.  Give the lower level arch
+        * specific lock code a chance to acquire the lock. We have already
+        * printed a warning/backtrace at this point. The non-debug arch
+        * specific code might actually succeed in acquiring the lock.  If it is
+        * not successful, the end-result is the same - there is no forward
+        * progress.
+        */
+       arch_spin_lock(&lock->raw_lock);
 }
 
 void do_raw_spin_lock(raw_spinlock_t *lock)
index 0e337541f005d8f29a36434dae555b7477d12164..39c99fea7c0386f5cb12cfe814085d182d9c4db9 100644 (file)
@@ -174,35 +174,25 @@ char *put_dec_trunc8(char *buf, unsigned r)
        unsigned q;
 
        /* Copy of previous function's body with added early returns */
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 2 */
-       if (q == 0)
-               return buf;
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 3 */
-       if (r == 0)
-               return buf;
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 4 */
-       if (q == 0)
-               return buf;
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 5 */
-       if (r == 0)
-               return buf;
-       q      = (r * 0x199a) >> 16;
-       *buf++ = (r - 10 * q)  + '0'; /* 6 */
+       while (r >= 10000) {
+               q = r + '0';
+               r  = (r * (uint64_t)0x1999999a) >> 32;
+               *buf++ = q - 10*r;
+       }
+
+       q      = (r * 0x199a) >> 16;    /* r <= 9999 */
+       *buf++ = (r - 10 * q)  + '0';
        if (q == 0)
                return buf;
-       r      = (q * 0xcd) >> 11;
-       *buf++ = (q - 10 * r)  + '0'; /* 7 */
+       r      = (q * 0xcd) >> 11;      /* q <= 999 */
+       *buf++ = (q - 10 * r)  + '0';
        if (r == 0)
                return buf;
-       q      = (r * 0xcd) >> 11;
-       *buf++ = (r - 10 * q) + '0'; /* 8 */
+       q      = (r * 0xcd) >> 11;      /* r <= 99 */
+       *buf++ = (r - 10 * q) + '0';
        if (q == 0)
                return buf;
-       *buf++ = q + '0'; /* 9 */
+       *buf++ = q + '0';                /* q <= 9 */
        return buf;
 }
 
@@ -243,18 +233,34 @@ char *put_dec(char *buf, unsigned long long n)
 
 /* Second algorithm: valid only for 64-bit long longs */
 
+/* See comment in put_dec_full9 for choice of constants */
 static noinline_for_stack
-char *put_dec_full4(char *buf, unsigned q)
+void put_dec_full4(char *buf, unsigned q)
 {
        unsigned r;
-       r      = (q * 0xcccd) >> 19;
-       *buf++ = (q - 10 * r) + '0';
-       q      = (r * 0x199a) >> 16;
-       *buf++ = (r - 10 * q)  + '0';
+       r      = (q * 0xccd) >> 15;
+       buf[0] = (q - 10 * r) + '0';
+       q      = (r * 0xcd) >> 11;
+       buf[1] = (r - 10 * q)  + '0';
        r      = (q * 0xcd) >> 11;
-       *buf++ = (q - 10 * r)  + '0';
-       *buf++ = r + '0';
-       return buf;
+       buf[2] = (q - 10 * r)  + '0';
+       buf[3] = r + '0';
+}
+
+/*
+ * Call put_dec_full4 on x % 10000, return x / 10000.
+ * The approximation x/10000 == (x * 0x346DC5D7) >> 43
+ * holds for all x < 1,128,869,999.  The largest value this
+ * helper will ever be asked to convert is 1,125,520,955.
+ * (d1 in the put_dec code, assuming n is all-ones).
+ */
+static
+unsigned put_dec_helper4(char *buf, unsigned x)
+{
+        uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
+
+        put_dec_full4(buf, x - q * 10000);
+        return q;
 }
 
 /* Based on code by Douglas W. Jones found at
@@ -276,28 +282,19 @@ char *put_dec(char *buf, unsigned long long n)
        d3  = (h >> 16); /* implicit "& 0xffff" */
 
        q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
+       q = put_dec_helper4(buf, q);
+
+       q += 7671 * d3 + 9496 * d2 + 6 * d1;
+       q = put_dec_helper4(buf+4, q);
+
+       q += 4749 * d3 + 42 * d2;
+       q = put_dec_helper4(buf+8, q);
 
-       buf = put_dec_full4(buf, q % 10000);
-       q   = q / 10000;
-
-       d1  = q + 7671 * d3 + 9496 * d2 + 6 * d1;
-       buf = put_dec_full4(buf, d1 % 10000);
-       q   = d1 / 10000;
-
-       d2  = q + 4749 * d3 + 42 * d2;
-       buf = put_dec_full4(buf, d2 % 10000);
-       q   = d2 / 10000;
-
-       d3  = q + 281 * d3;
-       if (!d3)
-               goto done;
-       buf = put_dec_full4(buf, d3 % 10000);
-       q   = d3 / 10000;
-       if (!q)
-               goto done;
-       buf = put_dec_full4(buf, q);
- done:
-       while (buf[-1] == '0')
+       q += 281 * d3;
+       buf += 12;
+       if (q)
+               buf = put_dec_trunc8(buf, q);
+       else while (buf[-1] == '0')
                --buf;
 
        return buf;
@@ -990,7 +987,7 @@ int kptr_restrict __read_mostly;
  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
  * - 'MF' For a 6-byte MAC FDDI address, it prints the address
  *       with a dash-separated hex notation
- * - '[mM]R For a 6-byte MAC address, Reverse order (Bluetooth)
+ * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
  *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
  *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
@@ -1341,7 +1338,10 @@ qualifier:
  * %pR output the address range in a struct resource with decoded flags
  * %pr output the address range in a struct resource with raw flags
  * %pM output a 6-byte MAC address with colons
+ * %pMR output a 6-byte MAC address with colons in reversed order
+ * %pMF output a 6-byte MAC address with dashes
  * %pm output a 6-byte MAC address without colons
+ * %pmR output a 6-byte MAC address without colons in reversed order
  * %pI4 print an IPv4 address without leading zeros
  * %pi4 print an IPv4 address with leading zeros
  * %pI6 print an IPv6 address with colons
@@ -2017,7 +2017,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
        s16 field_width;
        bool is_sign;
 
-       while (*fmt && *str) {
+       while (*fmt) {
                /* skip any white space in format */
                /* white space in format matchs any amount of
                 * white space, including none, in the input.
@@ -2042,6 +2042,8 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                 * advance both strings to next white space
                 */
                if (*fmt == '*') {
+                       if (!*str)
+                               break;
                        while (!isspace(*fmt) && *fmt != '%' && *fmt)
                                fmt++;
                        while (!isspace(*str) && *str)
@@ -2070,7 +2072,17 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                        }
                }
 
-               if (!*fmt || !*str)
+               if (!*fmt)
+                       break;
+
+               if (*fmt == 'n') {
+                       /* return number of characters read so far */
+                       *va_arg(args, int *) = str - buf;
+                       ++fmt;
+                       continue;
+               }
+
+               if (!*str)
                        break;
 
                base = 10;
@@ -2103,13 +2115,6 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                        num++;
                }
                continue;
-               case 'n':
-                       /* return number of characters read so far */
-               {
-                       int *i = (int *)va_arg(args, int*);
-                       *i = str - buf;
-               }
-               continue;
                case 'o':
                        base = 8;
                        break;
@@ -2210,16 +2215,6 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                str = next;
        }
 
-       /*
-        * Now we've come all the way through so either the input string or the
-        * format ended. In the former case, there can be a %n at the current
-        * position in the format that needs to be filled.
-        */
-       if (*fmt == '%' && *(fmt + 1) == 'n') {
-               int *p = (int *)va_arg(args, int *);
-               *p = str - buf;
-       }
-
        return num;
 }
 EXPORT_SYMBOL(vsscanf);
index bb4be7435ce34bad95f11c5bb59c435aba38f64f..ddc5efb9c5bbe419d790f7e87af82ec7d30cffbc 100644 (file)
@@ -1370,7 +1370,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
 
 #ifdef CONFIG_SMP
 
-const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
+const char * const pcpu_fc_names[PCPU_FC_NR] __initconst = {
        [PCPU_FC_AUTO]  = "auto",
        [PCPU_FC_EMBED] = "embed",
        [PCPU_FC_PAGE]  = "page",
index 11339110271ef8296771a76f5aaebe7acf6b5230..33d3363658df78bc95b928202856a01ed7c54d77 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -498,14 +498,6 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 
 #endif
 
-#ifdef CONFIG_TRACING
-size_t slab_buffer_size(struct kmem_cache *cachep)
-{
-       return cachep->size;
-}
-EXPORT_SYMBOL(slab_buffer_size);
-#endif
-
 /*
  * Do not go above this order unless 0 objects fit into the slab or
  * overridden on the command line.
@@ -515,13 +507,6 @@ EXPORT_SYMBOL(slab_buffer_size);
 static int slab_max_order = SLAB_MAX_ORDER_LO;
 static bool slab_max_order_set __initdata;
 
-static inline struct kmem_cache *page_get_cache(struct page *page)
-{
-       page = compound_head(page);
-       BUG_ON(!PageSlab(page));
-       return page->slab_cache;
-}
-
 static inline struct kmem_cache *virt_to_cache(const void *obj)
 {
        struct page *page = virt_to_head_page(obj);
@@ -585,9 +570,9 @@ static struct arraycache_init initarray_generic =
     { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
-static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES];
-static struct kmem_cache cache_cache = {
-       .nodelists = cache_cache_nodelists,
+static struct kmem_list3 *kmem_cache_nodelists[MAX_NUMNODES];
+static struct kmem_cache kmem_cache_boot = {
+       .nodelists = kmem_cache_nodelists,
        .batchcount = 1,
        .limit = BOOT_CPUCACHE_ENTRIES,
        .shared = 1,
@@ -810,6 +795,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
        *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
+#if DEBUG
 #define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
 
 static void __slab_error(const char *function, struct kmem_cache *cachep,
@@ -818,7 +804,9 @@ static void __slab_error(const char *function, struct kmem_cache *cachep,
        printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
               function, cachep->name, msg);
        dump_stack();
+       add_taint(TAINT_BAD_PAGE);
 }
+#endif
 
 /*
  * By default on NUMA we use alien caches to stage the freeing of
@@ -1601,15 +1589,17 @@ void __init kmem_cache_init(void)
        int order;
        int node;
 
+       kmem_cache = &kmem_cache_boot;
+
        if (num_possible_nodes() == 1)
                use_alien_caches = 0;
 
        for (i = 0; i < NUM_INIT_LISTS; i++) {
                kmem_list3_init(&initkmem_list3[i]);
                if (i < MAX_NUMNODES)
-                       cache_cache.nodelists[i] = NULL;
+                       kmem_cache->nodelists[i] = NULL;
        }
-       set_up_list3s(&cache_cache, CACHE_CACHE);
+       set_up_list3s(kmem_cache, CACHE_CACHE);
 
        /*
         * Fragmentation resistance on low memory - only use bigger
@@ -1621,9 +1611,9 @@ void __init kmem_cache_init(void)
 
        /* Bootstrap is tricky, because several objects are allocated
         * from caches that do not exist yet:
-        * 1) initialize the cache_cache cache: it contains the struct
-        *    kmem_cache structures of all caches, except cache_cache itself:
-        *    cache_cache is statically allocated.
+        * 1) initialize the kmem_cache cache: it contains the struct
+        *    kmem_cache structures of all caches, except kmem_cache itself:
+        *    kmem_cache is statically allocated.
         *    Initially an __init data area is used for the head array and the
         *    kmem_list3 structures, it's replaced with a kmalloc allocated
         *    array at the end of the bootstrap.
@@ -1632,43 +1622,43 @@ void __init kmem_cache_init(void)
         *    An __init data area is used for the head array.
         * 3) Create the remaining kmalloc caches, with minimally sized
         *    head arrays.
-        * 4) Replace the __init data head arrays for cache_cache and the first
+        * 4) Replace the __init data head arrays for kmem_cache and the first
         *    kmalloc cache with kmalloc allocated arrays.
-        * 5) Replace the __init data for kmem_list3 for cache_cache and
+        * 5) Replace the __init data for kmem_list3 for kmem_cache and
         *    the other cache's with kmalloc allocated memory.
         * 6) Resize the head arrays of the kmalloc caches to their final sizes.
         */
 
        node = numa_mem_id();
 
-       /* 1) create the cache_cache */
+       /* 1) create the kmem_cache */
        INIT_LIST_HEAD(&slab_caches);
-       list_add(&cache_cache.list, &slab_caches);
-       cache_cache.colour_off = cache_line_size();
-       cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
-       cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
+       list_add(&kmem_cache->list, &slab_caches);
+       kmem_cache->colour_off = cache_line_size();
+       kmem_cache->array[smp_processor_id()] = &initarray_cache.cache;
+       kmem_cache->nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
 
        /*
         * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids
         */
-       cache_cache.size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
+       kmem_cache->size = offsetof(struct kmem_cache, array[nr_cpu_ids]) +
                                  nr_node_ids * sizeof(struct kmem_list3 *);
-       cache_cache.object_size = cache_cache.size;
-       cache_cache.size = ALIGN(cache_cache.size,
+       kmem_cache->object_size = kmem_cache->size;
+       kmem_cache->size = ALIGN(kmem_cache->object_size,
                                        cache_line_size());
-       cache_cache.reciprocal_buffer_size =
-               reciprocal_value(cache_cache.size);
+       kmem_cache->reciprocal_buffer_size =
+               reciprocal_value(kmem_cache->size);
 
        for (order = 0; order < MAX_ORDER; order++) {
-               cache_estimate(order, cache_cache.size,
-                       cache_line_size(), 0, &left_over, &cache_cache.num);
-               if (cache_cache.num)
+               cache_estimate(order, kmem_cache->size,
+                       cache_line_size(), 0, &left_over, &kmem_cache->num);
+               if (kmem_cache->num)
                        break;
        }
-       BUG_ON(!cache_cache.num);
-       cache_cache.gfporder = order;
-       cache_cache.colour = left_over / cache_cache.colour_off;
-       cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
+       BUG_ON(!kmem_cache->num);
+       kmem_cache->gfporder = order;
+       kmem_cache->colour = left_over / kmem_cache->colour_off;
+       kmem_cache->slab_size = ALIGN(kmem_cache->num * sizeof(kmem_bufctl_t) +
                                      sizeof(struct slab), cache_line_size());
 
        /* 2+3) create the kmalloc caches */
@@ -1681,19 +1671,22 @@ void __init kmem_cache_init(void)
         * bug.
         */
 
-       sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name,
-                                       sizes[INDEX_AC].cs_size,
-                                       ARCH_KMALLOC_MINALIGN,
-                                       ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-                                       NULL);
+       sizes[INDEX_AC].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+       sizes[INDEX_AC].cs_cachep->name = names[INDEX_AC].name;
+       sizes[INDEX_AC].cs_cachep->size = sizes[INDEX_AC].cs_size;
+       sizes[INDEX_AC].cs_cachep->object_size = sizes[INDEX_AC].cs_size;
+       sizes[INDEX_AC].cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+       __kmem_cache_create(sizes[INDEX_AC].cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
+       list_add(&sizes[INDEX_AC].cs_cachep->list, &slab_caches);
 
        if (INDEX_AC != INDEX_L3) {
-               sizes[INDEX_L3].cs_cachep =
-                       __kmem_cache_create(names[INDEX_L3].name,
-                               sizes[INDEX_L3].cs_size,
-                               ARCH_KMALLOC_MINALIGN,
-                               ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-                               NULL);
+               sizes[INDEX_L3].cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+               sizes[INDEX_L3].cs_cachep->name = names[INDEX_L3].name;
+               sizes[INDEX_L3].cs_cachep->size = sizes[INDEX_L3].cs_size;
+               sizes[INDEX_L3].cs_cachep->object_size = sizes[INDEX_L3].cs_size;
+               sizes[INDEX_L3].cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+               __kmem_cache_create(sizes[INDEX_L3].cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
+               list_add(&sizes[INDEX_L3].cs_cachep->list, &slab_caches);
        }
 
        slab_early_init = 0;
@@ -1707,20 +1700,23 @@ void __init kmem_cache_init(void)
                 * allow tighter packing of the smaller caches.
                 */
                if (!sizes->cs_cachep) {
-                       sizes->cs_cachep = __kmem_cache_create(names->name,
-                                       sizes->cs_size,
-                                       ARCH_KMALLOC_MINALIGN,
-                                       ARCH_KMALLOC_FLAGS|SLAB_PANIC,
-                                       NULL);
+                       sizes->cs_cachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+                       sizes->cs_cachep->name = names->name;
+                       sizes->cs_cachep->size = sizes->cs_size;
+                       sizes->cs_cachep->object_size = sizes->cs_size;
+                       sizes->cs_cachep->align = ARCH_KMALLOC_MINALIGN;
+                       __kmem_cache_create(sizes->cs_cachep, ARCH_KMALLOC_FLAGS|SLAB_PANIC);
+                       list_add(&sizes->cs_cachep->list, &slab_caches);
                }
 #ifdef CONFIG_ZONE_DMA
-               sizes->cs_dmacachep = __kmem_cache_create(
-                                       names->name_dma,
-                                       sizes->cs_size,
-                                       ARCH_KMALLOC_MINALIGN,
-                                       ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
-                                               SLAB_PANIC,
-                                       NULL);
+               sizes->cs_dmacachep = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+               sizes->cs_dmacachep->name = names->name_dma;
+               sizes->cs_dmacachep->size = sizes->cs_size;
+               sizes->cs_dmacachep->object_size = sizes->cs_size;
+               sizes->cs_dmacachep->align = ARCH_KMALLOC_MINALIGN;
+               __kmem_cache_create(sizes->cs_dmacachep,
+                              ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA| SLAB_PANIC);
+               list_add(&sizes->cs_dmacachep->list, &slab_caches);
 #endif
                sizes++;
                names++;
@@ -1731,15 +1727,15 @@ void __init kmem_cache_init(void)
 
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
 
-               BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
-               memcpy(ptr, cpu_cache_get(&cache_cache),
+               BUG_ON(cpu_cache_get(kmem_cache) != &initarray_cache.cache);
+               memcpy(ptr, cpu_cache_get(kmem_cache),
                       sizeof(struct arraycache_init));
                /*
                 * Do not assume that spinlocks can be initialized via memcpy:
                 */
                spin_lock_init(&ptr->lock);
 
-               cache_cache.array[smp_processor_id()] = ptr;
+               kmem_cache->array[smp_processor_id()] = ptr;
 
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);
 
@@ -1760,7 +1756,7 @@ void __init kmem_cache_init(void)
                int nid;
 
                for_each_online_node(nid) {
-                       init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
+                       init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
 
                        init_list(malloc_sizes[INDEX_AC].cs_cachep,
                                  &initkmem_list3[SIZE_AC + nid], nid);
@@ -1781,9 +1777,6 @@ void __init kmem_cache_init_late(void)
 
        slab_state = UP;
 
-       /* Annotate slab for lockdep -- annotate the malloc caches */
-       init_lock_keys();
-
        /* 6) resize the head arrays to their final sizes */
        mutex_lock(&slab_mutex);
        list_for_each_entry(cachep, &slab_caches, list)
@@ -1791,6 +1784,9 @@ void __init kmem_cache_init_late(void)
                        BUG();
        mutex_unlock(&slab_mutex);
 
+       /* Annotate slab for lockdep -- annotate the malloc caches */
+       init_lock_keys();
+
        /* Done! */
        slab_state = FULL;
 
@@ -2209,27 +2205,6 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp)
        }
 }
 
-static void __kmem_cache_destroy(struct kmem_cache *cachep)
-{
-       int i;
-       struct kmem_list3 *l3;
-
-       for_each_online_cpu(i)
-           kfree(cachep->array[i]);
-
-       /* NUMA: free the list3 structures */
-       for_each_online_node(i) {
-               l3 = cachep->nodelists[i];
-               if (l3) {
-                       kfree(l3->shared);
-                       free_alien_cache(l3->alien);
-                       kfree(l3);
-               }
-       }
-       kmem_cache_free(&cache_cache, cachep);
-}
-
-
 /**
  * calculate_slab_order - calculate size (page order) of slabs
  * @cachep: pointer to the cache that is being created
@@ -2366,9 +2341,6 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
  * Cannot be called within a int, but can be interrupted.
  * The @ctor is run when new pages are allocated by the cache.
  *
- * @name must be valid until the cache is destroyed. This implies that
- * the module calling this has to destroy the cache before getting unloaded.
- *
  * The flags are
  *
  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
@@ -2381,13 +2353,13 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
  * cacheline.  This can be beneficial if you're counting cycles as closely
  * as davem.
  */
-struct kmem_cache *
-__kmem_cache_create (const char *name, size_t size, size_t align,
-       unsigned long flags, void (*ctor)(void *))
+int
+__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 {
        size_t left_over, slab_size, ralign;
-       struct kmem_cache *cachep = NULL;
        gfp_t gfp;
+       int err;
+       size_t size = cachep->size;
 
 #if DEBUG
 #if FORCED_DEBUG
@@ -2459,8 +2431,8 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
                ralign = ARCH_SLAB_MINALIGN;
        }
        /* 3) caller mandated alignment */
-       if (ralign < align) {
-               ralign = align;
+       if (ralign < cachep->align) {
+               ralign = cachep->align;
        }
        /* disable debug if necessary */
        if (ralign > __alignof__(unsigned long long))
@@ -2468,21 +2440,14 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
        /*
         * 4) Store it.
         */
-       align = ralign;
+       cachep->align = ralign;
 
        if (slab_is_available())
                gfp = GFP_KERNEL;
        else
                gfp = GFP_NOWAIT;
 
-       /* Get cache's description obj. */
-       cachep = kmem_cache_zalloc(&cache_cache, gfp);
-       if (!cachep)
-               return NULL;
-
        cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids];
-       cachep->object_size = size;
-       cachep->align = align;
 #if DEBUG
 
        /*
@@ -2506,8 +2471,9 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
        }
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
        if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
-           && cachep->object_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) {
-               cachep->obj_offset += PAGE_SIZE - ALIGN(size, align);
+           && cachep->object_size > cache_line_size()
+           && ALIGN(size, cachep->align) < PAGE_SIZE) {
+               cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
                size = PAGE_SIZE;
        }
 #endif
@@ -2527,18 +2493,15 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
                 */
                flags |= CFLGS_OFF_SLAB;
 
-       size = ALIGN(size, align);
+       size = ALIGN(size, cachep->align);
 
-       left_over = calculate_slab_order(cachep, size, align, flags);
+       left_over = calculate_slab_order(cachep, size, cachep->align, flags);
+
+       if (!cachep->num)
+               return -E2BIG;
 
-       if (!cachep->num) {
-               printk(KERN_ERR
-                      "kmem_cache_create: couldn't create cache %s.\n", name);
-               kmem_cache_free(&cache_cache, cachep);
-               return NULL;
-       }
        slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
-                         + sizeof(struct slab), align);
+                         + sizeof(struct slab), cachep->align);
 
        /*
         * If the slab has been placed off-slab, and we have enough space then
@@ -2566,8 +2529,8 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
 
        cachep->colour_off = cache_line_size();
        /* Offset must be a multiple of the alignment. */
-       if (cachep->colour_off < align)
-               cachep->colour_off = align;
+       if (cachep->colour_off < cachep->align)
+               cachep->colour_off = cachep->align;
        cachep->colour = left_over / cachep->colour_off;
        cachep->slab_size = slab_size;
        cachep->flags = flags;
@@ -2588,12 +2551,11 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
                 */
                BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache));
        }
-       cachep->ctor = ctor;
-       cachep->name = name;
 
-       if (setup_cpu_cache(cachep, gfp)) {
-               __kmem_cache_destroy(cachep);
-               return NULL;
+       err = setup_cpu_cache(cachep, gfp);
+       if (err) {
+               __kmem_cache_shutdown(cachep);
+               return err;
        }
 
        if (flags & SLAB_DEBUG_OBJECTS) {
@@ -2606,9 +2568,7 @@ __kmem_cache_create (const char *name, size_t size, size_t align,
                slab_set_debugobj_lock_classes(cachep);
        }
 
-       /* cache setup completed, link it into the list */
-       list_add(&cachep->list, &slab_caches);
-       return cachep;
+       return 0;
 }
 
 #if DEBUG
@@ -2767,49 +2727,29 @@ int kmem_cache_shrink(struct kmem_cache *cachep)
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
-/**
- * kmem_cache_destroy - delete a cache
- * @cachep: the cache to destroy
- *
- * Remove a &struct kmem_cache object from the slab cache.
- *
- * It is expected this function will be called by a module when it is
- * unloaded.  This will remove the cache completely, and avoid a duplicate
- * cache being allocated each time a module is loaded and unloaded, if the
- * module doesn't have persistent in-kernel storage across loads and unloads.
- *
- * The cache must be empty before calling this function.
- *
- * The caller must guarantee that no one will allocate memory from the cache
- * during the kmem_cache_destroy().
- */
-void kmem_cache_destroy(struct kmem_cache *cachep)
+int __kmem_cache_shutdown(struct kmem_cache *cachep)
 {
-       BUG_ON(!cachep || in_interrupt());
+       int i;
+       struct kmem_list3 *l3;
+       int rc = __cache_shrink(cachep);
 
-       /* Find the cache in the chain of caches. */
-       get_online_cpus();
-       mutex_lock(&slab_mutex);
-       /*
-        * the chain is never empty, cache_cache is never destroyed
-        */
-       list_del(&cachep->list);
-       if (__cache_shrink(cachep)) {
-               slab_error(cachep, "Can't free all objects");
-               list_add(&cachep->list, &slab_caches);
-               mutex_unlock(&slab_mutex);
-               put_online_cpus();
-               return;
-       }
+       if (rc)
+               return rc;
 
-       if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
-               rcu_barrier();
+       for_each_online_cpu(i)
+           kfree(cachep->array[i]);
 
-       __kmem_cache_destroy(cachep);
-       mutex_unlock(&slab_mutex);
-       put_online_cpus();
+       /* NUMA: free the list3 structures */
+       for_each_online_node(i) {
+               l3 = cachep->nodelists[i];
+               if (l3) {
+                       kfree(l3->shared);
+                       free_alien_cache(l3->alien);
+                       kfree(l3);
+               }
+       }
+       return 0;
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 /*
  * Get the memory for a slab management obj.
@@ -3098,7 +3038,7 @@ static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
 }
 
 static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
-                                  void *caller)
+                                  unsigned long caller)
 {
        struct page *page;
        unsigned int objnr;
@@ -3118,7 +3058,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
                *dbg_redzone2(cachep, objp) = RED_INACTIVE;
        }
        if (cachep->flags & SLAB_STORE_USER)
-               *dbg_userword(cachep, objp) = caller;
+               *dbg_userword(cachep, objp) = (void *)caller;
 
        objnr = obj_to_index(cachep, slabp, objp);
 
@@ -3131,7 +3071,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
        if (cachep->flags & SLAB_POISON) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
                if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
-                       store_stackinfo(cachep, objp, (unsigned long)caller);
+                       store_stackinfo(cachep, objp, caller);
                        kernel_map_pages(virt_to_page(objp),
                                         cachep->size / PAGE_SIZE, 0);
                } else {
@@ -3285,7 +3225,7 @@ static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
 
 #if DEBUG
 static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
-                               gfp_t flags, void *objp, void *caller)
+                               gfp_t flags, void *objp, unsigned long caller)
 {
        if (!objp)
                return objp;
@@ -3302,7 +3242,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                poison_obj(cachep, objp, POISON_INUSE);
        }
        if (cachep->flags & SLAB_STORE_USER)
-               *dbg_userword(cachep, objp) = caller;
+               *dbg_userword(cachep, objp) = (void *)caller;
 
        if (cachep->flags & SLAB_RED_ZONE) {
                if (*dbg_redzone1(cachep, objp) != RED_INACTIVE ||
@@ -3343,7 +3283,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 
 static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
 {
-       if (cachep == &cache_cache)
+       if (cachep == kmem_cache)
                return false;
 
        return should_failslab(cachep->object_size, flags, cachep->flags);
@@ -3576,8 +3516,8 @@ done:
  * Fallback to other node is possible if __GFP_THISNODE is not set.
  */
 static __always_inline void *
-__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
-                  void *caller)
+slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
+                  unsigned long caller)
 {
        unsigned long save_flags;
        void *ptr;
@@ -3663,7 +3603,7 @@ __do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 #endif /* CONFIG_NUMA */
 
 static __always_inline void *
-__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
+slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller)
 {
        unsigned long save_flags;
        void *objp;
@@ -3799,7 +3739,7 @@ free_done:
  * be in this state _before_ it is released.  Called with disabled ints.
  */
 static inline void __cache_free(struct kmem_cache *cachep, void *objp,
-    void *caller)
+                               unsigned long caller)
 {
        struct array_cache *ac = cpu_cache_get(cachep);
 
@@ -3839,7 +3779,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
  */
 void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-       void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0));
+       void *ret = slab_alloc(cachep, flags, _RET_IP_);
 
        trace_kmem_cache_alloc(_RET_IP_, ret,
                               cachep->object_size, cachep->size, flags);
@@ -3850,14 +3790,14 @@ EXPORT_SYMBOL(kmem_cache_alloc);
 
 #ifdef CONFIG_TRACING
 void *
-kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags)
+kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size)
 {
        void *ret;
 
-       ret = __cache_alloc(cachep, flags, __builtin_return_address(0));
+       ret = slab_alloc(cachep, flags, _RET_IP_);
 
        trace_kmalloc(_RET_IP_, ret,
-                     size, slab_buffer_size(cachep), flags);
+                     size, cachep->size, flags);
        return ret;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_trace);
@@ -3866,8 +3806,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_trace);
 #ifdef CONFIG_NUMA
 void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
-       void *ret = __cache_alloc_node(cachep, flags, nodeid,
-                                      __builtin_return_address(0));
+       void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
 
        trace_kmem_cache_alloc_node(_RET_IP_, ret,
                                    cachep->object_size, cachep->size,
@@ -3878,17 +3817,17 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
 #ifdef CONFIG_TRACING
-void *kmem_cache_alloc_node_trace(size_t size,
-                                 struct kmem_cache *cachep,
+void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep,
                                  gfp_t flags,
-                                 int nodeid)
+                                 int nodeid,
+                                 size_t size)
 {
        void *ret;
 
-       ret = __cache_alloc_node(cachep, flags, nodeid,
-                                 __builtin_return_address(0));
+       ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
+
        trace_kmalloc_node(_RET_IP_, ret,
-                          size, slab_buffer_size(cachep),
+                          size, cachep->size,
                           flags, nodeid);
        return ret;
 }
@@ -3896,34 +3835,33 @@ EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
 #endif
 
 static __always_inline void *
-__do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller)
+__do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)
 {
        struct kmem_cache *cachep;
 
        cachep = kmem_find_general_cachep(size, flags);
        if (unlikely(ZERO_OR_NULL_PTR(cachep)))
                return cachep;
-       return kmem_cache_alloc_node_trace(size, cachep, flags, node);
+       return kmem_cache_alloc_node_trace(cachep, flags, node, size);
 }
 
 #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
 void *__kmalloc_node(size_t size, gfp_t flags, int node)
 {
-       return __do_kmalloc_node(size, flags, node,
-                       __builtin_return_address(0));
+       return __do_kmalloc_node(size, flags, node, _RET_IP_);
 }
 EXPORT_SYMBOL(__kmalloc_node);
 
 void *__kmalloc_node_track_caller(size_t size, gfp_t flags,
                int node, unsigned long caller)
 {
-       return __do_kmalloc_node(size, flags, node, (void *)caller);
+       return __do_kmalloc_node(size, flags, node, caller);
 }
 EXPORT_SYMBOL(__kmalloc_node_track_caller);
 #else
 void *__kmalloc_node(size_t size, gfp_t flags, int node)
 {
-       return __do_kmalloc_node(size, flags, node, NULL);
+       return __do_kmalloc_node(size, flags, node, 0);
 }
 EXPORT_SYMBOL(__kmalloc_node);
 #endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */
@@ -3936,7 +3874,7 @@ EXPORT_SYMBOL(__kmalloc_node);
  * @caller: function caller for debug tracking of the caller
  */
 static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
-                                         void *caller)
+                                         unsigned long caller)
 {
        struct kmem_cache *cachep;
        void *ret;
@@ -3949,9 +3887,9 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
        cachep = __find_general_cachep(size, flags);
        if (unlikely(ZERO_OR_NULL_PTR(cachep)))
                return cachep;
-       ret = __cache_alloc(cachep, flags, caller);
+       ret = slab_alloc(cachep, flags, caller);
 
-       trace_kmalloc((unsigned long) caller, ret,
+       trace_kmalloc(caller, ret,
                      size, cachep->size, flags);
 
        return ret;
@@ -3961,20 +3899,20 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
 #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING)
 void *__kmalloc(size_t size, gfp_t flags)
 {
-       return __do_kmalloc(size, flags, __builtin_return_address(0));
+       return __do_kmalloc(size, flags, _RET_IP_);
 }
 EXPORT_SYMBOL(__kmalloc);
 
 void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller)
 {
-       return __do_kmalloc(size, flags, (void *)caller);
+       return __do_kmalloc(size, flags, caller);
 }
 EXPORT_SYMBOL(__kmalloc_track_caller);
 
 #else
 void *__kmalloc(size_t size, gfp_t flags)
 {
-       return __do_kmalloc(size, flags, NULL);
+       return __do_kmalloc(size, flags, 0);
 }
 EXPORT_SYMBOL(__kmalloc);
 #endif
@@ -3995,7 +3933,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
        debug_check_no_locks_freed(objp, cachep->object_size);
        if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
                debug_check_no_obj_freed(objp, cachep->object_size);
-       __cache_free(cachep, objp, __builtin_return_address(0));
+       __cache_free(cachep, objp, _RET_IP_);
        local_irq_restore(flags);
 
        trace_kmem_cache_free(_RET_IP_, objp);
@@ -4026,7 +3964,7 @@ void kfree(const void *objp)
        debug_check_no_locks_freed(objp, c->object_size);
 
        debug_check_no_obj_freed(objp, c->object_size);
-       __cache_free(c, (void *)objp, __builtin_return_address(0));
+       __cache_free(c, (void *)objp, _RET_IP_);
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL(kfree);
index db7848caaa25a67b01a1d5318c48b92972722f5c..7deeb449a3013ea279fde16bf6935b9d23ba752a 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -25,9 +25,26 @@ extern enum slab_state slab_state;
 
 /* The slab cache mutex protects the management structures during changes */
 extern struct mutex slab_mutex;
+
+/* The list of all slab caches on the system */
 extern struct list_head slab_caches;
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+/* The slab cache that manages slab cache information */
+extern struct kmem_cache *kmem_cache;
+
+/* Functions provided by the slab allocators */
+extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags);
+
+#ifdef CONFIG_SLUB
+struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
        size_t align, unsigned long flags, void (*ctor)(void *));
+#else
+static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
+       size_t align, unsigned long flags, void (*ctor)(void *))
+{ return NULL; }
+#endif
+
+
+int __kmem_cache_shutdown(struct kmem_cache *);
 
 #endif
index aa3ca5bb01b55a097f1397a6a92728f81b3167a5..9c217255ac49374834689590f6e2bd9752e23da2 100644 (file)
 enum slab_state slab_state;
 LIST_HEAD(slab_caches);
 DEFINE_MUTEX(slab_mutex);
+struct kmem_cache *kmem_cache;
+
+#ifdef CONFIG_DEBUG_VM
+static int kmem_cache_sanity_check(const char *name, size_t size)
+{
+       struct kmem_cache *s = NULL;
+
+       if (!name || in_interrupt() || size < sizeof(void *) ||
+               size > KMALLOC_MAX_SIZE) {
+               pr_err("kmem_cache_create(%s) integrity check failed\n", name);
+               return -EINVAL;
+       }
+
+       list_for_each_entry(s, &slab_caches, list) {
+               char tmp;
+               int res;
+
+               /*
+                * This happens when the module gets unloaded and doesn't
+                * destroy its slab cache and no-one else reuses the vmalloc
+                * area of the module.  Print a warning.
+                */
+               res = probe_kernel_address(s->name, tmp);
+               if (res) {
+                       pr_err("Slab cache with size %d has lost its name\n",
+                              s->object_size);
+                       continue;
+               }
+
+               if (!strcmp(s->name, name)) {
+                       pr_err("%s (%s): Cache name already exists.\n",
+                              __func__, name);
+                       dump_stack();
+                       s = NULL;
+                       return -EINVAL;
+               }
+       }
+
+       WARN_ON(strchr(name, ' '));     /* It confuses parsers */
+       return 0;
+}
+#else
+static inline int kmem_cache_sanity_check(const char *name, size_t size)
+{
+       return 0;
+}
+#endif
 
 /*
  * kmem_cache_create - Create a cache.
@@ -52,68 +99,92 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align
                unsigned long flags, void (*ctor)(void *))
 {
        struct kmem_cache *s = NULL;
-
-#ifdef CONFIG_DEBUG_VM
-       if (!name || in_interrupt() || size < sizeof(void *) ||
-               size > KMALLOC_MAX_SIZE) {
-               printk(KERN_ERR "kmem_cache_create(%s) integrity check"
-                       " failed\n", name);
-               goto out;
-       }
-#endif
+       int err = 0;
 
        get_online_cpus();
        mutex_lock(&slab_mutex);
 
-#ifdef CONFIG_DEBUG_VM
-       list_for_each_entry(s, &slab_caches, list) {
-               char tmp;
-               int res;
+       if (!kmem_cache_sanity_check(name, size) == 0)
+               goto out_locked;
 
-               /*
-                * This happens when the module gets unloaded and doesn't
-                * destroy its slab cache and no-one else reuses the vmalloc
-                * area of the module.  Print a warning.
-                */
-               res = probe_kernel_address(s->name, tmp);
-               if (res) {
-                       printk(KERN_ERR
-                              "Slab cache with size %d has lost its name\n",
-                              s->object_size);
-                       continue;
-               }
 
-               if (!strcmp(s->name, name)) {
-                       printk(KERN_ERR "kmem_cache_create(%s): Cache name"
-                               " already exists.\n",
-                               name);
-                       dump_stack();
-                       s = NULL;
-                       goto oops;
+       s = __kmem_cache_alias(name, size, align, flags, ctor);
+       if (s)
+               goto out_locked;
+
+       s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL);
+       if (s) {
+               s->object_size = s->size = size;
+               s->align = align;
+               s->ctor = ctor;
+               s->name = kstrdup(name, GFP_KERNEL);
+               if (!s->name) {
+                       kmem_cache_free(kmem_cache, s);
+                       err = -ENOMEM;
+                       goto out_locked;
                }
-       }
 
-       WARN_ON(strchr(name, ' '));     /* It confuses parsers */
-#endif
+               err = __kmem_cache_create(s, flags);
+               if (!err) {
 
-       s = __kmem_cache_create(name, size, align, flags, ctor);
+                       s->refcount = 1;
+                       list_add(&s->list, &slab_caches);
 
-#ifdef CONFIG_DEBUG_VM
-oops:
-#endif
+               } else {
+                       kfree(s->name);
+                       kmem_cache_free(kmem_cache, s);
+               }
+       } else
+               err = -ENOMEM;
+
+out_locked:
        mutex_unlock(&slab_mutex);
        put_online_cpus();
 
-#ifdef CONFIG_DEBUG_VM
-out:
-#endif
-       if (!s && (flags & SLAB_PANIC))
-               panic("kmem_cache_create: Failed to create slab '%s'\n", name);
+       if (err) {
+
+               if (flags & SLAB_PANIC)
+                       panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n",
+                               name, err);
+               else {
+                       printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d",
+                               name, err);
+                       dump_stack();
+               }
+
+               return NULL;
+       }
 
        return s;
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
+void kmem_cache_destroy(struct kmem_cache *s)
+{
+       get_online_cpus();
+       mutex_lock(&slab_mutex);
+       s->refcount--;
+       if (!s->refcount) {
+               list_del(&s->list);
+
+               if (!__kmem_cache_shutdown(s)) {
+                       if (s->flags & SLAB_DESTROY_BY_RCU)
+                               rcu_barrier();
+
+                       kfree(s->name);
+                       kmem_cache_free(kmem_cache, s);
+               } else {
+                       list_add(&s->list, &slab_caches);
+                       printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n",
+                               s->name);
+                       dump_stack();
+               }
+       }
+       mutex_unlock(&slab_mutex);
+       put_online_cpus();
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
 int slab_is_available(void)
 {
        return slab_state >= UP;
index 45d4ca79933a84eec7e9e824f5d3117f3dc4dc64..a08e4681fd0d630ff212e299f5b657f71e48c4b0 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -194,7 +194,7 @@ static void *slob_new_pages(gfp_t gfp, int order, int node)
        void *page;
 
 #ifdef CONFIG_NUMA
-       if (node != -1)
+       if (node != NUMA_NO_NODE)
                page = alloc_pages_exact_node(node, gfp, order);
        else
 #endif
@@ -290,7 +290,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
                 * If there's a node specification, search for a partial
                 * page with a matching node id in the freelist.
                 */
-               if (node != -1 && page_to_nid(sp) != node)
+               if (node != NUMA_NO_NODE && page_to_nid(sp) != node)
                        continue;
 #endif
                /* Enough room on this page? */
@@ -425,7 +425,8 @@ out:
  * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend.
  */
 
-void *__kmalloc_node(size_t size, gfp_t gfp, int node)
+static __always_inline void *
+__do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
 {
        unsigned int *m;
        int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
@@ -446,7 +447,7 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node)
                *m = size;
                ret = (void *)m + align;
 
-               trace_kmalloc_node(_RET_IP_, ret,
+               trace_kmalloc_node(caller, ret,
                                   size, size + align, gfp, node);
        } else {
                unsigned int order = get_order(size);
@@ -460,15 +461,35 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node)
                        page->private = size;
                }
 
-               trace_kmalloc_node(_RET_IP_, ret,
+               trace_kmalloc_node(caller, ret,
                                   size, PAGE_SIZE << order, gfp, node);
        }
 
        kmemleak_alloc(ret, size, 1, gfp);
        return ret;
 }
+
+void *__kmalloc_node(size_t size, gfp_t gfp, int node)
+{
+       return __do_kmalloc_node(size, gfp, node, _RET_IP_);
+}
 EXPORT_SYMBOL(__kmalloc_node);
 
+#ifdef CONFIG_TRACING
+void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller)
+{
+       return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller);
+}
+
+#ifdef CONFIG_NUMA
+void *__kmalloc_node_track_caller(size_t size, gfp_t gfp,
+                                       int node, unsigned long caller)
+{
+       return __do_kmalloc_node(size, gfp, node, caller);
+}
+#endif
+#endif
+
 void kfree(const void *block)
 {
        struct page *sp;
@@ -508,44 +529,24 @@ size_t ksize(const void *block)
 }
 EXPORT_SYMBOL(ksize);
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
-       size_t align, unsigned long flags, void (*ctor)(void *))
+int __kmem_cache_create(struct kmem_cache *c, unsigned long flags)
 {
-       struct kmem_cache *c;
-
-       c = slob_alloc(sizeof(struct kmem_cache),
-               GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1);
+       size_t align = c->size;
 
-       if (c) {
-               c->name = name;
-               c->size = size;
-               if (flags & SLAB_DESTROY_BY_RCU) {
-                       /* leave room for rcu footer at the end of object */
-                       c->size += sizeof(struct slob_rcu);
-               }
-               c->flags = flags;
-               c->ctor = ctor;
-               /* ignore alignment unless it's forced */
-               c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
-               if (c->align < ARCH_SLAB_MINALIGN)
-                       c->align = ARCH_SLAB_MINALIGN;
-               if (c->align < align)
-                       c->align = align;
-
-               kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL);
-               c->refcount = 1;
+       if (flags & SLAB_DESTROY_BY_RCU) {
+               /* leave room for rcu footer at the end of object */
+               c->size += sizeof(struct slob_rcu);
        }
-       return c;
-}
+       c->flags = flags;
+       /* ignore alignment unless it's forced */
+       c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+       if (c->align < ARCH_SLAB_MINALIGN)
+               c->align = ARCH_SLAB_MINALIGN;
+       if (c->align < align)
+               c->align = align;
 
-void kmem_cache_destroy(struct kmem_cache *c)
-{
-       kmemleak_free(c);
-       if (c->flags & SLAB_DESTROY_BY_RCU)
-               rcu_barrier();
-       slob_free(c, sizeof(struct kmem_cache));
+       return 0;
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node)
 {
@@ -613,14 +614,28 @@ unsigned int kmem_cache_size(struct kmem_cache *c)
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
+int __kmem_cache_shutdown(struct kmem_cache *c)
+{
+       /* No way to check for remaining objects */
+       return 0;
+}
+
 int kmem_cache_shrink(struct kmem_cache *d)
 {
        return 0;
 }
 EXPORT_SYMBOL(kmem_cache_shrink);
 
+struct kmem_cache kmem_cache_boot = {
+       .name = "kmem_cache",
+       .size = sizeof(struct kmem_cache),
+       .flags = SLAB_PANIC,
+       .align = ARCH_KMALLOC_MINALIGN,
+};
+
 void __init kmem_cache_init(void)
 {
+       kmem_cache = &kmem_cache_boot;
        slab_state = UP;
 }
 
index 2fdd96f9e9986b4c1244c13fde954d586afa7952..a0d698467f706bd617b960240cbb775cdc9cd034 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -210,11 +210,7 @@ static void sysfs_slab_remove(struct kmem_cache *);
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
                                                        { return 0; }
-static inline void sysfs_slab_remove(struct kmem_cache *s)
-{
-       kfree(s->name);
-       kfree(s);
-}
+static inline void sysfs_slab_remove(struct kmem_cache *s) { }
 
 #endif
 
@@ -568,6 +564,8 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...)
        printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf);
        printk(KERN_ERR "----------------------------------------"
                        "-------------------------------------\n\n");
+
+       add_taint(TAINT_BAD_PAGE);
 }
 
 static void slab_fix(struct kmem_cache *s, char *fmt, ...)
@@ -624,7 +622,7 @@ static void object_err(struct kmem_cache *s, struct page *page,
        print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...)
+static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...)
 {
        va_list args;
        char buf[100];
@@ -1069,13 +1067,13 @@ bad:
        return 0;
 }
 
-static noinline int free_debug_processing(struct kmem_cache *s,
-                struct page *page, void *object, unsigned long addr)
+static noinline struct kmem_cache_node *free_debug_processing(
+       struct kmem_cache *s, struct page *page, void *object,
+       unsigned long addr, unsigned long *flags)
 {
-       unsigned long flags;
-       int rc = 0;
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
 
-       local_irq_save(flags);
+       spin_lock_irqsave(&n->list_lock, *flags);
        slab_lock(page);
 
        if (!check_slab(s, page))
@@ -1113,15 +1111,19 @@ static noinline int free_debug_processing(struct kmem_cache *s,
                set_track(s, object, TRACK_FREE, addr);
        trace(s, page, object, 0);
        init_object(s, object, SLUB_RED_INACTIVE);
-       rc = 1;
 out:
        slab_unlock(page);
-       local_irq_restore(flags);
-       return rc;
+       /*
+        * Keep node_lock to preserve integrity
+        * until the object is actually freed
+        */
+       return n;
 
 fail:
+       slab_unlock(page);
+       spin_unlock_irqrestore(&n->list_lock, *flags);
        slab_fix(s, "Object at 0x%p not freed", object);
-       goto out;
+       return NULL;
 }
 
 static int __init setup_slub_debug(char *str)
@@ -1214,8 +1216,9 @@ static inline void setup_object_debug(struct kmem_cache *s,
 static inline int alloc_debug_processing(struct kmem_cache *s,
        struct page *page, void *object, unsigned long addr) { return 0; }
 
-static inline int free_debug_processing(struct kmem_cache *s,
-       struct page *page, void *object, unsigned long addr) { return 0; }
+static inline struct kmem_cache_node *free_debug_processing(
+       struct kmem_cache *s, struct page *page, void *object,
+       unsigned long addr, unsigned long *flags) { return NULL; }
 
 static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
                        { return 1; }
@@ -1714,7 +1717,7 @@ static inline void note_cmpxchg_failure(const char *n,
        stat(s, CMPXCHG_DOUBLE_CPU_FAIL);
 }
 
-void init_kmem_cache_cpus(struct kmem_cache *s)
+static void init_kmem_cache_cpus(struct kmem_cache *s)
 {
        int cpu;
 
@@ -1939,7 +1942,7 @@ static void unfreeze_partials(struct kmem_cache *s)
  * If we did not find a slot then simply move all the partials to the
  * per node partial list.
  */
-int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
+static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
 {
        struct page *oldpage;
        int pages;
@@ -1962,6 +1965,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                                local_irq_save(flags);
                                unfreeze_partials(s);
                                local_irq_restore(flags);
+                               oldpage = NULL;
                                pobjects = 0;
                                pages = 0;
                                stat(s, CPU_PARTIAL_DRAIN);
@@ -2310,7 +2314,7 @@ new_slab:
  *
  * Otherwise we can simply pick the next object from the lockless free list.
  */
-static __always_inline void *slab_alloc(struct kmem_cache *s,
+static __always_inline void *slab_alloc_node(struct kmem_cache *s,
                gfp_t gfpflags, int node, unsigned long addr)
 {
        void **object;
@@ -2380,9 +2384,15 @@ redo:
        return object;
 }
 
+static __always_inline void *slab_alloc(struct kmem_cache *s,
+               gfp_t gfpflags, unsigned long addr)
+{
+       return slab_alloc_node(s, gfpflags, NUMA_NO_NODE, addr);
+}
+
 void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
 {
-       void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_);
+       void *ret = slab_alloc(s, gfpflags, _RET_IP_);
 
        trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags);
 
@@ -2393,7 +2403,7 @@ EXPORT_SYMBOL(kmem_cache_alloc);
 #ifdef CONFIG_TRACING
 void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
 {
-       void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_);
+       void *ret = slab_alloc(s, gfpflags, _RET_IP_);
        trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags);
        return ret;
 }
@@ -2411,7 +2421,7 @@ EXPORT_SYMBOL(kmalloc_order_trace);
 #ifdef CONFIG_NUMA
 void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
 {
-       void *ret = slab_alloc(s, gfpflags, node, _RET_IP_);
+       void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_);
 
        trace_kmem_cache_alloc_node(_RET_IP_, ret,
                                    s->object_size, s->size, gfpflags, node);
@@ -2425,7 +2435,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
                                    gfp_t gfpflags,
                                    int node, size_t size)
 {
-       void *ret = slab_alloc(s, gfpflags, node, _RET_IP_);
+       void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_);
 
        trace_kmalloc_node(_RET_IP_, ret,
                           size, s->size, gfpflags, node);
@@ -2457,7 +2467,8 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 
        stat(s, FREE_SLOWPATH);
 
-       if (kmem_cache_debug(s) && !free_debug_processing(s, page, x, addr))
+       if (kmem_cache_debug(s) &&
+               !(n = free_debug_processing(s, page, x, addr, &flags)))
                return;
 
        do {
@@ -2612,6 +2623,13 @@ void kmem_cache_free(struct kmem_cache *s, void *x)
 
        page = virt_to_head_page(x);
 
+       if (kmem_cache_debug(s) && page->slab != s) {
+               pr_err("kmem_cache_free: Wrong slab cache. %s but object"
+                       " is from  %s\n", page->slab->name, s->name);
+               WARN_ON_ONCE(1);
+               return;
+       }
+
        slab_free(s, page, x, _RET_IP_);
 
        trace_kmem_cache_free(_RET_IP_, x);
@@ -3026,17 +3044,9 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 
 }
 
-static int kmem_cache_open(struct kmem_cache *s,
-               const char *name, size_t size,
-               size_t align, unsigned long flags,
-               void (*ctor)(void *))
+static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
 {
-       memset(s, 0, kmem_size);
-       s->name = name;
-       s->ctor = ctor;
-       s->object_size = size;
-       s->align = align;
-       s->flags = kmem_cache_flags(size, flags, name, ctor);
+       s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor);
        s->reserved = 0;
 
        if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU))
@@ -3098,7 +3108,6 @@ static int kmem_cache_open(struct kmem_cache *s,
        else
                s->cpu_partial = 30;
 
-       s->refcount = 1;
 #ifdef CONFIG_NUMA
        s->remote_node_defrag_ratio = 1000;
 #endif
@@ -3106,16 +3115,16 @@ static int kmem_cache_open(struct kmem_cache *s,
                goto error;
 
        if (alloc_kmem_cache_cpus(s))
-               return 1;
+               return 0;
 
        free_kmem_cache_nodes(s);
 error:
        if (flags & SLAB_PANIC)
                panic("Cannot create slab %s size=%lu realsize=%u "
                        "order=%u offset=%u flags=%lx\n",
-                       s->name, (unsigned long)size, s->size, oo_order(s->oo),
+                       s->name, (unsigned long)s->size, s->size, oo_order(s->oo),
                        s->offset, flags);
-       return 0;
+       return -EINVAL;
 }
 
 /*
@@ -3137,7 +3146,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
                                     sizeof(long), GFP_ATOMIC);
        if (!map)
                return;
-       slab_err(s, page, "%s", text);
+       slab_err(s, page, text, s->name);
        slab_lock(page);
 
        get_map(s, page, map);
@@ -3169,7 +3178,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
                        discard_slab(s, page);
                } else {
                        list_slab_objects(s, page,
-                               "Objects remaining on kmem_cache_close()");
+                       "Objects remaining in %s on kmem_cache_close()");
                }
        }
 }
@@ -3182,7 +3191,6 @@ static inline int kmem_cache_close(struct kmem_cache *s)
        int node;
 
        flush_all(s);
-       free_percpu(s->cpu_slab);
        /* Attempt to free all objects */
        for_each_node_state(node, N_NORMAL_MEMORY) {
                struct kmem_cache_node *n = get_node(s, node);
@@ -3191,33 +3199,20 @@ static inline int kmem_cache_close(struct kmem_cache *s)
                if (n->nr_partial || slabs_node(s, node))
                        return 1;
        }
+       free_percpu(s->cpu_slab);
        free_kmem_cache_nodes(s);
        return 0;
 }
 
-/*
- * Close a cache and release the kmem_cache structure
- * (must be used for caches created using kmem_cache_create)
- */
-void kmem_cache_destroy(struct kmem_cache *s)
+int __kmem_cache_shutdown(struct kmem_cache *s)
 {
-       mutex_lock(&slab_mutex);
-       s->refcount--;
-       if (!s->refcount) {
-               list_del(&s->list);
-               mutex_unlock(&slab_mutex);
-               if (kmem_cache_close(s)) {
-                       printk(KERN_ERR "SLUB %s: %s called for cache that "
-                               "still has objects.\n", s->name, __func__);
-                       dump_stack();
-               }
-               if (s->flags & SLAB_DESTROY_BY_RCU)
-                       rcu_barrier();
+       int rc = kmem_cache_close(s);
+
+       if (!rc)
                sysfs_slab_remove(s);
-       } else
-               mutex_unlock(&slab_mutex);
+
+       return rc;
 }
-EXPORT_SYMBOL(kmem_cache_destroy);
 
 /********************************************************************
  *             Kmalloc subsystem
@@ -3226,8 +3221,6 @@ EXPORT_SYMBOL(kmem_cache_destroy);
 struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT];
 EXPORT_SYMBOL(kmalloc_caches);
 
-static struct kmem_cache *kmem_cache;
-
 #ifdef CONFIG_ZONE_DMA
 static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT];
 #endif
@@ -3273,14 +3266,17 @@ static struct kmem_cache *__init create_kmalloc_cache(const char *name,
 {
        struct kmem_cache *s;
 
-       s = kmem_cache_alloc(kmem_cache, GFP_NOWAIT);
+       s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT);
+
+       s->name = name;
+       s->size = s->object_size = size;
+       s->align = ARCH_KMALLOC_MINALIGN;
 
        /*
         * This function is called with IRQs disabled during early-boot on
         * single CPU so there's no need to take slab_mutex here.
         */
-       if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN,
-                                                               flags, NULL))
+       if (kmem_cache_open(s, flags))
                goto panic;
 
        list_add(&s->list, &slab_caches);
@@ -3362,7 +3358,7 @@ void *__kmalloc(size_t size, gfp_t flags)
        if (unlikely(ZERO_OR_NULL_PTR(s)))
                return s;
 
-       ret = slab_alloc(s, flags, NUMA_NO_NODE, _RET_IP_);
+       ret = slab_alloc(s, flags, _RET_IP_);
 
        trace_kmalloc(_RET_IP_, ret, size, s->size, flags);
 
@@ -3405,7 +3401,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
        if (unlikely(ZERO_OR_NULL_PTR(s)))
                return s;
 
-       ret = slab_alloc(s, flags, node, _RET_IP_);
+       ret = slab_alloc_node(s, flags, node, _RET_IP_);
 
        trace_kmalloc_node(_RET_IP_, ret, size, s->size, flags, node);
 
@@ -3482,7 +3478,7 @@ void kfree(const void *x)
        if (unlikely(!PageSlab(page))) {
                BUG_ON(!PageCompound(page));
                kmemleak_free(x);
-               put_page(page);
+               __free_pages(page, compound_order(page));
                return;
        }
        slab_free(page->slab, page, object, _RET_IP_);
@@ -3719,12 +3715,12 @@ void __init kmem_cache_init(void)
                slub_max_order = 0;
 
        kmem_size = offsetof(struct kmem_cache, node) +
-                               nr_node_ids * sizeof(struct kmem_cache_node *);
+                       nr_node_ids * sizeof(struct kmem_cache_node *);
 
        /* Allocate two kmem_caches from the page allocator */
        kmalloc_size = ALIGN(kmem_size, cache_line_size());
        order = get_order(2 * kmalloc_size);
-       kmem_cache = (void *)__get_free_pages(GFP_NOWAIT, order);
+       kmem_cache = (void *)__get_free_pages(GFP_NOWAIT | __GFP_ZERO, order);
 
        /*
         * Must first have the slab cache available for the allocations of the
@@ -3733,9 +3729,10 @@ void __init kmem_cache_init(void)
         */
        kmem_cache_node = (void *)kmem_cache + kmalloc_size;
 
-       kmem_cache_open(kmem_cache_node, "kmem_cache_node",
-               sizeof(struct kmem_cache_node),
-               0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+       kmem_cache_node->name = "kmem_cache_node";
+       kmem_cache_node->size = kmem_cache_node->object_size =
+               sizeof(struct kmem_cache_node);
+       kmem_cache_open(kmem_cache_node, SLAB_HWCACHE_ALIGN | SLAB_PANIC);
 
        hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
 
@@ -3743,8 +3740,10 @@ void __init kmem_cache_init(void)
        slab_state = PARTIAL;
 
        temp_kmem_cache = kmem_cache;
-       kmem_cache_open(kmem_cache, "kmem_cache", kmem_size,
-               0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+       kmem_cache->name = "kmem_cache";
+       kmem_cache->size = kmem_cache->object_size = kmem_size;
+       kmem_cache_open(kmem_cache, SLAB_HWCACHE_ALIGN | SLAB_PANIC);
+
        kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT);
        memcpy(kmem_cache, temp_kmem_cache, kmem_size);
 
@@ -3933,11 +3932,10 @@ static struct kmem_cache *find_mergeable(size_t size,
        return NULL;
 }
 
-struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
+struct kmem_cache *__kmem_cache_alias(const char *name, size_t size,
                size_t align, unsigned long flags, void (*ctor)(void *))
 {
        struct kmem_cache *s;
-       char *n;
 
        s = find_mergeable(size, align, flags, name, ctor);
        if (s) {
@@ -3951,36 +3949,29 @@ struct kmem_cache *__kmem_cache_create(const char *name, size_t size,
 
                if (sysfs_slab_alias(s, name)) {
                        s->refcount--;
-                       return NULL;
+                       s = NULL;
                }
-               return s;
        }
 
-       n = kstrdup(name, GFP_KERNEL);
-       if (!n)
-               return NULL;
+       return s;
+}
 
-       s = kmalloc(kmem_size, GFP_KERNEL);
-       if (s) {
-               if (kmem_cache_open(s, n,
-                               size, align, flags, ctor)) {
-                       int r;
+int __kmem_cache_create(struct kmem_cache *s, unsigned long flags)
+{
+       int err;
 
-                       list_add(&s->list, &slab_caches);
-                       mutex_unlock(&slab_mutex);
-                       r = sysfs_slab_add(s);
-                       mutex_lock(&slab_mutex);
+       err = kmem_cache_open(s, flags);
+       if (err)
+               return err;
 
-                       if (!r)
-                               return s;
+       mutex_unlock(&slab_mutex);
+       err = sysfs_slab_add(s);
+       mutex_lock(&slab_mutex);
 
-                       list_del(&s->list);
-                       kmem_cache_close(s);
-               }
-               kfree(s);
-       }
-       kfree(n);
-       return NULL;
+       if (err)
+               kmem_cache_close(s);
+
+       return err;
 }
 
 #ifdef CONFIG_SMP
@@ -4033,7 +4024,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller)
        if (unlikely(ZERO_OR_NULL_PTR(s)))
                return s;
 
-       ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, caller);
+       ret = slab_alloc(s, gfpflags, caller);
 
        /* Honor the call site pointer we received. */
        trace_kmalloc(caller, ret, size, s->size, gfpflags);
@@ -4063,7 +4054,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
        if (unlikely(ZERO_OR_NULL_PTR(s)))
                return s;
 
-       ret = slab_alloc(s, gfpflags, node, caller);
+       ret = slab_alloc_node(s, gfpflags, node, caller);
 
        /* Honor the call site pointer we received. */
        trace_kmalloc_node(caller, ret, size, s->size, gfpflags, node);
@@ -5210,14 +5201,6 @@ static ssize_t slab_attr_store(struct kobject *kobj,
        return err;
 }
 
-static void kmem_cache_release(struct kobject *kobj)
-{
-       struct kmem_cache *s = to_slab(kobj);
-
-       kfree(s->name);
-       kfree(s);
-}
-
 static const struct sysfs_ops slab_sysfs_ops = {
        .show = slab_attr_show,
        .store = slab_attr_store,
@@ -5225,7 +5208,6 @@ static const struct sysfs_ops slab_sysfs_ops = {
 
 static struct kobj_type slab_ktype = {
        .sysfs_ops = &slab_sysfs_ops,
-       .release = kmem_cache_release
 };
 
 static int uevent_filter(struct kset *kset, struct kobject *kobj)
index 8c7265afa29f2109b884907daa050b79f0b25f8b..dc3036cdcc6a60ac4e8bea6521279b2cff687bcb 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -105,6 +105,25 @@ void *memdup_user(const void __user *src, size_t len)
 }
 EXPORT_SYMBOL(memdup_user);
 
+static __always_inline void *__do_krealloc(const void *p, size_t new_size,
+                                          gfp_t flags)
+{
+       void *ret;
+       size_t ks = 0;
+
+       if (p)
+               ks = ksize(p);
+
+       if (ks >= new_size)
+               return (void *)p;
+
+       ret = kmalloc_track_caller(new_size, flags);
+       if (ret && p)
+               memcpy(ret, p, ks);
+
+       return ret;
+}
+
 /**
  * __krealloc - like krealloc() but don't free @p.
  * @p: object to reallocate memory for.
@@ -117,23 +136,11 @@ EXPORT_SYMBOL(memdup_user);
  */
 void *__krealloc(const void *p, size_t new_size, gfp_t flags)
 {
-       void *ret;
-       size_t ks = 0;
-
        if (unlikely(!new_size))
                return ZERO_SIZE_PTR;
 
-       if (p)
-               ks = ksize(p);
+       return __do_krealloc(p, new_size, flags);
 
-       if (ks >= new_size)
-               return (void *)p;
-
-       ret = kmalloc_track_caller(new_size, flags);
-       if (ret && p)
-               memcpy(ret, p, ks);
-
-       return ret;
 }
 EXPORT_SYMBOL(__krealloc);
 
@@ -157,7 +164,7 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
                return ZERO_SIZE_PTR;
        }
 
-       ret = __krealloc(p, new_size, flags);
+       ret = __do_krealloc(p, new_size, flags);
        if (ret && p != ret)
                kfree(p);
 
index b258da88f6756d4f3ad6d52c992f86fb5a23a93d..add69d0fd99d2b34025c0d8fb42f703ca6ea38c0 100644 (file)
@@ -105,7 +105,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb)
                return NULL;
        memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
        skb->mac_header += VLAN_HLEN;
-       skb_reset_mac_len(skb);
        return skb;
 }
 
@@ -139,6 +138,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
 
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
+       skb_reset_mac_len(skb);
+
        return skb;
 
 err_free:
index 821022a7214f544090eb8504bce180484bf0d79e..ddac1ee2ed205bea3fb5157ee8be43a650291b2f 100644 (file)
@@ -63,7 +63,7 @@
 
 #include "af_can.h"
 
-static __initdata const char banner[] = KERN_INFO
+static __initconst const char banner[] = KERN_INFO
        "can: controller area network core (" CAN_VERSION_STRING ")\n";
 
 MODULE_DESCRIPTION("Controller Area Network PF_CAN core");
index 151b7730c12c72e430d0e277af67ac4846e22f05..6f747582718ed28464b4eaa2bd45740939c13506 100644 (file)
@@ -77,7 +77,7 @@
                     (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
 
 #define CAN_BCM_VERSION CAN_VERSION
-static __initdata const char banner[] = KERN_INFO
+static __initconst const char banner[] = KERN_INFO
        "can: broadcast manager protocol (rev " CAN_BCM_VERSION " t)\n";
 
 MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
index 127879c55fb66f9d3e6698def42013c1561ab58b..1f5c9785a262e02748b844e325f510f7a8c08dcc 100644 (file)
@@ -58,7 +58,7 @@
 #include <net/sock.h>
 
 #define CAN_GW_VERSION "20101209"
-static __initdata const char banner[] =
+static __initconst const char banner[] =
        KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
 
 MODULE_DESCRIPTION("PF_CAN netlink gateway");
index 3e9c89356a939db3901d6ee664873691ac2accb1..5b0e3e330d97c6f4172bf52db70a4cee6b7f4247 100644 (file)
@@ -55,7 +55,7 @@
 #include <net/net_namespace.h>
 
 #define CAN_RAW_VERSION CAN_VERSION
-static __initdata const char banner[] =
+static __initconst const char banner[] =
        KERN_INFO "can: raw protocol (rev " CAN_RAW_VERSION ")\n";
 
 MODULE_DESCRIPTION("PF_CAN raw protocol");
index e65f2c856e06bcc6b40147576adb286a047bc37e..faf7cc3483fe0822c26be6b915061ee8fdd8be9a 100644 (file)
@@ -220,7 +220,7 @@ static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
        dn_rt_cache_flush(-1);
 }
 
-static const struct fib_rules_ops __net_initdata dn_fib_rules_ops_template = {
+static const struct fib_rules_ops __net_initconst dn_fib_rules_ops_template = {
        .family         = AF_DECnet,
        .rule_size      = sizeof(struct dn_fib_rule),
        .addr_size      = sizeof(u16),
index 274309d3aded0ffbf351dbf5f4ad128d87ff5a0b..26aa65d1fce49dfeaa45cbc02046218b5bc70453 100644 (file)
@@ -262,7 +262,7 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
        rt_cache_flush(ops->fro_net);
 }
 
-static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = {
+static const struct fib_rules_ops __net_initconst fib4_rules_ops_template = {
        .family         = AF_INET,
        .rule_size      = sizeof(struct fib4_rule),
        .addr_size      = sizeof(u32),
index 3509065e409ab2782fe23cc8a174e369f0da501d..267753060ffc5c7efe6a3e183113d8dc3fbb49e6 100644 (file)
@@ -314,6 +314,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
                    nfi->fib_scope == fi->fib_scope &&
                    nfi->fib_prefsrc == fi->fib_prefsrc &&
                    nfi->fib_priority == fi->fib_priority &&
+                   nfi->fib_type == fi->fib_type &&
                    memcmp(nfi->fib_metrics, fi->fib_metrics,
                           sizeof(u32) * RTAX_MAX) == 0 &&
                    ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 &&
@@ -833,6 +834,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
        fi->fib_flags = cfg->fc_flags;
        fi->fib_priority = cfg->fc_priority;
        fi->fib_prefsrc = cfg->fc_prefsrc;
+       fi->fib_type = cfg->fc_type;
 
        fi->fib_nhs = nhs;
        change_nexthops(fi) {
index 1daa95c2a0bad8e532181dc4d67d4aead0f3671f..6168c4dc58b1db546c567ef0c55842ab42edee16 100644 (file)
@@ -221,7 +221,7 @@ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
        return 0;
 }
 
-static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = {
+static const struct fib_rules_ops __net_initconst ipmr_rules_ops_template = {
        .family         = RTNL_FAMILY_IPMR,
        .rule_size      = sizeof(struct ipmr_rule),
        .addr_size      = sizeof(u32),
index 480e68422efb3c0f3ff7267ac89b8fe2b0d42fee..d7c56f8a5b4e76028ebd4f66e5a928ea4ea0887e 100644 (file)
@@ -1769,14 +1769,6 @@ static void sit_route_add(struct net_device *dev)
 }
 #endif
 
-static void addrconf_add_lroute(struct net_device *dev)
-{
-       struct in6_addr addr;
-
-       ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
-       addrconf_prefix_route(&addr, 64, dev, 0, 0);
-}
-
 static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
 {
        struct inet6_dev *idev;
@@ -1794,8 +1786,6 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
        if (!(dev->flags & IFF_LOOPBACK))
                addrconf_add_mroute(dev);
 
-       /* Add link local route */
-       addrconf_add_lroute(dev);
        return idev;
 }
 
@@ -2474,10 +2464,9 @@ static void addrconf_sit_config(struct net_device *dev)
 
        sit_add_v4_addrs(idev);
 
-       if (dev->flags&IFF_POINTOPOINT) {
+       if (dev->flags&IFF_POINTOPOINT)
                addrconf_add_mroute(dev);
-               addrconf_add_lroute(dev);
-       } else
+       else
                sit_route_add(dev);
 }
 #endif
index 4be23da32b89c14ef19d5b0b349c244e33b881cd..ff76eecfd622ed80115fe691f9901739e7c7c0da 100644 (file)
@@ -79,7 +79,7 @@ struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl)
 
 #define IPV6_ADDR_LABEL_DEFAULT        0xffffffffUL
 
-static const __net_initdata struct ip6addrlbl_init_table
+static const __net_initconst struct ip6addrlbl_init_table
 {
        const struct in6_addr *prefix;
        int prefixlen;
index 0ff1cfd55bc4949fc02bf9dcef30fca58727c308..d9fb9110f607e8c587667147739979f34d52bc0a 100644 (file)
@@ -238,7 +238,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
               + nla_total_size(16); /* src */
 }
 
-static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = {
+static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
        .family                 = AF_INET6,
        .rule_size              = sizeof(struct fib6_rule),
        .addr_size              = sizeof(struct in6_addr),
index 08ea3f0b6e55f9557ec1e919e77f1496ccb1fdf1..f7c7c6319720246f67f3cdbf09daea76634df0ba 100644 (file)
@@ -205,7 +205,7 @@ static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
        return 0;
 }
 
-static const struct fib_rules_ops __net_initdata ip6mr_rules_ops_template = {
+static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
        .family         = RTNL_FAMILY_IP6MR,
        .rule_size      = sizeof(struct ip6mr_rule),
        .addr_size      = sizeof(struct in6_addr),
index d1ddbc6ddac50907ea22983be8fdf3389967b39a..7c7e963260e1792be01a329d4298dc1123c8f738 100644 (file)
@@ -1593,17 +1593,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
        struct fib6_table *table;
        struct net *net = dev_net(rt->dst.dev);
 
-       if (rt == net->ipv6.ip6_null_entry)
-               return -ENOENT;
+       if (rt == net->ipv6.ip6_null_entry) {
+               err = -ENOENT;
+               goto out;
+       }
 
        table = rt->rt6i_table;
        write_lock_bh(&table->tb6_lock);
-
        err = fib6_del(rt, info);
-       dst_release(&rt->dst);
-
        write_unlock_bh(&table->tb6_lock);
 
+out:
+       dst_release(&rt->dst);
        return err;
 }
 
index bb738c9f91461df7fb3d718a1ed6b771dae33f1a..b833677d83d6293724ba2d9948b37c9dbf472694 100644 (file)
@@ -468,7 +468,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
        notify_t notify;
 
        if (self->tsap) {
-               IRDA_WARNING("%s: busy!\n", __func__);
+               IRDA_DEBUG(0, "%s: busy!\n", __func__);
                return -EBUSY;
        }
 
index 5c93f2952b082b6fa5ef6c0bc8211dfdb68f3693..1002e3396f7287049b41c53e4aaa5cdc285a73e6 100644 (file)
@@ -440,7 +440,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
         */
        lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
        if (lsap == NULL) {
-               IRDA_WARNING("%s: unable to allocate LSAP!!\n", __func__);
+               IRDA_DEBUG(0, "%s: unable to allocate LSAP!!\n", __func__);
                return NULL;
        }
 
index 40f056debf9aaecd1fc7993a186a21230a111856..63e4cdc92376eb20e0569c34a5c167d1332c4e78 100644 (file)
@@ -497,15 +497,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
        pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
 
        if (!addr || len < sizeof(struct sockaddr_nfc) ||
-           addr->sa_family != AF_NFC) {
-               pr_err("Invalid socket\n");
+           addr->sa_family != AF_NFC)
                return -EINVAL;
-       }
 
-       if (addr->service_name_len == 0 && addr->dsap == 0) {
-               pr_err("Missing service name or dsap\n");
+       if (addr->service_name_len == 0 && addr->dsap == 0)
                return -EINVAL;
-       }
 
        pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx,
                 addr->target_idx, addr->nfc_protocol);
index 25dfe7380479e9598e5732a753349e324aea463a..8bd3c279427ef773ab1779a9d643d0fc1af2a183 100644 (file)
@@ -68,8 +68,8 @@
 static int sctp_rcv_ootb(struct sk_buff *);
 static struct sctp_association *__sctp_rcv_lookup(struct net *net,
                                      struct sk_buff *skb,
-                                     const union sctp_addr *laddr,
                                      const union sctp_addr *paddr,
+                                     const union sctp_addr *laddr,
                                      struct sctp_transport **transportp);
 static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
                                                const union sctp_addr *laddr);
index d16632e1503a56a4c592157936ab568a2be3a3a4..1b4a7f8ec3fd9186fdb6f6fd7cbfb1e9956c29cb 100644 (file)
@@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
 static void sctp_check_transmitted(struct sctp_outq *q,
                                   struct list_head *transmitted_queue,
                                   struct sctp_transport *transport,
+                                  union sctp_addr *saddr,
                                   struct sctp_sackhdr *sack,
                                   __u32 *highest_new_tsn);
 
@@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc,
  * Process the SACK against the outqueue.  Mostly, this just frees
  * things off the transmitted queue.
  */
-int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
+int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
 {
        struct sctp_association *asoc = q->asoc;
+       struct sctp_sackhdr *sack = chunk->subh.sack_hdr;
        struct sctp_transport *transport;
        struct sctp_chunk *tchunk = NULL;
        struct list_head *lchunk, *transport_list, *temp;
@@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
        /* Run through the retransmit queue.  Credit bytes received
         * and free those chunks that we can.
         */
-       sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn);
+       sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn);
 
        /* Run through the transmitted queue.
         * Credit bytes received and free those chunks which we can.
@@ -1219,7 +1221,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
         */
        list_for_each_entry(transport, transport_list, transports) {
                sctp_check_transmitted(q, &transport->transmitted,
-                                      transport, sack, &highest_new_tsn);
+                                      transport, &chunk->source, sack,
+                                      &highest_new_tsn);
                /*
                 * SFR-CACC algorithm:
                 * C) Let count_of_newacks be the number of
@@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q)
 static void sctp_check_transmitted(struct sctp_outq *q,
                                   struct list_head *transmitted_queue,
                                   struct sctp_transport *transport,
+                                  union sctp_addr *saddr,
                                   struct sctp_sackhdr *sack,
                                   __u32 *highest_new_tsn_in_sack)
 {
@@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                        /* Mark the destination transport address as
                         * active if it is not so marked.
                         */
-                       if ((transport->state == SCTP_INACTIVE) ||
-                           (transport->state == SCTP_UNCONFIRMED)) {
+                       if ((transport->state == SCTP_INACTIVE ||
+                            transport->state == SCTP_UNCONFIRMED) &&
+                           sctp_cmp_addr_exact(&transport->ipaddr, saddr)) {
                                sctp_assoc_control_transport(
                                        transport->asoc,
                                        transport,
index bcfebb91559d1d9e9a0b6472986f626021a3f358..57f7de839b038b8a6ae626820dd4a63e4ef0b384 100644 (file)
@@ -752,11 +752,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
 /* Helper function to process the process SACK command.  */
 static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
                                 struct sctp_association *asoc,
-                                struct sctp_sackhdr *sackh)
+                                struct sctp_chunk *chunk)
 {
        int err = 0;
 
-       if (sctp_outq_sack(&asoc->outqueue, sackh)) {
+       if (sctp_outq_sack(&asoc->outqueue, chunk)) {
                struct net *net = sock_net(asoc->base.sk);
 
                /* There are no more TSNs awaiting SACK.  */
index 094813b6c3c3cb99dddf407eeb93a2397a676cae..b6adef8a1e938d22b5cab026597e6f82c917794d 100644 (file)
@@ -3179,7 +3179,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net,
                return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
 
        /* Return this SACK for further processing.  */
-       sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh));
+       sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk));
 
        /* Note: We do the rest of the work on the PROCESS_SACK
         * sideeffect.
index 09dc5b97e07957d2ebb737cf402202efaf7c78ab..fd5f042dbff4d8a8a47c2a532e0d0ac5d0a70cd2 100644 (file)
@@ -220,6 +220,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
 
        sock_init_data(sock, sk);
        sk->sk_backlog_rcv = backlog_rcv;
+       sk->sk_rcvbuf = TIPC_FLOW_CONTROL_WIN * 2 * TIPC_MAX_USER_MSG_SIZE * 2;
        tipc_sk(sk)->p = tp_ptr;
        tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT;
 
index 6a3ee981931d3c2b4438cff1d220ec2e8039bd7e..afa44595f34868184bef73440f0c68f71c538452 100644 (file)
@@ -209,7 +209,7 @@ endif
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
 # in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
 
 # Find any prerequisites that is newer than target or that does not exist.
 # PHONY targets skipped in both cases.
index ca05ba217f5fd4038bcc511adff8a5b95823fb3e..21a9f5de0a2120c26b5f3bd0e70529078766a247 100755 (executable)
@@ -421,7 +421,7 @@ sub top_of_kernel_tree {
                }
        }
        return 1;
-    }
+}
 
 sub parse_email {
        my ($formatted_email) = @_;
@@ -1386,6 +1386,8 @@ sub process {
        my $in_header_lines = 1;
        my $in_commit_log = 0;          #Scanning lines before patch
 
+       my $non_utf8_charset = 0;
+
        our @report = ();
        our $cnt_lines = 0;
        our $cnt_error = 0;
@@ -1686,10 +1688,17 @@ sub process {
                        $in_commit_log = 1;
                }
 
-# Still not yet in a patch, check for any UTF-8
-               if ($in_commit_log && $realfile =~ /^$/ &&
+# Check if there is UTF-8 in a commit log when a mail header has explicitly
+# declined it, i.e defined some charset where it is missing.
+               if ($in_header_lines &&
+                   $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
+                   $1 !~ /utf-8/i) {
+                       $non_utf8_charset = 1;
+               }
+
+               if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
                    $rawline =~ /$NON_ASCII_UTF8/) {
-                       CHK("UTF8_BEFORE_PATCH",
+                       WARN("UTF8_BEFORE_PATCH",
                            "8-bit UTF-8 used in possible commit log\n" . $herecurr);
                }
 
@@ -1873,6 +1882,20 @@ sub process {
                            "No space is necessary after a cast\n" . $hereprev);
                }
 
+               if ($realfile =~ m@^(drivers/net/|net/)@ &&
+                   $rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
+                   $prevrawline =~ /^\+[ \t]*$/) {
+                       WARN("NETWORKING_BLOCK_COMMENT_STYLE",
+                            "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
+               }
+
+               if ($realfile =~ m@^(drivers/net/|net/)@ &&
+                   $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
+                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
+                       WARN("NETWORKING_BLOCK_COMMENT_STYLE",
+                            "networking block comments put the trailing */ on a separate line\n" . $herecurr);
+               }
+
 # check for spaces at the beginning of a line.
 # Exceptions:
 #  1) within comments
@@ -2390,8 +2413,10 @@ sub process {
                        my $orig = $1;
                        my $level = lc($orig);
                        $level = "warn" if ($level eq "warning");
+                       my $level2 = $level;
+                       $level2 = "dbg" if ($level eq "debug");
                        WARN("PREFER_PR_LEVEL",
-                            "Prefer pr_$level(... to printk(KERN_$1, ...\n" . $herecurr);
+                            "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
                }
 
                if ($line =~ /\bpr_warning\s*\(/) {
@@ -2947,7 +2972,7 @@ sub process {
                        my $exceptions = qr{
                                $Declare|
                                module_param_named|
-                               MODULE_PARAM_DESC|
+                               MODULE_PARM_DESC|
                                DECLARE_PER_CPU|
                                DEFINE_PER_CPU|
                                __typeof__\(|
index 8fd107a3fac49e32a0879549e88546d7f7f594dd..01e8a8e2260283d4551432406cb91d9b6e8e97cf 100755 (executable)
@@ -230,6 +230,7 @@ my $dohighlight = "";
 
 my $verbose = 0;
 my $output_mode = "man";
+my $output_preformatted = 0;
 my $no_doc_sections = 0;
 my %highlights = %highlights_man;
 my $blankline = $blankline_man;
@@ -280,9 +281,10 @@ my $doc_special = "\@\%\$\&";
 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
 my $doc_end = '\*/';
 my $doc_com = '\s*\*\s*';
+my $doc_com_body = '\s*\* ?';
 my $doc_decl = $doc_com . '(\w+)';
 my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
-my $doc_content = $doc_com . '(.*)';
+my $doc_content = $doc_com_body . '(.*)';
 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
 
 my %constants;
@@ -459,8 +461,13 @@ sub output_highlight {
 #   print STDERR "contents af:$contents\n";
 
     foreach $line (split "\n", $contents) {
+       if (! $output_preformatted) {
+           $line =~ s/^\s*//;
+       }
        if ($line eq ""){
-           print $lineprefix, local_unescape($blankline);
+           if (! $output_preformatted) {
+               print $lineprefix, local_unescape($blankline);
+           }
        } else {
            $line =~ s/\\\\\\/\&/g;
            if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
@@ -643,10 +650,12 @@ sub output_section_xml(%) {
        print "<title>$section</title>\n";
        if ($section =~ m/EXAMPLE/i) {
            print "<informalexample><programlisting>\n";
+           $output_preformatted = 1;
        } else {
            print "<para>\n";
        }
        output_highlight($args{'sections'}{$section});
+       $output_preformatted = 0;
        if ($section =~ m/EXAMPLE/i) {
            print "</programlisting></informalexample>\n";
        } else {
@@ -949,10 +958,12 @@ sub output_blockhead_xml(%) {
        }
        if ($section =~ m/EXAMPLE/i) {
            print "<example><para>\n";
+           $output_preformatted = 1;
        } else {
            print "<para>\n";
        }
        output_highlight($args{'sections'}{$section});
+       $output_preformatted = 0;
        if ($section =~ m/EXAMPLE/i) {
            print "</para></example>\n";
        } else {
@@ -1028,10 +1039,12 @@ sub output_function_gnome {
        print "<simplesect>\n <title>$section</title>\n";
        if ($section =~ m/EXAMPLE/i) {
            print "<example><programlisting>\n";
+           $output_preformatted = 1;
        } else {
        }
        print "<para>\n";
        output_highlight($args{'sections'}{$section});
+       $output_preformatted = 0;
        print "</para>\n";
        if ($section =~ m/EXAMPLE/i) {
            print "</programlisting></example>\n";
@@ -2046,6 +2059,9 @@ sub process_file($) {
 
     $section_counter = 0;
     while (<IN>) {
+       while (s/\\\s*$//) {
+           $_ .= <IN>;
+       }
        if ($state == 0) {
            if (/$doc_start/o) {
                $state = 1;             # next line is always the function name
@@ -2073,7 +2089,7 @@ sub process_file($) {
                    $descr= $1;
                    $descr =~ s/^\s*//;
                    $descr =~ s/\s*$//;
-                   $descr =~ s/\s+/ /;
+                   $descr =~ s/\s+/ /g;
                    $declaration_purpose = xml_escape($descr);
                    $in_purpose = 1;
                } else {
@@ -2165,6 +2181,7 @@ sub process_file($) {
                    # Continued declaration purpose
                    chomp($declaration_purpose);
                    $declaration_purpose .= " " . xml_escape($1);
+                   $declaration_purpose =~ s/\s+/ /g;
                } else {
                    $contents .= $1 . "\n";
                }
index 4b877a92a7ea3dc3a0307f5c5efb9e78c3289b17..44dfc415a379afc9c327388664e949bfcc855bcb 100644 (file)
 static DEFINE_MUTEX(devcgroup_mutex);
 
 /*
- * whitelist locking rules:
+ * exception list locking rules:
  * hold devcgroup_mutex for update/read.
  * hold rcu_read_lock() for read.
  */
 
-struct dev_whitelist_item {
+struct dev_exception_item {
        u32 major, minor;
        short type;
        short access;
@@ -41,7 +41,8 @@ struct dev_whitelist_item {
 
 struct dev_cgroup {
        struct cgroup_subsys_state css;
-       struct list_head whitelist;
+       struct list_head exceptions;
+       bool deny_all;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -74,12 +75,12 @@ static int devcgroup_can_attach(struct cgroup *new_cgrp,
 /*
  * called under devcgroup_mutex
  */
-static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
+static int dev_exceptions_copy(struct list_head *dest, struct list_head *orig)
 {
-       struct dev_whitelist_item *wh, *tmp, *new;
+       struct dev_exception_item *ex, *tmp, *new;
 
-       list_for_each_entry(wh, orig, list) {
-               new = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
+       list_for_each_entry(ex, orig, list) {
+               new = kmemdup(ex, sizeof(*ex), GFP_KERNEL);
                if (!new)
                        goto free_and_exit;
                list_add_tail(&new->list, dest);
@@ -88,64 +89,60 @@ static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
        return 0;
 
 free_and_exit:
-       list_for_each_entry_safe(wh, tmp, dest, list) {
-               list_del(&wh->list);
-               kfree(wh);
+       list_for_each_entry_safe(ex, tmp, dest, list) {
+               list_del(&ex->list);
+               kfree(ex);
        }
        return -ENOMEM;
 }
 
-/* Stupid prototype - don't bother combining existing entries */
 /*
  * called under devcgroup_mutex
  */
-static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
-                       struct dev_whitelist_item *wh)
+static int dev_exception_add(struct dev_cgroup *dev_cgroup,
+                            struct dev_exception_item *ex)
 {
-       struct dev_whitelist_item *whcopy, *walk;
+       struct dev_exception_item *excopy, *walk;
 
-       whcopy = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
-       if (!whcopy)
+       excopy = kmemdup(ex, sizeof(*ex), GFP_KERNEL);
+       if (!excopy)
                return -ENOMEM;
 
-       list_for_each_entry(walk, &dev_cgroup->whitelist, list) {
-               if (walk->type != wh->type)
+       list_for_each_entry(walk, &dev_cgroup->exceptions, list) {
+               if (walk->type != ex->type)
                        continue;
-               if (walk->major != wh->major)
+               if (walk->major != ex->major)
                        continue;
-               if (walk->minor != wh->minor)
+               if (walk->minor != ex->minor)
                        continue;
 
-               walk->access |= wh->access;
-               kfree(whcopy);
-               whcopy = NULL;
+               walk->access |= ex->access;
+               kfree(excopy);
+               excopy = NULL;
        }
 
-       if (whcopy != NULL)
-               list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
+       if (excopy != NULL)
+               list_add_tail_rcu(&excopy->list, &dev_cgroup->exceptions);
        return 0;
 }
 
 /*
  * called under devcgroup_mutex
  */
-static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
-                       struct dev_whitelist_item *wh)
+static void dev_exception_rm(struct dev_cgroup *dev_cgroup,
+                            struct dev_exception_item *ex)
 {
-       struct dev_whitelist_item *walk, *tmp;
+       struct dev_exception_item *walk, *tmp;
 
-       list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
-               if (walk->type == DEV_ALL)
-                       goto remove;
-               if (walk->type != wh->type)
+       list_for_each_entry_safe(walk, tmp, &dev_cgroup->exceptions, list) {
+               if (walk->type != ex->type)
                        continue;
-               if (walk->major != ~0 && walk->major != wh->major)
+               if (walk->major != ex->major)
                        continue;
-               if (walk->minor != ~0 && walk->minor != wh->minor)
+               if (walk->minor != ex->minor)
                        continue;
 
-remove:
-               walk->access &= ~wh->access;
+               walk->access &= ~ex->access;
                if (!walk->access) {
                        list_del_rcu(&walk->list);
                        kfree_rcu(walk, rcu);
@@ -153,6 +150,22 @@ remove:
        }
 }
 
+/**
+ * dev_exception_clean - frees all entries of the exception list
+ * @dev_cgroup: dev_cgroup with the exception list to be cleaned
+ *
+ * called under devcgroup_mutex
+ */
+static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
+{
+       struct dev_exception_item *ex, *tmp;
+
+       list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
+               list_del(&ex->list);
+               kfree(ex);
+       }
+}
+
 /*
  * called from kernel/cgroup.c with cgroup_lock() held.
  */
@@ -165,25 +178,17 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
        dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
        if (!dev_cgroup)
                return ERR_PTR(-ENOMEM);
-       INIT_LIST_HEAD(&dev_cgroup->whitelist);
+       INIT_LIST_HEAD(&dev_cgroup->exceptions);
        parent_cgroup = cgroup->parent;
 
-       if (parent_cgroup == NULL) {
-               struct dev_whitelist_item *wh;
-               wh = kmalloc(sizeof(*wh), GFP_KERNEL);
-               if (!wh) {
-                       kfree(dev_cgroup);
-                       return ERR_PTR(-ENOMEM);
-               }
-               wh->minor = wh->major = ~0;
-               wh->type = DEV_ALL;
-               wh->access = ACC_MASK;
-               list_add(&wh->list, &dev_cgroup->whitelist);
-       } else {
+       if (parent_cgroup == NULL)
+               dev_cgroup->deny_all = false;
+       else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
                mutex_lock(&devcgroup_mutex);
-               ret = dev_whitelist_copy(&dev_cgroup->whitelist,
-                               &parent_dev_cgroup->whitelist);
+               ret = dev_exceptions_copy(&dev_cgroup->exceptions,
+                                         &parent_dev_cgroup->exceptions);
+               dev_cgroup->deny_all = parent_dev_cgroup->deny_all;
                mutex_unlock(&devcgroup_mutex);
                if (ret) {
                        kfree(dev_cgroup);
@@ -197,13 +202,9 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
 static void devcgroup_destroy(struct cgroup *cgroup)
 {
        struct dev_cgroup *dev_cgroup;
-       struct dev_whitelist_item *wh, *tmp;
 
        dev_cgroup = cgroup_to_devcgroup(cgroup);
-       list_for_each_entry_safe(wh, tmp, &dev_cgroup->whitelist, list) {
-               list_del(&wh->list);
-               kfree(wh);
-       }
+       dev_exception_clean(dev_cgroup);
        kfree(dev_cgroup);
 }
 
@@ -249,59 +250,87 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
                                struct seq_file *m)
 {
        struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
-       struct dev_whitelist_item *wh;
+       struct dev_exception_item *ex;
        char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
 
        rcu_read_lock();
-       list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
-               set_access(acc, wh->access);
-               set_majmin(maj, wh->major);
-               set_majmin(min, wh->minor);
-               seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
+       /*
+        * To preserve the compatibility:
+        * - Only show the "all devices" when the default policy is to allow
+        * - List the exceptions in case the default policy is to deny
+        * This way, the file remains as a "whitelist of devices"
+        */
+       if (devcgroup->deny_all == false) {
+               set_access(acc, ACC_MASK);
+               set_majmin(maj, ~0);
+               set_majmin(min, ~0);
+               seq_printf(m, "%c %s:%s %s\n", type_to_char(DEV_ALL),
                           maj, min, acc);
+       } else {
+               list_for_each_entry_rcu(ex, &devcgroup->exceptions, list) {
+                       set_access(acc, ex->access);
+                       set_majmin(maj, ex->major);
+                       set_majmin(min, ex->minor);
+                       seq_printf(m, "%c %s:%s %s\n", type_to_char(ex->type),
+                                  maj, min, acc);
+               }
        }
        rcu_read_unlock();
 
        return 0;
 }
 
-/*
- * may_access_whitelist:
- * does the access granted to dev_cgroup c contain the access
- * requested in whitelist item refwh.
- * return 1 if yes, 0 if no.
- * call with devcgroup_mutex held
+/**
+ * may_access - verifies if a new exception is part of what is allowed
+ *             by a dev cgroup based on the default policy +
+ *             exceptions. This is used to make sure a child cgroup
+ *             won't have more privileges than its parent or to
+ *             verify if a certain access is allowed.
+ * @dev_cgroup: dev cgroup to be tested against
+ * @refex: new exception
  */
-static int may_access_whitelist(struct dev_cgroup *c,
-                                      struct dev_whitelist_item *refwh)
+static int may_access(struct dev_cgroup *dev_cgroup,
+                     struct dev_exception_item *refex)
 {
-       struct dev_whitelist_item *whitem;
+       struct dev_exception_item *ex;
+       bool match = false;
 
-       list_for_each_entry(whitem, &c->whitelist, list) {
-               if (whitem->type & DEV_ALL)
-                       return 1;
-               if ((refwh->type & DEV_BLOCK) && !(whitem->type & DEV_BLOCK))
+       list_for_each_entry(ex, &dev_cgroup->exceptions, list) {
+               if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
-               if ((refwh->type & DEV_CHAR) && !(whitem->type & DEV_CHAR))
+               if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
                        continue;
-               if (whitem->major != ~0 && whitem->major != refwh->major)
+               if (ex->major != ~0 && ex->major != refex->major)
                        continue;
-               if (whitem->minor != ~0 && whitem->minor != refwh->minor)
+               if (ex->minor != ~0 && ex->minor != refex->minor)
                        continue;
-               if (refwh->access & (~whitem->access))
+               if (refex->access & (~ex->access))
                        continue;
-               return 1;
+               match = true;
+               break;
        }
+
+       /*
+        * In two cases we'll consider this new exception valid:
+        * - the dev cgroup has its default policy to allow + exception list:
+        *   the new exception should *not* match any of the exceptions
+        *   (!deny_all, !match)
+        * - the dev cgroup has its default policy to deny + exception list:
+        *   the new exception *should* match the exceptions
+        *   (deny_all, match)
+        */
+       if (dev_cgroup->deny_all == match)
+               return 1;
        return 0;
 }
 
 /*
  * parent_has_perm:
- * when adding a new allow rule to a device whitelist, the rule
+ * when adding a new allow rule to a device exception list, the rule
  * must be allowed in the parent device
  */
 static int parent_has_perm(struct dev_cgroup *childcg,
-                                 struct dev_whitelist_item *wh)
+                                 struct dev_exception_item *ex)
 {
        struct cgroup *pcg = childcg->css.cgroup->parent;
        struct dev_cgroup *parent;
@@ -309,17 +338,17 @@ static int parent_has_perm(struct dev_cgroup *childcg,
        if (!pcg)
                return 1;
        parent = cgroup_to_devcgroup(pcg);
-       return may_access_whitelist(parent, wh);
+       return may_access(parent, ex);
 }
 
 /*
- * Modify the whitelist using allow/deny rules.
+ * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
  * so we can give a container CAP_MKNOD to let it create devices but not
- * modify the whitelist.
+ * modify the exception list.
  * It seems likely we'll want to add a CAP_CONTAINER capability to allow
  * us to also grant CAP_SYS_ADMIN to containers without giving away the
- * device whitelist controls, but for now we'll stick with CAP_SYS_ADMIN
+ * device exception list controls, but for now we'll stick with CAP_SYS_ADMIN
  *
  * Taking rules away is always allowed (given CAP_SYS_ADMIN).  Granting
  * new access is only allowed if you're in the top-level cgroup, or your
@@ -331,26 +360,36 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        const char *b;
        char *endp;
        int count;
-       struct dev_whitelist_item wh;
+       struct dev_exception_item ex;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       memset(&wh, 0, sizeof(wh));
+       memset(&ex, 0, sizeof(ex));
        b = buffer;
 
        switch (*b) {
        case 'a':
-               wh.type = DEV_ALL;
-               wh.access = ACC_MASK;
-               wh.major = ~0;
-               wh.minor = ~0;
-               goto handle;
+               switch (filetype) {
+               case DEVCG_ALLOW:
+                       if (!parent_has_perm(devcgroup, &ex))
+                               return -EPERM;
+                       dev_exception_clean(devcgroup);
+                       devcgroup->deny_all = false;
+                       break;
+               case DEVCG_DENY:
+                       dev_exception_clean(devcgroup);
+                       devcgroup->deny_all = true;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               return 0;
        case 'b':
-               wh.type = DEV_BLOCK;
+               ex.type = DEV_BLOCK;
                break;
        case 'c':
-               wh.type = DEV_CHAR;
+               ex.type = DEV_CHAR;
                break;
        default:
                return -EINVAL;
@@ -360,10 +399,10 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                return -EINVAL;
        b++;
        if (*b == '*') {
-               wh.major = ~0;
+               ex.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               wh.major = simple_strtoul(b, &endp, 10);
+               ex.major = simple_strtoul(b, &endp, 10);
                b = endp;
        } else {
                return -EINVAL;
@@ -374,10 +413,10 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 
        /* read minor */
        if (*b == '*') {
-               wh.minor = ~0;
+               ex.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               wh.minor = simple_strtoul(b, &endp, 10);
+               ex.minor = simple_strtoul(b, &endp, 10);
                b = endp;
        } else {
                return -EINVAL;
@@ -387,13 +426,13 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        for (b++, count = 0; count < 3; count++, b++) {
                switch (*b) {
                case 'r':
-                       wh.access |= ACC_READ;
+                       ex.access |= ACC_READ;
                        break;
                case 'w':
-                       wh.access |= ACC_WRITE;
+                       ex.access |= ACC_WRITE;
                        break;
                case 'm':
-                       wh.access |= ACC_MKNOD;
+                       ex.access |= ACC_MKNOD;
                        break;
                case '\n':
                case '\0':
@@ -404,15 +443,31 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                }
        }
 
-handle:
        switch (filetype) {
        case DEVCG_ALLOW:
-               if (!parent_has_perm(devcgroup, &wh))
+               if (!parent_has_perm(devcgroup, &ex))
                        return -EPERM;
-               return dev_whitelist_add(devcgroup, &wh);
+               /*
+                * If the default policy is to allow by default, try to remove
+                * an matching exception instead. And be silent about it: we
+                * don't want to break compatibility
+                */
+               if (devcgroup->deny_all == false) {
+                       dev_exception_rm(devcgroup, &ex);
+                       return 0;
+               }
+               return dev_exception_add(devcgroup, &ex);
        case DEVCG_DENY:
-               dev_whitelist_rm(devcgroup, &wh);
-               break;
+               /*
+                * If the default policy is to deny by default, try to remove
+                * an matching exception instead. And be silent about it: we
+                * don't want to break compatibility
+                */
+               if (devcgroup->deny_all == true) {
+                       dev_exception_rm(devcgroup, &ex);
+                       return 0;
+               }
+               return dev_exception_add(devcgroup, &ex);
        default:
                return -EINVAL;
        }
@@ -468,73 +523,71 @@ struct cgroup_subsys devices_subsys = {
        .broken_hierarchy = true,
 };
 
-int __devcgroup_inode_permission(struct inode *inode, int mask)
+/**
+ * __devcgroup_check_permission - checks if an inode operation is permitted
+ * @dev_cgroup: the dev cgroup to be tested against
+ * @type: device type
+ * @major: device major number
+ * @minor: device minor number
+ * @access: combination of ACC_WRITE, ACC_READ and ACC_MKNOD
+ *
+ * returns 0 on success, -EPERM case the operation is not permitted
+ */
+static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
+                                       short type, u32 major, u32 minor,
+                                       short access)
 {
-       struct dev_cgroup *dev_cgroup;
-       struct dev_whitelist_item *wh;
-
-       rcu_read_lock();
+       struct dev_exception_item ex;
+       int rc;
 
-       dev_cgroup = task_devcgroup(current);
+       memset(&ex, 0, sizeof(ex));
+       ex.type = type;
+       ex.major = major;
+       ex.minor = minor;
+       ex.access = access;
 
-       list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
-               if (wh->type & DEV_ALL)
-                       goto found;
-               if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
-                       continue;
-               if ((wh->type & DEV_CHAR) && !S_ISCHR(inode->i_mode))
-                       continue;
-               if (wh->major != ~0 && wh->major != imajor(inode))
-                       continue;
-               if (wh->minor != ~0 && wh->minor != iminor(inode))
-                       continue;
+       rcu_read_lock();
+       rc = may_access(dev_cgroup, &ex);
+       rcu_read_unlock();
 
-               if ((mask & MAY_WRITE) && !(wh->access & ACC_WRITE))
-                       continue;
-               if ((mask & MAY_READ) && !(wh->access & ACC_READ))
-                       continue;
-found:
-               rcu_read_unlock();
-               return 0;
-       }
+       if (!rc)
+               return -EPERM;
 
-       rcu_read_unlock();
+       return 0;
+}
 
-       return -EPERM;
+int __devcgroup_inode_permission(struct inode *inode, int mask)
+{
+       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
+       short type, access = 0;
+
+       if (S_ISBLK(inode->i_mode))
+               type = DEV_BLOCK;
+       if (S_ISCHR(inode->i_mode))
+               type = DEV_CHAR;
+       if (mask & MAY_WRITE)
+               access |= ACC_WRITE;
+       if (mask & MAY_READ)
+               access |= ACC_READ;
+
+       return __devcgroup_check_permission(dev_cgroup, type, imajor(inode),
+                                           iminor(inode), access);
 }
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
-       struct dev_cgroup *dev_cgroup;
-       struct dev_whitelist_item *wh;
+       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
+       short type;
 
        if (!S_ISBLK(mode) && !S_ISCHR(mode))
                return 0;
 
-       rcu_read_lock();
-
-       dev_cgroup = task_devcgroup(current);
-
-       list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
-               if (wh->type & DEV_ALL)
-                       goto found;
-               if ((wh->type & DEV_BLOCK) && !S_ISBLK(mode))
-                       continue;
-               if ((wh->type & DEV_CHAR) && !S_ISCHR(mode))
-                       continue;
-               if (wh->major != ~0 && wh->major != MAJOR(dev))
-                       continue;
-               if (wh->minor != ~0 && wh->minor != MINOR(dev))
-                       continue;
-
-               if (!(wh->access & ACC_MKNOD))
-                       continue;
-found:
-               rcu_read_unlock();
-               return 0;
-       }
+       if (S_ISBLK(mode))
+               type = DEV_BLOCK;
+       else
+               type = DEV_CHAR;
 
-       rcu_read_unlock();
+       return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev),
+                                           MINOR(dev), ACC_MKNOD);
 
-       return -EPERM;
 }
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 f4817292ef453c42626c4669ff0d6cd2305490a2..aa62c0e44cb61eb2d68b3d99b69544e1cfc85802 100644 (file)
@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
        { "PWM2", NULL, "PWM2 Driver" },
 };
 
-static const __devinitdata struct reg_default wm5100_reva_patches[] = {
+static const __devinitconst struct reg_default wm5100_reva_patches[] = {
        { WM5100_AUDIO_IF_1_10, 0 },
        { WM5100_AUDIO_IF_1_11, 1 },
        { WM5100_AUDIO_IF_1_12, 2 },
index f759f4f097c7f5ea2693a0257b914e78fea113bb..fd2f9221b24120e25d32c2c8d8b4849d8d24569a 100644 (file)
@@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type)
        dev->feature_len = 0;
        dev->num_vq = 0;
        dev->running = false;
+       dev->next = NULL;
 
        /*
         * Append to device list.  Prepending to a single-linked list is
index 85baf11e2acd7d11aa4990a0f7f53f8d28689a20..43480149119ee773f0a32cc8abe995903609fd11 100644 (file)
@@ -1,4 +1,4 @@
-TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug
+TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
 
 all:
        for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
new file mode 100644 (file)
index 0000000..19806ed
--- /dev/null
@@ -0,0 +1,11 @@
+# Makefile for epoll selftests
+
+all: test_epoll
+%: %.c
+       gcc -pthread -g -o $@ $^
+
+run_tests: all
+       ./test_epoll
+
+clean:
+       $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
new file mode 100644 (file)
index 0000000..e0fcff1
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ *  tools/testing/selftests/epoll/test_epoll.c
+ *
+ *  Copyright 2012 Adobe Systems Incorporated
+ *
+ *  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.
+ *
+ *  Paton J. Lewis <palewis@adobe.com>
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+
+/*
+ * A pointer to an epoll_item_private structure will be stored in the epoll
+ * item's event structure so that we can get access to the epoll_item_private
+ * data after calling epoll_wait:
+ */
+struct epoll_item_private {
+       int index;  /* Position of this struct within the epoll_items array. */
+       int fd;
+       uint32_t events;
+       pthread_mutex_t mutex;  /* Guards the following variables... */
+       int stop;
+       int status;  /* Stores any error encountered while handling item. */
+       /* The following variable allows us to test whether we have encountered
+          a problem while attempting to cancel and delete the associated
+          event. When the test program exits, 'deleted' should be exactly
+          one. If it is greater than one, then the failed test reflects a real
+          world situation where we would have tried to access the epoll item's
+          private data after deleting it: */
+       int deleted;
+};
+
+struct epoll_item_private *epoll_items;
+
+/*
+ * Delete the specified item from the epoll set. In a real-world secneario this
+ * is where we would free the associated data structure, but in this testing
+ * environment we retain the structure so that we can test for double-deletion:
+ */
+void delete_item(int index)
+{
+       __sync_fetch_and_add(&epoll_items[index].deleted, 1);
+}
+
+/*
+ * A pointer to a read_thread_data structure will be passed as the argument to
+ * each read thread:
+ */
+struct read_thread_data {
+       int stop;
+       int status;  /* Indicates any error encountered by the read thread. */
+       int epoll_set;
+};
+
+/*
+ * The function executed by the read threads:
+ */
+void *read_thread_function(void *function_data)
+{
+       struct read_thread_data *thread_data =
+               (struct read_thread_data *)function_data;
+       struct epoll_event event_data;
+       struct epoll_item_private *item_data;
+       char socket_data;
+
+       /* Handle events until we encounter an error or this thread's 'stop'
+          condition is set: */
+       while (1) {
+               int result = epoll_wait(thread_data->epoll_set,
+                                       &event_data,
+                                       1,      /* Number of desired events */
+                                       1000);  /* Timeout in ms */
+               if (result < 0) {
+                       /* Breakpoints signal all threads. Ignore that while
+                          debugging: */
+                       if (errno == EINTR)
+                               continue;
+                       thread_data->status = errno;
+                       return 0;
+               } else if (thread_data->stop)
+                       return 0;
+               else if (result == 0)  /* Timeout */
+                       continue;
+
+               /* We need the mutex here because checking for the stop
+                  condition and re-enabling the epoll item need to be done
+                  together as one atomic operation when EPOLL_CTL_DISABLE is
+                  available: */
+               item_data = (struct epoll_item_private *)event_data.data.ptr;
+               pthread_mutex_lock(&item_data->mutex);
+
+               /* Remove the item from the epoll set if we want to stop
+                  handling that event: */
+               if (item_data->stop)
+                       delete_item(item_data->index);
+               else {
+                       /* Clear the data that was written to the other end of
+                          our non-blocking socket: */
+                       do {
+                               if (read(item_data->fd, &socket_data, 1) < 1) {
+                                       if ((errno == EAGAIN) ||
+                                           (errno == EWOULDBLOCK))
+                                               break;
+                                       else
+                                               goto error_unlock;
+                               }
+                       } while (item_data->events & EPOLLET);
+
+                       /* The item was one-shot, so re-enable it: */
+                       event_data.events = item_data->events;
+                       if (epoll_ctl(thread_data->epoll_set,
+                                                 EPOLL_CTL_MOD,
+                                                 item_data->fd,
+                                                 &event_data) < 0)
+                               goto error_unlock;
+               }
+
+               pthread_mutex_unlock(&item_data->mutex);
+       }
+
+error_unlock:
+       thread_data->status = item_data->status = errno;
+       pthread_mutex_unlock(&item_data->mutex);
+       return 0;
+}
+
+/*
+ * A pointer to a write_thread_data structure will be passed as the argument to
+ * the write thread:
+ */
+struct write_thread_data {
+       int stop;
+       int status;  /* Indicates any error encountered by the write thread. */
+       int n_fds;
+       int *fds;
+};
+
+/*
+ * The function executed by the write thread. It writes a single byte to each
+ * socket in turn until the stop condition for this thread is set. If writing to
+ * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
+ * the moment and just move on to the next socket in the list. We don't care
+ * about the order in which we deliver events to the epoll set. In fact we don't
+ * care about the data we're writing to the pipes at all; we just want to
+ * trigger epoll events:
+ */
+void *write_thread_function(void *function_data)
+{
+       const char data = 'X';
+       int index;
+       struct write_thread_data *thread_data =
+               (struct write_thread_data *)function_data;
+       while (!write_thread_data->stop)
+               for (index = 0;
+                    !thread_data->stop && (index < thread_data->n_fds);
+                    ++index)
+                       if ((write(thread_data->fds[index], &data, 1) < 1) &&
+                               (errno != EAGAIN) &&
+                               (errno != EWOULDBLOCK)) {
+                               write_thread_data->status = errno;
+                               return;
+                       }
+}
+
+/*
+ * Arguments are currently ignored:
+ */
+int main(int argc, char **argv)
+{
+       const int n_read_threads = 100;
+       const int n_epoll_items = 500;
+       int index;
+       int epoll_set = epoll_create1(0);
+       struct write_thread_data write_thread_data = {
+               0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
+       };
+       struct read_thread_data *read_thread_data =
+               malloc(n_read_threads * sizeof(struct read_thread_data));
+       pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
+       pthread_t write_thread;
+
+       printf("-----------------\n");
+       printf("Runing test_epoll\n");
+       printf("-----------------\n");
+
+       epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
+
+       if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
+               read_thread_data == 0 || read_threads == 0)
+               goto error;
+
+       if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
+               printf("Error: please run this test on a multi-core system.\n");
+               goto error;
+       }
+
+       /* Create the socket pairs and epoll items: */
+       for (index = 0; index < n_epoll_items; ++index) {
+               int socket_pair[2];
+               struct epoll_event event_data;
+               if (socketpair(AF_UNIX,
+                              SOCK_STREAM | SOCK_NONBLOCK,
+                              0,
+                              socket_pair) < 0)
+                       goto error;
+               write_thread_data.fds[index] = socket_pair[0];
+               epoll_items[index].index = index;
+               epoll_items[index].fd = socket_pair[1];
+               if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
+                       goto error;
+               /* We always use EPOLLONESHOT because this test is currently
+                  structured to demonstrate the need for EPOLL_CTL_DISABLE,
+                  which only produces useful information in the EPOLLONESHOT
+                  case (without EPOLLONESHOT, calling epoll_ctl with
+                  EPOLL_CTL_DISABLE will never return EBUSY). If support for
+                  testing events without EPOLLONESHOT is desired, it should
+                  probably be implemented in a separate unit test. */
+               epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
+               if (index < n_epoll_items / 2)
+                       epoll_items[index].events |= EPOLLET;
+               epoll_items[index].stop = 0;
+               epoll_items[index].status = 0;
+               epoll_items[index].deleted = 0;
+               event_data.events = epoll_items[index].events;
+               event_data.data.ptr = &epoll_items[index];
+               if (epoll_ctl(epoll_set,
+                             EPOLL_CTL_ADD,
+                             epoll_items[index].fd,
+                             &event_data) < 0)
+                       goto error;
+       }
+
+       /* Create and start the read threads: */
+       for (index = 0; index < n_read_threads; ++index) {
+               read_thread_data[index].stop = 0;
+               read_thread_data[index].status = 0;
+               read_thread_data[index].epoll_set = epoll_set;
+               if (pthread_create(&read_threads[index],
+                                  NULL,
+                                  read_thread_function,
+                                  &read_thread_data[index]) != 0)
+                       goto error;
+       }
+
+       if (pthread_create(&write_thread,
+                          NULL,
+                          write_thread_function,
+                          &write_thread_data) != 0)
+               goto error;
+
+       /* Cancel all event pollers: */
+#ifdef EPOLL_CTL_DISABLE
+       for (index = 0; index < n_epoll_items; ++index) {
+               pthread_mutex_lock(&epoll_items[index].mutex);
+               ++epoll_items[index].stop;
+               if (epoll_ctl(epoll_set,
+                             EPOLL_CTL_DISABLE,
+                             epoll_items[index].fd,
+                             NULL) == 0)
+                       delete_item(index);
+               else if (errno != EBUSY) {
+                       pthread_mutex_unlock(&epoll_items[index].mutex);
+                       goto error;
+               }
+               /* EBUSY means events were being handled; allow the other thread
+                  to delete the item. */
+               pthread_mutex_unlock(&epoll_items[index].mutex);
+       }
+#else
+       for (index = 0; index < n_epoll_items; ++index) {
+               pthread_mutex_lock(&epoll_items[index].mutex);
+               ++epoll_items[index].stop;
+               pthread_mutex_unlock(&epoll_items[index].mutex);
+               /* Wait in case a thread running read_thread_function is
+                  currently executing code between epoll_wait and
+                  pthread_mutex_lock with this item. Note that a longer delay
+                  would make double-deletion less likely (at the expense of
+                  performance), but there is no guarantee that any delay would
+                  ever be sufficient. Note also that we delete all event
+                  pollers at once for testing purposes, but in a real-world
+                  environment we are likely to want to be able to cancel event
+                  pollers at arbitrary times. Therefore we can't improve this
+                  situation by just splitting this loop into two loops
+                  (i.e. signal 'stop' for all items, sleep, and then delete all
+                  items). We also can't fix the problem via EPOLL_CTL_DEL
+                  because that command can't prevent the case where some other
+                  thread is executing read_thread_function within the region
+                  mentioned above: */
+               usleep(1);
+               pthread_mutex_lock(&epoll_items[index].mutex);
+               if (!epoll_items[index].deleted)
+                       delete_item(index);
+               pthread_mutex_unlock(&epoll_items[index].mutex);
+       }
+#endif
+
+       /* Shut down the read threads: */
+       for (index = 0; index < n_read_threads; ++index)
+               __sync_fetch_and_add(&read_thread_data[index].stop, 1);
+       for (index = 0; index < n_read_threads; ++index) {
+               if (pthread_join(read_threads[index], NULL) != 0)
+                       goto error;
+               if (read_thread_data[index].status)
+                       goto error;
+       }
+
+       /* Shut down the write thread: */
+       __sync_fetch_and_add(&write_thread_data.stop, 1);
+       if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
+               goto error;
+
+       /* Check for final error conditions: */
+       for (index = 0; index < n_epoll_items; ++index) {
+               if (epoll_items[index].status != 0)
+                       goto error;
+               if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
+                       goto error;
+       }
+       for (index = 0; index < n_epoll_items; ++index)
+               if (epoll_items[index].deleted != 1) {
+                       printf("Error: item data deleted %1d times.\n",
+                                  epoll_items[index].deleted);
+                       goto error;
+               }
+
+       printf("[PASS]\n");
+       return 0;
+
+ error:
+       printf("[FAIL]\n");
+       return errno;
+}
diff --git a/tools/virtio/virtio-trace/Makefile b/tools/virtio/virtio-trace/Makefile
new file mode 100644 (file)
index 0000000..0d23816
--- /dev/null
@@ -0,0 +1,13 @@
+CC = gcc
+CFLAGS = -O2 -Wall -pthread
+
+all: trace-agent
+
+.c.o:
+       $(CC) $(CFLAGS) -c $^ -o $@
+
+trace-agent: trace-agent.o trace-agent-ctl.o trace-agent-rw.o
+       $(CC) $(CFLAGS) -o $@ $^
+
+clean:
+       rm -f *.o trace-agent
diff --git a/tools/virtio/virtio-trace/README b/tools/virtio/virtio-trace/README
new file mode 100644 (file)
index 0000000..b64845b
--- /dev/null
@@ -0,0 +1,118 @@
+Trace Agent for virtio-trace
+============================
+
+Trace agent is a user tool for sending trace data of a guest to a Host in low
+overhead. Trace agent has the following functions:
+ - splice a page of ring-buffer to read_pipe without memory copying
+ - splice the page from write_pipe to virtio-console without memory copying
+ - write trace data to stdout by using -o option
+ - controlled by start/stop orders from a Host
+
+The trace agent operates as follows:
+ 1) Initialize all structures.
+ 2) Create a read/write thread per CPU. Each thread is bound to a CPU.
+    The read/write threads hold it.
+ 3) A controller thread does poll() for a start order of a host.
+ 4) After the controller of the trace agent receives a start order from a host,
+    the controller wake read/write threads.
+ 5) The read/write threads start to read trace data from ring-buffers and
+    write the data to virtio-serial.
+ 6) If the controller receives a stop order from a host, the read/write threads
+    stop to read trace data.
+
+
+Files
+=====
+
+README: this file
+Makefile: Makefile of trace agent for virtio-trace
+trace-agent.c: includes main function, sets up for operating trace agent
+trace-agent.h: includes all structures and some macros
+trace-agent-ctl.c: includes controller function for read/write threads
+trace-agent-rw.c: includes read/write threads function
+
+
+Setup
+=====
+
+To use this trace agent for virtio-trace, we need to prepare some virtio-serial
+I/Fs.
+
+1) Make FIFO in a host
+ virtio-trace uses virtio-serial pipe as trace data paths as to the number
+of CPUs and a control path, so FIFO (named pipe) should be created as follows:
+       # mkdir /tmp/virtio-trace/
+       # mkfifo /tmp/virtio-trace/trace-path-cpu{0,1,2,...,X}.{in,out}
+       # mkfifo /tmp/virtio-trace/agent-ctl-path.{in,out}
+
+For example, if a guest use three CPUs, the names are
+       trace-path-cpu{0,1,2}.{in.out}
+and
+       agent-ctl-path.{in,out}.
+
+2) Set up of virtio-serial pipe in a host
+ Add qemu option to use virtio-serial pipe.
+
+ ##virtio-serial device##
+     -device virtio-serial-pci,id=virtio-serial0\
+ ##control path##
+     -chardev pipe,id=charchannel0,path=/tmp/virtio-trace/agent-ctl-path\
+     -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,\
+      id=channel0,name=agent-ctl-path\
+ ##data path##
+     -chardev pipe,id=charchannel1,path=/tmp/virtio-trace/trace-path-cpu0\
+     -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel0,\
+      id=channel1,name=trace-path-cpu0\
+      ...
+
+If you manage guests with libvirt, add the following tags to domain XML files.
+Then, libvirt passes the same command option to qemu.
+
+       <channel type='pipe'>
+          <source path='/tmp/virtio-trace/agent-ctl-path'/>
+          <target type='virtio' name='agent-ctl-path'/>
+          <address type='virtio-serial' controller='0' bus='0' port='0'/>
+       </channel>
+       <channel type='pipe'>
+          <source path='/tmp/virtio-trace/trace-path-cpu0'/>
+          <target type='virtio' name='trace-path-cpu0'/>
+          <address type='virtio-serial' controller='0' bus='0' port='1'/>
+       </channel>
+       ...
+Here, chardev names are restricted to trace-path-cpuX and agent-ctl-path. For
+example, if a guest use three CPUs, chardev names should be trace-path-cpu0,
+trace-path-cpu1, trace-path-cpu2, and agent-ctl-path.
+
+3) Boot the guest
+ You can find some chardev in /dev/virtio-ports/ in the guest.
+
+
+Run
+===
+
+0) Build trace agent in a guest
+       $ make
+
+1) Enable ftrace in the guest
+ <Example>
+       # echo 1 > /sys/kernel/debug/tracing/events/sched/enable
+
+2) Run trace agent in the guest
+ This agent must be operated as root.
+       # ./trace-agent
+read/write threads in the agent wait for start order from host. If you add -o
+option, trace data are output via stdout in the guest.
+
+3) Open FIFO in a host
+       # cat /tmp/virtio-trace/trace-path-cpu0.out
+If a host does not open these, trace data get stuck in buffers of virtio. Then,
+the guest will stop by specification of chardev in QEMU. This blocking mode may
+be solved in the future.
+
+4) Start to read trace data by ordering from a host
+ A host injects read start order to the guest via virtio-serial.
+       # echo 1 > /tmp/virtio-trace/agent-ctl-path.in
+
+5) Stop to read trace data by ordering from a host
+ A host injects read stop order to the guest via virtio-serial.
+       # echo 0 > /tmp/virtio-trace/agent-ctl-path.in
diff --git a/tools/virtio/virtio-trace/trace-agent-ctl.c b/tools/virtio/virtio-trace/trace-agent-ctl.c
new file mode 100644 (file)
index 0000000..a2d0403
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Controller of read/write threads for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "trace-agent.h"
+
+#define HOST_MSG_SIZE          256
+#define EVENT_WAIT_MSEC                100
+
+static volatile sig_atomic_t global_signal_val;
+bool global_sig_receive;       /* default false */
+bool global_run_operation;     /* default false*/
+
+/* Handle SIGTERM/SIGINT/SIGQUIT to exit */
+static void signal_handler(int sig)
+{
+       global_signal_val = sig;
+}
+
+int rw_ctl_init(const char *ctl_path)
+{
+       int ctl_fd;
+
+       ctl_fd = open(ctl_path, O_RDONLY);
+       if (ctl_fd == -1) {
+               pr_err("Cannot open ctl_fd\n");
+               goto error;
+       }
+
+       return ctl_fd;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+static int wait_order(int ctl_fd)
+{
+       struct pollfd poll_fd;
+       int ret = 0;
+
+       while (!global_sig_receive) {
+               poll_fd.fd = ctl_fd;
+               poll_fd.events = POLLIN;
+
+               ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
+
+               if (global_signal_val) {
+                       global_sig_receive = true;
+                       pr_info("Receive interrupt %d\n", global_signal_val);
+
+                       /* Wakes rw-threads when they are sleeping */
+                       if (!global_run_operation)
+                               pthread_cond_broadcast(&cond_wakeup);
+
+                       ret = -1;
+                       break;
+               }
+
+               if (ret < 0) {
+                       pr_err("Polling error\n");
+                       goto error;
+               }
+
+               if (ret)
+                       break;
+       };
+
+       return ret;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+/*
+ * contol read/write threads by handling global_run_operation
+ */
+void *rw_ctl_loop(int ctl_fd)
+{
+       ssize_t rlen;
+       char buf[HOST_MSG_SIZE];
+       int ret;
+
+       /* Setup signal handlers */
+       signal(SIGTERM, signal_handler);
+       signal(SIGINT, signal_handler);
+       signal(SIGQUIT, signal_handler);
+
+       while (!global_sig_receive) {
+
+               ret = wait_order(ctl_fd);
+               if (ret < 0)
+                       break;
+
+               rlen = read(ctl_fd, buf, sizeof(buf));
+               if (rlen < 0) {
+                       pr_err("read data error in ctl thread\n");
+                       goto error;
+               }
+
+               if (rlen == 2 && buf[0] == '1') {
+                       /*
+                        * If host writes '1' to a control path,
+                        * this controller wakes all read/write threads.
+                        */
+                       global_run_operation = true;
+                       pthread_cond_broadcast(&cond_wakeup);
+                       pr_debug("Wake up all read/write threads\n");
+               } else if (rlen == 2 && buf[0] == '0') {
+                       /*
+                        * If host writes '0' to a control path, read/write
+                        * threads will wait for notification from Host.
+                        */
+                       global_run_operation = false;
+                       pr_debug("Stop all read/write threads\n");
+               } else
+                       pr_info("Invalid host notification: %s\n", buf);
+       }
+
+       return NULL;
+
+error:
+       exit(EXIT_FAILURE);
+}
diff --git a/tools/virtio/virtio-trace/trace-agent-rw.c b/tools/virtio/virtio-trace/trace-agent-rw.c
new file mode 100644 (file)
index 0000000..3aace5e
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Read/write thread of a guest agent for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include "trace-agent.h"
+
+#define READ_WAIT_USEC 100000
+
+void *rw_thread_info_new(void)
+{
+       struct rw_thread_info *rw_ti;
+
+       rw_ti = zalloc(sizeof(struct rw_thread_info));
+       if (rw_ti == NULL) {
+               pr_err("rw_thread_info zalloc error\n");
+               exit(EXIT_FAILURE);
+       }
+
+       rw_ti->cpu_num = -1;
+       rw_ti->in_fd = -1;
+       rw_ti->out_fd = -1;
+       rw_ti->read_pipe = -1;
+       rw_ti->write_pipe = -1;
+       rw_ti->pipe_size = PIPE_INIT;
+
+       return rw_ti;
+}
+
+void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
+                               bool stdout_flag, unsigned long pipe_size,
+                               struct rw_thread_info *rw_ti)
+{
+       int data_pipe[2];
+
+       rw_ti->cpu_num = cpu;
+
+       /* set read(input) fd */
+       rw_ti->in_fd = open(in_path, O_RDONLY);
+       if (rw_ti->in_fd == -1) {
+               pr_err("Could not open in_fd (CPU:%d)\n", cpu);
+               goto error;
+       }
+
+       /* set write(output) fd */
+       if (!stdout_flag) {
+               /* virtio-serial output mode */
+               rw_ti->out_fd = open(out_path, O_WRONLY);
+               if (rw_ti->out_fd == -1) {
+                       pr_err("Could not open out_fd (CPU:%d)\n", cpu);
+                       goto error;
+               }
+       } else
+               /* stdout mode */
+               rw_ti->out_fd = STDOUT_FILENO;
+
+       if (pipe2(data_pipe, O_NONBLOCK) < 0) {
+               pr_err("Could not create pipe in rw-thread(%d)\n", cpu);
+               goto error;
+       }
+
+       /*
+        * Size of pipe is 64kB in default based on fs/pipe.c.
+        * To read/write trace data speedy, pipe size is changed.
+        */
+       if (fcntl(*data_pipe, F_SETPIPE_SZ, pipe_size) < 0) {
+               pr_err("Could not change pipe size in rw-thread(%d)\n", cpu);
+               goto error;
+       }
+
+       rw_ti->read_pipe = data_pipe[1];
+       rw_ti->write_pipe = data_pipe[0];
+       rw_ti->pipe_size = pipe_size;
+
+       return NULL;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+/* Bind a thread to a cpu */
+static void bind_cpu(int cpu_num)
+{
+       cpu_set_t mask;
+
+       CPU_ZERO(&mask);
+       CPU_SET(cpu_num, &mask);
+
+       /* bind my thread to cpu_num by assigning zero to the first argument */
+       if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
+               pr_err("Could not set CPU#%d affinity\n", (int)cpu_num);
+}
+
+static void *rw_thread_main(void *thread_info)
+{
+       ssize_t rlen, wlen;
+       ssize_t ret;
+       struct rw_thread_info *ts = (struct rw_thread_info *)thread_info;
+
+       bind_cpu(ts->cpu_num);
+
+       while (1) {
+               /* Wait for a read order of trace data by Host OS */
+               if (!global_run_operation) {
+                       pthread_mutex_lock(&mutex_notify);
+                       pthread_cond_wait(&cond_wakeup, &mutex_notify);
+                       pthread_mutex_unlock(&mutex_notify);
+               }
+
+               if (global_sig_receive)
+                       break;
+
+               /*
+                * Each thread read trace_pipe_raw of each cpu bounding the
+                * thread, so contention of multi-threads does not occur.
+                */
+               rlen = splice(ts->in_fd, NULL, ts->read_pipe, NULL,
+                               ts->pipe_size, SPLICE_F_MOVE | SPLICE_F_MORE);
+
+               if (rlen < 0) {
+                       pr_err("Splice_read in rw-thread(%d)\n", ts->cpu_num);
+                       goto error;
+               } else if (rlen == 0) {
+                       /*
+                        * If trace data do not exist or are unreadable not
+                        * for exceeding the page size, splice_read returns
+                        * NULL. Then, this waits for being filled the data in a
+                        * ring-buffer.
+                        */
+                       usleep(READ_WAIT_USEC);
+                       pr_debug("Read retry(cpu:%d)\n", ts->cpu_num);
+                       continue;
+               }
+
+               wlen = 0;
+
+               do {
+                       ret = splice(ts->write_pipe, NULL, ts->out_fd, NULL,
+                                       rlen - wlen,
+                                       SPLICE_F_MOVE | SPLICE_F_MORE);
+
+                       if (ret < 0) {
+                               pr_err("Splice_write in rw-thread(%d)\n",
+                                                               ts->cpu_num);
+                               goto error;
+                       } else if (ret == 0)
+                               /*
+                                * When host reader is not in time for reading
+                                * trace data, guest will be stopped. This is
+                                * because char dev in QEMU is not supported
+                                * non-blocking mode. Then, writer might be
+                                * sleep in that case.
+                                * This sleep will be removed by supporting
+                                * non-blocking mode.
+                                */
+                               sleep(1);
+                       wlen += ret;
+               } while (wlen < rlen);
+       }
+
+       return NULL;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+
+pthread_t rw_thread_run(struct rw_thread_info *rw_ti)
+{
+       int ret;
+       pthread_t rw_thread_per_cpu;
+
+       ret = pthread_create(&rw_thread_per_cpu, NULL, rw_thread_main, rw_ti);
+       if (ret != 0) {
+               pr_err("Could not create a rw thread(%d)\n", rw_ti->cpu_num);
+               exit(EXIT_FAILURE);
+       }
+
+       return rw_thread_per_cpu;
+}
diff --git a/tools/virtio/virtio-trace/trace-agent.c b/tools/virtio/virtio-trace/trace-agent.c
new file mode 100644 (file)
index 0000000..0a0a7dd
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Guest agent for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "trace-agent.h"
+
+#define PAGE_SIZE              (sysconf(_SC_PAGE_SIZE))
+#define PIPE_DEF_BUFS          16
+#define PIPE_MIN_SIZE          (PAGE_SIZE*PIPE_DEF_BUFS)
+#define PIPE_MAX_SIZE          (1024*1024)
+#define READ_PATH_FMT  \
+               "/sys/kernel/debug/tracing/per_cpu/cpu%d/trace_pipe_raw"
+#define WRITE_PATH_FMT         "/dev/virtio-ports/trace-path-cpu%d"
+#define CTL_PATH               "/dev/virtio-ports/agent-ctl-path"
+
+pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond_wakeup = PTHREAD_COND_INITIALIZER;
+
+static int get_total_cpus(void)
+{
+       int nr_cpus = (int)sysconf(_SC_NPROCESSORS_CONF);
+
+       if (nr_cpus <= 0) {
+               pr_err("Could not read cpus\n");
+               goto error;
+       } else if (nr_cpus > MAX_CPUS) {
+               pr_err("Exceed max cpus(%d)\n", (int)MAX_CPUS);
+               goto error;
+       }
+
+       return nr_cpus;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+static void *agent_info_new(void)
+{
+       struct agent_info *s;
+       int i;
+
+       s = zalloc(sizeof(struct agent_info));
+       if (s == NULL) {
+               pr_err("agent_info zalloc error\n");
+               exit(EXIT_FAILURE);
+       }
+
+       s->pipe_size = PIPE_INIT;
+       s->use_stdout = false;
+       s->cpus = get_total_cpus();
+       s->ctl_fd = -1;
+
+       /* read/write threads init */
+       for (i = 0; i < s->cpus; i++)
+               s->rw_ti[i] = rw_thread_info_new();
+
+       return s;
+}
+
+static unsigned long parse_size(const char *arg)
+{
+       unsigned long value, round;
+       char *ptr;
+
+       value = strtoul(arg, &ptr, 10);
+       switch (*ptr) {
+       case 'K': case 'k':
+               value <<= 10;
+               break;
+       case 'M': case 'm':
+               value <<= 20;
+               break;
+       default:
+               break;
+       }
+
+       if (value > PIPE_MAX_SIZE) {
+               pr_err("Pipe size must be less than 1MB\n");
+               goto error;
+       } else if (value < PIPE_MIN_SIZE) {
+               pr_err("Pipe size must be over 64KB\n");
+               goto error;
+       }
+
+       /* Align buffer size with page unit */
+       round = value & (PAGE_SIZE - 1);
+       value = value - round;
+
+       return value;
+error:
+       return 0;
+}
+
+static void usage(char const *prg)
+{
+       pr_err("usage: %s [-h] [-o] [-s <size of pipe>]\n", prg);
+}
+
+static const char *make_path(int cpu_num, bool this_is_write_path)
+{
+       int ret;
+       char *buf;
+
+       buf = zalloc(PATH_MAX);
+       if (buf == NULL) {
+               pr_err("Could not allocate buffer\n");
+               goto error;
+       }
+
+       if (this_is_write_path)
+               /* write(output) path */
+               ret = snprintf(buf, PATH_MAX, WRITE_PATH_FMT, cpu_num);
+       else
+               /* read(input) path */
+               ret = snprintf(buf, PATH_MAX, READ_PATH_FMT, cpu_num);
+
+       if (ret <= 0) {
+               pr_err("Failed to generate %s path(CPU#%d):%d\n",
+                       this_is_write_path ? "read" : "write", cpu_num, ret);
+               goto error;
+       }
+
+       return buf;
+
+error:
+       free(buf);
+       return NULL;
+}
+
+static const char *make_input_path(int cpu_num)
+{
+       return make_path(cpu_num, false);
+}
+
+static const char *make_output_path(int cpu_num)
+{
+       return make_path(cpu_num, true);
+}
+
+static void *agent_info_init(struct agent_info *s)
+{
+       int cpu;
+       const char *in_path = NULL;
+       const char *out_path = NULL;
+
+       /* init read/write threads */
+       for (cpu = 0; cpu < s->cpus; cpu++) {
+               /* set read(input) path per read/write thread */
+               in_path = make_input_path(cpu);
+               if (in_path == NULL)
+                       goto error;
+
+               /* set write(output) path per read/write thread*/
+               if (!s->use_stdout) {
+                       out_path = make_output_path(cpu);
+                       if (out_path == NULL)
+                               goto error;
+               } else
+                       /* stdout mode */
+                       pr_debug("stdout mode\n");
+
+               rw_thread_init(cpu, in_path, out_path, s->use_stdout,
+                                               s->pipe_size, s->rw_ti[cpu]);
+       }
+
+       /* init controller of read/write threads */
+       s->ctl_fd = rw_ctl_init((const char *)CTL_PATH);
+
+       return NULL;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+static void *parse_args(int argc, char *argv[], struct agent_info *s)
+{
+       int cmd;
+       unsigned long size;
+
+       while ((cmd = getopt(argc, argv, "hos:")) != -1) {
+               switch (cmd) {
+               /* stdout mode */
+               case 'o':
+                       s->use_stdout = true;
+                       break;
+               /* size of pipe */
+               case 's':
+                       size = parse_size(optarg);
+                       if (size == 0)
+                               goto error;
+                       s->pipe_size = size;
+                       break;
+               case 'h':
+               default:
+                       usage(argv[0]);
+                       goto error;
+               }
+       }
+
+       agent_info_init(s);
+
+       return NULL;
+
+error:
+       exit(EXIT_FAILURE);
+}
+
+static void agent_main_loop(struct agent_info *s)
+{
+       int cpu;
+       pthread_t rw_thread_per_cpu[MAX_CPUS];
+
+       /* Start all read/write threads */
+       for (cpu = 0; cpu < s->cpus; cpu++)
+               rw_thread_per_cpu[cpu] = rw_thread_run(s->rw_ti[cpu]);
+
+       rw_ctl_loop(s->ctl_fd);
+
+       /* Finish all read/write threads */
+       for (cpu = 0; cpu < s->cpus; cpu++) {
+               int ret;
+
+               ret = pthread_join(rw_thread_per_cpu[cpu], NULL);
+               if (ret != 0) {
+                       pr_err("pthread_join() error:%d (cpu %d)\n", ret, cpu);
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+static void agent_info_free(struct agent_info *s)
+{
+       int i;
+
+       close(s->ctl_fd);
+       for (i = 0; i < s->cpus; i++) {
+               close(s->rw_ti[i]->in_fd);
+               close(s->rw_ti[i]->out_fd);
+               close(s->rw_ti[i]->read_pipe);
+               close(s->rw_ti[i]->write_pipe);
+               free(s->rw_ti[i]);
+       }
+       free(s);
+}
+
+int main(int argc, char *argv[])
+{
+       struct agent_info *s = NULL;
+
+       s = agent_info_new();
+       parse_args(argc, argv, s);
+
+       agent_main_loop(s);
+
+       agent_info_free(s);
+
+       return 0;
+}
diff --git a/tools/virtio/virtio-trace/trace-agent.h b/tools/virtio/virtio-trace/trace-agent.h
new file mode 100644 (file)
index 0000000..8de79bf
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __TRACE_AGENT_H__
+#define __TRACE_AGENT_H__
+#include <pthread.h>
+#include <stdbool.h>
+
+#define MAX_CPUS       256
+#define PIPE_INIT       (1024*1024)
+
+/*
+ * agent_info - structure managing total information of guest agent
+ * @pipe_size: size of pipe (default 1MB)
+ * @use_stdout:        set to true when o option is added (default false)
+ * @cpus:      total number of CPUs
+ * @ctl_fd:    fd of control path, /dev/virtio-ports/agent-ctl-path
+ * @rw_ti:     structure managing information of read/write threads
+ */
+struct agent_info {
+       unsigned long pipe_size;
+       bool use_stdout;
+       int cpus;
+       int ctl_fd;
+       struct rw_thread_info *rw_ti[MAX_CPUS];
+};
+
+/*
+ * rw_thread_info - structure managing a read/write thread a cpu
+ * @cpu_num:   cpu number operating this read/write thread
+ * @in_fd:     fd of reading trace data path in cpu_num
+ * @out_fd:    fd of writing trace data path in cpu_num
+ * @read_pipe: fd of read pipe
+ * @write_pipe:        fd of write pipe
+ * @pipe_size: size of pipe (default 1MB)
+ */
+struct rw_thread_info {
+       int cpu_num;
+       int in_fd;
+       int out_fd;
+       int read_pipe;
+       int write_pipe;
+       unsigned long pipe_size;
+};
+
+/* use for stopping rw threads */
+extern bool global_sig_receive;
+
+/* use for notification */
+extern bool global_run_operation;
+extern pthread_mutex_t mutex_notify;
+extern pthread_cond_t cond_wakeup;
+
+/* for controller of read/write threads */
+extern int rw_ctl_init(const char *ctl_path);
+extern void *rw_ctl_loop(int ctl_fd);
+
+/* for trace read/write thread */
+extern void *rw_thread_info_new(void);
+extern void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
+                       bool stdout_flag, unsigned long pipe_size,
+                       struct rw_thread_info *rw_ti);
+extern pthread_t rw_thread_run(struct rw_thread_info *rw_ti);
+
+static inline void *zalloc(size_t size)
+{
+       return calloc(1, size);
+}
+
+#define pr_err(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
+#define pr_info(format, ...) fprintf(stdout, format, ## __VA_ARGS__)
+#ifdef DEBUG
+#define pr_debug(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
+#else
+#define pr_debug(format, ...) do {} while (0)
+#endif
+
+#endif /*__TRACE_AGENT_H__*/
index c353b4599cecdb4db0d3b276e1c12b81974cd2e7..e59bb63cb089634c7d9bed701be0581bf536726a 100644 (file)
@@ -1568,8 +1568,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,
        if (memslot && memslot->dirty_bitmap) {
                unsigned long rel_gfn = gfn - memslot->base_gfn;
 
-               /* TODO: introduce set_bit_le() and use it */
-               test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap);
+               set_bit_le(rel_gfn, memslot->dirty_bitmap);
        }
 }