summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/accessibility/braille/braille_console.c2
-rw-r--r--drivers/acpi/acpica/acglobal.h2
-rw-r--r--drivers/acpi/apei/ghes.c2
-rw-r--r--drivers/acpi/apei/hest.c2
-rw-r--r--drivers/acpi/dock.c2
-rw-r--r--drivers/acpi/pci_irq.c10
-rw-r--r--drivers/acpi/pci_slot.c2
-rw-r--r--drivers/acpi/video.c6
-rw-r--r--drivers/ata/ata_piix.c7
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/ata/libata-transport.c1
-rw-r--r--drivers/ata/pata_bf54x.c167
-rw-r--r--drivers/ata/sata_fsl.c11
-rw-r--r--drivers/ata/sata_nv.c6
-rw-r--r--drivers/ata/sata_sil24.c2
-rw-r--r--drivers/atm/he.c6
-rw-r--r--drivers/base/Kconfig6
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/cpu.c30
-rw-r--r--drivers/base/memory.c17
-rw-r--r--drivers/base/power/domain.c15
-rw-r--r--drivers/base/power/domain_governor.c24
-rw-r--r--drivers/bcma/bcma_private.h1
-rw-r--r--drivers/bcma/host_pci.c43
-rw-r--r--drivers/bcma/main.c24
-rw-r--r--drivers/block/Kconfig13
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/cciss.c6
-rw-r--r--drivers/block/drbd/drbd_int.h4
-rw-r--r--drivers/block/drbd/drbd_main.c4
-rw-r--r--drivers/block/mtip32xx/Kconfig9
-rw-r--r--drivers/block/mtip32xx/Makefile5
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c3651
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h423
-rw-r--r--drivers/block/nvme.c1745
-rw-r--r--drivers/block/paride/bpck6.c5
-rw-r--r--drivers/block/paride/pcd.c2
-rw-r--r--drivers/block/paride/pd.c3
-rw-r--r--drivers/block/paride/pf.c4
-rw-r--r--drivers/block/paride/pg.c3
-rw-r--r--drivers/block/paride/pt.c4
-rw-r--r--drivers/block/rbd.c2
-rw-r--r--drivers/block/sx8.c12
-rw-r--r--drivers/block/ub.c3
-rw-r--r--drivers/block/virtio_blk.c91
-rw-r--r--drivers/block/xd.c2
-rw-r--r--drivers/block/xen-blkback/blkback.c84
-rw-r--r--drivers/block/xen-blkback/common.h67
-rw-r--r--drivers/block/xen-blkback/xenbus.c12
-rw-r--r--drivers/block/xen-blkfront.c79
-rw-r--r--drivers/block/xsysace.c10
-rw-r--r--drivers/bluetooth/btusb.c12
-rw-r--r--drivers/bluetooth/hci_bcsp.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/cdrom/cdrom.c15
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/sis-agp.c2
-rw-r--r--drivers/char/hw_random/atmel-rng.c12
-rw-r--r--drivers/char/hw_random/n2-drv.c13
-rw-r--r--drivers/char/hw_random/octeon-rng.c13
-rw-r--r--drivers/char/hw_random/pasemi-rng.c12
-rw-r--r--drivers/char/hw_random/picoxcell-rng.c12
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c12
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c13
-rw-r--r--drivers/char/hw_random/virtio-rng.c2
-rw-r--r--drivers/char/i8k.c8
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/lp.c2
-rw-r--r--drivers/char/nwflash.c2
-rw-r--r--drivers/char/pcmcia/synclink_cs.c2
-rw-r--r--drivers/char/ramoops.c24
-rw-r--r--drivers/char/random.c8
-rw-r--r--drivers/char/tpm/Kconfig2
-rw-r--r--drivers/char/tpm/tpm.c137
-rw-r--r--drivers/char/tpm/tpm.h9
-rw-r--r--drivers/char/tpm/tpm_tis.c90
-rw-r--r--drivers/char/virtio_console.c140
-rw-r--r--drivers/cpufreq/Kconfig.arm15
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c3
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c8
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c290
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c643
-rw-r--r--drivers/cpufreq/omap-cpufreq.c274
-rw-r--r--drivers/cpufreq/powernow-k8.c47
-rw-r--r--drivers/cpufreq/s3c64xx-cpufreq.c35
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c13
-rw-r--r--drivers/crypto/caam/caamalg.c67
-rw-r--r--drivers/crypto/caam/compat.h1
-rw-r--r--drivers/crypto/caam/ctrl.c26
-rw-r--r--drivers/crypto/caam/desc.h2265
-rw-r--r--drivers/crypto/caam/desc_constr.h7
-rw-r--r--drivers/crypto/caam/regs.h1
-rw-r--r--drivers/crypto/mv_cesa.c12
-rw-r--r--drivers/crypto/picoxcell_crypto.c16
-rw-r--r--drivers/crypto/s5p-sss.c13
-rw-r--r--drivers/crypto/talitos.c493
-rw-r--r--drivers/crypto/talitos.h45
-rw-r--r--drivers/dma/Kconfig27
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/amba-pl08x.c41
-rw-r--r--drivers/dma/at_hdmac.c103
-rw-r--r--drivers/dma/at_hdmac_regs.h1
-rw-r--r--drivers/dma/coh901318.c12
-rw-r--r--drivers/dma/coh901318_lli.c23
-rw-r--r--drivers/dma/coh901318_lli.h4
-rw-r--r--drivers/dma/dmaengine.c4
-rw-r--r--drivers/dma/dw_dmac.c83
-rw-r--r--drivers/dma/dw_dmac_regs.h1
-rw-r--r--drivers/dma/ep93xx_dma.c90
-rw-r--r--drivers/dma/fsldma.c4
-rw-r--r--drivers/dma/imx-dma.c10
-rw-r--r--drivers/dma/imx-sdma.c27
-rw-r--r--drivers/dma/intel_mid_dma.c39
-rw-r--r--drivers/dma/intel_mid_dma_regs.h4
-rw-r--r--drivers/dma/iop-adma.c16
-rw-r--r--drivers/dma/ipu/ipu_idmac.c29
-rw-r--r--drivers/dma/mpc512x_dma.c12
-rw-r--r--drivers/dma/mxs-dma.c53
-rw-r--r--drivers/dma/pch_dma.c20
-rw-r--r--drivers/dma/pl330.c31
-rw-r--r--drivers/dma/shdma.c72
-rw-r--r--drivers/dma/sirf-dma.c707
-rw-r--r--drivers/dma/ste_dma40.c441
-rw-r--r--drivers/dma/ste_dma40_ll.h11
-rw-r--r--drivers/dma/timb_dma.c30
-rw-r--r--drivers/dma/txx9dmac.c12
-rw-r--r--drivers/edac/r82600_edac.c2
-rw-r--r--drivers/firewire/sbp2.c2
-rw-r--r--drivers/firmware/Kconfig12
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/sigma.c153
-rw-r--r--drivers/gpio/Kconfig1
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/devres.c90
-rw-r--r--drivers/gpio/gpio-pl061.c200
-rw-r--r--drivers/gpio/gpio-sa1100.c6
-rw-r--r--drivers/gpio/gpio-stmpe.c25
-rw-r--r--drivers/gpio/gpio-tegra.c9
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_crt.c6
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_hdmi.c14
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi.c6
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_sdvo.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c79
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c1
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/r100.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c2
-rw-r--r--drivers/gpu/drm/radeon/rs600.c13
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c5
-rw-r--r--drivers/hid/hid-prodikeys.c2
-rw-r--r--drivers/hid/hid-wacom.c16
-rw-r--r--drivers/hid/hid-wiimote-core.c10
-rw-r--r--drivers/hwmon/Kconfig8
-rw-r--r--drivers/hwmon/abituguru.c2
-rw-r--r--drivers/hwmon/abituguru3.c4
-rw-r--r--drivers/hwmon/acpi_power_meter.c2
-rw-r--r--drivers/hwmon/adm1021.c2
-rw-r--r--drivers/hwmon/adm1031.c153
-rw-r--r--drivers/hwmon/ads7828.c4
-rw-r--r--drivers/hwmon/coretemp.c26
-rw-r--r--drivers/hwmon/dme1737.c4
-rw-r--r--drivers/hwmon/emc2103.c2
-rw-r--r--drivers/hwmon/it87.c65
-rw-r--r--drivers/hwmon/lm63.c592
-rw-r--r--drivers/hwmon/lm90.c2
-rw-r--r--drivers/hwmon/lm93.c4
-rw-r--r--drivers/hwmon/max1111.c15
-rw-r--r--drivers/hwmon/max1668.c2
-rw-r--r--drivers/hwmon/w83627hf.c2
-rw-r--r--drivers/hwmon/w83781d.c4
-rw-r--r--drivers/hwmon/w83791d.c4
-rw-r--r--drivers/hwmon/w83792d.c2
-rw-r--r--drivers/hwmon/w83793.c2
-rw-r--r--drivers/hwmon/w83795.c2
-rw-r--r--drivers/hwmon/w83l786ng.c2
-rw-r--r--drivers/i2c/busses/Kconfig4
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c38
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c2
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c2
-rw-r--r--drivers/i2c/busses/i2c-amd756.c2
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c2
-rw-r--r--drivers/i2c/busses/i2c-at91.c17
-rw-r--r--drivers/i2c/busses/i2c-au1550.c13
-rw-r--r--drivers/i2c/busses/i2c-cpm.c13
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c2
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c2
-rw-r--r--drivers/i2c/busses/i2c-highlander.c15
-rw-r--r--drivers/i2c/busses/i2c-hydra.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c17
-rw-r--r--drivers/i2c/busses/i2c-intel-mid.c2
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c16
-rw-r--r--drivers/i2c/busses/i2c-isch.c13
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c13
-rw-r--r--drivers/i2c/busses/i2c-mpc.c13
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c15
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c4
-rw-r--r--drivers/i2c/busses/i2c-ocores.c17
-rw-r--r--drivers/i2c/busses/i2c-octeon.c16
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c14
-rw-r--r--drivers/i2c/busses/i2c-piix4.c2
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c17
-rw-r--r--drivers/i2c/busses/i2c-powermac.c19
-rw-r--r--drivers/i2c/busses/i2c-puv3.c16
-rw-r--r--drivers/i2c/busses/i2c-pxa-pci.c2
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c13
-rw-r--r--drivers/i2c/busses/i2c-simtec.c18
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c6
-rw-r--r--drivers/i2c/busses/i2c-sis630.c12
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c2
-rw-r--r--drivers/i2c/busses/i2c-via.c2
-rw-r--r--drivers/i2c/busses/i2c-viapro.c11
-rw-r--r--drivers/i2c/busses/i2c-xiic.c18
-rw-r--r--drivers/i2c/busses/scx200_acb.c2
-rw-r--r--drivers/i2c/i2c-dev.c13
-rw-r--r--drivers/i2c/muxes/gpio-i2cmux.c13
-rw-r--r--drivers/ide/ali14xx.c2
-rw-r--r--drivers/ide/cmd640.c2
-rw-r--r--drivers/ide/dtc2278.c2
-rw-r--r--drivers/ide/gayle.c2
-rw-r--r--drivers/ide/ht6560b.c2
-rw-r--r--drivers/ide/ide-4drives.c2
-rw-r--r--drivers/ide/ide-acpi.c6
-rw-r--r--drivers/ide/ide-floppy_ioctl.c3
-rw-r--r--drivers/ide/ide-pci-generic.c2
-rw-r--r--drivers/ide/qd65xx.c2
-rw-r--r--drivers/ide/umc8672.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c10
-rw-r--r--drivers/infiniband/hw/nes/nes.c2
-rw-r--r--drivers/input/joystick/xpad.c6
-rw-r--r--drivers/input/keyboard/amikbd.c15
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c13
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c13
-rw-r--r--drivers/input/misc/ab8500-ponkey.c2
-rw-r--r--drivers/input/misc/twl4030-pwrbutton.c15
-rw-r--r--drivers/input/misc/wistron_btns.c2
-rw-r--r--drivers/input/mouse/amimouse.c16
-rw-r--r--drivers/input/mouse/bcm5974.c3
-rw-r--r--drivers/input/mouse/psmouse-base.c2
-rw-r--r--drivers/input/mouse/synaptics_i2c.c6
-rw-r--r--drivers/input/serio/at32psif.c14
-rw-r--r--drivers/input/serio/hp_sdc.c2
-rw-r--r--drivers/input/serio/serio_raw.c8
-rw-r--r--drivers/input/serio/xilinx_ps2.c2
-rw-r--r--drivers/input/touchscreen/atmel-wm97xx.c13
-rw-r--r--drivers/input/touchscreen/eeti_ts.c4
-rw-r--r--drivers/input/touchscreen/htcpen.c4
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c13
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c2
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c4
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c2
-rw-r--r--drivers/isdn/hardware/avm/c4.c2
-rw-r--r--drivers/isdn/i4l/Kconfig2
-rw-r--r--drivers/isdn/sc/init.c2
-rw-r--r--drivers/leds/Kconfig15
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/leds-88pm860x.c12
-rw-r--r--drivers/leds/leds-adp5520.c12
-rw-r--r--drivers/leds/leds-ams-delta.c13
-rw-r--r--drivers/leds/leds-asic3.c16
-rw-r--r--drivers/leds/leds-atmel-pwm.c17
-rw-r--r--drivers/leds/leds-bd2802.c15
-rw-r--r--drivers/leds/leds-clevo-mail.c2
-rw-r--r--drivers/leds/leds-cobalt-qube.c17
-rw-r--r--drivers/leds/leds-da903x.c12
-rw-r--r--drivers/leds/leds-dac124s085.c13
-rw-r--r--drivers/leds/leds-fsg.c15
-rw-r--r--drivers/leds/leds-gpio.c16
-rw-r--r--drivers/leds/leds-hp6xx.c17
-rw-r--r--drivers/leds/leds-lm3530.c13
-rw-r--r--drivers/leds/leds-lp3944.c13
-rw-r--r--drivers/leds/leds-lp5521.c20
-rw-r--r--drivers/leds/leds-lp5523.c22
-rw-r--r--drivers/leds/leds-lt3593.c16
-rw-r--r--drivers/leds/leds-max8997.c372
-rw-r--r--drivers/leds/leds-mc13783.c14
-rw-r--r--drivers/leds/leds-netxbig.c39
-rw-r--r--drivers/leds/leds-ns2.c15
-rw-r--r--drivers/leds/leds-pca9532.c14
-rw-r--r--drivers/leds/leds-pca955x.c13
-rw-r--r--drivers/leds/leds-pwm.c13
-rw-r--r--drivers/leds/leds-rb532.c16
-rw-r--r--drivers/leds/leds-regulator.c12
-rw-r--r--drivers/leds/leds-renesas-tpu.c13
-rw-r--r--drivers/leds/leds-s3c24xx.c13
-rw-r--r--drivers/leds/leds-ss4200.c2
-rw-r--r--drivers/leds/leds-tca6507.c779
-rw-r--r--drivers/leds/leds-wm831x-status.c17
-rw-r--r--drivers/leds/leds-wm8350.c19
-rw-r--r--drivers/lguest/Makefile2
-rw-r--r--drivers/lguest/lguest_device.c18
-rw-r--r--drivers/lguest/segments.c28
-rw-r--r--drivers/macintosh/ams/ams-core.c2
-rw-r--r--drivers/macintosh/ams/ams-input.c4
-rw-r--r--drivers/macintosh/therm_adt746x.c2
-rw-r--r--drivers/md/dm-flakey.c11
-rw-r--r--drivers/md/dm-linear.c12
-rw-r--r--drivers/md/dm-mpath.c6
-rw-r--r--drivers/md/dm-table.c6
-rw-r--r--drivers/md/md.c7
-rw-r--r--drivers/md/raid1.c11
-rw-r--r--drivers/media/common/tuners/Kconfig9
-rw-r--r--drivers/media/common/tuners/Makefile1
-rw-r--r--drivers/media/common/tuners/max2165.c39
-rw-r--r--drivers/media/common/tuners/mc44s803.c10
-rw-r--r--drivers/media/common/tuners/mt2060.c13
-rw-r--r--drivers/media/common/tuners/mt2060_priv.h1
-rw-r--r--drivers/media/common/tuners/mt2063.c2307
-rw-r--r--drivers/media/common/tuners/mt2063.h36
-rw-r--r--drivers/media/common/tuners/mt2131.c20
-rw-r--r--drivers/media/common/tuners/mt2131_priv.h1
-rw-r--r--drivers/media/common/tuners/mt2266.c25
-rw-r--r--drivers/media/common/tuners/mxl5005s.c69
-rw-r--r--drivers/media/common/tuners/mxl5007t.c98
-rw-r--r--drivers/media/common/tuners/qt1010.c21
-rw-r--r--drivers/media/common/tuners/qt1010_priv.h1
-rw-r--r--drivers/media/common/tuners/tda18212.c72
-rw-r--r--drivers/media/common/tuners/tda18212.h4
-rw-r--r--drivers/media/common/tuners/tda18218.c34
-rw-r--r--drivers/media/common/tuners/tda18218_priv.h2
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c83
-rw-r--r--drivers/media/common/tuners/tda18271-maps.c4
-rw-r--r--drivers/media/common/tuners/tda18271-priv.h2
-rw-r--r--drivers/media/common/tuners/tda18271.h1
-rw-r--r--drivers/media/common/tuners/tda827x.c52
-rw-r--r--drivers/media/common/tuners/tuner-simple.c68
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c116
-rw-r--r--drivers/media/common/tuners/xc4000.c105
-rw-r--r--drivers/media/common/tuners/xc5000.c147
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c29
-rw-r--r--drivers/media/dvb/bt8xx/dst.c72
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h2
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c205
-rw-r--r--drivers/media/dvb/ddbridge/ddbridge-core.c2
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c7
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c4
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c885
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h27
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c4
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig5
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-fe.c105
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.c25
-rw-r--r--drivers/media/dvb/dvb-usb/af9005.h2
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c492
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h6
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c411
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.h6
-rw-r--r--drivers/media/dvb/dvb-usb/cinergyT2-fe.c33
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c11
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c717
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c33
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h6
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c93
-rw-r--r--drivers/media/dvb/dvb-usb/friio-fe.c29
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk-fe.c24
-rw-r--r--drivers/media/dvb/dvb-usb/it913x.c336
-rw-r--r--drivers/media/dvb/dvb-usb/lmedm04.c8
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-demod.c42
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf-tuner.c102
-rw-r--r--drivers/media/dvb/dvb-usb/mxl111sf.c16
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c19
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c20
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c32
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c98
-rw-r--r--drivers/media/dvb/firewire/firedtv-dvb.c5
-rw-r--r--drivers/media/dvb/firewire/firedtv-fe.c35
-rw-r--r--drivers/media/dvb/firewire/firedtv.h4
-rw-r--r--drivers/media/dvb/frontends/Kconfig7
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/af9013.c1727
-rw-r--r--drivers/media/dvb/frontends/af9013.h113
-rw-r--r--drivers/media/dvb/frontends/af9013_priv.h93
-rw-r--r--drivers/media/dvb/frontends/atbm8830.c27
-rw-r--r--drivers/media/dvb/frontends/au8522_dig.c58
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c18
-rw-r--r--drivers/media/dvb/frontends/bsbe1.h7
-rw-r--r--drivers/media/dvb/frontends/bsru6.h9
-rw-r--r--drivers/media/dvb/frontends/cx22700.c51
-rw-r--r--drivers/media/dvb/frontends/cx22702.c69
-rw-r--r--drivers/media/dvb/frontends/cx24110.c20
-rw-r--r--drivers/media/dvb/frontends/cx24113.c10
-rw-r--r--drivers/media/dvb/frontends/cx24116.c36
-rw-r--r--drivers/media/dvb/frontends/cx24123.c56
-rw-r--r--drivers/media/dvb/frontends/cxd2820r.h13
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_c.c25
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_core.c641
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_priv.h23
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t.c63
-rw-r--r--drivers/media/dvb/frontends/cxd2820r_t2.c70
-rw-r--r--drivers/media/dvb/frontends/dib0070.c10
-rw-r--r--drivers/media/dvb/frontends/dib0090.c165
-rw-r--r--drivers/media/dvb/frontends/dib0090.h54
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c113
-rw-r--r--drivers/media/dvb/frontends/dib3000mb_priv.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c132
-rw-r--r--drivers/media/dvb/frontends/dib7000m.c136
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c456
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h16
-rw-r--r--drivers/media/dvb/frontends/dib8000.c1073
-rw-r--r--drivers/media/dvb/frontends/dib8000.h42
-rw-r--r--drivers/media/dvb/frontends/dib9000.c36
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.h17
-rw-r--r--drivers/media/dvb/frontends/drxd.h2
-rw-r--r--drivers/media/dvb/frontends/drxd_hard.c62
-rw-r--r--drivers/media/dvb/frontends/drxk.h11
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.c314
-rw-r--r--drivers/media/dvb/frontends/drxk_hard.h8
-rw-r--r--drivers/media/dvb/frontends/ds3000.c36
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c65
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c18
-rw-r--r--drivers/media/dvb/frontends/ec100.c20
-rw-r--r--drivers/media/dvb/frontends/hd29l2.c861
-rw-r--r--drivers/media/dvb/frontends/hd29l2.h66
-rw-r--r--drivers/media/dvb/frontends/hd29l2_priv.h314
-rw-r--r--drivers/media/dvb/frontends/it913x-fe-priv.h806
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.c289
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.h43
-rw-r--r--drivers/media/dvb/frontends/itd1000.c7
-rw-r--r--drivers/media/dvb/frontends/ix2505v.c8
-rw-r--r--drivers/media/dvb/frontends/l64781.c117
-rw-r--r--drivers/media/dvb/frontends/lgdt3305.c98
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c37
-rw-r--r--drivers/media/dvb/frontends/lgs8gl5.c29
-rw-r--r--drivers/media/dvb/frontends/lgs8gxx.c26
-rw-r--r--drivers/media/dvb/frontends/mb86a16.c8
-rw-r--r--drivers/media/dvb/frontends/mb86a20s.c546
-rw-r--r--drivers/media/dvb/frontends/mt312.c37
-rw-r--r--drivers/media/dvb/frontends/mt352.c65
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c17
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c32
-rw-r--r--drivers/media/dvb/frontends/or51132.c52
-rw-r--r--drivers/media/dvb/frontends/or51211.c13
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c48
-rw-r--r--drivers/media/dvb/frontends/s5h1411.c48
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c71
-rw-r--r--drivers/media/dvb/frontends/s5h1432.c36
-rw-r--r--drivers/media/dvb/frontends/s921.c23
-rw-r--r--drivers/media/dvb/frontends/si21xx.c20
-rw-r--r--drivers/media/dvb/frontends/sp8870.c29
-rw-r--r--drivers/media/dvb/frontends/sp887x.c50
-rw-r--r--drivers/media/dvb/frontends/stb0899_drv.c37
-rw-r--r--drivers/media/dvb/frontends/stb6000.c8
-rw-r--r--drivers/media/dvb/frontends/stb6100.c6
-rw-r--r--drivers/media/dvb/frontends/stv0288.c17
-rw-r--r--drivers/media/dvb/frontends/stv0297.c37
-rw-r--r--drivers/media/dvb/frontends/stv0299.c32
-rw-r--r--drivers/media/dvb/frontends/stv0367.c156
-rw-r--r--drivers/media/dvb/frontends/stv0900_core.c37
-rw-r--r--drivers/media/dvb/frontends/stv090x.c13
-rw-r--r--drivers/media/dvb/frontends/stv6110.c3
-rw-r--r--drivers/media/dvb/frontends/tda10021.c111
-rw-r--r--drivers/media/dvb/frontends/tda10023.c103
-rw-r--r--drivers/media/dvb/frontends/tda10048.c83
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c111
-rw-r--r--drivers/media/dvb/frontends/tda10071.c8
-rw-r--r--drivers/media/dvb/frontends/tda10086.c62
-rw-r--r--drivers/media/dvb/frontends/tda18271c2dd.c52
-rw-r--r--drivers/media/dvb/frontends/tda8083.c19
-rw-r--r--drivers/media/dvb/frontends/tda826x.c7
-rw-r--r--drivers/media/dvb/frontends/tdhd1.h11
-rw-r--r--drivers/media/dvb/frontends/tua6100.c31
-rw-r--r--drivers/media/dvb/frontends/ves1820.c23
-rw-r--r--drivers/media/dvb/frontends/ves1x93.c23
-rw-r--r--drivers/media/dvb/frontends/zl10036.c10
-rw-r--r--drivers/media/dvb/frontends/zl10039.c10
-rw-r--r--drivers/media/dvb/frontends/zl10353.c116
-rw-r--r--drivers/media/dvb/mantis/mantis_vp1033.c8
-rw-r--r--drivers/media/dvb/mantis/mantis_vp2033.c9
-rw-r--r--drivers/media/dvb/mantis/mantis_vp2040.c9
-rw-r--r--drivers/media/dvb/ngene/ngene-cards.c2
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c6
-rw-r--r--drivers/media/dvb/pt1/va1j5jf8007s.c6
-rw-r--r--drivers/media/dvb/pt1/va1j5jf8007t.c6
-rw-r--r--drivers/media/dvb/siano/smsdvb.c33
-rw-r--r--drivers/media/dvb/ttpci/av7110.c102
-rw-r--r--drivers/media/dvb/ttpci/av7110.h3
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c50
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c51
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c27
-rw-r--r--drivers/media/dvb/ttpci/budget.c68
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c102
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c14
-rw-r--r--drivers/media/media-device.c3
-rw-r--r--drivers/media/radio/Kconfig297
-rw-r--r--drivers/media/radio/radio-gemtek.c10
-rw-r--r--drivers/media/radio/radio-miropcm20.c2
-rw-r--r--drivers/media/radio/radio-si4713.c15
-rw-r--r--drivers/media/radio/radio-timb.c15
-rw-r--r--drivers/media/radio/radio-wl1273.c17
-rw-r--r--drivers/media/radio/tef6862.c8
-rw-r--r--drivers/media/radio/wl128x/Kconfig2
-rw-r--r--drivers/media/radio/wl128x/fmdrv_common.c58
-rw-r--r--drivers/media/radio/wl128x/fmdrv_common.h28
-rw-r--r--drivers/media/radio/wl128x/fmdrv_rx.c84
-rw-r--r--drivers/media/radio/wl128x/fmdrv_rx.h50
-rw-r--r--drivers/media/radio/wl128x/fmdrv_tx.c61
-rw-r--r--drivers/media/radio/wl128x/fmdrv_tx.h20
-rw-r--r--drivers/media/radio/wl128x/fmdrv_v4l2.c1
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ir-nec-decoder.c4
-rw-r--r--drivers/media/rc/ir-raw.c1
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c67
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c205
-rw-r--r--drivers/media/rc/keymaps/rc-hauppauge.c51
-rw-r--r--drivers/media/rc/keymaps/rc-videomate-m1f.c24
-rw-r--r--drivers/media/rc/lirc_dev.c2
-rw-r--r--drivers/media/rc/mceusb.c4
-rw-r--r--drivers/media/rc/rc-core-priv.h12
-rw-r--r--drivers/media/rc/rc-main.c1
-rw-r--r--drivers/media/rc/redrat3.c52
-rw-r--r--drivers/media/rc/streamzap.c4
-rw-r--r--drivers/media/rc/winbond-cir.c4
-rw-r--r--drivers/media/video/Kconfig427
-rw-r--r--drivers/media/video/Makefile4
-rw-r--r--drivers/media/video/adv7170.c62
-rw-r--r--drivers/media/video/as3645a.c904
-rw-r--r--drivers/media/video/atmel-isi.c35
-rw-r--r--drivers/media/video/au0828/Kconfig1
-rw-r--r--drivers/media/video/au0828/au0828-i2c.c2
-rw-r--r--drivers/media/video/bt8xx/bt848.h5
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c58
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c1
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c2
-rw-r--r--drivers/media/video/bt8xx/bttv.h3
-rw-r--r--drivers/media/video/c-qcam.c2
-rw-r--r--drivers/media/video/cs5345.c2
-rw-r--r--drivers/media/video/cs53l32a.c2
-rw-r--r--drivers/media/video/cx18/cx18-driver.c2
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c2
-rw-r--r--drivers/media/video/cx18/cx18-i2c.h2
-rw-r--r--drivers/media/video/cx231xx/Kconfig6
-rw-r--r--drivers/media/video/cx231xx/cx231xx-audio.c24
-rw-r--r--drivers/media/video/cx231xx/cx231xx-cards.c86
-rw-r--r--drivers/media/video/cx231xx/cx231xx-core.c7
-rw-r--r--drivers/media/video/cx231xx/cx231xx-dvb.c4
-rw-r--r--drivers/media/video/cx231xx/cx231xx-input.c11
-rw-r--r--drivers/media/video/cx231xx/cx231xx-vbi.c4
-rw-r--r--drivers/media/video/cx231xx/cx231xx-video.c14
-rw-r--r--drivers/media/video/cx231xx/cx231xx.h2
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c141
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c75
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c24
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c108
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c175
-rw-r--r--drivers/media/video/cx23885/cx23885.h14
-rw-r--r--drivers/media/video/cx25821/cx25821-alsa.c75
-rw-r--r--drivers/media/video/cx25821/cx25821-audio-upstream.c113
-rw-r--r--drivers/media/video/cx25821/cx25821-audio.h39
-rw-r--r--drivers/media/video/cx25821/cx25821-cards.c2
-rw-r--r--drivers/media/video/cx25821/cx25821-core.c57
-rw-r--r--drivers/media/video/cx25821/cx25821-i2c.c12
-rw-r--r--drivers/media/video/cx25821/cx25821-medusa-defines.h6
-rw-r--r--drivers/media/video/cx25821/cx25821-medusa-reg.h518
-rw-r--r--drivers/media/video/cx25821/cx25821-medusa-video.c410
-rw-r--r--drivers/media/video/cx25821/cx25821-video-upstream-ch2.c138
-rw-r--r--drivers/media/video/cx25821/cx25821-video-upstream.c156
-rw-r--r--drivers/media/video/cx25821/cx25821-video.c145
-rw-r--r--drivers/media/video/cx25821/cx25821.h4
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c10
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c3241
-rw-r--r--drivers/media/video/cx88/Kconfig10
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c2
-rw-r--r--drivers/media/video/cx88/cx88-cards.c94
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c30
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c2
-rw-r--r--drivers/media/video/cx88/cx88-input.c4
-rw-r--r--drivers/media/video/cx88/cx88.h2
-rw-r--r--drivers/media/video/davinci/dm355_ccdc.c13
-rw-r--r--drivers/media/video/davinci/dm644x_ccdc.c13
-rw-r--r--drivers/media/video/davinci/isif.c13
-rw-r--r--drivers/media/video/davinci/vpbe.c76
-rw-r--r--drivers/media/video/davinci/vpbe_display.c43
-rw-r--r--drivers/media/video/davinci/vpbe_osd.c491
-rw-r--r--drivers/media/video/davinci/vpbe_venc.c223
-rw-r--r--drivers/media/video/davinci/vpfe_capture.c18
-rw-r--r--drivers/media/video/davinci/vpif_capture.c14
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c256
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c61
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c190
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c7
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h5
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c14
-rw-r--r--drivers/media/video/em28xx/em28xx.h8
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c4
-rw-r--r--drivers/media/video/fsl-viu.c13
-rw-r--r--drivers/media/video/gspca/Kconfig10
-rw-r--r--drivers/media/video/gspca/Makefile2
-rw-r--r--drivers/media/video/gspca/benq.c7
-rw-r--r--drivers/media/video/gspca/gl860/gl860.c1
-rw-r--r--drivers/media/video/gspca/gspca.c73
-rw-r--r--drivers/media/video/gspca/gspca.h5
-rw-r--r--drivers/media/video/gspca/jl2005bcd.c554
-rw-r--r--drivers/media/video/gspca/konica.c3
-rw-r--r--drivers/media/video/gspca/m5602/m5602_core.c4
-rw-r--r--drivers/media/video/gspca/m5602/m5602_mt9m111.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov7660.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_ov9650.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_po1030.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.h2
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.h2
-rw-r--r--drivers/media/video/gspca/mars.c1
-rw-r--r--drivers/media/video/gspca/nw80x.c2
-rw-r--r--drivers/media/video/gspca/ov519.c5
-rw-r--r--drivers/media/video/gspca/ov534_9.c141
-rw-r--r--drivers/media/video/gspca/pac207.c10
-rw-r--r--drivers/media/video/gspca/pac7302.c1
-rw-r--r--drivers/media/video/gspca/se401.c10
-rw-r--r--drivers/media/video/gspca/sn9c20x.c38
-rw-r--r--drivers/media/video/gspca/sonixb.c15
-rw-r--r--drivers/media/video/gspca/sonixj.c18
-rw-r--r--drivers/media/video/gspca/spca561.c2
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx.c8
-rw-r--r--drivers/media/video/gspca/t613.c25
-rw-r--r--drivers/media/video/gspca/topro.c2
-rw-r--r--drivers/media/video/gspca/vicam.c3
-rw-r--r--drivers/media/video/gspca/xirlink_cit.c6
-rw-r--r--drivers/media/video/gspca/zc3xx.c117
-rw-r--r--drivers/media/video/hdpvr/hdpvr-core.c2
-rw-r--r--drivers/media/video/ir-kbd-i2c.c25
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.h2
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c2
-rw-r--r--drivers/media/video/m5mols/m5mols.h46
-rw-r--r--drivers/media/video/m5mols/m5mols_capture.c83
-rw-r--r--drivers/media/video/m5mols/m5mols_core.c288
-rw-r--r--drivers/media/video/m5mols/m5mols_reg.h247
-rw-r--r--drivers/media/video/marvell-ccic/mcam-core.c42
-rw-r--r--drivers/media/video/marvell-ccic/mmp-driver.c35
-rw-r--r--drivers/media/video/msp3400-driver.c6
-rw-r--r--drivers/media/video/msp3400-driver.h6
-rw-r--r--drivers/media/video/mt9m001.c5
-rw-r--r--drivers/media/video/mt9m111.c380
-rw-r--r--drivers/media/video/mt9p031.c5
-rw-r--r--drivers/media/video/mt9t001.c5
-rw-r--r--drivers/media/video/mt9t031.c5
-rw-r--r--drivers/media/video/mt9v022.c5
-rw-r--r--drivers/media/video/mt9v032.c8
-rw-r--r--drivers/media/video/mx1_camera.c2
-rw-r--r--drivers/media/video/mx2_camera.c299
-rw-r--r--drivers/media/video/mx3_camera.c19
-rw-r--r--drivers/media/video/omap/omap_vout.c226
-rw-r--r--drivers/media/video/omap/omap_vout_vrfb.c2
-rw-r--r--drivers/media/video/omap/omap_voutdef.h2
-rw-r--r--drivers/media/video/omap1_camera.c16
-rw-r--r--drivers/media/video/omap24xxcam.c19
-rw-r--r--drivers/media/video/omap3isp/isp.c72
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c14
-rw-r--r--drivers/media/video/omap3isp/ispccdc.h2
-rw-r--r--drivers/media/video/omap3isp/ispccp2.c22
-rw-r--r--drivers/media/video/omap3isp/ispccp2.h3
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.c18
-rw-r--r--drivers/media/video/omap3isp/ispcsi2.h2
-rw-r--r--drivers/media/video/omap3isp/isppreview.c25
-rw-r--r--drivers/media/video/omap3isp/isppreview.h2
-rw-r--r--drivers/media/video/omap3isp/ispresizer.c7
-rw-r--r--drivers/media/video/omap3isp/ispresizer.h1
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c27
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h8
-rw-r--r--drivers/media/video/ov7670.c2
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c5
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c726
-rw-r--r--drivers/media/video/pwc/pwc-dec23.c288
-rw-r--r--drivers/media/video/pwc/pwc-dec23.h5
-rw-r--r--drivers/media/video/pwc/pwc-if.c297
-rw-r--r--drivers/media/video/pwc/pwc-kiara.h2
-rw-r--r--drivers/media/video/pwc/pwc-misc.c87
-rw-r--r--drivers/media/video/pwc/pwc-timon.h2
-rw-r--r--drivers/media/video/pwc/pwc-uncompress.c46
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c258
-rw-r--r--drivers/media/video/pwc/pwc.h66
-rw-r--r--drivers/media/video/pxa_camera.c17
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c11
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c134
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h30
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c53
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c22
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.h3
-rw-r--r--drivers/media/video/s5p-fimc/regs-fimc.h5
-rw-r--r--drivers/media/video/s5p-g2d/Makefile3
-rw-r--r--drivers/media/video/s5p-g2d/g2d-hw.c104
-rw-r--r--drivers/media/video/s5p-g2d/g2d-regs.h115
-rw-r--r--drivers/media/video/s5p-g2d/g2d.c810
-rw-r--r--drivers/media/video/s5p-g2d/g2d.h83
-rw-r--r--drivers/media/video/s5p-jpeg/Makefile2
-rw-r--r--drivers/media/video/s5p-jpeg/jpeg-core.c1481
-rw-r--r--drivers/media/video/s5p-jpeg/jpeg-core.h143
-rw-r--r--drivers/media/video/s5p-jpeg/jpeg-hw.h353
-rw-r--r--drivers/media/video/s5p-jpeg/jpeg-regs.h170
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc.c22
-rw-r--r--drivers/media/video/s5p-tv/hdmi_drv.c30
-rw-r--r--drivers/media/video/s5p-tv/mixer.h14
-rw-r--r--drivers/media/video/s5p-tv/mixer_grp_layer.c157
-rw-r--r--drivers/media/video/s5p-tv/mixer_video.c342
-rw-r--r--drivers/media/video/s5p-tv/mixer_vp_layer.c108
-rw-r--r--drivers/media/video/s5p-tv/sdo_drv.c22
-rw-r--r--drivers/media/video/saa7115.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c33
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c33
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c23
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c65
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
-rw-r--r--drivers/media/video/saa7164/saa7164-bus.c4
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c11
-rw-r--r--drivers/media/video/sh_mobile_csi2.c13
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c4
-rw-r--r--drivers/media/video/soc_camera.c4
-rw-r--r--drivers/media/video/soc_camera_platform.c13
-rw-r--r--drivers/media/video/stk-webcam.c8
-rw-r--r--drivers/media/video/timblogiw.c17
-rw-r--r--drivers/media/video/tlg2300/pd-common.h2
-rw-r--r--drivers/media/video/tlg2300/pd-dvb.c22
-rw-r--r--drivers/media/video/tm6000/Kconfig6
-rw-r--r--drivers/media/video/tm6000/tm6000-alsa.c23
-rw-r--r--drivers/media/video/tm6000/tm6000-cards.c35
-rw-r--r--drivers/media/video/tm6000/tm6000-core.c86
-rw-r--r--drivers/media/video/tm6000/tm6000-dvb.c21
-rw-r--r--drivers/media/video/tm6000/tm6000-i2c.c8
-rw-r--r--drivers/media/video/tm6000/tm6000-input.c407
-rw-r--r--drivers/media/video/tm6000/tm6000-regs.h14
-rw-r--r--drivers/media/video/tm6000/tm6000-stds.c89
-rw-r--r--drivers/media/video/tm6000/tm6000-video.c21
-rw-r--r--drivers/media/video/tm6000/tm6000.h3
-rw-r--r--drivers/media/video/tuner-core.c1
-rw-r--r--drivers/media/video/tvp514x.c2
-rw-r--r--drivers/media/video/tvp5150.c81
-rw-r--r--drivers/media/video/tvp7002.c2
-rw-r--r--drivers/media/video/upd64083.c2
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c46
-rw-r--r--drivers/media/video/uvc/Kconfig1
-rw-r--r--drivers/media/video/uvc/Makefile2
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c19
-rw-r--r--drivers/media/video/uvc/uvc_debugfs.c136
-rw-r--r--drivers/media/video/uvc/uvc_driver.c30
-rw-r--r--drivers/media/video/uvc/uvc_isight.c10
-rw-r--r--drivers/media/video/uvc/uvc_queue.c564
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c29
-rw-r--r--drivers/media/video/uvc/uvc_video.c625
-rw-r--r--drivers/media/video/uvc/uvcvideo.h128
-rw-r--r--drivers/media/video/v4l2-compat-ioctl32.c2
-rw-r--r--drivers/media/video/v4l2-ctrls.c5
-rw-r--r--drivers/media/video/v4l2-dev.c14
-rw-r--r--drivers/media/video/v4l2-device.c4
-rw-r--r--drivers/media/video/v4l2-ioctl.c120
-rw-r--r--drivers/media/video/v4l2-subdev.c4
-rw-r--r--drivers/media/video/via-camera.c26
-rw-r--r--drivers/media/video/videobuf-dvb.c7
-rw-r--r--drivers/media/video/videobuf2-core.c118
-rw-r--r--drivers/media/video/videobuf2-dma-sg.c3
-rw-r--r--drivers/media/video/videobuf2-memops.c28
-rw-r--r--drivers/media/video/videobuf2-vmalloc.c90
-rw-r--r--drivers/media/video/vino.c2
-rw-r--r--drivers/media/video/zoran/zoran_device.c2
-rw-r--r--drivers/media/video/zoran/zr36060.c2
-rw-r--r--drivers/memstick/host/jmb38x_ms.c2
-rw-r--r--drivers/memstick/host/r592.c2
-rw-r--r--drivers/memstick/host/tifm_ms.c2
-rw-r--r--drivers/mfd/88pm860x-i2c.c241
-rw-r--r--drivers/mfd/Kconfig36
-rw-r--r--drivers/mfd/Makefile5
-rw-r--r--drivers/mfd/aat2870-core.c25
-rw-r--r--drivers/mfd/ab5500-core.c2
-rw-r--r--drivers/mfd/ab5500-debugfs.c2
-rw-r--r--drivers/mfd/ab8500-core.c2
-rw-r--r--drivers/mfd/ab8500-debugfs.c2
-rw-r--r--drivers/mfd/ab8500-gpadc.c4
-rw-r--r--drivers/mfd/ab8500-i2c.c2
-rw-r--r--drivers/mfd/ab8500-sysctrl.c4
-rw-r--r--drivers/mfd/cs5535-mfd.c8
-rw-r--r--drivers/mfd/dm355evm_msp.c3
-rw-r--r--drivers/mfd/intel_msic.c12
-rw-r--r--drivers/mfd/janz-cmodio.c2
-rw-r--r--drivers/mfd/jz4740-adc.c14
-rw-r--r--drivers/mfd/lpc_sch.c2
-rw-r--r--drivers/mfd/max8925-core.c15
-rw-r--r--drivers/mfd/max8925-i2c.c27
-rw-r--r--drivers/mfd/max8997.c3
-rw-r--r--drivers/mfd/max8998.c6
-rw-r--r--drivers/mfd/mc13xxx-core.c111
-rw-r--r--drivers/mfd/mcp-core.c44
-rw-r--r--drivers/mfd/mcp-sa11x0.c182
-rw-r--r--drivers/mfd/omap-usb-host.c18
-rw-r--r--drivers/mfd/pcf50633-adc.c12
-rw-r--r--drivers/mfd/s5m-core.c176
-rw-r--r--drivers/mfd/s5m-irq.c487
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/mfd/stmpe-i2c.c109
-rw-r--r--drivers/mfd/stmpe-spi.c150
-rw-r--r--drivers/mfd/stmpe.c277
-rw-r--r--drivers/mfd/stmpe.h53
-rw-r--r--drivers/mfd/t7l66xb.c16
-rw-r--r--drivers/mfd/tc6387xb.c14
-rw-r--r--drivers/mfd/ti-ssp.c12
-rw-r--r--drivers/mfd/timberdale.c2
-rw-r--r--drivers/mfd/tps65910-irq.c3
-rw-r--r--drivers/mfd/tps65910.c7
-rw-r--r--drivers/mfd/tps65912-spi.c1
-rw-r--r--drivers/mfd/twl-core.c51
-rw-r--r--drivers/mfd/twl4030-audio.c12
-rw-r--r--drivers/mfd/twl4030-irq.c3
-rw-r--r--drivers/mfd/twl4030-madc.c14
-rw-r--r--drivers/mfd/twl4030-power.c42
-rw-r--r--drivers/mfd/twl6040-core.c20
-rw-r--r--drivers/mfd/ucb1x00-core.c48
-rw-r--r--drivers/mfd/ucb1x00-ts.c2
-rw-r--r--drivers/mfd/vx855.c2
-rw-r--r--drivers/mfd/wm831x-core.c4
-rw-r--r--drivers/mfd/wm831x-i2c.c3
-rw-r--r--drivers/mfd/wm831x-irq.c8
-rw-r--r--drivers/mfd/wm831x-spi.c4
-rw-r--r--drivers/mfd/wm8350-core.c2
-rw-r--r--drivers/mfd/wm8350-i2c.c4
-rw-r--r--drivers/mfd/wm8400-core.c7
-rw-r--r--drivers/mfd/wm8994-core.c158
-rw-r--r--drivers/mfd/wm8994-irq.c206
-rw-r--r--drivers/mfd/wm8994-regmap.c1238
-rw-r--r--drivers/mfd/wm8994.h25
-rw-r--r--drivers/misc/Kconfig8
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ab8500-pwm.c2
-rw-r--r--drivers/misc/carma/carma-fpga-program.c2
-rw-r--r--drivers/misc/iwmc3200top/main.c12
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d.c2
-rw-r--r--drivers/misc/max8997-muic.c505
-rw-r--r--drivers/mmc/Makefile3
-rw-r--r--drivers/mmc/card/block.c247
-rw-r--r--drivers/mmc/card/mmc_test.c1
-rw-r--r--drivers/mmc/card/queue.c5
-rw-r--r--drivers/mmc/core/Makefile2
-rw-r--r--drivers/mmc/core/bus.c5
-rw-r--r--drivers/mmc/core/cd-gpio.c74
-rw-r--r--drivers/mmc/core/core.c101
-rw-r--r--drivers/mmc/core/core.h5
-rw-r--r--drivers/mmc/core/debugfs.c5
-rw-r--r--drivers/mmc/core/host.c53
-rw-r--r--drivers/mmc/core/mmc.c203
-rw-r--r--drivers/mmc/core/sd.c21
-rw-r--r--drivers/mmc/core/sdio.c342
-rw-r--r--drivers/mmc/core/sdio_io.c8
-rw-r--r--drivers/mmc/core/sdio_ops.c14
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/at91_mci.c8
-rw-r--r--drivers/mmc/host/atmel-mci.c10
-rw-r--r--drivers/mmc/host/au1xmmc.c45
-rw-r--r--drivers/mmc/host/bfin_sdh.c12
-rw-r--r--drivers/mmc/host/cb710-mmc.c13
-rw-r--r--drivers/mmc/host/dw_mmc.c71
-rw-r--r--drivers/mmc/host/dw_mmc.h2
-rw-r--r--drivers/mmc/host/jz4740_mmc.c12
-rw-r--r--drivers/mmc/host/mmc_spi.c1
-rw-r--r--drivers/mmc/host/mmci.c12
-rw-r--r--drivers/mmc/host/msm_sdcc.c19
-rw-r--r--drivers/mmc/host/mxcmmc.c23
-rw-r--r--drivers/mmc/host/mxs-mmc.c23
-rw-r--r--drivers/mmc/host/omap_hsmmc.c43
-rw-r--r--drivers/mmc/host/pxamci.c13
-rw-r--r--drivers/mmc/host/s3cmci.c13
-rw-r--r--drivers/mmc/host/sdhci-cns3xxx.c12
-rw-r--r--drivers/mmc/host/sdhci-dove.c12
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c12
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h2
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c12
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c12
-rw-r--r--drivers/mmc/host/sdhci-pci-data.c5
-rw-r--r--drivers/mmc/host/sdhci-pci.c181
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c12
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c12
-rw-r--r--drivers/mmc/host/sdhci-s3c.c18
-rw-r--r--drivers/mmc/host/sdhci-spear.c51
-rw-r--r--drivers/mmc/host/sdhci-tegra.c12
-rw-r--r--drivers/mmc/host/sdhci.c150
-rw-r--r--drivers/mmc/host/sdhci.h1
-rw-r--r--drivers/mmc/host/sh_mmcif.c730
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c13
-rw-r--r--drivers/mmc/host/tifm_sd.c20
-rw-r--r--drivers/mmc/host/tmio_mmc.c14
-rw-r--r--drivers/mmc/host/tmio_mmc.h4
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c4
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c30
-rw-r--r--drivers/mmc/host/vub300.c10
-rw-r--r--drivers/mtd/mtdoops.c3
-rw-r--r--drivers/mtd/nand/au1550nd.c298
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c22
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c2
-rw-r--r--drivers/mtd/nand/r852.c2
-rw-r--r--drivers/mtd/ubi/cdev.c3
-rw-r--r--drivers/mtd/ubi/debug.h5
-rw-r--r--drivers/mtd/ubi/eba.c6
-rw-r--r--drivers/mtd/ubi/ubi.h2
-rw-r--r--drivers/mtd/ubi/vtbl.c6
-rw-r--r--drivers/mtd/ubi/wl.c12
-rw-r--r--drivers/net/bonding/bond_alb.c112
-rw-r--r--drivers/net/ethernet/8390/ax88796.c3
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.c3
-rw-r--r--drivers/net/ethernet/amd/au1000_eth.c3
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c298
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h1
-rw-r--r--drivers/net/ethernet/broadcom/sb1250-mac.c3
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c27
-rw-r--r--drivers/net/ethernet/cadence/macb.c3
-rw-r--r--drivers/net/ethernet/dnet.c3
-rw-r--r--drivers/net/ethernet/freescale/fec.c12
-rw-r--r--drivers/net/ethernet/freescale/fec.h4
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c34
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h3
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_ethtool.c2
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_main.c32
-rw-r--r--drivers/net/ethernet/ibm/ehea/ehea_qmr.c14
-rw-r--r--drivers/net/ethernet/lantiq_etop.c5
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c3
-rw-r--r--drivers/net/ethernet/marvell/pxa168_eth.c3
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c4
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c2
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c3
-rw-r--r--drivers/net/ethernet/s6gmac.c2
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc_core.c1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c2
-rw-r--r--drivers/net/ethernet/ti/cpmac.c2
-rw-r--r--drivers/net/ethernet/ti/davinci_mdio.c3
-rw-r--r--drivers/net/ethernet/tundra/tsi108_eth.c6
-rw-r--r--drivers/net/ethernet/via/via-rhine.c668
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c2
-rw-r--r--drivers/net/irda/Kconfig6
-rw-r--r--drivers/net/irda/au1000_ircc.h125
-rw-r--r--drivers/net/irda/au1k_ir.c1229
-rw-r--r--drivers/net/phy/dp83640.c2
-rw-r--r--drivers/net/phy/fixed.c2
-rw-r--r--drivers/net/phy/mdio-gpio.c2
-rw-r--r--drivers/net/phy/mdio-octeon.c3
-rw-r--r--drivers/net/phy/mdio_bus.c24
-rw-r--r--drivers/net/ppp/pptp.c4
-rw-r--r--drivers/net/usb/asix.c15
-rw-r--r--drivers/net/virtio_net.c125
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c8
-rw-r--r--drivers/net/wireless/b43/main.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c40
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/srom.c31
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c2
-rw-r--r--drivers/net/wireless/mwl8k.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c28
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c4
-rw-r--r--drivers/of/address.c16
-rw-r--r--drivers/of/fdt.c1
-rw-r--r--drivers/of/irq.c11
-rw-r--r--drivers/parisc/dino.c47
-rw-r--r--drivers/parisc/lba_pci.c72
-rw-r--r--drivers/parport/parport_ip32.c2
-rw-r--r--drivers/parport/parport_pc.c4
-rw-r--r--drivers/pci/access.c76
-rw-r--r--drivers/pci/ats.c17
-rw-r--r--drivers/pci/bus.c32
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c2
-rw-r--r--drivers/pci/hotplug/cpcihp_zt5550.c4
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c4
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c2
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h6
-rw-r--r--drivers/pci/hotplug/pciehp_core.c6
-rw-r--r--drivers/pci/hotplug/pcihp_skeleton.c2
-rw-r--r--drivers/pci/hotplug/rpaphp.h2
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp.h4
-rw-r--r--drivers/pci/hotplug/shpchp_core.c4
-rw-r--r--drivers/pci/iov.c16
-rw-r--r--drivers/pci/msi.c43
-rw-r--r--drivers/pci/pci-driver.c3
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c153
-rw-r--r--drivers/pci/pci.h10
-rw-r--r--drivers/pci/pcie/Kconfig2
-rw-r--r--drivers/pci/pcie/aer/aer_inject.c2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c4
-rw-r--r--drivers/pci/probe.c68
-rw-r--r--drivers/pci/remove.c10
-rw-r--r--drivers/pci/setup-res.c6
-rw-r--r--drivers/pcmcia/Kconfig8
-rw-r--r--drivers/pcmcia/Makefile4
-rw-r--r--drivers/pcmcia/au1000_generic.c545
-rw-r--r--drivers/pcmcia/au1000_generic.h135
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c294
-rw-r--r--drivers/pcmcia/db1xxx_ss.c26
-rw-r--r--drivers/pcmcia/yenta_socket.c6
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/platform/x86/compal-laptop.c2
-rw-r--r--drivers/platform/x86/intel_oaktrail.c2
-rw-r--r--drivers/platform/x86/msi-laptop.c2
-rw-r--r--drivers/platform/x86/samsung-laptop.c4
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c16
-rw-r--r--drivers/platform/x86/wmi.c4
-rw-r--r--drivers/pnp/quirks.c42
-rw-r--r--drivers/power/Kconfig32
-rw-r--r--drivers/power/Makefile5
-rw-r--r--drivers/power/bq27x00_battery.c210
-rw-r--r--drivers/power/charger-manager.c1072
-rw-r--r--drivers/power/collie_battery.c55
-rw-r--r--drivers/power/da9030_battery.c13
-rw-r--r--drivers/power/da9052-battery.c664
-rw-r--r--drivers/power/ds2760_battery.c21
-rw-r--r--drivers/power/ds2780_battery.c18
-rw-r--r--drivers/power/gpio-charger.c12
-rw-r--r--drivers/power/intel_mid_battery.c13
-rw-r--r--drivers/power/isp1704_charger.c14
-rw-r--r--drivers/power/jz4740-battery.c14
-rw-r--r--drivers/power/lp8727_charger.c494
-rw-r--r--drivers/power/max17042_battery.c94
-rw-r--r--drivers/power/max8903_charger.c14
-rw-r--r--drivers/power/max8925_power.c75
-rw-r--r--drivers/power/max8997_charger.c4
-rw-r--r--drivers/power/max8998_charger.c14
-rw-r--r--drivers/power/olpc_battery.c75
-rw-r--r--drivers/power/pcf50633-charger.c12
-rw-r--r--drivers/power/pda_power.c89
-rw-r--r--drivers/power/power_supply_core.c19
-rw-r--r--drivers/power/power_supply_sysfs.c12
-rw-r--r--drivers/power/s3c_adc_battery.c37
-rw-r--r--drivers/power/sbs-battery.c (renamed from drivers/power/bq20z75.c)481
-rw-r--r--drivers/power/tosa_battery.c79
-rw-r--r--drivers/power/wm831x_backup.c12
-rw-r--r--drivers/power/wm831x_power.c56
-rw-r--r--drivers/power/wm8350_power.c12
-rw-r--r--drivers/power/wm97xx_battery.c20
-rw-r--r--drivers/power/z2_battery.c4
-rw-r--r--drivers/regulator/ab8500.c2
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/interface.c4
-rw-r--r--drivers/rtc/rtc-88pm860x.c12
-rw-r--r--drivers/rtc/rtc-ab8500.c138
-rw-r--r--drivers/rtc/rtc-bfin.c13
-rw-r--r--drivers/rtc/rtc-bq4802.c13
-rw-r--r--drivers/rtc/rtc-cmos.c2
-rw-r--r--drivers/rtc/rtc-dm355evm.c12
-rw-r--r--drivers/rtc/rtc-ds1286.c13
-rw-r--r--drivers/rtc/rtc-ds1511.c15
-rw-r--r--drivers/rtc/rtc-ds1553.c13
-rw-r--r--drivers/rtc/rtc-ds1742.c13
-rw-r--r--drivers/rtc/rtc-jz4740.c14
-rw-r--r--drivers/rtc/rtc-lpc32xx.c12
-rw-r--r--drivers/rtc/rtc-m41t93.c1
-rw-r--r--drivers/rtc/rtc-m41t94.c1
-rw-r--r--drivers/rtc/rtc-m48t35.c13
-rw-r--r--drivers/rtc/rtc-m48t59.c13
-rw-r--r--drivers/rtc/rtc-m48t86.c13
-rw-r--r--drivers/rtc/rtc-max6902.c1
-rw-r--r--drivers/rtc/rtc-max8925.c38
-rw-r--r--drivers/rtc/rtc-max8998.c12
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mpc5121.c12
-rw-r--r--drivers/rtc/rtc-mrst.c13
-rw-r--r--drivers/rtc/rtc-mxc.c123
-rw-r--r--drivers/rtc/rtc-pcf2123.c1
-rw-r--r--drivers/rtc/rtc-pcf50633.c12
-rw-r--r--drivers/rtc/rtc-pm8xxx.c12
-rw-r--r--drivers/rtc/rtc-puv3.c22
-rw-r--r--drivers/rtc/rtc-rs5c348.c1
-rw-r--r--drivers/rtc/rtc-s3c.c16
-rw-r--r--drivers/rtc/rtc-sa1100.c13
-rw-r--r--drivers/rtc/rtc-spear.c12
-rw-r--r--drivers/rtc/rtc-stk17ta8.c13
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c13
-rw-r--r--drivers/rtc/rtc-twl.c10
-rw-r--r--drivers/rtc/rtc-v3020.c13
-rw-r--r--drivers/rtc/rtc-vr41xx.c13
-rw-r--r--drivers/rtc/rtc-vt8500.c12
-rw-r--r--drivers/rtc/rtc-wm831x.c36
-rw-r--r--drivers/rtc/rtc-wm8350.c12
-rw-r--r--drivers/s390/char/raw3270.c2
-rw-r--r--drivers/s390/char/vmwatchdog.c4
-rw-r--r--drivers/s390/cio/cmf.c2
-rw-r--r--drivers/s390/kvm/kvm_virtio.c2
-rw-r--r--drivers/scsi/aha1542.c2
-rw-r--r--drivers/scsi/dc395x.c2
-rw-r--r--drivers/scsi/ipr.c67
-rw-r--r--drivers/scsi/ipr.h1
-rw-r--r--drivers/scsi/nsp32.c4
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c2
-rw-r--r--drivers/scsi/scsi_netlink.c2
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/sd.c13
-rw-r--r--drivers/sh/Makefile9
-rw-r--r--drivers/sh/clk/core.c9
-rw-r--r--drivers/sh/clk/cpg.c79
-rw-r--r--drivers/sh/pfc.c273
-rw-r--r--drivers/spi/Kconfig7
-rw-r--r--drivers/spi/spi-dw-mid.c8
-rw-r--r--drivers/spi/spi-ep93xx.c9
-rw-r--r--drivers/spi/spi-pl022.c8
-rw-r--r--drivers/spi/spi-topcliff-pch.c4
-rw-r--r--drivers/staging/comedi/comedi_fops.c2
-rw-r--r--drivers/staging/comedi/comedi_fops.h3
-rw-r--r--drivers/staging/media/as102/Kconfig1
-rw-r--r--drivers/staging/media/as102/Makefile2
-rw-r--r--drivers/staging/media/as102/as102_drv.c126
-rw-r--r--drivers/staging/media/as102/as102_drv.h59
-rw-r--r--drivers/staging/media/as102/as102_fe.c81
-rw-r--r--drivers/staging/media/as102/as102_fw.c44
-rw-r--r--drivers/staging/media/as102/as102_fw.h10
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.c48
-rw-r--r--drivers/staging/media/as102/as102_usb_drv.h6
-rw-r--r--drivers/staging/media/as102/as10x_cmd.c143
-rw-r--r--drivers/staging/media/as102/as10x_cmd.h895
-rw-r--r--drivers/staging/media/as102/as10x_cmd_cfg.c66
-rw-r--r--drivers/staging/media/as102/as10x_cmd_stream.c56
-rw-r--r--drivers/staging/media/as102/as10x_handle.h26
-rw-r--r--drivers/staging/media/as102/as10x_types.h250
-rw-r--r--drivers/staging/media/dt3155v4l/dt3155v4l.c17
-rw-r--r--drivers/staging/media/easycap/easycap.h93
-rw-r--r--drivers/staging/media/easycap/easycap_ioctl.c60
-rw-r--r--drivers/staging/media/easycap/easycap_low.c273
-rw-r--r--drivers/staging/media/easycap/easycap_main.c379
-rw-r--r--drivers/staging/media/easycap/easycap_settings.c2
-rw-r--r--drivers/staging/media/easycap/easycap_sound.c340
-rw-r--r--drivers/staging/media/go7007/go7007-usb.c8
-rw-r--r--drivers/staging/media/go7007/snd-go7007.c2
-rw-r--r--drivers/staging/media/lirc/lirc_bt829.c2
-rw-r--r--drivers/staging/media/lirc/lirc_igorplugusb.c4
-rw-r--r--drivers/staging/media/lirc/lirc_imon.c4
-rw-r--r--drivers/staging/media/lirc/lirc_parallel.c6
-rw-r--r--drivers/staging/media/lirc/lirc_serial.c123
-rw-r--r--drivers/staging/media/lirc/lirc_sir.c2
-rw-r--r--drivers/staging/media/lirc/lirc_zilog.c4
-rw-r--r--drivers/staging/media/solo6x10/Makefile2
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-jpeg.h (renamed from drivers/staging/media/solo6x10/jpeg.h)0
-rw-r--r--drivers/staging/media/solo6x10/v4l2-enc.c2
-rw-r--r--drivers/staging/octeon/Makefile5
-rw-r--r--drivers/staging/octeon/cvmx-address.h274
-rw-r--r--drivers/staging/octeon/cvmx-asxx-defs.h475
-rw-r--r--drivers/staging/octeon/cvmx-cmd-queue.c306
-rw-r--r--drivers/staging/octeon/cvmx-cmd-queue.h617
-rw-r--r--drivers/staging/octeon/cvmx-config.h169
-rw-r--r--drivers/staging/octeon/cvmx-dbg-defs.h72
-rw-r--r--drivers/staging/octeon/cvmx-fau.h597
-rw-r--r--drivers/staging/octeon/cvmx-fpa-defs.h403
-rw-r--r--drivers/staging/octeon/cvmx-fpa.c183
-rw-r--r--drivers/staging/octeon/cvmx-fpa.h299
-rw-r--r--drivers/staging/octeon/cvmx-gmxx-defs.h2529
-rw-r--r--drivers/staging/octeon/cvmx-helper-board.c695
-rw-r--r--drivers/staging/octeon/cvmx-helper-board.h151
-rw-r--r--drivers/staging/octeon/cvmx-helper-fpa.c243
-rw-r--r--drivers/staging/octeon/cvmx-helper-fpa.h64
-rw-r--r--drivers/staging/octeon/cvmx-helper-loop.c85
-rw-r--r--drivers/staging/octeon/cvmx-helper-loop.h59
-rw-r--r--drivers/staging/octeon/cvmx-helper-npi.c113
-rw-r--r--drivers/staging/octeon/cvmx-helper-npi.h60
-rw-r--r--drivers/staging/octeon/cvmx-helper-rgmii.c525
-rw-r--r--drivers/staging/octeon/cvmx-helper-rgmii.h110
-rw-r--r--drivers/staging/octeon/cvmx-helper-sgmii.c550
-rw-r--r--drivers/staging/octeon/cvmx-helper-sgmii.h104
-rw-r--r--drivers/staging/octeon/cvmx-helper-spi.c195
-rw-r--r--drivers/staging/octeon/cvmx-helper-spi.h84
-rw-r--r--drivers/staging/octeon/cvmx-helper-util.c433
-rw-r--r--drivers/staging/octeon/cvmx-helper-util.h215
-rw-r--r--drivers/staging/octeon/cvmx-helper-xaui.c348
-rw-r--r--drivers/staging/octeon/cvmx-helper-xaui.h103
-rw-r--r--drivers/staging/octeon/cvmx-helper.c1058
-rw-r--r--drivers/staging/octeon/cvmx-helper.h227
-rw-r--r--drivers/staging/octeon/cvmx-interrupt-decodes.c371
-rw-r--r--drivers/staging/octeon/cvmx-interrupt-rsl.c140
-rw-r--r--drivers/staging/octeon/cvmx-ipd.h338
-rw-r--r--drivers/staging/octeon/cvmx-mdio.h506
-rw-r--r--drivers/staging/octeon/cvmx-packet.h65
-rw-r--r--drivers/staging/octeon/cvmx-pcsx-defs.h370
-rw-r--r--drivers/staging/octeon/cvmx-pcsxx-defs.h316
-rw-r--r--drivers/staging/octeon/cvmx-pip-defs.h1267
-rw-r--r--drivers/staging/octeon/cvmx-pip.h524
-rw-r--r--drivers/staging/octeon/cvmx-pko-defs.h1133
-rw-r--r--drivers/staging/octeon/cvmx-pko.c506
-rw-r--r--drivers/staging/octeon/cvmx-pko.h610
-rw-r--r--drivers/staging/octeon/cvmx-pow.h1982
-rw-r--r--drivers/staging/octeon/cvmx-scratch.h139
-rw-r--r--drivers/staging/octeon/cvmx-smix-defs.h178
-rw-r--r--drivers/staging/octeon/cvmx-spi.c667
-rw-r--r--drivers/staging/octeon/cvmx-spi.h269
-rw-r--r--drivers/staging/octeon/cvmx-spxx-defs.h347
-rw-r--r--drivers/staging/octeon/cvmx-srxx-defs.h126
-rw-r--r--drivers/staging/octeon/cvmx-stxx-defs.h292
-rw-r--r--drivers/staging/octeon/cvmx-wqe.h397
-rw-r--r--drivers/staging/octeon/ethernet-defines.h2
-rw-r--r--drivers/staging/octeon/ethernet-mdio.c4
-rw-r--r--drivers/staging/octeon/ethernet-mem.c2
-rw-r--r--drivers/staging/octeon/ethernet-rgmii.c4
-rw-r--r--drivers/staging/octeon/ethernet-rx.c16
-rw-r--r--drivers/staging/octeon/ethernet-rx.h2
-rw-r--r--drivers/staging/octeon/ethernet-sgmii.c4
-rw-r--r--drivers/staging/octeon/ethernet-spi.c6
-rw-r--r--drivers/staging/octeon/ethernet-tx.c12
-rw-r--r--drivers/staging/octeon/ethernet-xaui.c4
-rw-r--r--drivers/staging/octeon/ethernet.c16
-rw-r--r--drivers/staging/quatech_usb2/quatech_usb2.c2
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c2
-rw-r--r--drivers/staging/speakup/speakup.h2
-rw-r--r--drivers/staging/speakup/synth.c2
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c2
-rw-r--r--drivers/tty/rocket.c2
-rw-r--r--drivers/tty/serial/Kconfig23
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/amba-pl011.c8
-rw-r--r--drivers/tty/serial/ar933x_uart.c688
-rw-r--r--drivers/tty/serial/pch_uart.c4
-rw-r--r--drivers/tty/serial/sh-sci.c187
-rw-r--r--drivers/tty/serial/sh-sci.h4
-rw-r--r--drivers/tty/synclink.c2
-rw-r--r--drivers/tty/synclinkmp.c2
-rw-r--r--drivers/uio/uio_pci_generic.c78
-rw-r--r--drivers/usb/atm/speedtch.c6
-rw-r--r--drivers/usb/atm/ueagle-atm.c2
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/hub.c8
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/amd5536udc.c8
-rw-r--r--drivers/usb/gadget/ether.c4
-rw-r--r--drivers/usb/gadget/file_storage.c10
-rw-r--r--drivers/usb/gadget/net2272.c2
-rw-r--r--drivers/usb/gadget/net2280.c6
-rw-r--r--drivers/usb/gadget/omap_udc.c2
-rw-r--r--drivers/usb/gadget/pch_udc.c2
-rw-r--r--drivers/usb/gadget/serial.c4
-rw-r--r--drivers/usb/gadget/zero.c2
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/alchemy-common.c277
-rw-r--r--drivers/usb/host/ehci-ath79.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/ohci-au1xxx.c13
-rw-r--r--drivers/usb/host/ohci-hcd.c4
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/host/u132-hcd.c2
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/misc/ftdi-elan.c2
-rw-r--r--drivers/usb/misc/iowarrior.c2
-rw-r--r--drivers/usb/musb/cppi_dma.c2
-rw-r--r--drivers/usb/musb/musb_core.c2
-rw-r--r--drivers/usb/musb/ux500_dma.c4
-rw-r--r--drivers/usb/otg/ab8500-usb.c2
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c4
-rw-r--r--drivers/usb/serial/aircable.c2
-rw-r--r--drivers/usb/serial/ark3116.c2
-rw-r--r--drivers/usb/serial/belkin_sa.c2
-rw-r--r--drivers/usb/serial/ch341.c2
-rw-r--r--drivers/usb/serial/cp210x.c2
-rw-r--r--drivers/usb/serial/cyberjack.c2
-rw-r--r--drivers/usb/serial/cypress_m8.c6
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/empeg.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/funsoft.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/io_ti.c4
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/ipw.c2
-rw-r--r--drivers/usb/serial/ir-usb.c2
-rw-r--r--drivers/usb/serial/iuu_phoenix.c6
-rw-r--r--drivers/usb/serial/keyspan.c2
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/kl5kusb105.c2
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/mos7720.c2
-rw-r--r--drivers/usb/serial/mos7840.c2
-rw-r--r--drivers/usb/serial/navman.c2
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/opticon.c2
-rw-r--r--drivers/usb/serial/option.c2
-rw-r--r--drivers/usb/serial/oti6858.c2
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/qcserial.c2
-rw-r--r--drivers/usb/serial/safe_serial.c6
-rw-r--r--drivers/usb/serial/sierra.c4
-rw-r--r--drivers/usb/serial/spcp8x5.c2
-rw-r--r--drivers/usb/serial/ssu100.c2
-rw-r--r--drivers/usb/serial/symbolserial.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c2
-rw-r--r--drivers/usb/serial/usb-serial.c2
-rw-r--r--drivers/usb/serial/usb_wwan.c2
-rw-r--r--drivers/usb/serial/visor.c2
-rw-r--r--drivers/usb/serial/whiteheat.c2
-rw-r--r--drivers/vhost/net.c8
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c3732
-rw-r--r--drivers/video/atmel_lcdfb.c37
-rw-r--r--drivers/video/aty/atyfb_base.c4
-rw-r--r--drivers/video/aty/radeon_base.c18
-rw-r--r--drivers/video/au1100fb.c12
-rw-r--r--drivers/video/au1200fb.c273
-rw-r--r--drivers/video/backlight/88pm860x_bl.c12
-rw-r--r--drivers/video/backlight/Kconfig8
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/adp5520_bl.c12
-rw-r--r--drivers/video/backlight/adx_bl.c182
-rw-r--r--drivers/video/backlight/backlight.c6
-rw-r--r--drivers/video/backlight/da903x_bl.c12
-rw-r--r--drivers/video/backlight/ep93xx_bl.c13
-rw-r--r--drivers/video/backlight/generic_bl.c13
-rw-r--r--drivers/video/backlight/jornada720_bl.c13
-rw-r--r--drivers/video/backlight/jornada720_lcd.c13
-rw-r--r--drivers/video/backlight/lcd.c26
-rw-r--r--drivers/video/backlight/ld9040.c71
-rw-r--r--drivers/video/backlight/max8925_bl.c12
-rw-r--r--drivers/video/backlight/omap1_bl.c13
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c12
-rw-r--r--drivers/video/backlight/platform_lcd.c22
-rw-r--r--drivers/video/backlight/pwm_bl.c33
-rw-r--r--drivers/video/backlight/wm831x_bl.c12
-rw-r--r--drivers/video/cirrusfb.c270
-rw-r--r--drivers/video/console/newport_con.c63
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/display/Kconfig24
-rw-r--r--drivers/video/display/Makefile6
-rw-r--r--drivers/video/display/display-sysfs.c219
-rw-r--r--drivers/video/fbmem.c14
-rw-r--r--drivers/video/fsl-diu-fb.c587
-rw-r--r--drivers/video/grvga.c4
-rw-r--r--drivers/video/hgafb.c2
-rw-r--r--drivers/video/i810/i810_main.c16
-rw-r--r--drivers/video/intelfb/intelfbdrv.c18
-rw-r--r--drivers/video/logo/logo.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c1
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c1
-rw-r--r--drivers/video/mbx/mbxfb.c13
-rw-r--r--drivers/video/mx3fb.c65
-rw-r--r--drivers/video/mxsfb.c13
-rw-r--r--drivers/video/neofb.c10
-rw-r--r--drivers/video/nuc900fb.c13
-rw-r--r--drivers/video/nvidia/nvidia.c6
-rw-r--r--drivers/video/omap/lcd_ams_delta.c15
-rw-r--r--drivers/video/omap/lcd_h3.c16
-rw-r--r--drivers/video/omap/lcd_htcherald.c16
-rw-r--r--drivers/video/omap/lcd_inn1510.c16
-rw-r--r--drivers/video/omap/lcd_inn1610.c16
-rw-r--r--drivers/video/omap/lcd_mipid.c1
-rw-r--r--drivers/video/omap/lcd_osk.c16
-rw-r--r--drivers/video/omap/lcd_palmte.c16
-rw-r--r--drivers/video/omap/lcd_palmtt.c15
-rw-r--r--drivers/video/omap/lcd_palmz71.c15
-rw-r--r--drivers/video/omap/omapfb_main.c4
-rw-r--r--drivers/video/omap2/displays/Kconfig2
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c1
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c66
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c1
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c62
-rw-r--r--drivers/video/omap2/displays/panel-taal.c38
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c1
-rw-r--r--drivers/video/omap2/dss/Makefile3
-rw-r--r--drivers/video/omap2/dss/apply.c1324
-rw-r--r--drivers/video/omap2/dss/core.c4
-rw-r--r--drivers/video/omap2/dss/dispc.c407
-rw-r--r--drivers/video/omap2/dss/dispc.h11
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c326
-rw-r--r--drivers/video/omap2/dss/dpi.c7
-rw-r--r--drivers/video/omap2/dss/dsi.c616
-rw-r--r--drivers/video/omap2/dss/dss.h76
-rw-r--r--drivers/video/omap2/dss/dss_features.c11
-rw-r--r--drivers/video/omap2/dss/dss_features.h1
-rw-r--r--drivers/video/omap2/dss/hdmi.c59
-rw-r--r--drivers/video/omap2/dss/manager.c1221
-rw-r--r--drivers/video/omap2/dss/overlay.c435
-rw-r--r--drivers/video/omap2/dss/rfbi.c1
-rw-r--r--drivers/video/omap2/dss/sdi.c8
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h10
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c37
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h3
-rw-r--r--drivers/video/omap2/dss/venc.c28
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c42
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c22
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c4
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h13
-rw-r--r--drivers/video/pm2fb.c8
-rw-r--r--drivers/video/pm3fb.c4
-rw-r--r--drivers/video/pnx4008/pnxrgbfb.c13
-rw-r--r--drivers/video/pnx4008/sdum.c13
-rw-r--r--drivers/video/pxa168fb.c12
-rw-r--r--drivers/video/pxa3xx-gcu.c15
-rw-r--r--drivers/video/riva/fbdev.c6
-rw-r--r--drivers/video/s3c-fb.c202
-rw-r--r--drivers/video/s3c2410fb.c29
-rw-r--r--drivers/video/s3fb.c30
-rw-r--r--drivers/video/sbuslib.c2
-rw-r--r--drivers/video/sh7760fb.c13
-rw-r--r--drivers/video/sh_mipi_dsi.c218
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c375
-rw-r--r--drivers/video/sh_mobile_meram.c13
-rw-r--r--drivers/video/sm501fb.c13
-rw-r--r--drivers/video/smscufx.c4
-rw-r--r--drivers/video/sstfb.c6
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--drivers/video/udlfb.c6
-rw-r--r--drivers/video/uvesafb.c6
-rw-r--r--drivers/video/vfb.c2
-rw-r--r--drivers/video/vt8500lcdfb.c13
-rw-r--r--drivers/video/w100fb.c13
-rw-r--r--drivers/video/wm8505fb.c13
-rw-r--r--drivers/video/wmt_ge_rops.c13
-rw-r--r--drivers/video/xilinxfb.c20
-rw-r--r--drivers/virtio/virtio_balloon.c108
-rw-r--r--drivers/virtio/virtio_mmio.c4
-rw-r--r--drivers/virtio/virtio_pci.c110
-rw-r--r--drivers/virtio/virtio_ring.c245
-rw-r--r--drivers/watchdog/f71808e_wdt.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c2
-rw-r--r--drivers/xen/biomerge.c1
-rw-r--r--drivers/xen/xen-balloon.c2
-rw-r--r--drivers/xen/xen-pciback/conf_space.c2
-rw-r--r--drivers/xen/xen-pciback/xenbus.c2
1431 files changed, 62729 insertions, 51598 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 1b31421..c07be02 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -97,7 +97,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
-obj-$(CONFIG_MMC) += mmc/
+obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index cb423f5..c339a08 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -44,7 +44,7 @@ MODULE_LICENSE("GPL");
*/
/* Emit various sounds */
-static int sound;
+static bool sound;
module_param(sound, bool, 0);
MODULE_PARM_DESC(sound, "emit sounds");
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 76dc02f..e6652d7 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -108,7 +108,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
/*
* Optionally enable output from the AML Debug Object.
*/
-u32 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
+bool ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
/*
* Optionally copy the entire DSDT to local memory (instead of simply
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index b8e08cb..ebaf037 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -118,7 +118,7 @@ struct ghes_estatus_cache {
struct rcu_head rcu;
};
-int ghes_disable;
+bool ghes_disable;
module_param_named(disable, ghes_disable, bool, 0);
static int ghes_panic_timeout __read_mostly = 30;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 05fee06..ee7fddc 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -41,7 +41,7 @@
#define HEST_PFX "HEST: "
-int hest_disable;
+bool hest_disable;
EXPORT_SYMBOL_GPL(hest_disable);
/* HEST table parsing */
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 19a6113..88eb143 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -43,7 +43,7 @@ MODULE_AUTHOR("Kristen Carlson Accardi");
MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
MODULE_LICENSE("GPL");
-static int immediate_undock = 1;
+static bool immediate_undock = 1;
module_param(immediate_undock, bool, 0644);
MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
"undock immediately when the undock button is pressed, 0 will cause"
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 7f9eba9..0eefa12 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -487,10 +487,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
else
link_desc[0] = '\0';
- dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
- pin_name(pin), link_desc, gsi,
- (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
+ pin_name(pin), link_desc, gsi,
+ (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return 0;
}
@@ -524,6 +524,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
* (e.g. PCI_UNDEFINED_IRQ).
*/
- dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
+ dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
acpi_unregister_gsi(gsi);
}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index 07f7fea..e50e31a 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -34,7 +34,7 @@
#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
-static int debug;
+static bool debug;
static int check_sta_before_sun;
#define DRIVER_VERSION "0.1"
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 08a44b5..eaef02a 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -69,21 +69,21 @@ MODULE_AUTHOR("Bruno Ducrot");
MODULE_DESCRIPTION("ACPI Video Driver");
MODULE_LICENSE("GPL");
-static int brightness_switch_enabled = 1;
+static bool brightness_switch_enabled = 1;
module_param(brightness_switch_enabled, bool, 0644);
/*
* By default, we don't allow duplicate ACPI video bus devices
* under the same VGA controller
*/
-static int allow_duplicates;
+static bool allow_duplicates;
module_param(allow_duplicates, bool, 0644);
/*
* Some BIOSes claim they use minimum backlight at boot,
* and this may bring dimming screen after boot
*/
-static int use_bios_initial_backlight = 1;
+static bool use_bios_initial_backlight = 1;
module_param(use_bios_initial_backlight, bool, 0644);
static int register_count = 0;
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 69ac373c7..fdf27b9 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1117,6 +1117,13 @@ static int piix_broken_suspend(void)
},
},
{
+ .ident = "Satellite Pro A120",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"),
+ },
+ },
+ {
.ident = "Portege M500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 11c9aea..c06e0ec 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4125,6 +4125,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
* device and controller are SATA.
*/
{ "PIONEER DVD-RW DVRTD08", NULL, ATA_HORKAGE_NOSETXFER },
+ { "PIONEER DVD-RW DVRTD08A", NULL, ATA_HORKAGE_NOSETXFER },
+ { "PIONEER DVD-RW DVR-215", NULL, ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index 9a7f0ea..74aaee3 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -291,6 +291,7 @@ int ata_tport_add(struct device *parent,
goto tport_err;
}
+ device_enable_async_suspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index d6a4677..1e65842 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -251,6 +251,8 @@ static const u32 udma_tenvmin = 20;
static const u32 udma_tackmin = 20;
static const u32 udma_tssmin = 50;
+#define BFIN_MAX_SG_SEGMENTS 4
+
/**
*
* Function: num_clocks_min
@@ -829,79 +831,61 @@ static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
{
- unsigned short config = WDSIZE_16;
+ struct ata_port *ap = qc->ap;
+ struct dma_desc_array *dma_desc_cpu = (struct dma_desc_array *)ap->bmdma_prd;
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ unsigned short config = DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_16 | DMAEN;
struct scatterlist *sg;
unsigned int si;
+ unsigned int channel;
+ unsigned int dir;
+ unsigned int size = 0;
dev_dbg(qc->ap->dev, "in atapi dma setup\n");
/* Program the ATA_CTRL register with dir */
if (qc->tf.flags & ATA_TFLAG_WRITE) {
- /* fill the ATAPI DMA controller */
- set_dma_config(CH_ATAPI_TX, config);
- set_dma_x_modify(CH_ATAPI_TX, 2);
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
- set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
- }
+ channel = CH_ATAPI_TX;
+ dir = DMA_TO_DEVICE;
} else {
+ channel = CH_ATAPI_RX;
+ dir = DMA_FROM_DEVICE;
config |= WNR;
- /* fill the ATAPI DMA controller */
- set_dma_config(CH_ATAPI_RX, config);
- set_dma_x_modify(CH_ATAPI_RX, 2);
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
- set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
- }
}
-}
-/**
- * bfin_bmdma_start - Start an IDE DMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_start().
- */
+ dma_map_sg(ap->dev, qc->sg, qc->n_elem, dir);
-static void bfin_bmdma_start(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- struct scatterlist *sg;
- unsigned int si;
+ /* fill the ATAPI DMA controller */
+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ dma_desc_cpu[si].start_addr = sg_dma_address(sg);
+ dma_desc_cpu[si].cfg = config;
+ dma_desc_cpu[si].x_count = sg_dma_len(sg) >> 1;
+ dma_desc_cpu[si].x_modify = 2;
+ size += sg_dma_len(sg);
+ }
- dev_dbg(qc->ap->dev, "in atapi dma start\n");
- if (!(ap->udma_mask || ap->mwdma_mask))
- return;
+ /* Set the last descriptor to stop mode */
+ dma_desc_cpu[qc->n_elem - 1].cfg &= ~(DMAFLOW | NDSIZE);
- /* start ATAPI DMA controller*/
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- /*
- * On blackfin arch, uncacheable memory is not
- * allocated with flag GFP_DMA. DMA buffer from
- * common kenel code should be flushed if WB
- * data cache is enabled. Otherwise, this loop
- * is an empty loop and optimized out.
- */
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- flush_dcache_range(sg_dma_address(sg),
- sg_dma_address(sg) + sg_dma_len(sg));
- }
- enable_dma(CH_ATAPI_TX);
- dev_dbg(qc->ap->dev, "enable udma write\n");
+ flush_dcache_range((unsigned int)dma_desc_cpu,
+ (unsigned int)dma_desc_cpu +
+ qc->n_elem * sizeof(struct dma_desc_array));
- /* Send ATA DMA write command */
- bfin_exec_command(ap, &qc->tf);
+ /* Enable ATA DMA operation*/
+ set_dma_curr_desc_addr(channel, (unsigned long *)ap->bmdma_prd_dma);
+ set_dma_x_count(channel, 0);
+ set_dma_x_modify(channel, 0);
+ set_dma_config(channel, config);
+
+ SSYNC();
+
+ /* Send ATA DMA command */
+ bfin_exec_command(ap, &qc->tf);
+ if (qc->tf.flags & ATA_TFLAG_WRITE) {
/* set ATA DMA write direction */
ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
| XFER_DIR));
} else {
- enable_dma(CH_ATAPI_RX);
- dev_dbg(qc->ap->dev, "enable udma read\n");
-
- /* Send ATA DMA read command */
- bfin_exec_command(ap, &qc->tf);
-
/* set ATA DMA read direction */
ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
& ~XFER_DIR));
@@ -913,12 +897,28 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
/* Set ATAPI state machine contorl in terminate sequence */
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM);
- /* Set transfer length to buffer len */
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
- }
+ /* Set transfer length to the total size of sg buffers */
+ ATAPI_SET_XFER_LEN(base, size >> 1);
+}
- /* Enable ATA DMA operation*/
+/**
+ * bfin_bmdma_start - Start an IDE DMA transaction
+ * @qc: Info associated with this ATA transaction.
+ *
+ * Note: Original code is ata_bmdma_start().
+ */
+
+static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+
+ dev_dbg(qc->ap->dev, "in atapi dma start\n");
+
+ if (!(ap->udma_mask || ap->mwdma_mask))
+ return;
+
+ /* start ATAPI transfer*/
if (ap->udma_mask)
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base)
| ULTRA_START);
@@ -935,34 +935,23 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- struct scatterlist *sg;
- unsigned int si;
+ unsigned int dir;
dev_dbg(qc->ap->dev, "in atapi dma stop\n");
+
if (!(ap->udma_mask || ap->mwdma_mask))
return;
/* stop ATAPI DMA controller*/
- if (qc->tf.flags & ATA_TFLAG_WRITE)
+ if (qc->tf.flags & ATA_TFLAG_WRITE) {
+ dir = DMA_TO_DEVICE;
disable_dma(CH_ATAPI_TX);
- else {
+ } else {
+ dir = DMA_FROM_DEVICE;
disable_dma(CH_ATAPI_RX);
- if (ap->hsm_task_state & HSM_ST_LAST) {
- /*
- * On blackfin arch, uncacheable memory is not
- * allocated with flag GFP_DMA. DMA buffer from
- * common kenel code should be invalidated if
- * data cache is enabled. Otherwise, this loop
- * is an empty loop and optimized out.
- */
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- invalidate_dcache_range(
- sg_dma_address(sg),
- sg_dma_address(sg)
- + sg_dma_len(sg));
- }
- }
}
+
+ dma_unmap_sg(ap->dev, qc->sg, qc->n_elem, dir);
}
/**
@@ -1260,6 +1249,11 @@ static void bfin_port_stop(struct ata_port *ap)
{
dev_dbg(ap->dev, "in atapi port stop\n");
if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
+ dma_free_coherent(ap->dev,
+ BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+ ap->bmdma_prd,
+ ap->bmdma_prd_dma);
+
free_dma(CH_ATAPI_RX);
free_dma(CH_ATAPI_TX);
}
@@ -1271,14 +1265,29 @@ static int bfin_port_start(struct ata_port *ap)
if (!(ap->udma_mask || ap->mwdma_mask))
return 0;
+ ap->bmdma_prd = dma_alloc_coherent(ap->dev,
+ BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+ &ap->bmdma_prd_dma,
+ GFP_KERNEL);
+
+ if (ap->bmdma_prd == NULL) {
+ dev_info(ap->dev, "Unable to allocate DMA descriptor array.\n");
+ goto out;
+ }
+
if (request_dma(CH_ATAPI_RX, "BFIN ATAPI RX DMA") >= 0) {
if (request_dma(CH_ATAPI_TX,
"BFIN ATAPI TX DMA") >= 0)
return 0;
free_dma(CH_ATAPI_RX);
+ dma_free_coherent(ap->dev,
+ BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
+ ap->bmdma_prd,
+ ap->bmdma_prd_dma);
}
+out:
ap->udma_mask = 0;
ap->mwdma_mask = 0;
dev_err(ap->dev, "Unable to request ATAPI DMA!"
@@ -1400,7 +1409,7 @@ static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
static struct scsi_host_template bfin_sht = {
ATA_BASE_SHT(DRV_NAME),
- .sg_tablesize = SG_NONE,
+ .sg_tablesize = BFIN_MAX_SG_SEGMENTS,
.dma_boundary = ATA_DMA_BOUNDARY,
};
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 5a2c95b..0120b0d 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -140,6 +140,7 @@ enum {
*/
HCONTROL_ONLINE_PHY_RST = (1 << 31),
HCONTROL_FORCE_OFFLINE = (1 << 30),
+ HCONTROL_LEGACY = (1 << 28),
HCONTROL_PARITY_PROT_MOD = (1 << 14),
HCONTROL_DPATH_PARITY = (1 << 12),
HCONTROL_SNOOP_ENABLE = (1 << 10),
@@ -1223,6 +1224,10 @@ static int sata_fsl_init_controller(struct ata_host *host)
* part of the port_start() callback
*/
+ /* sata controller to operate in enterprise mode */
+ temp = ioread32(hcr_base + HCONTROL);
+ iowrite32(temp & ~HCONTROL_LEGACY, hcr_base + HCONTROL);
+
/* ack. any pending IRQs for this controller/port */
temp = ioread32(hcr_base + HSTATUS);
if (temp & 0x3F)
@@ -1421,6 +1426,12 @@ static int sata_fsl_resume(struct platform_device *op)
/* Recovery the CHBA register in host controller cmd register set */
iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA);
+ iowrite32((ioread32(hcr_base + HCONTROL)
+ | HCONTROL_ONLINE_PHY_RST
+ | HCONTROL_SNOOP_ENABLE
+ | HCONTROL_PMP_ATTACHED),
+ hcr_base + HCONTROL);
+
ata_host_resume(host);
return 0;
}
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index e0bc964..55d6179 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -599,9 +599,9 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-static int adma_enabled;
-static int swncq_enabled = 1;
-static int msi_enabled;
+static bool adma_enabled;
+static bool swncq_enabled = 1;
+static bool msi_enabled;
static void nv_adma_register_mode(struct ata_port *ap)
{
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 1e91406..e7e610a 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -417,7 +417,7 @@ static struct ata_port_operations sil24_ops = {
#endif
};
-static int sata_sil24_msi; /* Disable MSI */
+static bool sata_sil24_msi; /* Disable MSI */
module_param_named(msi, sata_sil24_msi, bool, S_IRUGO);
MODULE_PARM_DESC(msi, "Enable MSI (Default: false)");
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 9a51df4..b182c2f 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -112,12 +112,12 @@ static u8 read_prom_byte(struct he_dev *he_dev, int addr);
/* globals */
static struct he_dev *he_devs;
-static int disable64;
+static bool disable64;
static short nvpibits = -1;
static short nvcibits = -1;
static short rx_skb_reserve = 16;
-static int irq_coalesce = 1;
-static int sdh = 0;
+static bool irq_coalesce = 1;
+static bool sdh = 0;
/* Read from EEPROM = 0000 0011b */
static unsigned int readtab[] = {
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index e95c67e..7be9f79 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -172,10 +172,14 @@ config SYS_HYPERVISOR
bool
default n
+config GENERIC_CPU_DEVICES
+ bool
+ default n
+
source "drivers/base/regmap/Kconfig"
config DMA_SHARED_BUFFER
- bool "Buffer framework to be shared between drivers"
+ bool
default n
select ANON_INODES
depends on EXPERIMENTAL
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 7a6ae42..b858dfd 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -94,7 +94,7 @@ extern int hypervisor_init(void);
static inline int hypervisor_init(void) { return 0; }
#endif
extern int platform_bus_init(void);
-extern int cpu_dev_init(void);
+extern void cpu_dev_init(void);
extern int bus_add_device(struct device *dev);
extern void bus_probe_device(struct device *dev);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 9a5578e..db87e78 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -2,6 +2,7 @@
* CPU subsystem support
*/
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -10,6 +11,7 @@
#include <linux/device.h>
#include <linux/node.h>
#include <linux/gfp.h>
+#include <linux/percpu.h>
#include "base.h"
@@ -274,16 +276,30 @@ bool cpu_is_hotpluggable(unsigned cpu)
}
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
-int __init cpu_dev_init(void)
+#ifdef CONFIG_GENERIC_CPU_DEVICES
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+#endif
+
+static void __init cpu_dev_register_generic(void)
+{
+#ifdef CONFIG_GENERIC_CPU_DEVICES
+ int i;
+
+ for_each_possible_cpu(i) {
+ if (register_cpu(&per_cpu(cpu_devices, i), i))
+ panic("Failed to register CPU device");
+ }
+#endif
+}
+
+void __init cpu_dev_init(void)
{
- int err;
+ if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
+ panic("Failed to register CPU subsystem");
- err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
- if (err)
- return err;
+ cpu_dev_register_generic();
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
+ sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
#endif
- return err;
}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index f17e3ea..ed5de58 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -295,11 +295,22 @@ static int memory_block_change_state(struct memory_block *mem,
ret = memory_block_action(mem->start_section_nr, to_state);
- if (ret)
+ if (ret) {
mem->state = from_state_req;
- else
- mem->state = to_state;
+ goto out;
+ }
+ mem->state = to_state;
+ switch (mem->state) {
+ case MEM_OFFLINE:
+ kobject_uevent(&mem->dev.kobj, KOBJ_OFFLINE);
+ break;
+ case MEM_ONLINE:
+ kobject_uevent(&mem->dev.kobj, KOBJ_ONLINE);
+ break;
+ default:
+ break;
+ }
out:
mutex_unlock(&mem->state_mutex);
return ret;
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 92e6a90..978bbf7 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1429,6 +1429,8 @@ static int pm_genpd_default_restore_state(struct device *dev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+
/**
* pm_genpd_default_suspend - Default "device suspend" for PM domians.
* @dev: Device to handle.
@@ -1517,6 +1519,19 @@ static int pm_genpd_default_thaw(struct device *dev)
return cb ? cb(dev) : pm_generic_thaw(dev);
}
+#else /* !CONFIG_PM_SLEEP */
+
+#define pm_genpd_default_suspend NULL
+#define pm_genpd_default_suspend_late NULL
+#define pm_genpd_default_resume_early NULL
+#define pm_genpd_default_resume NULL
+#define pm_genpd_default_freeze NULL
+#define pm_genpd_default_freeze_late NULL
+#define pm_genpd_default_thaw_early NULL
+#define pm_genpd_default_thaw NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
/**
* pm_genpd_init - Initialize a generic I/O PM domain object.
* @genpd: PM domain object to initialize.
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 51527ee..66a265b 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -12,6 +12,8 @@
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
+#ifdef CONFIG_PM_RUNTIME
+
/**
* default_stop_ok - Default PM domain governor routine for stopping devices.
* @dev: Device to check.
@@ -137,16 +139,28 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
return true;
}
-struct dev_power_governor simple_qos_governor = {
- .stop_ok = default_stop_ok,
- .power_down_ok = default_power_down_ok,
-};
-
static bool always_on_power_down_ok(struct dev_pm_domain *domain)
{
return false;
}
+#else /* !CONFIG_PM_RUNTIME */
+
+bool default_stop_ok(struct device *dev)
+{
+ return false;
+}
+
+#define default_power_down_ok NULL
+#define always_on_power_down_ok NULL
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+struct dev_power_governor simple_qos_governor = {
+ .stop_ok = default_stop_ok,
+ .power_down_ok = default_power_down_ok,
+};
+
/**
* pm_genpd_gov_always_on - A governor implementing an always-on policy
*/
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index fda56bd..0def898 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -19,6 +19,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
struct bcma_device *core_cc,
struct bcma_device *core_mips);
#ifdef CONFIG_PM
+int bcma_bus_suspend(struct bcma_bus *bus);
int bcma_bus_resume(struct bcma_bus *bus);
#endif
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 443b83a..f59244e 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -235,38 +235,32 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
}
#ifdef CONFIG_PM
-static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
+static int bcma_host_pci_suspend(struct device *dev)
{
- /* Host specific */
- pci_save_state(dev);
- pci_disable_device(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct bcma_bus *bus = pci_get_drvdata(pdev);
- return 0;
+ bus->mapped_core = NULL;
+
+ return bcma_bus_suspend(bus);
}
-static int bcma_host_pci_resume(struct pci_dev *dev)
+static int bcma_host_pci_resume(struct device *dev)
{
- struct bcma_bus *bus = pci_get_drvdata(dev);
- int err;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct bcma_bus *bus = pci_get_drvdata(pdev);
- /* Host specific */
- pci_set_power_state(dev, 0);
- err = pci_enable_device(dev);
- if (err)
- return err;
- pci_restore_state(dev);
+ return bcma_bus_resume(bus);
+}
- /* Bus specific */
- err = bcma_bus_resume(bus);
- if (err)
- return err;
+static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
+ bcma_host_pci_resume);
+#define BCMA_PM_OPS (&bcma_pm_ops)
- return 0;
-}
#else /* CONFIG_PM */
-# define bcma_host_pci_suspend NULL
-# define bcma_host_pci_resume NULL
+
+#define BCMA_PM_OPS NULL
+
#endif /* CONFIG_PM */
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
@@ -284,8 +278,7 @@ static struct pci_driver bcma_pci_bridge_driver = {
.id_table = bcma_pci_bridge_tbl,
.probe = bcma_host_pci_probe,
.remove = bcma_host_pci_remove,
- .suspend = bcma_host_pci_suspend,
- .resume = bcma_host_pci_resume,
+ .driver.pm = BCMA_PM_OPS,
};
int __init bcma_host_pci_init(void)
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 10f92b3..febbc0a 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -241,6 +241,21 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
}
#ifdef CONFIG_PM
+int bcma_bus_suspend(struct bcma_bus *bus)
+{
+ struct bcma_device *core;
+
+ list_for_each_entry(core, &bus->cores, list) {
+ struct device_driver *drv = core->dev.driver;
+ if (drv) {
+ struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
+ if (adrv->suspend)
+ adrv->suspend(core);
+ }
+ }
+ return 0;
+}
+
int bcma_bus_resume(struct bcma_bus *bus)
{
struct bcma_device *core;
@@ -252,6 +267,15 @@ int bcma_bus_resume(struct bcma_bus *bus)
bcma_core_chipcommon_init(&bus->drv_cc);
}
+ list_for_each_entry(core, &bus->cores, list) {
+ struct device_driver *drv = core->dev.driver;
+ if (drv) {
+ struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
+ if (adrv->resume)
+ adrv->resume(core);
+ }
+ }
+
return 0;
}
#endif
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 6f07ec1..4e4c8a4 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -116,6 +116,8 @@ config PARIDE
source "drivers/block/paride/Kconfig"
+source "drivers/block/mtip32xx/Kconfig"
+
config BLK_CPQ_DA
tristate "Compaq SMART2 support"
depends on PCI && VIRT_TO_BUS
@@ -315,6 +317,17 @@ config BLK_DEV_NBD
If unsure, say N.
+config BLK_DEV_NVME
+ tristate "NVM Express block device"
+ depends on PCI
+ ---help---
+ The NVM Express driver is for solid state drives directly
+ connected to the PCI or PCI Express bus. If you know you
+ don't have one of these, it is safe to answer N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nvme.
+
config BLK_DEV_OSD
tristate "OSD object-as-blkdev support"
depends on SCSI_OSD_ULD
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 76646e9..5b79505 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_MG_DISK) += mg_disk.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
+obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
@@ -39,5 +40,6 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o
obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/
obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
+obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
swim_mod-y := swim.o swim_asm.o
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 587cce5..b0f553b 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1735,7 +1735,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_BIG_PASSTHRU:
return cciss_bigpassthru(h, argp);
- /* scsi_cmd_ioctl handles these, below, though some are not */
+ /* scsi_cmd_blk_ioctl handles these, below, though some are not */
/* very meaningful for cciss. SG_IO is the main one people want. */
case SG_GET_VERSION_NUM:
@@ -1746,9 +1746,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case SG_EMULATED_HOST:
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
- /* scsi_cmd_ioctl would normally handle these, below, but */
+ /* scsi_cmd_blk_ioctl would normally handle these, below, but */
/* they aren't a good fit for cciss, as CD-ROMs are */
/* not supported, and we don't have any bus/target/lun */
/* which we present to the kernel. */
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 9cf2035..8d68056 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -59,8 +59,8 @@
/* module parameter, defined in drbd_main.c */
extern unsigned int minor_count;
-extern int disable_sendpage;
-extern int allow_oos;
+extern bool disable_sendpage;
+extern bool allow_oos;
extern unsigned int cn_idx;
#ifdef CONFIG_DRBD_FAULT_INJECTION
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 0358e55..211fc44 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -117,8 +117,8 @@ module_param(fault_devs, int, 0644);
/* module parameter, defined */
unsigned int minor_count = DRBD_MINOR_COUNT_DEF;
-int disable_sendpage;
-int allow_oos;
+bool disable_sendpage;
+bool allow_oos;
unsigned int cn_idx = CN_IDX_DRBD;
int proc_details; /* Detail level in proc drbd*/
diff --git a/drivers/block/mtip32xx/Kconfig b/drivers/block/mtip32xx/Kconfig
new file mode 100644
index 0000000..b5dd14e
--- /dev/null
+++ b/drivers/block/mtip32xx/Kconfig
@@ -0,0 +1,9 @@
+#
+# mtip32xx device driver configuration
+#
+
+config BLK_DEV_PCIESSD_MTIP32XX
+ tristate "Block Device Driver for Micron PCIe SSDs"
+ depends on HOTPLUG_PCI_PCIE
+ help
+ This enables the block driver for Micron PCIe SSDs.
diff --git a/drivers/block/mtip32xx/Makefile b/drivers/block/mtip32xx/Makefile
new file mode 100644
index 0000000..4fbef8c
--- /dev/null
+++ b/drivers/block/mtip32xx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Block device driver for Micron PCIe SSD
+#
+
+obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx.o
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
new file mode 100644
index 0000000..b74eab7
--- /dev/null
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -0,0 +1,3651 @@
+/*
+ * Driver for the Micron P320 SSD
+ * Copyright (C) 2011 Micron Technology, Inc.
+ *
+ * Portions of this code were derived from works subjected to the
+ * following copyright:
+ * Copyright (C) 2009 Integrated Device Technology, 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.
+ *
+ * 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/pci.h>
+#include <linux/interrupt.h>
+#include <linux/ata.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/compat.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include <linux/kthread.h>
+#include <../drivers/ata/ahci.h>
+#include "mtip32xx.h"
+
+#define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32)
+#define HW_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (MTIP_MAX_SG * 16))
+#define HW_CMD_TBL_AR_SZ (HW_CMD_TBL_SZ * MTIP_MAX_COMMAND_SLOTS)
+#define HW_PORT_PRIV_DMA_SZ \
+ (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ)
+
+#define HOST_HSORG 0xFC
+#define HSORG_DISABLE_SLOTGRP_INTR (1<<24)
+#define HSORG_DISABLE_SLOTGRP_PXIS (1<<16)
+#define HSORG_HWREV 0xFF00
+#define HSORG_STYLE 0x8
+#define HSORG_SLOTGROUPS 0x7
+
+#define PORT_COMMAND_ISSUE 0x38
+#define PORT_SDBV 0x7C
+
+#define PORT_OFFSET 0x100
+#define PORT_MEM_SIZE 0x80
+
+#define PORT_IRQ_ERR \
+ (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_CONNECT | \
+ PORT_IRQ_PHYRDY | PORT_IRQ_UNK_FIS | PORT_IRQ_BAD_PMP | \
+ PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_NONFATAL | \
+ PORT_IRQ_OVERFLOW)
+#define PORT_IRQ_LEGACY \
+ (PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+#define PORT_IRQ_HANDLED \
+ (PORT_IRQ_SDB_FIS | PORT_IRQ_LEGACY | \
+ PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR | \
+ PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)
+#define DEF_PORT_IRQ \
+ (PORT_IRQ_ERR | PORT_IRQ_LEGACY | PORT_IRQ_SDB_FIS)
+
+/* product numbers */
+#define MTIP_PRODUCT_UNKNOWN 0x00
+#define MTIP_PRODUCT_ASICFPGA 0x11
+
+/* Device instance number, incremented each time a device is probed. */
+static int instance;
+
+/*
+ * Global variable used to hold the major block device number
+ * allocated in mtip_init().
+ */
+static int mtip_major;
+
+static DEFINE_SPINLOCK(rssd_index_lock);
+static DEFINE_IDA(rssd_index_ida);
+
+static int mtip_block_initialize(struct driver_data *dd);
+
+#ifdef CONFIG_COMPAT
+struct mtip_compat_ide_task_request_s {
+ __u8 io_ports[8];
+ __u8 hob_ports[8];
+ ide_reg_valid_t out_flags;
+ ide_reg_valid_t in_flags;
+ int data_phase;
+ int req_cmd;
+ compat_ulong_t out_size;
+ compat_ulong_t in_size;
+};
+#endif
+
+/*
+ * This function check_for_surprise_removal is called
+ * while card is removed from the system and it will
+ * read the vendor id from the configration space
+ *
+ * @pdev Pointer to the pci_dev structure.
+ *
+ * return value
+ * true if device removed, else false
+ */
+static bool mtip_check_surprise_removal(struct pci_dev *pdev)
+{
+ u16 vendor_id = 0;
+
+ /* Read the vendorID from the configuration space */
+ pci_read_config_word(pdev, 0x00, &vendor_id);
+ if (vendor_id == 0xFFFF)
+ return true; /* device removed */
+
+ return false; /* device present */
+}
+
+/*
+ * This function is called for clean the pending command in the
+ * command slot during the surprise removal of device and return
+ * error to the upper layer.
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_command_cleanup(struct driver_data *dd)
+{
+ int group = 0, commandslot = 0, commandindex = 0;
+ struct mtip_cmd *command;
+ struct mtip_port *port = dd->port;
+
+ for (group = 0; group < 4; group++) {
+ for (commandslot = 0; commandslot < 32; commandslot++) {
+ if (!(port->allocated[group] & (1 << commandslot)))
+ continue;
+
+ commandindex = group << 5 | commandslot;
+ command = &port->commands[commandindex];
+
+ if (atomic_read(&command->active)
+ && (command->async_callback)) {
+ command->async_callback(command->async_data,
+ -ENODEV);
+ command->async_callback = NULL;
+ command->async_data = NULL;
+ }
+
+ dma_unmap_sg(&port->dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+ }
+ }
+
+ up(&port->cmd_slot);
+
+ atomic_set(&dd->drv_cleanup_done, true);
+}
+
+/*
+ * Obtain an empty command slot.
+ *
+ * This function needs to be reentrant since it could be called
+ * at the same time on multiple CPUs. The allocation of the
+ * command slot must be atomic.
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ * >= 0 Index of command slot obtained.
+ * -1 No command slots available.
+ */
+static int get_slot(struct mtip_port *port)
+{
+ int slot, i;
+ unsigned int num_command_slots = port->dd->slot_groups * 32;
+
+ /*
+ * Try 10 times, because there is a small race here.
+ * that's ok, because it's still cheaper than a lock.
+ *
+ * Race: Since this section is not protected by lock, same bit
+ * could be chosen by different process contexts running in
+ * different processor. So instead of costly lock, we are going
+ * with loop.
+ */
+ for (i = 0; i < 10; i++) {
+ slot = find_next_zero_bit(port->allocated,
+ num_command_slots, 1);
+ if ((slot < num_command_slots) &&
+ (!test_and_set_bit(slot, port->allocated)))
+ return slot;
+ }
+ dev_warn(&port->dd->pdev->dev, "Failed to get a tag.\n");
+
+ if (mtip_check_surprise_removal(port->dd->pdev)) {
+ /* Device not present, clean outstanding commands */
+ mtip_command_cleanup(port->dd);
+ }
+ return -1;
+}
+
+/*
+ * Release a command slot.
+ *
+ * @port Pointer to the port data structure.
+ * @tag Tag of command to release
+ *
+ * return value
+ * None
+ */
+static inline void release_slot(struct mtip_port *port, int tag)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(tag, port->allocated);
+ smp_mb__after_clear_bit();
+}
+
+/*
+ * Reset the HBA (without sleeping)
+ *
+ * Just like hba_reset, except does not call sleep, so can be
+ * run from interrupt/tasklet context.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 The reset was successful.
+ * -1 The HBA Reset bit did not clear.
+ */
+static int hba_reset_nosleep(struct driver_data *dd)
+{
+ unsigned long timeout;
+
+ /* Chip quirk: quiesce any chip function */
+ mdelay(10);
+
+ /* Set the reset bit */
+ writel(HOST_RESET, dd->mmio + HOST_CTL);
+
+ /* Flush */
+ readl(dd->mmio + HOST_CTL);
+
+ /*
+ * Wait 10ms then spin for up to 1 second
+ * waiting for reset acknowledgement
+ */
+ timeout = jiffies + msecs_to_jiffies(1000);
+ mdelay(10);
+ while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
+ && time_before(jiffies, timeout))
+ mdelay(1);
+
+ if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Issue a command to the hardware.
+ *
+ * Set the appropriate bit in the s_active and Command Issue hardware
+ * registers, causing hardware command processing to begin.
+ *
+ * @port Pointer to the port structure.
+ * @tag The tag of the command to be issued.
+ *
+ * return value
+ * None
+ */
+static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag)
+{
+ unsigned long flags = 0;
+
+ atomic_set(&port->commands[tag].active, 1);
+
+ spin_lock_irqsave(&port->cmd_issue_lock, flags);
+
+ writel((1 << MTIP_TAG_BIT(tag)),
+ port->s_active[MTIP_TAG_INDEX(tag)]);
+ writel((1 << MTIP_TAG_BIT(tag)),
+ port->cmd_issue[MTIP_TAG_INDEX(tag)]);
+
+ spin_unlock_irqrestore(&port->cmd_issue_lock, flags);
+}
+
+/*
+ * Enable/disable the reception of FIS
+ *
+ * @port Pointer to the port data structure
+ * @enable 1 to enable, 0 to disable
+ *
+ * return value
+ * Previous state: 1 enabled, 0 disabled
+ */
+static int mtip_enable_fis(struct mtip_port *port, int enable)
+{
+ u32 tmp;
+
+ /* enable FIS reception */
+ tmp = readl(port->mmio + PORT_CMD);
+ if (enable)
+ writel(tmp | PORT_CMD_FIS_RX, port->mmio + PORT_CMD);
+ else
+ writel(tmp & ~PORT_CMD_FIS_RX, port->mmio + PORT_CMD);
+
+ /* Flush */
+ readl(port->mmio + PORT_CMD);
+
+ return (((tmp & PORT_CMD_FIS_RX) == PORT_CMD_FIS_RX));
+}
+
+/*
+ * Enable/disable the DMA engine
+ *
+ * @port Pointer to the port data structure
+ * @enable 1 to enable, 0 to disable
+ *
+ * return value
+ * Previous state: 1 enabled, 0 disabled.
+ */
+static int mtip_enable_engine(struct mtip_port *port, int enable)
+{
+ u32 tmp;
+
+ /* enable FIS reception */
+ tmp = readl(port->mmio + PORT_CMD);
+ if (enable)
+ writel(tmp | PORT_CMD_START, port->mmio + PORT_CMD);
+ else
+ writel(tmp & ~PORT_CMD_START, port->mmio + PORT_CMD);
+
+ readl(port->mmio + PORT_CMD);
+ return (((tmp & PORT_CMD_START) == PORT_CMD_START));
+}
+
+/*
+ * Enables the port DMA engine and FIS reception.
+ *
+ * return value
+ * None
+ */
+static inline void mtip_start_port(struct mtip_port *port)
+{
+ /* Enable FIS reception */
+ mtip_enable_fis(port, 1);
+
+ /* Enable the DMA engine */
+ mtip_enable_engine(port, 1);
+}
+
+/*
+ * Deinitialize a port by disabling port interrupts, the DMA engine,
+ * and FIS reception.
+ *
+ * @port Pointer to the port structure
+ *
+ * return value
+ * None
+ */
+static inline void mtip_deinit_port(struct mtip_port *port)
+{
+ /* Disable interrupts on this port */
+ writel(0, port->mmio + PORT_IRQ_MASK);
+
+ /* Disable the DMA engine */
+ mtip_enable_engine(port, 0);
+
+ /* Disable FIS reception */
+ mtip_enable_fis(port, 0);
+}
+
+/*
+ * Initialize a port.
+ *
+ * This function deinitializes the port by calling mtip_deinit_port() and
+ * then initializes it by setting the command header and RX FIS addresses,
+ * clearing the SError register and any pending port interrupts before
+ * re-enabling the default set of port interrupts.
+ *
+ * @port Pointer to the port structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_init_port(struct mtip_port *port)
+{
+ int i;
+ mtip_deinit_port(port);
+
+ /* Program the command list base and FIS base addresses */
+ if (readl(port->dd->mmio + HOST_CAP) & HOST_CAP_64) {
+ writel((port->command_list_dma >> 16) >> 16,
+ port->mmio + PORT_LST_ADDR_HI);
+ writel((port->rxfis_dma >> 16) >> 16,
+ port->mmio + PORT_FIS_ADDR_HI);
+ }
+
+ writel(port->command_list_dma & 0xFFFFFFFF,
+ port->mmio + PORT_LST_ADDR);
+ writel(port->rxfis_dma & 0xFFFFFFFF, port->mmio + PORT_FIS_ADDR);
+
+ /* Clear SError */
+ writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+
+ /* reset the completed registers.*/
+ for (i = 0; i < port->dd->slot_groups; i++)
+ writel(0xFFFFFFFF, port->completed[i]);
+
+ /* Clear any pending interrupts for this port */
+ writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT);
+
+ /* Enable port interrupts */
+ writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK);
+}
+
+/*
+ * Restart a port
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_restart_port(struct mtip_port *port)
+{
+ unsigned long timeout;
+
+ /* Disable the DMA engine */
+ mtip_enable_engine(port, 0);
+
+ /* Chip quirk: wait up to 500ms for PxCMD.CR == 0 */
+ timeout = jiffies + msecs_to_jiffies(500);
+ while ((readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON)
+ && time_before(jiffies, timeout))
+ ;
+
+ /*
+ * Chip quirk: escalate to hba reset if
+ * PxCMD.CR not clear after 500 ms
+ */
+ if (readl(port->mmio + PORT_CMD) & PORT_CMD_LIST_ON) {
+ dev_warn(&port->dd->pdev->dev,
+ "PxCMD.CR not clear, escalating reset\n");
+
+ if (hba_reset_nosleep(port->dd))
+ dev_err(&port->dd->pdev->dev,
+ "HBA reset escalation failed.\n");
+
+ /* 30 ms delay before com reset to quiesce chip */
+ mdelay(30);
+ }
+
+ dev_warn(&port->dd->pdev->dev, "Issuing COM reset\n");
+
+ /* Set PxSCTL.DET */
+ writel(readl(port->mmio + PORT_SCR_CTL) |
+ 1, port->mmio + PORT_SCR_CTL);
+ readl(port->mmio + PORT_SCR_CTL);
+
+ /* Wait 1 ms to quiesce chip function */
+ timeout = jiffies + msecs_to_jiffies(1);
+ while (time_before(jiffies, timeout))
+ ;
+
+ /* Clear PxSCTL.DET */
+ writel(readl(port->mmio + PORT_SCR_CTL) & ~1,
+ port->mmio + PORT_SCR_CTL);
+ readl(port->mmio + PORT_SCR_CTL);
+
+ /* Wait 500 ms for bit 0 of PORT_SCR_STS to be set */
+ timeout = jiffies + msecs_to_jiffies(500);
+ while (((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
+ && time_before(jiffies, timeout))
+ ;
+
+ if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
+ dev_warn(&port->dd->pdev->dev,
+ "COM reset failed\n");
+
+ /* Clear SError, the PxSERR.DIAG.x should be set so clear it */
+ writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+
+ /* Enable the DMA engine */
+ mtip_enable_engine(port, 1);
+}
+
+/*
+ * Called periodically to see if any read/write commands are
+ * taking too long to complete.
+ *
+ * @data Pointer to the PORT data structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_timeout_function(unsigned long int data)
+{
+ struct mtip_port *port = (struct mtip_port *) data;
+ struct host_to_dev_fis *fis;
+ struct mtip_cmd *command;
+ int tag, cmdto_cnt = 0;
+ unsigned int bit, group;
+ unsigned int num_command_slots = port->dd->slot_groups * 32;
+
+ if (unlikely(!port))
+ return;
+
+ if (atomic_read(&port->dd->resumeflag) == true) {
+ mod_timer(&port->cmd_timer,
+ jiffies + msecs_to_jiffies(30000));
+ return;
+ }
+
+ for (tag = 0; tag < num_command_slots; tag++) {
+ /*
+ * Skip internal command slot as it has
+ * its own timeout mechanism
+ */
+ if (tag == MTIP_TAG_INTERNAL)
+ continue;
+
+ if (atomic_read(&port->commands[tag].active) &&
+ (time_after(jiffies, port->commands[tag].comp_time))) {
+ group = tag >> 5;
+ bit = tag & 0x1F;
+
+ command = &port->commands[tag];
+ fis = (struct host_to_dev_fis *) command->command;
+
+ dev_warn(&port->dd->pdev->dev,
+ "Timeout for command tag %d\n", tag);
+
+ cmdto_cnt++;
+ if (cmdto_cnt == 1)
+ set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+
+ /*
+ * Clear the completed bit. This should prevent
+ * any interrupt handlers from trying to retire
+ * the command.
+ */
+ writel(1 << bit, port->completed[group]);
+
+ /* Call the async completion callback. */
+ if (likely(command->async_callback))
+ command->async_callback(command->async_data,
+ -EIO);
+ command->async_callback = NULL;
+ command->comp_func = NULL;
+
+ /* Unmap the DMA scatter list entries */
+ dma_unmap_sg(&port->dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+
+ /*
+ * Clear the allocated bit and active tag for the
+ * command.
+ */
+ atomic_set(&port->commands[tag].active, 0);
+ release_slot(port, tag);
+
+ up(&port->cmd_slot);
+ }
+ }
+
+ if (cmdto_cnt) {
+ dev_warn(&port->dd->pdev->dev,
+ "%d commands timed out: restarting port",
+ cmdto_cnt);
+ mtip_restart_port(port);
+ clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+ }
+
+ /* Restart the timer */
+ mod_timer(&port->cmd_timer,
+ jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+}
+
+/*
+ * IO completion function.
+ *
+ * This completion function is called by the driver ISR when a
+ * command that was issued by the kernel completes. It first calls the
+ * asynchronous completion function which normally calls back into the block
+ * layer passing the asynchronous callback data, then unmaps the
+ * scatter list associated with the completed command, and finally
+ * clears the allocated bit associated with the completed command.
+ *
+ * @port Pointer to the port data structure.
+ * @tag Tag of the command.
+ * @data Pointer to driver_data.
+ * @status Completion status.
+ *
+ * return value
+ * None
+ */
+static void mtip_async_complete(struct mtip_port *port,
+ int tag,
+ void *data,
+ int status)
+{
+ struct mtip_cmd *command;
+ struct driver_data *dd = data;
+ int cb_status = status ? -EIO : 0;
+
+ if (unlikely(!dd) || unlikely(!port))
+ return;
+
+ command = &port->commands[tag];
+
+ if (unlikely(status == PORT_IRQ_TF_ERR)) {
+ dev_warn(&port->dd->pdev->dev,
+ "Command tag %d failed due to TFE\n", tag);
+ }
+
+ /* Upper layer callback */
+ if (likely(command->async_callback))
+ command->async_callback(command->async_data, cb_status);
+
+ command->async_callback = NULL;
+ command->comp_func = NULL;
+
+ /* Unmap the DMA scatter list entries */
+ dma_unmap_sg(&dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+
+ /* Clear the allocated and active bits for the command */
+ atomic_set(&port->commands[tag].active, 0);
+ release_slot(port, tag);
+
+ up(&port->cmd_slot);
+}
+
+/*
+ * Internal command completion callback function.
+ *
+ * This function is normally called by the driver ISR when an internal
+ * command completed. This function signals the command completion by
+ * calling complete().
+ *
+ * @port Pointer to the port data structure.
+ * @tag Tag of the command that has completed.
+ * @data Pointer to a completion structure.
+ * @status Completion status.
+ *
+ * return value
+ * None
+ */
+static void mtip_completion(struct mtip_port *port,
+ int tag,
+ void *data,
+ int status)
+{
+ struct mtip_cmd *command = &port->commands[tag];
+ struct completion *waiting = data;
+ if (unlikely(status == PORT_IRQ_TF_ERR))
+ dev_warn(&port->dd->pdev->dev,
+ "Internal command %d completed with TFE\n", tag);
+
+ command->async_callback = NULL;
+ command->comp_func = NULL;
+
+ complete(waiting);
+}
+
+/*
+ * Helper function for tag logging
+ */
+static void print_tags(struct driver_data *dd,
+ char *msg,
+ unsigned long *tagbits)
+{
+ unsigned int tag, count = 0;
+
+ for (tag = 0; tag < (dd->slot_groups) * 32; tag++) {
+ if (test_bit(tag, tagbits))
+ count++;
+ }
+ if (count)
+ dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count);
+}
+
+/*
+ * Handle an error.
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_handle_tfe(struct driver_data *dd)
+{
+ int group, tag, bit, reissue;
+ struct mtip_port *port;
+ struct mtip_cmd *command;
+ u32 completed;
+ struct host_to_dev_fis *fis;
+ unsigned long tagaccum[SLOTBITS_IN_LONGS];
+
+ dev_warn(&dd->pdev->dev, "Taskfile error\n");
+
+ port = dd->port;
+
+ /* Stop the timer to prevent command timeouts. */
+ del_timer(&port->cmd_timer);
+
+ /* Set eh_active */
+ set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+
+ /* Loop through all the groups */
+ for (group = 0; group < dd->slot_groups; group++) {
+ completed = readl(port->completed[group]);
+
+ /* clear completed status register in the hardware.*/
+ writel(completed, port->completed[group]);
+
+ /* clear the tag accumulator */
+ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
+ /* Process successfully completed commands */
+ for (bit = 0; bit < 32 && completed; bit++) {
+ if (!(completed & (1<<bit)))
+ continue;
+ tag = (group << 5) + bit;
+
+ /* Skip the internal command slot */
+ if (tag == MTIP_TAG_INTERNAL)
+ continue;
+
+ command = &port->commands[tag];
+ if (likely(command->comp_func)) {
+ set_bit(tag, tagaccum);
+ atomic_set(&port->commands[tag].active, 0);
+ command->comp_func(port,
+ tag,
+ command->comp_data,
+ 0);
+ } else {
+ dev_err(&port->dd->pdev->dev,
+ "Missing completion func for tag %d",
+ tag);
+ if (mtip_check_surprise_removal(dd->pdev)) {
+ mtip_command_cleanup(dd);
+ /* don't proceed further */
+ return;
+ }
+ }
+ }
+ }
+ print_tags(dd, "TFE tags completed:", tagaccum);
+
+ /* Restart the port */
+ mdelay(20);
+ mtip_restart_port(port);
+
+ /* clear the tag accumulator */
+ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
+ /* Loop through all the groups */
+ for (group = 0; group < dd->slot_groups; group++) {
+ for (bit = 0; bit < 32; bit++) {
+ reissue = 1;
+ tag = (group << 5) + bit;
+
+ /* If the active bit is set re-issue the command */
+ if (atomic_read(&port->commands[tag].active) == 0)
+ continue;
+
+ fis = (struct host_to_dev_fis *)
+ port->commands[tag].command;
+
+ /* Should re-issue? */
+ if (tag == MTIP_TAG_INTERNAL ||
+ fis->command == ATA_CMD_SET_FEATURES)
+ reissue = 0;
+
+ /*
+ * First check if this command has
+ * exceeded its retries.
+ */
+ if (reissue &&
+ (port->commands[tag].retries-- > 0)) {
+
+ set_bit(tag, tagaccum);
+
+ /* Update the timeout value. */
+ port->commands[tag].comp_time =
+ jiffies + msecs_to_jiffies(
+ MTIP_NCQ_COMMAND_TIMEOUT_MS);
+ /* Re-issue the command. */
+ mtip_issue_ncq_command(port, tag);
+
+ continue;
+ }
+
+ /* Retire a command that will not be reissued */
+ dev_warn(&port->dd->pdev->dev,
+ "retiring tag %d\n", tag);
+ atomic_set(&port->commands[tag].active, 0);
+
+ if (port->commands[tag].comp_func)
+ port->commands[tag].comp_func(
+ port,
+ tag,
+ port->commands[tag].comp_data,
+ PORT_IRQ_TF_ERR);
+ else
+ dev_warn(&port->dd->pdev->dev,
+ "Bad completion for tag %d\n",
+ tag);
+ }
+ }
+ print_tags(dd, "TFE tags reissued:", tagaccum);
+
+ /* clear eh_active */
+ clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+
+ mod_timer(&port->cmd_timer,
+ jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+}
+
+/*
+ * Handle a set device bits interrupt
+ */
+static inline void mtip_process_sdbf(struct driver_data *dd)
+{
+ struct mtip_port *port = dd->port;
+ int group, tag, bit;
+ u32 completed;
+ struct mtip_cmd *command;
+
+ /* walk all bits in all slot groups */
+ for (group = 0; group < dd->slot_groups; group++) {
+ completed = readl(port->completed[group]);
+
+ /* clear completed status register in the hardware.*/
+ writel(completed, port->completed[group]);
+
+ /* Process completed commands. */
+ for (bit = 0;
+ (bit < 32) && completed;
+ bit++, completed >>= 1) {
+ if (completed & 0x01) {
+ tag = (group << 5) | bit;
+
+ /* skip internal command slot. */
+ if (unlikely(tag == MTIP_TAG_INTERNAL))
+ continue;
+
+ command = &port->commands[tag];
+ /* make internal callback */
+ if (likely(command->comp_func)) {
+ command->comp_func(
+ port,
+ tag,
+ command->comp_data,
+ 0);
+ } else {
+ dev_warn(&dd->pdev->dev,
+ "Null completion "
+ "for tag %d",
+ tag);
+
+ if (mtip_check_surprise_removal(
+ dd->pdev)) {
+ mtip_command_cleanup(dd);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Process legacy pio and d2h interrupts
+ */
+static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat)
+{
+ struct mtip_port *port = dd->port;
+ struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL];
+
+ if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+ (cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+ & (1 << MTIP_TAG_INTERNAL))) {
+ if (cmd->comp_func) {
+ cmd->comp_func(port,
+ MTIP_TAG_INTERNAL,
+ cmd->comp_data,
+ 0);
+ return;
+ }
+ }
+
+ dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat);
+
+ return;
+}
+
+/*
+ * Demux and handle errors
+ */
+static inline void mtip_process_errors(struct driver_data *dd, u32 port_stat)
+{
+ if (likely(port_stat & (PORT_IRQ_TF_ERR | PORT_IRQ_IF_ERR)))
+ mtip_handle_tfe(dd);
+
+ if (unlikely(port_stat & PORT_IRQ_CONNECT)) {
+ dev_warn(&dd->pdev->dev,
+ "Clearing PxSERR.DIAG.x\n");
+ writel((1 << 26), dd->port->mmio + PORT_SCR_ERR);
+ }
+
+ if (unlikely(port_stat & PORT_IRQ_PHYRDY)) {
+ dev_warn(&dd->pdev->dev,
+ "Clearing PxSERR.DIAG.n\n");
+ writel((1 << 16), dd->port->mmio + PORT_SCR_ERR);
+ }
+
+ if (unlikely(port_stat & ~PORT_IRQ_HANDLED)) {
+ dev_warn(&dd->pdev->dev,
+ "Port stat errors %x unhandled\n",
+ (port_stat & ~PORT_IRQ_HANDLED));
+ }
+}
+
+static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
+{
+ struct driver_data *dd = (struct driver_data *) data;
+ struct mtip_port *port = dd->port;
+ u32 hba_stat, port_stat;
+ int rv = IRQ_NONE;
+
+ hba_stat = readl(dd->mmio + HOST_IRQ_STAT);
+ if (hba_stat) {
+ rv = IRQ_HANDLED;
+
+ /* Acknowledge the interrupt status on the port.*/
+ port_stat = readl(port->mmio + PORT_IRQ_STAT);
+ writel(port_stat, port->mmio + PORT_IRQ_STAT);
+
+ /* Demux port status */
+ if (likely(port_stat & PORT_IRQ_SDB_FIS))
+ mtip_process_sdbf(dd);
+
+ if (unlikely(port_stat & PORT_IRQ_ERR)) {
+ if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
+ mtip_command_cleanup(dd);
+ /* don't proceed further */
+ return IRQ_HANDLED;
+ }
+
+ mtip_process_errors(dd, port_stat & PORT_IRQ_ERR);
+ }
+
+ if (unlikely(port_stat & PORT_IRQ_LEGACY))
+ mtip_process_legacy(dd, port_stat & PORT_IRQ_LEGACY);
+ }
+
+ /* acknowledge interrupt */
+ writel(hba_stat, dd->mmio + HOST_IRQ_STAT);
+
+ return rv;
+}
+
+/*
+ * Wrapper for mtip_handle_irq
+ * (ignores return code)
+ */
+static void mtip_tasklet(unsigned long data)
+{
+ mtip_handle_irq((struct driver_data *) data);
+}
+
+/*
+ * HBA interrupt subroutine.
+ *
+ * @irq IRQ number.
+ * @instance Pointer to the driver data structure.
+ *
+ * return value
+ * IRQ_HANDLED A HBA interrupt was pending and handled.
+ * IRQ_NONE This interrupt was not for the HBA.
+ */
+static irqreturn_t mtip_irq_handler(int irq, void *instance)
+{
+ struct driver_data *dd = instance;
+ tasklet_schedule(&dd->tasklet);
+ return IRQ_HANDLED;
+}
+
+static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag)
+{
+ atomic_set(&port->commands[tag].active, 1);
+ writel(1 << MTIP_TAG_BIT(tag),
+ port->cmd_issue[MTIP_TAG_INDEX(tag)]);
+}
+
+/*
+ * Wait for port to quiesce
+ *
+ * @port Pointer to port data structure
+ * @timeout Max duration to wait (ms)
+ *
+ * return value
+ * 0 Success
+ * -EBUSY Commands still active
+ */
+static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
+{
+ unsigned long to;
+ unsigned int n;
+ unsigned int active = 1;
+
+ to = jiffies + msecs_to_jiffies(timeout);
+ do {
+ if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) &&
+ test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+ msleep(20);
+ continue; /* svc thd is actively issuing commands */
+ }
+ /*
+ * Ignore s_active bit 0 of array element 0.
+ * This bit will always be set
+ */
+ active = readl(port->s_active[0]) & 0xFFFFFFFE;
+ for (n = 1; n < port->dd->slot_groups; n++)
+ active |= readl(port->s_active[n]);
+
+ if (!active)
+ break;
+
+ msleep(20);
+ } while (time_before(jiffies, to));
+
+ return active ? -EBUSY : 0;
+}
+
+/*
+ * Execute an internal command and wait for the completion.
+ *
+ * @port Pointer to the port data structure.
+ * @fis Pointer to the FIS that describes the command.
+ * @fis_len Length in WORDS of the FIS.
+ * @buffer DMA accessible for command data.
+ * @buf_len Length, in bytes, of the data buffer.
+ * @opts Command header options, excluding the FIS length
+ * and the number of PRD entries.
+ * @timeout Time in ms to wait for the command to complete.
+ *
+ * return value
+ * 0 Command completed successfully.
+ * -EFAULT The buffer address is not correctly aligned.
+ * -EBUSY Internal command or other IO in progress.
+ * -EAGAIN Time out waiting for command to complete.
+ */
+static int mtip_exec_internal_command(struct mtip_port *port,
+ void *fis,
+ int fis_len,
+ dma_addr_t buffer,
+ int buf_len,
+ u32 opts,
+ gfp_t atomic,
+ unsigned long timeout)
+{
+ struct mtip_cmd_sg *command_sg;
+ DECLARE_COMPLETION_ONSTACK(wait);
+ int rv = 0;
+ struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
+
+ /* Make sure the buffer is 8 byte aligned. This is asic specific. */
+ if (buffer & 0x00000007) {
+ dev_err(&port->dd->pdev->dev,
+ "SG buffer is not 8 byte aligned\n");
+ return -EFAULT;
+ }
+
+ /* Only one internal command should be running at a time */
+ if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) {
+ dev_warn(&port->dd->pdev->dev,
+ "Internal command already active\n");
+ return -EBUSY;
+ }
+ set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+
+ if (atomic == GFP_KERNEL) {
+ /* wait for io to complete if non atomic */
+ if (mtip_quiesce_io(port, 5000) < 0) {
+ dev_warn(&port->dd->pdev->dev,
+ "Failed to quiesce IO\n");
+ release_slot(port, MTIP_TAG_INTERNAL);
+ clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+ return -EBUSY;
+ }
+
+ /* Set the completion function and data for the command. */
+ int_cmd->comp_data = &wait;
+ int_cmd->comp_func = mtip_completion;
+
+ } else {
+ /* Clear completion - we're going to poll */
+ int_cmd->comp_data = NULL;
+ int_cmd->comp_func = NULL;
+ }
+
+ /* Copy the command to the command table */
+ memcpy(int_cmd->command, fis, fis_len*4);
+
+ /* Populate the SG list */
+ int_cmd->command_header->opts =
+ __force_bit2int cpu_to_le32(opts | fis_len);
+ if (buf_len) {
+ command_sg = int_cmd->command + AHCI_CMD_TBL_HDR_SZ;
+
+ command_sg->info =
+ __force_bit2int cpu_to_le32((buf_len-1) & 0x3FFFFF);
+ command_sg->dba =
+ __force_bit2int cpu_to_le32(buffer & 0xFFFFFFFF);
+ command_sg->dba_upper =
+ __force_bit2int cpu_to_le32((buffer >> 16) >> 16);
+
+ int_cmd->command_header->opts |=
+ __force_bit2int cpu_to_le32((1 << 16));
+ }
+
+ /* Populate the command header */
+ int_cmd->command_header->byte_count = 0;
+
+ /* Issue the command to the hardware */
+ mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
+
+ /* Poll if atomic, wait_for_completion otherwise */
+ if (atomic == GFP_KERNEL) {
+ /* Wait for the command to complete or timeout. */
+ if (wait_for_completion_timeout(
+ &wait,
+ msecs_to_jiffies(timeout)) == 0) {
+ dev_err(&port->dd->pdev->dev,
+ "Internal command did not complete [%d] "
+ "within timeout of %lu ms\n",
+ atomic, timeout);
+ rv = -EAGAIN;
+ }
+
+ if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+ & (1 << MTIP_TAG_INTERNAL)) {
+ dev_warn(&port->dd->pdev->dev,
+ "Retiring internal command but CI is 1.\n");
+ }
+
+ } else {
+ /* Spin for <timeout> checking if command still outstanding */
+ timeout = jiffies + msecs_to_jiffies(timeout);
+
+ while ((readl(
+ port->cmd_issue[MTIP_TAG_INTERNAL])
+ & (1 << MTIP_TAG_INTERNAL))
+ && time_before(jiffies, timeout))
+ ;
+
+ if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+ & (1 << MTIP_TAG_INTERNAL)) {
+ dev_err(&port->dd->pdev->dev,
+ "Internal command did not complete [%d]\n",
+ atomic);
+ rv = -EAGAIN;
+ }
+ }
+
+ /* Clear the allocated and active bits for the internal command. */
+ atomic_set(&int_cmd->active, 0);
+ release_slot(port, MTIP_TAG_INTERNAL);
+ clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+
+ return rv;
+}
+
+/*
+ * Byte-swap ATA ID strings.
+ *
+ * ATA identify data contains strings in byte-swapped 16-bit words.
+ * They must be swapped (on all architectures) to be usable as C strings.
+ * This function swaps bytes in-place.
+ *
+ * @buf The buffer location of the string
+ * @len The number of bytes to swap
+ *
+ * return value
+ * None
+ */
+static inline void ata_swap_string(u16 *buf, unsigned int len)
+{
+ int i;
+ for (i = 0; i < (len/2); i++)
+ be16_to_cpus(&buf[i]);
+}
+
+/*
+ * Request the device identity information.
+ *
+ * If a user space buffer is not specified, i.e. is NULL, the
+ * identify information is still read from the drive and placed
+ * into the identify data buffer (@e port->identify) in the
+ * port data structure.
+ * When the identify buffer contains valid identify information @e
+ * port->identify_valid is non-zero.
+ *
+ * @port Pointer to the port structure.
+ * @user_buffer A user space buffer where the identify data should be
+ * copied.
+ *
+ * return value
+ * 0 Command completed successfully.
+ * -EFAULT An error occurred while coping data to the user buffer.
+ * -1 Command failed.
+ */
+static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer)
+{
+ int rv = 0;
+ struct host_to_dev_fis fis;
+
+ /* Build the FIS. */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = ATA_CMD_ID_ATA;
+
+ /* Set the identify information as invalid. */
+ port->identify_valid = 0;
+
+ /* Clear the identify information. */
+ memset(port->identify, 0, sizeof(u16) * ATA_ID_WORDS);
+
+ /* Execute the command. */
+ if (mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ port->identify_dma,
+ sizeof(u16) * ATA_ID_WORDS,
+ 0,
+ GFP_KERNEL,
+ MTIP_INTERNAL_COMMAND_TIMEOUT_MS)
+ < 0) {
+ rv = -1;
+ goto out;
+ }
+
+ /*
+ * Perform any necessary byte-swapping. Yes, the kernel does in fact
+ * perform field-sensitive swapping on the string fields.
+ * See the kernel use of ata_id_string() for proof of this.
+ */
+#ifdef __LITTLE_ENDIAN
+ ata_swap_string(port->identify + 27, 40); /* model string*/
+ ata_swap_string(port->identify + 23, 8); /* firmware string*/
+ ata_swap_string(port->identify + 10, 20); /* serial# string*/
+#else
+ {
+ int i;
+ for (i = 0; i < ATA_ID_WORDS; i++)
+ port->identify[i] = le16_to_cpu(port->identify[i]);
+ }
+#endif
+
+ /* Set the identify buffer as valid. */
+ port->identify_valid = 1;
+
+ if (user_buffer) {
+ if (copy_to_user(
+ user_buffer,
+ port->identify,
+ ATA_ID_WORDS * sizeof(u16))) {
+ rv = -EFAULT;
+ goto out;
+ }
+ }
+
+out:
+ return rv;
+}
+
+/*
+ * Issue a standby immediate command to the device.
+ *
+ * @port Pointer to the port structure.
+ *
+ * return value
+ * 0 Command was executed successfully.
+ * -1 An error occurred while executing the command.
+ */
+static int mtip_standby_immediate(struct mtip_port *port)
+{
+ int rv;
+ struct host_to_dev_fis fis;
+
+ /* Build the FIS. */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = ATA_CMD_STANDBYNOW1;
+
+ /* Execute the command. Use a 15-second timeout for large drives. */
+ rv = mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ 0,
+ 0,
+ 0,
+ GFP_KERNEL,
+ 15000);
+
+ return rv;
+}
+
+/*
+ * Get the drive capacity.
+ *
+ * @dd Pointer to the device data structure.
+ * @sectors Pointer to the variable that will receive the sector count.
+ *
+ * return value
+ * 1 Capacity was returned successfully.
+ * 0 The identify information is invalid.
+ */
+static bool mtip_hw_get_capacity(struct driver_data *dd, sector_t *sectors)
+{
+ struct mtip_port *port = dd->port;
+ u64 total, raw0, raw1, raw2, raw3;
+ raw0 = port->identify[100];
+ raw1 = port->identify[101];
+ raw2 = port->identify[102];
+ raw3 = port->identify[103];
+ total = raw0 | raw1<<16 | raw2<<32 | raw3<<48;
+ *sectors = total;
+ return (bool) !!port->identify_valid;
+}
+
+/*
+ * Reset the HBA.
+ *
+ * Resets the HBA by setting the HBA Reset bit in the Global
+ * HBA Control register. After setting the HBA Reset bit the
+ * function waits for 1 second before reading the HBA Reset
+ * bit to make sure it has cleared. If HBA Reset is not clear
+ * an error is returned. Cannot be used in non-blockable
+ * context.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 The reset was successful.
+ * -1 The HBA Reset bit did not clear.
+ */
+static int mtip_hba_reset(struct driver_data *dd)
+{
+ mtip_deinit_port(dd->port);
+
+ /* Set the reset bit */
+ writel(HOST_RESET, dd->mmio + HOST_CTL);
+
+ /* Flush */
+ readl(dd->mmio + HOST_CTL);
+
+ /* Wait for reset to clear */
+ ssleep(1);
+
+ /* Check the bit has cleared */
+ if (readl(dd->mmio + HOST_CTL) & HOST_RESET) {
+ dev_err(&dd->pdev->dev,
+ "Reset bit did not clear.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Display the identify command data.
+ *
+ * @port Pointer to the port data structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_dump_identify(struct mtip_port *port)
+{
+ sector_t sectors;
+ unsigned short revid;
+ char cbuf[42];
+
+ if (!port->identify_valid)
+ return;
+
+ strlcpy(cbuf, (char *)(port->identify+10), 21);
+ dev_info(&port->dd->pdev->dev,
+ "Serial No.: %s\n", cbuf);
+
+ strlcpy(cbuf, (char *)(port->identify+23), 9);
+ dev_info(&port->dd->pdev->dev,
+ "Firmware Ver.: %s\n", cbuf);
+
+ strlcpy(cbuf, (char *)(port->identify+27), 41);
+ dev_info(&port->dd->pdev->dev, "Model: %s\n", cbuf);
+
+ if (mtip_hw_get_capacity(port->dd, &sectors))
+ dev_info(&port->dd->pdev->dev,
+ "Capacity: %llu sectors (%llu MB)\n",
+ (u64)sectors,
+ ((u64)sectors) * ATA_SECT_SIZE >> 20);
+
+ pci_read_config_word(port->dd->pdev, PCI_REVISION_ID, &revid);
+ switch (revid & 0xFF) {
+ case 0x1:
+ strlcpy(cbuf, "A0", 3);
+ break;
+ case 0x3:
+ strlcpy(cbuf, "A2", 3);
+ break;
+ default:
+ strlcpy(cbuf, "?", 2);
+ break;
+ }
+ dev_info(&port->dd->pdev->dev,
+ "Card Type: %s\n", cbuf);
+}
+
+/*
+ * Map the commands scatter list into the command table.
+ *
+ * @command Pointer to the command.
+ * @nents Number of scatter list entries.
+ *
+ * return value
+ * None
+ */
+static inline void fill_command_sg(struct driver_data *dd,
+ struct mtip_cmd *command,
+ int nents)
+{
+ int n;
+ unsigned int dma_len;
+ struct mtip_cmd_sg *command_sg;
+ struct scatterlist *sg = command->sg;
+
+ command_sg = command->command + AHCI_CMD_TBL_HDR_SZ;
+
+ for (n = 0; n < nents; n++) {
+ dma_len = sg_dma_len(sg);
+ if (dma_len > 0x400000)
+ dev_err(&dd->pdev->dev,
+ "DMA segment length truncated\n");
+ command_sg->info = __force_bit2int
+ cpu_to_le32((dma_len-1) & 0x3FFFFF);
+ command_sg->dba = __force_bit2int
+ cpu_to_le32(sg_dma_address(sg));
+ command_sg->dba_upper = __force_bit2int
+ cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
+ command_sg++;
+ sg++;
+ }
+}
+
+/*
+ * @brief Execute a drive command.
+ *
+ * return value 0 The command completed successfully.
+ * return value -1 An error occurred while executing the command.
+ */
+static int exec_drive_task(struct mtip_port *port, u8 *command)
+{
+ struct host_to_dev_fis fis;
+ struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG);
+
+ /* Build the FIS. */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = command[0];
+ fis.features = command[1];
+ fis.sect_count = command[2];
+ fis.sector = command[3];
+ fis.cyl_low = command[4];
+ fis.cyl_hi = command[5];
+ fis.device = command[6] & ~0x10; /* Clear the dev bit*/
+
+
+ dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, "
+ "nsect %x, sect %x, lcyl %x, "
+ "hcyl %x, sel %x\n",
+ __func__,
+ command[0],
+ command[1],
+ command[2],
+ command[3],
+ command[4],
+ command[5],
+ command[6]);
+
+ /* Execute the command. */
+ if (mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ 0,
+ 0,
+ 0,
+ GFP_KERNEL,
+ MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) {
+ return -1;
+ }
+
+ command[0] = reply->command; /* Status*/
+ command[1] = reply->features; /* Error*/
+ command[4] = reply->cyl_low;
+ command[5] = reply->cyl_hi;
+
+ dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, "
+ "err %x , cyl_lo %x cyl_hi %x\n",
+ __func__,
+ command[0],
+ command[1],
+ command[4],
+ command[5]);
+
+ return 0;
+}
+
+/*
+ * @brief Execute a drive command.
+ *
+ * @param port Pointer to the port data structure.
+ * @param command Pointer to the user specified command parameters.
+ * @param user_buffer Pointer to the user space buffer where read sector
+ * data should be copied.
+ *
+ * return value 0 The command completed successfully.
+ * return value -EFAULT An error occurred while copying the completion
+ * data to the user space buffer.
+ * return value -1 An error occurred while executing the command.
+ */
+static int exec_drive_command(struct mtip_port *port, u8 *command,
+ void __user *user_buffer)
+{
+ struct host_to_dev_fis fis;
+ struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG);
+
+ /* Build the FIS. */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = command[0];
+ fis.features = command[2];
+ fis.sect_count = command[3];
+ if (fis.command == ATA_CMD_SMART) {
+ fis.sector = command[1];
+ fis.cyl_low = 0x4F;
+ fis.cyl_hi = 0xC2;
+ }
+
+ dbg_printk(MTIP_DRV_NAME
+ "%s: User Command: cmd %x, sect %x, "
+ "feat %x, sectcnt %x\n",
+ __func__,
+ command[0],
+ command[1],
+ command[2],
+ command[3]);
+
+ memset(port->sector_buffer, 0x00, ATA_SECT_SIZE);
+
+ /* Execute the command. */
+ if (mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ port->sector_buffer_dma,
+ (command[3] != 0) ? ATA_SECT_SIZE : 0,
+ 0,
+ GFP_KERNEL,
+ MTIP_IOCTL_COMMAND_TIMEOUT_MS)
+ < 0) {
+ return -1;
+ }
+
+ /* Collect the completion status. */
+ command[0] = reply->command; /* Status*/
+ command[1] = reply->features; /* Error*/
+ command[2] = command[3];
+
+ dbg_printk(MTIP_DRV_NAME
+ "%s: Completion Status: stat %x, "
+ "err %x, cmd %x\n",
+ __func__,
+ command[0],
+ command[1],
+ command[2]);
+
+ if (user_buffer && command[3]) {
+ if (copy_to_user(user_buffer,
+ port->sector_buffer,
+ ATA_SECT_SIZE * command[3])) {
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Indicates whether a command has a single sector payload.
+ *
+ * @command passed to the device to perform the certain event.
+ * @features passed to the device to perform the certain event.
+ *
+ * return value
+ * 1 command is one that always has a single sector payload,
+ * regardless of the value in the Sector Count field.
+ * 0 otherwise
+ *
+ */
+static unsigned int implicit_sector(unsigned char command,
+ unsigned char features)
+{
+ unsigned int rv = 0;
+
+ /* list of commands that have an implicit sector count of 1 */
+ switch (command) {
+ case ATA_CMD_SEC_SET_PASS:
+ case ATA_CMD_SEC_UNLOCK:
+ case ATA_CMD_SEC_ERASE_PREP:
+ case ATA_CMD_SEC_ERASE_UNIT:
+ case ATA_CMD_SEC_FREEZE_LOCK:
+ case ATA_CMD_SEC_DISABLE_PASS:
+ case ATA_CMD_PMP_READ:
+ case ATA_CMD_PMP_WRITE:
+ rv = 1;
+ break;
+ case ATA_CMD_SET_MAX:
+ if (features == ATA_SET_MAX_UNLOCK)
+ rv = 1;
+ break;
+ case ATA_CMD_SMART:
+ if ((features == ATA_SMART_READ_VALUES) ||
+ (features == ATA_SMART_READ_THRESHOLDS))
+ rv = 1;
+ break;
+ case ATA_CMD_CONF_OVERLAY:
+ if ((features == ATA_DCO_IDENTIFY) ||
+ (features == ATA_DCO_SET))
+ rv = 1;
+ break;
+ }
+ return rv;
+}
+
+/*
+ * Executes a taskfile
+ * See ide_taskfile_ioctl() for derivation
+ */
+static int exec_drive_taskfile(struct driver_data *dd,
+ void __user *buf,
+ ide_task_request_t *req_task,
+ int outtotal)
+{
+ struct host_to_dev_fis fis;
+ struct host_to_dev_fis *reply;
+ u8 *outbuf = NULL;
+ u8 *inbuf = NULL;
+ dma_addr_t outbuf_dma = 0;
+ dma_addr_t inbuf_dma = 0;
+ dma_addr_t dma_buffer = 0;
+ int err = 0;
+ unsigned int taskin = 0;
+ unsigned int taskout = 0;
+ u8 nsect = 0;
+ unsigned int timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
+ unsigned int force_single_sector;
+ unsigned int transfer_size;
+ unsigned long task_file_data;
+ int intotal = outtotal + req_task->out_size;
+
+ taskout = req_task->out_size;
+ taskin = req_task->in_size;
+ /* 130560 = 512 * 0xFF*/
+ if (taskin > 130560 || taskout > 130560) {
+ err = -EINVAL;
+ goto abort;
+ }
+
+ if (taskout) {
+ outbuf = kzalloc(taskout, GFP_KERNEL);
+ if (outbuf == NULL) {
+ err = -ENOMEM;
+ goto abort;
+ }
+ if (copy_from_user(outbuf, buf + outtotal, taskout)) {
+ err = -EFAULT;
+ goto abort;
+ }
+ outbuf_dma = pci_map_single(dd->pdev,
+ outbuf,
+ taskout,
+ DMA_TO_DEVICE);
+ if (outbuf_dma == 0) {
+ err = -ENOMEM;
+ goto abort;
+ }
+ dma_buffer = outbuf_dma;
+ }
+
+ if (taskin) {
+ inbuf = kzalloc(taskin, GFP_KERNEL);
+ if (inbuf == NULL) {
+ err = -ENOMEM;
+ goto abort;
+ }
+
+ if (copy_from_user(inbuf, buf + intotal, taskin)) {
+ err = -EFAULT;
+ goto abort;
+ }
+ inbuf_dma = pci_map_single(dd->pdev,
+ inbuf,
+ taskin, DMA_FROM_DEVICE);
+ if (inbuf_dma == 0) {
+ err = -ENOMEM;
+ goto abort;
+ }
+ dma_buffer = inbuf_dma;
+ }
+
+ /* only supports PIO and non-data commands from this ioctl. */
+ switch (req_task->data_phase) {
+ case TASKFILE_OUT:
+ nsect = taskout / ATA_SECT_SIZE;
+ reply = (dd->port->rxfis + RX_FIS_PIO_SETUP);
+ break;
+ case TASKFILE_IN:
+ reply = (dd->port->rxfis + RX_FIS_PIO_SETUP);
+ break;
+ case TASKFILE_NO_DATA:
+ reply = (dd->port->rxfis + RX_FIS_D2H_REG);
+ break;
+ default:
+ err = -EINVAL;
+ goto abort;
+ }
+
+ /* Build the FIS. */
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = req_task->io_ports[7];
+ fis.features = req_task->io_ports[1];
+ fis.sect_count = req_task->io_ports[2];
+ fis.lba_low = req_task->io_ports[3];
+ fis.lba_mid = req_task->io_ports[4];
+ fis.lba_hi = req_task->io_ports[5];
+ /* Clear the dev bit*/
+ fis.device = req_task->io_ports[6] & ~0x10;
+
+ if ((req_task->in_flags.all == 0) && (req_task->out_flags.all & 1)) {
+ req_task->in_flags.all =
+ IDE_TASKFILE_STD_IN_FLAGS |
+ (IDE_HOB_STD_IN_FLAGS << 8);
+ fis.lba_low_ex = req_task->hob_ports[3];
+ fis.lba_mid_ex = req_task->hob_ports[4];
+ fis.lba_hi_ex = req_task->hob_ports[5];
+ fis.features_ex = req_task->hob_ports[1];
+ fis.sect_cnt_ex = req_task->hob_ports[2];
+
+ } else {
+ req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
+ }
+
+ force_single_sector = implicit_sector(fis.command, fis.features);
+
+ if ((taskin || taskout) && (!fis.sect_count)) {
+ if (nsect)
+ fis.sect_count = nsect;
+ else {
+ if (!force_single_sector) {
+ dev_warn(&dd->pdev->dev,
+ "data movement but "
+ "sect_count is 0\n");
+ err = -EINVAL;
+ goto abort;
+ }
+ }
+ }
+
+ dbg_printk(MTIP_DRV_NAME
+ "taskfile: cmd %x, feat %x, nsect %x,"
+ " sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x,"
+ " head/dev %x\n",
+ fis.command,
+ fis.features,
+ fis.sect_count,
+ fis.lba_low,
+ fis.lba_mid,
+ fis.lba_hi,
+ fis.device);
+
+ switch (fis.command) {
+ case ATA_CMD_DOWNLOAD_MICRO:
+ /* Change timeout for Download Microcode to 60 seconds.*/
+ timeout = 60000;
+ break;
+ case ATA_CMD_SEC_ERASE_UNIT:
+ /* Change timeout for Security Erase Unit to 4 minutes.*/
+ timeout = 240000;
+ break;
+ case ATA_CMD_STANDBYNOW1:
+ /* Change timeout for standby immediate to 10 seconds.*/
+ timeout = 10000;
+ break;
+ case 0xF7:
+ case 0xFA:
+ /* Change timeout for vendor unique command to 10 secs */
+ timeout = 10000;
+ break;
+ case ATA_CMD_SMART:
+ /* Change timeout for vendor unique command to 10 secs */
+ timeout = 10000;
+ break;
+ default:
+ timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
+ break;
+ }
+
+ /* Determine the correct transfer size.*/
+ if (force_single_sector)
+ transfer_size = ATA_SECT_SIZE;
+ else
+ transfer_size = ATA_SECT_SIZE * fis.sect_count;
+
+ /* Execute the command.*/
+ if (mtip_exec_internal_command(dd->port,
+ &fis,
+ 5,
+ dma_buffer,
+ transfer_size,
+ 0,
+ GFP_KERNEL,
+ timeout) < 0) {
+ err = -EIO;
+ goto abort;
+ }
+
+ task_file_data = readl(dd->port->mmio+PORT_TFDATA);
+
+ if ((req_task->data_phase == TASKFILE_IN) && !(task_file_data & 1)) {
+ reply = dd->port->rxfis + RX_FIS_PIO_SETUP;
+ req_task->io_ports[7] = reply->control;
+ } else {
+ reply = dd->port->rxfis + RX_FIS_D2H_REG;
+ req_task->io_ports[7] = reply->command;
+ }
+
+ /* reclaim the DMA buffers.*/
+ if (inbuf_dma)
+ pci_unmap_single(dd->pdev, inbuf_dma,
+ taskin, DMA_FROM_DEVICE);
+ if (outbuf_dma)
+ pci_unmap_single(dd->pdev, outbuf_dma,
+ taskout, DMA_TO_DEVICE);
+ inbuf_dma = 0;
+ outbuf_dma = 0;
+
+ /* return the ATA registers to the caller.*/
+ req_task->io_ports[1] = reply->features;
+ req_task->io_ports[2] = reply->sect_count;
+ req_task->io_ports[3] = reply->lba_low;
+ req_task->io_ports[4] = reply->lba_mid;
+ req_task->io_ports[5] = reply->lba_hi;
+ req_task->io_ports[6] = reply->device;
+
+ if (req_task->out_flags.all & 1) {
+
+ req_task->hob_ports[3] = reply->lba_low_ex;
+ req_task->hob_ports[4] = reply->lba_mid_ex;
+ req_task->hob_ports[5] = reply->lba_hi_ex;
+ req_task->hob_ports[1] = reply->features_ex;
+ req_task->hob_ports[2] = reply->sect_cnt_ex;
+ }
+
+ /* Com rest after secure erase or lowlevel format */
+ if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) ||
+ ((fis.command == 0xFC) &&
+ (fis.features == 0x27 || fis.features == 0x72 ||
+ fis.features == 0x62 || fis.features == 0x26))) &&
+ !(reply->command & 1)) {
+ mtip_restart_port(dd->port);
+ }
+
+ dbg_printk(MTIP_DRV_NAME
+ "%s: Completion: stat %x,"
+ "err %x, sect_cnt %x, lbalo %x,"
+ "lbamid %x, lbahi %x, dev %x\n",
+ __func__,
+ req_task->io_ports[7],
+ req_task->io_ports[1],
+ req_task->io_ports[2],
+ req_task->io_ports[3],
+ req_task->io_ports[4],
+ req_task->io_ports[5],
+ req_task->io_ports[6]);
+
+ if (taskout) {
+ if (copy_to_user(buf + outtotal, outbuf, taskout)) {
+ err = -EFAULT;
+ goto abort;
+ }
+ }
+ if (taskin) {
+ if (copy_to_user(buf + intotal, inbuf, taskin)) {
+ err = -EFAULT;
+ goto abort;
+ }
+ }
+abort:
+ if (inbuf_dma)
+ pci_unmap_single(dd->pdev, inbuf_dma,
+ taskin, DMA_FROM_DEVICE);
+ if (outbuf_dma)
+ pci_unmap_single(dd->pdev, outbuf_dma,
+ taskout, DMA_TO_DEVICE);
+ kfree(outbuf);
+ kfree(inbuf);
+
+ return err;
+}
+
+/*
+ * Handle IOCTL calls from the Block Layer.
+ *
+ * This function is called by the Block Layer when it receives an IOCTL
+ * command that it does not understand. If the IOCTL command is not supported
+ * this function returns -ENOTTY.
+ *
+ * @dd Pointer to the driver data structure.
+ * @cmd IOCTL command passed from the Block Layer.
+ * @arg IOCTL argument passed from the Block Layer.
+ *
+ * return value
+ * 0 The IOCTL completed successfully.
+ * -ENOTTY The specified command is not supported.
+ * -EFAULT An error occurred copying data to a user space buffer.
+ * -EIO An error occurred while executing the command.
+ */
+static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case HDIO_GET_IDENTITY:
+ if (mtip_get_identify(dd->port, (void __user *) arg) < 0) {
+ dev_warn(&dd->pdev->dev,
+ "Unable to read identity\n");
+ return -EIO;
+ }
+
+ break;
+ case HDIO_DRIVE_CMD:
+ {
+ u8 drive_command[4];
+
+ /* Copy the user command info to our buffer. */
+ if (copy_from_user(drive_command,
+ (void __user *) arg,
+ sizeof(drive_command)))
+ return -EFAULT;
+
+ /* Execute the drive command. */
+ if (exec_drive_command(dd->port,
+ drive_command,
+ (void __user *) (arg+4)))
+ return -EIO;
+
+ /* Copy the status back to the users buffer. */
+ if (copy_to_user((void __user *) arg,
+ drive_command,
+ sizeof(drive_command)))
+ return -EFAULT;
+
+ break;
+ }
+ case HDIO_DRIVE_TASK:
+ {
+ u8 drive_command[7];
+
+ /* Copy the user command info to our buffer. */
+ if (copy_from_user(drive_command,
+ (void __user *) arg,
+ sizeof(drive_command)))
+ return -EFAULT;
+
+ /* Execute the drive command. */
+ if (exec_drive_task(dd->port, drive_command))
+ return -EIO;
+
+ /* Copy the status back to the users buffer. */
+ if (copy_to_user((void __user *) arg,
+ drive_command,
+ sizeof(drive_command)))
+ return -EFAULT;
+
+ break;
+ }
+ case HDIO_DRIVE_TASKFILE: {
+ ide_task_request_t req_task;
+ int ret, outtotal;
+
+ if (copy_from_user(&req_task, (void __user *) arg,
+ sizeof(req_task)))
+ return -EFAULT;
+
+ outtotal = sizeof(req_task);
+
+ ret = exec_drive_taskfile(dd, (void __user *) arg,
+ &req_task, outtotal);
+
+ if (copy_to_user((void __user *) arg, &req_task,
+ sizeof(req_task)))
+ return -EFAULT;
+
+ return ret;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Submit an IO to the hw
+ *
+ * This function is called by the block layer to issue an io
+ * to the device. Upon completion, the callback function will
+ * be called with the data parameter passed as the callback data.
+ *
+ * @dd Pointer to the driver data structure.
+ * @start First sector to read.
+ * @nsect Number of sectors to read.
+ * @nents Number of entries in scatter list for the read command.
+ * @tag The tag of this read command.
+ * @callback Pointer to the function that should be called
+ * when the read completes.
+ * @data Callback data passed to the callback function
+ * when the read completes.
+ * @barrier If non-zero, this command must be completed before
+ * issuing any other commands.
+ * @dir Direction (read or write)
+ *
+ * return value
+ * None
+ */
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+ int nsect, int nents, int tag, void *callback,
+ void *data, int barrier, int dir)
+{
+ struct host_to_dev_fis *fis;
+ struct mtip_port *port = dd->port;
+ struct mtip_cmd *command = &port->commands[tag];
+
+ /* Map the scatter list for DMA access */
+ if (dir == READ)
+ nents = dma_map_sg(&dd->pdev->dev, command->sg,
+ nents, DMA_FROM_DEVICE);
+ else
+ nents = dma_map_sg(&dd->pdev->dev, command->sg,
+ nents, DMA_TO_DEVICE);
+
+ command->scatter_ents = nents;
+
+ /*
+ * The number of retries for this command before it is
+ * reported as a failure to the upper layers.
+ */
+ command->retries = MTIP_MAX_RETRIES;
+
+ /* Fill out fis */
+ fis = command->command;
+ fis->type = 0x27;
+ fis->opts = 1 << 7;
+ fis->command =
+ (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
+ *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
+ *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+ fis->device = 1 << 6;
+ if (barrier)
+ fis->device |= FUA_BIT;
+ fis->features = nsect & 0xFF;
+ fis->features_ex = (nsect >> 8) & 0xFF;
+ fis->sect_count = ((tag << 3) | (tag >> 5));
+ fis->sect_cnt_ex = 0;
+ fis->control = 0;
+ fis->res2 = 0;
+ fis->res3 = 0;
+ fill_command_sg(dd, command, nents);
+
+ /* Populate the command header */
+ command->command_header->opts =
+ __force_bit2int cpu_to_le32(
+ (nents << 16) | 5 | AHCI_CMD_PREFETCH);
+ command->command_header->byte_count = 0;
+
+ /*
+ * Set the completion function and data for the command
+ * within this layer.
+ */
+ command->comp_data = dd;
+ command->comp_func = mtip_async_complete;
+ command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+
+ /*
+ * Set the completion function and data for the command passed
+ * from the upper layer.
+ */
+ command->async_data = data;
+ command->async_callback = callback;
+
+ /*
+ * To prevent this command from being issued
+ * if an internal command is in progress or error handling is active.
+ */
+ if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) ||
+ test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) {
+ set_bit(tag, port->cmds_to_issue);
+ set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+ return;
+ }
+
+ /* Issue the command to the hardware */
+ mtip_issue_ncq_command(port, tag);
+
+ /* Set the command's timeout value.*/
+ port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
+ MTIP_NCQ_COMMAND_TIMEOUT_MS);
+}
+
+/*
+ * Release a command slot.
+ *
+ * @dd Pointer to the driver data structure.
+ * @tag Slot tag
+ *
+ * return value
+ * None
+ */
+static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag)
+{
+ release_slot(dd->port, tag);
+}
+
+/*
+ * Obtain a command slot and return its associated scatter list.
+ *
+ * @dd Pointer to the driver data structure.
+ * @tag Pointer to an int that will receive the allocated command
+ * slot tag.
+ *
+ * return value
+ * Pointer to the scatter list for the allocated command slot
+ * or NULL if no command slots are available.
+ */
+static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
+ int *tag)
+{
+ /*
+ * It is possible that, even with this semaphore, a thread
+ * may think that no command slots are available. Therefore, we
+ * need to make an attempt to get_slot().
+ */
+ down(&dd->port->cmd_slot);
+ *tag = get_slot(dd->port);
+
+ if (unlikely(*tag < 0))
+ return NULL;
+
+ return dd->port->commands[*tag].sg;
+}
+
+/*
+ * Sysfs register/status dump.
+ *
+ * @dev Pointer to the device structure, passed by the kernrel.
+ * @attr Pointer to the device_attribute structure passed by the kernel.
+ * @buf Pointer to the char buffer that will receive the stats info.
+ *
+ * return value
+ * The size, in bytes, of the data copied into buf.
+ */
+static ssize_t hw_show_registers(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ u32 group_allocated;
+ struct driver_data *dd = dev_to_disk(dev)->private_data;
+ int size = 0;
+ int n;
+
+ size += sprintf(&buf[size], "%s:\ns_active:\n", __func__);
+
+ for (n = 0; n < dd->slot_groups; n++)
+ size += sprintf(&buf[size], "0x%08x\n",
+ readl(dd->port->s_active[n]));
+
+ size += sprintf(&buf[size], "Command Issue:\n");
+
+ for (n = 0; n < dd->slot_groups; n++)
+ size += sprintf(&buf[size], "0x%08x\n",
+ readl(dd->port->cmd_issue[n]));
+
+ size += sprintf(&buf[size], "Allocated:\n");
+
+ for (n = 0; n < dd->slot_groups; n++) {
+ if (sizeof(long) > sizeof(u32))
+ group_allocated =
+ dd->port->allocated[n/2] >> (32*(n&1));
+ else
+ group_allocated = dd->port->allocated[n];
+ size += sprintf(&buf[size], "0x%08x\n",
+ group_allocated);
+ }
+
+ size += sprintf(&buf[size], "completed:\n");
+
+ for (n = 0; n < dd->slot_groups; n++)
+ size += sprintf(&buf[size], "0x%08x\n",
+ readl(dd->port->completed[n]));
+
+ size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n",
+ readl(dd->port->mmio + PORT_IRQ_STAT));
+ size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n",
+ readl(dd->mmio + HOST_IRQ_STAT));
+
+ return size;
+}
+static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL);
+
+/*
+ * Create the sysfs related attributes.
+ *
+ * @dd Pointer to the driver data structure.
+ * @kobj Pointer to the kobj for the block device.
+ *
+ * return value
+ * 0 Operation completed successfully.
+ * -EINVAL Invalid parameter.
+ */
+static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj)
+{
+ if (!kobj || !dd)
+ return -EINVAL;
+
+ if (sysfs_create_file(kobj, &dev_attr_registers.attr))
+ dev_warn(&dd->pdev->dev,
+ "Error creating registers sysfs entry\n");
+ return 0;
+}
+
+/*
+ * Remove the sysfs related attributes.
+ *
+ * @dd Pointer to the driver data structure.
+ * @kobj Pointer to the kobj for the block device.
+ *
+ * return value
+ * 0 Operation completed successfully.
+ * -EINVAL Invalid parameter.
+ */
+static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj)
+{
+ if (!kobj || !dd)
+ return -EINVAL;
+
+ sysfs_remove_file(kobj, &dev_attr_registers.attr);
+
+ return 0;
+}
+
+/*
+ * Perform any init/resume time hardware setup
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * None
+ */
+static inline void hba_setup(struct driver_data *dd)
+{
+ u32 hwdata;
+ hwdata = readl(dd->mmio + HOST_HSORG);
+
+ /* interrupt bug workaround: use only 1 IS bit.*/
+ writel(hwdata |
+ HSORG_DISABLE_SLOTGRP_INTR |
+ HSORG_DISABLE_SLOTGRP_PXIS,
+ dd->mmio + HOST_HSORG);
+}
+
+/*
+ * Detect the details of the product, and store anything needed
+ * into the driver data structure. This includes product type and
+ * version and number of slot groups.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_detect_product(struct driver_data *dd)
+{
+ u32 hwdata;
+ unsigned int rev, slotgroups;
+
+ /*
+ * HBA base + 0xFC [15:0] - vendor-specific hardware interface
+ * info register:
+ * [15:8] hardware/software interface rev#
+ * [ 3] asic-style interface
+ * [ 2:0] number of slot groups, minus 1 (only valid for asic-style).
+ */
+ hwdata = readl(dd->mmio + HOST_HSORG);
+
+ dd->product_type = MTIP_PRODUCT_UNKNOWN;
+ dd->slot_groups = 1;
+
+ if (hwdata & 0x8) {
+ dd->product_type = MTIP_PRODUCT_ASICFPGA;
+ rev = (hwdata & HSORG_HWREV) >> 8;
+ slotgroups = (hwdata & HSORG_SLOTGROUPS) + 1;
+ dev_info(&dd->pdev->dev,
+ "ASIC-FPGA design, HS rev 0x%x, "
+ "%i slot groups [%i slots]\n",
+ rev,
+ slotgroups,
+ slotgroups * 32);
+
+ if (slotgroups > MTIP_MAX_SLOT_GROUPS) {
+ dev_warn(&dd->pdev->dev,
+ "Warning: driver only supports "
+ "%i slot groups.\n", MTIP_MAX_SLOT_GROUPS);
+ slotgroups = MTIP_MAX_SLOT_GROUPS;
+ }
+ dd->slot_groups = slotgroups;
+ return;
+ }
+
+ dev_warn(&dd->pdev->dev, "Unrecognized product id\n");
+}
+
+/*
+ * Blocking wait for FTL rebuild to complete
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ * 0 FTL rebuild completed successfully
+ * -EFAULT FTL rebuild error/timeout/interruption
+ */
+static int mtip_ftl_rebuild_poll(struct driver_data *dd)
+{
+ unsigned long timeout, cnt = 0, start;
+
+ dev_warn(&dd->pdev->dev,
+ "FTL rebuild in progress. Polling for completion.\n");
+
+ start = jiffies;
+ dd->ftlrebuildflag = 1;
+ timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS);
+
+ do {
+ if (mtip_check_surprise_removal(dd->pdev))
+ return -EFAULT;
+
+ if (mtip_get_identify(dd->port, NULL) < 0)
+ return -EFAULT;
+
+ if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
+ MTIP_FTL_REBUILD_MAGIC) {
+ ssleep(1);
+ /* Print message every 3 minutes */
+ if (cnt++ >= 180) {
+ dev_warn(&dd->pdev->dev,
+ "FTL rebuild in progress (%d secs).\n",
+ jiffies_to_msecs(jiffies - start) / 1000);
+ cnt = 0;
+ }
+ } else {
+ dev_warn(&dd->pdev->dev,
+ "FTL rebuild complete (%d secs).\n",
+ jiffies_to_msecs(jiffies - start) / 1000);
+ dd->ftlrebuildflag = 0;
+ mtip_block_initialize(dd);
+ break;
+ }
+ ssleep(10);
+ } while (time_before(jiffies, timeout));
+
+ /* Check for timeout */
+ if (dd->ftlrebuildflag) {
+ dev_err(&dd->pdev->dev,
+ "Timed out waiting for FTL rebuild to complete (%d secs).\n",
+ jiffies_to_msecs(jiffies - start) / 1000);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*
+ * service thread to issue queued commands
+ *
+ * @data Pointer to the driver data structure.
+ *
+ * return value
+ * 0
+ */
+
+static int mtip_service_thread(void *data)
+{
+ struct driver_data *dd = (struct driver_data *)data;
+ unsigned long slot, slot_start, slot_wrap;
+ unsigned int num_cmd_slots = dd->slot_groups * 32;
+ struct mtip_port *port = dd->port;
+
+ while (1) {
+ /*
+ * the condition is to check neither an internal command is
+ * is in progress nor error handling is active
+ */
+ wait_event_interruptible(port->svc_wait, (port->flags) &&
+ !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+ !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags));
+
+ if (kthread_should_stop())
+ break;
+
+ set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+ if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+ slot = 1;
+ /* used to restrict the loop to one iteration */
+ slot_start = num_cmd_slots;
+ slot_wrap = 0;
+ while (1) {
+ slot = find_next_bit(port->cmds_to_issue,
+ num_cmd_slots, slot);
+ if (slot_wrap == 1) {
+ if ((slot_start >= slot) ||
+ (slot >= num_cmd_slots))
+ break;
+ }
+ if (unlikely(slot_start == num_cmd_slots))
+ slot_start = slot;
+
+ if (unlikely(slot == num_cmd_slots)) {
+ slot = 1;
+ slot_wrap = 1;
+ continue;
+ }
+
+ /* Issue the command to the hardware */
+ mtip_issue_ncq_command(port, slot);
+
+ /* Set the command's timeout value.*/
+ port->commands[slot].comp_time = jiffies +
+ msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS);
+
+ clear_bit(slot, port->cmds_to_issue);
+ }
+
+ clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+ } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) {
+ mtip_ftl_rebuild_poll(dd);
+ clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags);
+ }
+ clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+
+ if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags))
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Called once for each card.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 on success, else an error code.
+ */
+static int mtip_hw_init(struct driver_data *dd)
+{
+ int i;
+ int rv;
+ unsigned int num_command_slots;
+
+ dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
+
+ mtip_detect_product(dd);
+ if (dd->product_type == MTIP_PRODUCT_UNKNOWN) {
+ rv = -EIO;
+ goto out1;
+ }
+ num_command_slots = dd->slot_groups * 32;
+
+ hba_setup(dd);
+
+ tasklet_init(&dd->tasklet, mtip_tasklet, (unsigned long)dd);
+
+ dd->port = kzalloc(sizeof(struct mtip_port), GFP_KERNEL);
+ if (!dd->port) {
+ dev_err(&dd->pdev->dev,
+ "Memory allocation: port structure\n");
+ return -ENOMEM;
+ }
+
+ /* Counting semaphore to track command slot usage */
+ sema_init(&dd->port->cmd_slot, num_command_slots - 1);
+
+ /* Spinlock to prevent concurrent issue */
+ spin_lock_init(&dd->port->cmd_issue_lock);
+
+ /* Set the port mmio base address. */
+ dd->port->mmio = dd->mmio + PORT_OFFSET;
+ dd->port->dd = dd;
+
+ /* Allocate memory for the command list. */
+ dd->port->command_list =
+ dmam_alloc_coherent(&dd->pdev->dev,
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ &dd->port->command_list_dma,
+ GFP_KERNEL);
+ if (!dd->port->command_list) {
+ dev_err(&dd->pdev->dev,
+ "Memory allocation: command list\n");
+ rv = -ENOMEM;
+ goto out1;
+ }
+
+ /* Clear the memory we have allocated. */
+ memset(dd->port->command_list,
+ 0,
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2));
+
+ /* Setup the addresse of the RX FIS. */
+ dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ;
+ dd->port->rxfis_dma = dd->port->command_list_dma + HW_CMD_SLOT_SZ;
+
+ /* Setup the address of the command tables. */
+ dd->port->command_table = dd->port->rxfis + AHCI_RX_FIS_SZ;
+ dd->port->command_tbl_dma = dd->port->rxfis_dma + AHCI_RX_FIS_SZ;
+
+ /* Setup the address of the identify data. */
+ dd->port->identify = dd->port->command_table +
+ HW_CMD_TBL_AR_SZ;
+ dd->port->identify_dma = dd->port->command_tbl_dma +
+ HW_CMD_TBL_AR_SZ;
+
+ /* Setup the address of the sector buffer. */
+ dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE;
+ dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE;
+
+ /* Point the command headers at the command tables. */
+ for (i = 0; i < num_command_slots; i++) {
+ dd->port->commands[i].command_header =
+ dd->port->command_list +
+ (sizeof(struct mtip_cmd_hdr) * i);
+ dd->port->commands[i].command_header_dma =
+ dd->port->command_list_dma +
+ (sizeof(struct mtip_cmd_hdr) * i);
+
+ dd->port->commands[i].command =
+ dd->port->command_table + (HW_CMD_TBL_SZ * i);
+ dd->port->commands[i].command_dma =
+ dd->port->command_tbl_dma + (HW_CMD_TBL_SZ * i);
+
+ if (readl(dd->mmio + HOST_CAP) & HOST_CAP_64)
+ dd->port->commands[i].command_header->ctbau =
+ __force_bit2int cpu_to_le32(
+ (dd->port->commands[i].command_dma >> 16) >> 16);
+ dd->port->commands[i].command_header->ctba =
+ __force_bit2int cpu_to_le32(
+ dd->port->commands[i].command_dma & 0xFFFFFFFF);
+
+ /*
+ * If this is not done, a bug is reported by the stock
+ * FC11 i386. Due to the fact that it has lots of kernel
+ * debugging enabled.
+ */
+ sg_init_table(dd->port->commands[i].sg, MTIP_MAX_SG);
+
+ /* Mark all commands as currently inactive.*/
+ atomic_set(&dd->port->commands[i].active, 0);
+ }
+
+ /* Setup the pointers to the extended s_active and CI registers. */
+ for (i = 0; i < dd->slot_groups; i++) {
+ dd->port->s_active[i] =
+ dd->port->mmio + i*0x80 + PORT_SCR_ACT;
+ dd->port->cmd_issue[i] =
+ dd->port->mmio + i*0x80 + PORT_COMMAND_ISSUE;
+ dd->port->completed[i] =
+ dd->port->mmio + i*0x80 + PORT_SDBV;
+ }
+
+ /* Reset the HBA. */
+ if (mtip_hba_reset(dd) < 0) {
+ dev_err(&dd->pdev->dev,
+ "Card did not reset within timeout\n");
+ rv = -EIO;
+ goto out2;
+ }
+
+ mtip_init_port(dd->port);
+ mtip_start_port(dd->port);
+
+ /* Setup the ISR and enable interrupts. */
+ rv = devm_request_irq(&dd->pdev->dev,
+ dd->pdev->irq,
+ mtip_irq_handler,
+ IRQF_SHARED,
+ dev_driver_string(&dd->pdev->dev),
+ dd);
+
+ if (rv) {
+ dev_err(&dd->pdev->dev,
+ "Unable to allocate IRQ %d\n", dd->pdev->irq);
+ goto out2;
+ }
+
+ /* Enable interrupts on the HBA. */
+ writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+
+ init_timer(&dd->port->cmd_timer);
+ init_waitqueue_head(&dd->port->svc_wait);
+
+ dd->port->cmd_timer.data = (unsigned long int) dd->port;
+ dd->port->cmd_timer.function = mtip_timeout_function;
+ mod_timer(&dd->port->cmd_timer,
+ jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+
+ if (mtip_get_identify(dd->port, NULL) < 0) {
+ rv = -EFAULT;
+ goto out3;
+ }
+
+ if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
+ MTIP_FTL_REBUILD_MAGIC) {
+ set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags);
+ return MTIP_FTL_REBUILD_MAGIC;
+ }
+ mtip_dump_identify(dd->port);
+ return rv;
+
+out3:
+ del_timer_sync(&dd->port->cmd_timer);
+
+ /* Disable interrupts on the HBA. */
+ writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+
+ /*Release the IRQ. */
+ devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
+
+out2:
+ mtip_deinit_port(dd->port);
+
+ /* Free the command/command header memory. */
+ dmam_free_coherent(&dd->pdev->dev,
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ dd->port->command_list,
+ dd->port->command_list_dma);
+out1:
+ /* Free the memory allocated for the for structure. */
+ kfree(dd->port);
+
+ return rv;
+}
+
+/*
+ * Called to deinitialize an interface.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0
+ */
+static int mtip_hw_exit(struct driver_data *dd)
+{
+ /*
+ * Send standby immediate (E0h) to the drive so that it
+ * saves its state.
+ */
+ if (atomic_read(&dd->drv_cleanup_done) != true) {
+
+ mtip_standby_immediate(dd->port);
+
+ /* de-initialize the port. */
+ mtip_deinit_port(dd->port);
+
+ /* Disable interrupts on the HBA. */
+ writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+ }
+
+ del_timer_sync(&dd->port->cmd_timer);
+
+ /* Release the IRQ. */
+ devm_free_irq(&dd->pdev->dev, dd->pdev->irq, dd);
+
+ /* Stop the bottom half tasklet. */
+ tasklet_kill(&dd->tasklet);
+
+ /* Free the command/command header memory. */
+ dmam_free_coherent(&dd->pdev->dev,
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ dd->port->command_list,
+ dd->port->command_list_dma);
+ /* Free the memory allocated for the for structure. */
+ kfree(dd->port);
+
+ return 0;
+}
+
+/*
+ * Issue a Standby Immediate command to the device.
+ *
+ * This function is called by the Block Layer just before the
+ * system powers off during a shutdown.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0
+ */
+static int mtip_hw_shutdown(struct driver_data *dd)
+{
+ /*
+ * Send standby immediate (E0h) to the drive so that it
+ * saves its state.
+ */
+ mtip_standby_immediate(dd->port);
+
+ return 0;
+}
+
+/*
+ * Suspend function
+ *
+ * This function is called by the Block Layer just before the
+ * system hibernates.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 Suspend was successful
+ * -EFAULT Suspend was not successful
+ */
+static int mtip_hw_suspend(struct driver_data *dd)
+{
+ /*
+ * Send standby immediate (E0h) to the drive
+ * so that it saves its state.
+ */
+ if (mtip_standby_immediate(dd->port) != 0) {
+ dev_err(&dd->pdev->dev,
+ "Failed standby-immediate command\n");
+ return -EFAULT;
+ }
+
+ /* Disable interrupts on the HBA.*/
+ writel(readl(dd->mmio + HOST_CTL) & ~HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+ mtip_deinit_port(dd->port);
+
+ return 0;
+}
+
+/*
+ * Resume function
+ *
+ * This function is called by the Block Layer as the
+ * system resumes.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 Resume was successful
+ * -EFAULT Resume was not successful
+ */
+static int mtip_hw_resume(struct driver_data *dd)
+{
+ /* Perform any needed hardware setup steps */
+ hba_setup(dd);
+
+ /* Reset the HBA */
+ if (mtip_hba_reset(dd) != 0) {
+ dev_err(&dd->pdev->dev,
+ "Unable to reset the HBA\n");
+ return -EFAULT;
+ }
+
+ /*
+ * Enable the port, DMA engine, and FIS reception specific
+ * h/w in controller.
+ */
+ mtip_init_port(dd->port);
+ mtip_start_port(dd->port);
+
+ /* Enable interrupts on the HBA.*/
+ writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+
+ return 0;
+}
+
+/*
+ * Helper function for reusing disk name
+ * upon hot insertion.
+ */
+static int rssd_disk_name_format(char *prefix,
+ int index,
+ char *buf,
+ int buflen)
+{
+ const int base = 'z' - 'a' + 1;
+ char *begin = buf + strlen(prefix);
+ char *end = buf + buflen;
+ char *p;
+ int unit;
+
+ p = end - 1;
+ *p = '\0';
+ unit = base;
+ do {
+ if (p == begin)
+ return -EINVAL;
+ *--p = 'a' + (index % unit);
+ index = (index / unit) - 1;
+ } while (index >= 0);
+
+ memmove(begin, p, end - p);
+ memcpy(buf, prefix, strlen(prefix));
+
+ return 0;
+}
+
+/*
+ * Block layer IOCTL handler.
+ *
+ * @dev Pointer to the block_device structure.
+ * @mode ignored
+ * @cmd IOCTL command passed from the user application.
+ * @arg Argument passed from the user application.
+ *
+ * return value
+ * 0 IOCTL completed successfully.
+ * -ENOTTY IOCTL not supported or invalid driver data
+ * structure pointer.
+ */
+static int mtip_block_ioctl(struct block_device *dev,
+ fmode_t mode,
+ unsigned cmd,
+ unsigned long arg)
+{
+ struct driver_data *dd = dev->bd_disk->private_data;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (!dd)
+ return -ENOTTY;
+
+ switch (cmd) {
+ case BLKFLSBUF:
+ return -ENOTTY;
+ default:
+ return mtip_hw_ioctl(dd, cmd, arg);
+ }
+}
+
+#ifdef CONFIG_COMPAT
+/*
+ * Block layer compat IOCTL handler.
+ *
+ * @dev Pointer to the block_device structure.
+ * @mode ignored
+ * @cmd IOCTL command passed from the user application.
+ * @arg Argument passed from the user application.
+ *
+ * return value
+ * 0 IOCTL completed successfully.
+ * -ENOTTY IOCTL not supported or invalid driver data
+ * structure pointer.
+ */
+static int mtip_block_compat_ioctl(struct block_device *dev,
+ fmode_t mode,
+ unsigned cmd,
+ unsigned long arg)
+{
+ struct driver_data *dd = dev->bd_disk->private_data;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (!dd)
+ return -ENOTTY;
+
+ switch (cmd) {
+ case BLKFLSBUF:
+ return -ENOTTY;
+ case HDIO_DRIVE_TASKFILE: {
+ struct mtip_compat_ide_task_request_s __user *compat_req_task;
+ ide_task_request_t req_task;
+ int compat_tasksize, outtotal, ret;
+
+ compat_tasksize =
+ sizeof(struct mtip_compat_ide_task_request_s);
+
+ compat_req_task =
+ (struct mtip_compat_ide_task_request_s __user *) arg;
+
+ if (copy_from_user(&req_task, (void __user *) arg,
+ compat_tasksize - (2 * sizeof(compat_long_t))))
+ return -EFAULT;
+
+ if (get_user(req_task.out_size, &compat_req_task->out_size))
+ return -EFAULT;
+
+ if (get_user(req_task.in_size, &compat_req_task->in_size))
+ return -EFAULT;
+
+ outtotal = sizeof(struct mtip_compat_ide_task_request_s);
+
+ ret = exec_drive_taskfile(dd, (void __user *) arg,
+ &req_task, outtotal);
+
+ if (copy_to_user((void __user *) arg, &req_task,
+ compat_tasksize -
+ (2 * sizeof(compat_long_t))))
+ return -EFAULT;
+
+ if (put_user(req_task.out_size, &compat_req_task->out_size))
+ return -EFAULT;
+
+ if (put_user(req_task.in_size, &compat_req_task->in_size))
+ return -EFAULT;
+
+ return ret;
+ }
+ default:
+ return mtip_hw_ioctl(dd, cmd, arg);
+ }
+}
+#endif
+
+/*
+ * Obtain the geometry of the device.
+ *
+ * You may think that this function is obsolete, but some applications,
+ * fdisk for example still used CHS values. This function describes the
+ * device as having 224 heads and 56 sectors per cylinder. These values are
+ * chosen so that each cylinder is aligned on a 4KB boundary. Since a
+ * partition is described in terms of a start and end cylinder this means
+ * that each partition is also 4KB aligned. Non-aligned partitions adversely
+ * affects performance.
+ *
+ * @dev Pointer to the block_device strucutre.
+ * @geo Pointer to a hd_geometry structure.
+ *
+ * return value
+ * 0 Operation completed successfully.
+ * -ENOTTY An error occurred while reading the drive capacity.
+ */
+static int mtip_block_getgeo(struct block_device *dev,
+ struct hd_geometry *geo)
+{
+ struct driver_data *dd = dev->bd_disk->private_data;
+ sector_t capacity;
+
+ if (!dd)
+ return -ENOTTY;
+
+ if (!(mtip_hw_get_capacity(dd, &capacity))) {
+ dev_warn(&dd->pdev->dev,
+ "Could not get drive capacity.\n");
+ return -ENOTTY;
+ }
+
+ geo->heads = 224;
+ geo->sectors = 56;
+ sector_div(capacity, (geo->heads * geo->sectors));
+ geo->cylinders = capacity;
+ return 0;
+}
+
+/*
+ * Block device operation function.
+ *
+ * This structure contains pointers to the functions required by the block
+ * layer.
+ */
+static const struct block_device_operations mtip_block_ops = {
+ .ioctl = mtip_block_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = mtip_block_compat_ioctl,
+#endif
+ .getgeo = mtip_block_getgeo,
+ .owner = THIS_MODULE
+};
+
+/*
+ * Block layer make request function.
+ *
+ * This function is called by the kernel to process a BIO for
+ * the P320 device.
+ *
+ * @queue Pointer to the request queue. Unused other than to obtain
+ * the driver data structure.
+ * @bio Pointer to the BIO.
+ *
+ */
+static void mtip_make_request(struct request_queue *queue, struct bio *bio)
+{
+ struct driver_data *dd = queue->queuedata;
+ struct scatterlist *sg;
+ struct bio_vec *bvec;
+ int nents = 0;
+ int tag = 0;
+
+ if (unlikely(!bio_has_data(bio))) {
+ blk_queue_flush(queue, 0);
+ bio_endio(bio, 0);
+ return;
+ }
+
+ sg = mtip_hw_get_scatterlist(dd, &tag);
+ if (likely(sg != NULL)) {
+ blk_queue_bounce(queue, &bio);
+
+ if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
+ dev_warn(&dd->pdev->dev,
+ "Maximum number of SGL entries exceeded");
+ bio_io_error(bio);
+ mtip_hw_release_scatterlist(dd, tag);
+ return;
+ }
+
+ /* Create the scatter list for this bio. */
+ bio_for_each_segment(bvec, bio, nents) {
+ sg_set_page(&sg[nents],
+ bvec->bv_page,
+ bvec->bv_len,
+ bvec->bv_offset);
+ }
+
+ /* Issue the read/write. */
+ mtip_hw_submit_io(dd,
+ bio->bi_sector,
+ bio_sectors(bio),
+ nents,
+ tag,
+ bio_endio,
+ bio,
+ bio->bi_rw & REQ_FUA,
+ bio_data_dir(bio));
+ } else
+ bio_io_error(bio);
+}
+
+/*
+ * Block layer initialization function.
+ *
+ * This function is called once by the PCI layer for each P320
+ * device that is connected to the system.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0 on success else an error code.
+ */
+static int mtip_block_initialize(struct driver_data *dd)
+{
+ int rv = 0, wait_for_rebuild = 0;
+ sector_t capacity;
+ unsigned int index = 0;
+ struct kobject *kobj;
+ unsigned char thd_name[16];
+
+ if (dd->disk)
+ goto skip_create_disk; /* hw init done, before rebuild */
+
+ /* Initialize the protocol layer. */
+ wait_for_rebuild = mtip_hw_init(dd);
+ if (wait_for_rebuild < 0) {
+ dev_err(&dd->pdev->dev,
+ "Protocol layer initialization failed\n");
+ rv = -EINVAL;
+ goto protocol_init_error;
+ }
+
+ dd->disk = alloc_disk(MTIP_MAX_MINORS);
+ if (dd->disk == NULL) {
+ dev_err(&dd->pdev->dev,
+ "Unable to allocate gendisk structure\n");
+ rv = -EINVAL;
+ goto alloc_disk_error;
+ }
+
+ /* Generate the disk name, implemented same as in sd.c */
+ do {
+ if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL))
+ goto ida_get_error;
+
+ spin_lock(&rssd_index_lock);
+ rv = ida_get_new(&rssd_index_ida, &index);
+ spin_unlock(&rssd_index_lock);
+ } while (rv == -EAGAIN);
+
+ if (rv)
+ goto ida_get_error;
+
+ rv = rssd_disk_name_format("rssd",
+ index,
+ dd->disk->disk_name,
+ DISK_NAME_LEN);
+ if (rv)
+ goto disk_index_error;
+
+ dd->disk->driverfs_dev = &dd->pdev->dev;
+ dd->disk->major = dd->major;
+ dd->disk->first_minor = dd->instance * MTIP_MAX_MINORS;
+ dd->disk->fops = &mtip_block_ops;
+ dd->disk->private_data = dd;
+ dd->index = index;
+
+ /*
+ * if rebuild pending, start the service thread, and delay the block
+ * queue creation and add_disk()
+ */
+ if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
+ goto start_service_thread;
+
+skip_create_disk:
+ /* Allocate the request queue. */
+ dd->queue = blk_alloc_queue(GFP_KERNEL);
+ if (dd->queue == NULL) {
+ dev_err(&dd->pdev->dev,
+ "Unable to allocate request queue\n");
+ rv = -ENOMEM;
+ goto block_queue_alloc_init_error;
+ }
+
+ /* Attach our request function to the request queue. */
+ blk_queue_make_request(dd->queue, mtip_make_request);
+
+ dd->disk->queue = dd->queue;
+ dd->queue->queuedata = dd;
+
+ /* Set device limits. */
+ set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags);
+ blk_queue_max_segments(dd->queue, MTIP_MAX_SG);
+ blk_queue_physical_block_size(dd->queue, 4096);
+ blk_queue_io_min(dd->queue, 4096);
+ blk_queue_flush(dd->queue, 0);
+
+ /* Set the capacity of the device in 512 byte sectors. */
+ if (!(mtip_hw_get_capacity(dd, &capacity))) {
+ dev_warn(&dd->pdev->dev,
+ "Could not read drive capacity\n");
+ rv = -EIO;
+ goto read_capacity_error;
+ }
+ set_capacity(dd->disk, capacity);
+
+ /* Enable the block device and add it to /dev */
+ add_disk(dd->disk);
+
+ /*
+ * Now that the disk is active, initialize any sysfs attributes
+ * managed by the protocol layer.
+ */
+ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+ if (kobj) {
+ mtip_hw_sysfs_init(dd, kobj);
+ kobject_put(kobj);
+ }
+
+ if (dd->mtip_svc_handler)
+ return rv; /* service thread created for handling rebuild */
+
+start_service_thread:
+ sprintf(thd_name, "mtip_svc_thd_%02d", index);
+
+ dd->mtip_svc_handler = kthread_run(mtip_service_thread,
+ dd, thd_name);
+
+ if (IS_ERR(dd->mtip_svc_handler)) {
+ printk(KERN_ERR "mtip32xx: service thread failed to start\n");
+ dd->mtip_svc_handler = NULL;
+ rv = -EFAULT;
+ goto kthread_run_error;
+ }
+
+ return rv;
+
+kthread_run_error:
+ /* Delete our gendisk. This also removes the device from /dev */
+ del_gendisk(dd->disk);
+
+read_capacity_error:
+ blk_cleanup_queue(dd->queue);
+
+block_queue_alloc_init_error:
+disk_index_error:
+ spin_lock(&rssd_index_lock);
+ ida_remove(&rssd_index_ida, index);
+ spin_unlock(&rssd_index_lock);
+
+ida_get_error:
+ put_disk(dd->disk);
+
+alloc_disk_error:
+ mtip_hw_exit(dd); /* De-initialize the protocol layer. */
+
+protocol_init_error:
+ return rv;
+}
+
+/*
+ * Block layer deinitialization function.
+ *
+ * Called by the PCI layer as each P320 device is removed.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0
+ */
+static int mtip_block_remove(struct driver_data *dd)
+{
+ struct kobject *kobj;
+
+ if (dd->mtip_svc_handler) {
+ set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags);
+ wake_up_interruptible(&dd->port->svc_wait);
+ kthread_stop(dd->mtip_svc_handler);
+ }
+
+ /* Clean up the sysfs attributes managed by the protocol layer. */
+ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+ if (kobj) {
+ mtip_hw_sysfs_exit(dd, kobj);
+ kobject_put(kobj);
+ }
+
+ /*
+ * Delete our gendisk structure. This also removes the device
+ * from /dev
+ */
+ del_gendisk(dd->disk);
+ blk_cleanup_queue(dd->queue);
+ dd->disk = NULL;
+ dd->queue = NULL;
+
+ /* De-initialize the protocol layer. */
+ mtip_hw_exit(dd);
+
+ return 0;
+}
+
+/*
+ * Function called by the PCI layer when just before the
+ * machine shuts down.
+ *
+ * If a protocol layer shutdown function is present it will be called
+ * by this function.
+ *
+ * @dd Pointer to the driver data structure.
+ *
+ * return value
+ * 0
+ */
+static int mtip_block_shutdown(struct driver_data *dd)
+{
+ dev_info(&dd->pdev->dev,
+ "Shutting down %s ...\n", dd->disk->disk_name);
+
+ /* Delete our gendisk structure, and cleanup the blk queue. */
+ del_gendisk(dd->disk);
+ blk_cleanup_queue(dd->queue);
+ dd->disk = NULL;
+ dd->queue = NULL;
+
+ mtip_hw_shutdown(dd);
+ return 0;
+}
+
+static int mtip_block_suspend(struct driver_data *dd)
+{
+ dev_info(&dd->pdev->dev,
+ "Suspending %s ...\n", dd->disk->disk_name);
+ mtip_hw_suspend(dd);
+ return 0;
+}
+
+static int mtip_block_resume(struct driver_data *dd)
+{
+ dev_info(&dd->pdev->dev, "Resuming %s ...\n",
+ dd->disk->disk_name);
+ mtip_hw_resume(dd);
+ return 0;
+}
+
+/*
+ * Called for each supported PCI device detected.
+ *
+ * This function allocates the private data structure, enables the
+ * PCI device and then calls the block layer initialization function.
+ *
+ * return value
+ * 0 on success else an error code.
+ */
+static int mtip_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rv = 0;
+ struct driver_data *dd = NULL;
+
+ /* Allocate memory for this devices private data. */
+ dd = kzalloc(sizeof(struct driver_data), GFP_KERNEL);
+ if (dd == NULL) {
+ dev_err(&pdev->dev,
+ "Unable to allocate memory for driver data\n");
+ return -ENOMEM;
+ }
+
+ /* Set the atomic variable as 1 in case of SRSI */
+ atomic_set(&dd->drv_cleanup_done, true);
+
+ atomic_set(&dd->resumeflag, false);
+
+ /* Attach the private data to this PCI device. */
+ pci_set_drvdata(pdev, dd);
+
+ rv = pcim_enable_device(pdev);
+ if (rv < 0) {
+ dev_err(&pdev->dev, "Unable to enable device\n");
+ goto iomap_err;
+ }
+
+ /* Map BAR5 to memory. */
+ rv = pcim_iomap_regions(pdev, 1 << MTIP_ABAR, MTIP_DRV_NAME);
+ if (rv < 0) {
+ dev_err(&pdev->dev, "Unable to map regions\n");
+ goto iomap_err;
+ }
+
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ rv = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+
+ if (rv) {
+ rv = pci_set_consistent_dma_mask(pdev,
+ DMA_BIT_MASK(32));
+ if (rv) {
+ dev_warn(&pdev->dev,
+ "64-bit DMA enable failed\n");
+ goto setmask_err;
+ }
+ }
+ }
+
+ pci_set_master(pdev);
+
+ if (pci_enable_msi(pdev)) {
+ dev_warn(&pdev->dev,
+ "Unable to enable MSI interrupt.\n");
+ goto block_initialize_err;
+ }
+
+ /* Copy the info we may need later into the private data structure. */
+ dd->major = mtip_major;
+ dd->instance = instance;
+ dd->pdev = pdev;
+
+ /* Initialize the block layer. */
+ rv = mtip_block_initialize(dd);
+ if (rv < 0) {
+ dev_err(&pdev->dev,
+ "Unable to initialize block layer\n");
+ goto block_initialize_err;
+ }
+
+ /*
+ * Increment the instance count so that each device has a unique
+ * instance number.
+ */
+ instance++;
+
+ goto done;
+
+block_initialize_err:
+ pci_disable_msi(pdev);
+
+setmask_err:
+ pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
+
+iomap_err:
+ kfree(dd);
+ pci_set_drvdata(pdev, NULL);
+ return rv;
+done:
+ /* Set the atomic variable as 0 in case of SRSI */
+ atomic_set(&dd->drv_cleanup_done, true);
+
+ return rv;
+}
+
+/*
+ * Called for each probed device when the device is removed or the
+ * driver is unloaded.
+ *
+ * return value
+ * None
+ */
+static void mtip_pci_remove(struct pci_dev *pdev)
+{
+ struct driver_data *dd = pci_get_drvdata(pdev);
+ int counter = 0;
+
+ if (mtip_check_surprise_removal(pdev)) {
+ while (atomic_read(&dd->drv_cleanup_done) == false) {
+ counter++;
+ msleep(20);
+ if (counter == 10) {
+ /* Cleanup the outstanding commands */
+ mtip_command_cleanup(dd);
+ break;
+ }
+ }
+ }
+ /* Set the atomic variable as 1 in case of SRSI */
+ atomic_set(&dd->drv_cleanup_done, true);
+
+ /* Clean up the block layer. */
+ mtip_block_remove(dd);
+
+ pci_disable_msi(pdev);
+
+ kfree(dd);
+ pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
+}
+
+/*
+ * Called for each probed device when the device is suspended.
+ *
+ * return value
+ * 0 Success
+ * <0 Error
+ */
+static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ int rv = 0;
+ struct driver_data *dd = pci_get_drvdata(pdev);
+
+ if (!dd) {
+ dev_err(&pdev->dev,
+ "Driver private datastructure is NULL\n");
+ return -EFAULT;
+ }
+
+ atomic_set(&dd->resumeflag, true);
+
+ /* Disable ports & interrupts then send standby immediate */
+ rv = mtip_block_suspend(dd);
+ if (rv < 0) {
+ dev_err(&pdev->dev,
+ "Failed to suspend controller\n");
+ return rv;
+ }
+
+ /*
+ * Save the pci config space to pdev structure &
+ * disable the device
+ */
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ /* Move to Low power state*/
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return rv;
+}
+
+/*
+ * Called for each probed device when the device is resumed.
+ *
+ * return value
+ * 0 Success
+ * <0 Error
+ */
+static int mtip_pci_resume(struct pci_dev *pdev)
+{
+ int rv = 0;
+ struct driver_data *dd;
+
+ dd = pci_get_drvdata(pdev);
+ if (!dd) {
+ dev_err(&pdev->dev,
+ "Driver private datastructure is NULL\n");
+ return -EFAULT;
+ }
+
+ /* Move the device to active State */
+ pci_set_power_state(pdev, PCI_D0);
+
+ /* Restore PCI configuration space */
+ pci_restore_state(pdev);
+
+ /* Enable the PCI device*/
+ rv = pcim_enable_device(pdev);
+ if (rv < 0) {
+ dev_err(&pdev->dev,
+ "Failed to enable card during resume\n");
+ goto err;
+ }
+ pci_set_master(pdev);
+
+ /*
+ * Calls hbaReset, initPort, & startPort function
+ * then enables interrupts
+ */
+ rv = mtip_block_resume(dd);
+ if (rv < 0)
+ dev_err(&pdev->dev, "Unable to resume\n");
+
+err:
+ atomic_set(&dd->resumeflag, false);
+
+ return rv;
+}
+
+/*
+ * Shutdown routine
+ *
+ * return value
+ * None
+ */
+static void mtip_pci_shutdown(struct pci_dev *pdev)
+{
+ struct driver_data *dd = pci_get_drvdata(pdev);
+ if (dd)
+ mtip_block_shutdown(dd);
+}
+
+/* Table of device ids supported by this driver. */
+static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) },
+ { 0 }
+};
+
+/* Structure that describes the PCI driver functions. */
+static struct pci_driver mtip_pci_driver = {
+ .name = MTIP_DRV_NAME,
+ .id_table = mtip_pci_tbl,
+ .probe = mtip_pci_probe,
+ .remove = mtip_pci_remove,
+ .suspend = mtip_pci_suspend,
+ .resume = mtip_pci_resume,
+ .shutdown = mtip_pci_shutdown,
+};
+
+MODULE_DEVICE_TABLE(pci, mtip_pci_tbl);
+
+/*
+ * Module initialization function.
+ *
+ * Called once when the module is loaded. This function allocates a major
+ * block device number to the Cyclone devices and registers the PCI layer
+ * of the driver.
+ *
+ * Return value
+ * 0 on success else error code.
+ */
+static int __init mtip_init(void)
+{
+ printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
+
+ /* Allocate a major block device number to use with this driver. */
+ mtip_major = register_blkdev(0, MTIP_DRV_NAME);
+ if (mtip_major < 0) {
+ printk(KERN_ERR "Unable to register block device (%d)\n",
+ mtip_major);
+ return -EBUSY;
+ }
+
+ /* Register our PCI operations. */
+ return pci_register_driver(&mtip_pci_driver);
+}
+
+/*
+ * Module de-initialization function.
+ *
+ * Called once when the module is unloaded. This function deallocates
+ * the major block device number allocated by mtip_init() and
+ * unregisters the PCI layer of the driver.
+ *
+ * Return value
+ * none
+ */
+static void __exit mtip_exit(void)
+{
+ /* Release the allocated major block device number. */
+ unregister_blkdev(mtip_major, MTIP_DRV_NAME);
+
+ /* Unregister the PCI driver. */
+ pci_unregister_driver(&mtip_pci_driver);
+}
+
+MODULE_AUTHOR("Micron Technology, Inc");
+MODULE_DESCRIPTION("Micron RealSSD PCIe Block Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MTIP_DRV_VERSION);
+
+module_init(mtip_init);
+module_exit(mtip_exit);
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
new file mode 100644
index 0000000..723d7c4
--- /dev/null
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -0,0 +1,423 @@
+/*
+ * mtip32xx.h - Header file for the P320 SSD Block Driver
+ * Copyright (C) 2011 Micron Technology, Inc.
+ *
+ * Portions of this code were derived from works subjected to the
+ * following copyright:
+ * Copyright (C) 2009 Integrated Device Technology, 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MTIP32XX_H__
+#define __MTIP32XX_H__
+
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+#include <linux/ata.h>
+#include <linux/interrupt.h>
+#include <linux/genhd.h>
+#include <linux/version.h>
+
+/* Offset of Subsystem Device ID in pci confoguration space */
+#define PCI_SUBSYSTEM_DEVICEID 0x2E
+
+/* offset of Device Control register in PCIe extended capabilites space */
+#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
+
+/* # of times to retry timed out IOs */
+#define MTIP_MAX_RETRIES 5
+
+/* Various timeout values in ms */
+#define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000
+#define MTIP_IOCTL_COMMAND_TIMEOUT_MS 5000
+#define MTIP_INTERNAL_COMMAND_TIMEOUT_MS 5000
+
+/* check for timeouts every 500ms */
+#define MTIP_TIMEOUT_CHECK_PERIOD 500
+
+/* ftl rebuild */
+#define MTIP_FTL_REBUILD_OFFSET 142
+#define MTIP_FTL_REBUILD_MAGIC 0xED51
+#define MTIP_FTL_REBUILD_TIMEOUT_MS 2400000
+
+/* Macro to extract the tag bit number from a tag value. */
+#define MTIP_TAG_BIT(tag) (tag & 0x1F)
+
+/*
+ * Macro to extract the tag index from a tag value. The index
+ * is used to access the correct s_active/Command Issue register based
+ * on the tag value.
+ */
+#define MTIP_TAG_INDEX(tag) (tag >> 5)
+
+/*
+ * Maximum number of scatter gather entries
+ * a single command may have.
+ */
+#define MTIP_MAX_SG 128
+
+/*
+ * Maximum number of slot groups (Command Issue & s_active registers)
+ * NOTE: This is the driver maximum; check dd->slot_groups for actual value.
+ */
+#define MTIP_MAX_SLOT_GROUPS 8
+
+/* Internal command tag. */
+#define MTIP_TAG_INTERNAL 0
+
+/* Micron Vendor ID & P320x SSD Device ID */
+#define PCI_VENDOR_ID_MICRON 0x1344
+#define P320_DEVICE_ID 0x5150
+
+/* Driver name and version strings */
+#define MTIP_DRV_NAME "mtip32xx"
+#define MTIP_DRV_VERSION "1.2.6os3"
+
+/* Maximum number of minor device numbers per device. */
+#define MTIP_MAX_MINORS 16
+
+/* Maximum number of supported command slots. */
+#define MTIP_MAX_COMMAND_SLOTS (MTIP_MAX_SLOT_GROUPS * 32)
+
+/*
+ * Per-tag bitfield size in longs.
+ * Linux bit manipulation functions
+ * (i.e. test_and_set_bit, find_next_zero_bit)
+ * manipulate memory in longs, so we try to make the math work.
+ * take the slot groups and find the number of longs, rounding up.
+ * Careful! i386 and x86_64 use different size longs!
+ */
+#define U32_PER_LONG (sizeof(long) / sizeof(u32))
+#define SLOTBITS_IN_LONGS ((MTIP_MAX_SLOT_GROUPS + \
+ (U32_PER_LONG-1))/U32_PER_LONG)
+
+/* BAR number used to access the HBA registers. */
+#define MTIP_ABAR 5
+
+/* Forced Unit Access Bit */
+#define FUA_BIT 0x80
+
+#ifdef DEBUG
+ #define dbg_printk(format, arg...) \
+ printk(pr_fmt(format), ##arg);
+#else
+ #define dbg_printk(format, arg...)
+#endif
+
+#define __force_bit2int (unsigned int __force)
+
+/* below are bit numbers in 'flags' defined in mtip_port */
+#define MTIP_FLAG_IC_ACTIVE_BIT 0
+#define MTIP_FLAG_EH_ACTIVE_BIT 1
+#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2
+#define MTIP_FLAG_ISSUE_CMDS_BIT 4
+#define MTIP_FLAG_REBUILD_BIT 5
+#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8
+
+/* Register Frame Information Structure (FIS), host to device. */
+struct host_to_dev_fis {
+ /*
+ * FIS type.
+ * - 27h Register FIS, host to device.
+ * - 34h Register FIS, device to host.
+ * - 39h DMA Activate FIS, device to host.
+ * - 41h DMA Setup FIS, bi-directional.
+ * - 46h Data FIS, bi-directional.
+ * - 58h BIST Activate FIS, bi-directional.
+ * - 5Fh PIO Setup FIS, device to host.
+ * - A1h Set Device Bits FIS, device to host.
+ */
+ unsigned char type;
+ unsigned char opts;
+ unsigned char command;
+ unsigned char features;
+
+ union {
+ unsigned char lba_low;
+ unsigned char sector;
+ };
+ union {
+ unsigned char lba_mid;
+ unsigned char cyl_low;
+ };
+ union {
+ unsigned char lba_hi;
+ unsigned char cyl_hi;
+ };
+ union {
+ unsigned char device;
+ unsigned char head;
+ };
+
+ union {
+ unsigned char lba_low_ex;
+ unsigned char sector_ex;
+ };
+ union {
+ unsigned char lba_mid_ex;
+ unsigned char cyl_low_ex;
+ };
+ union {
+ unsigned char lba_hi_ex;
+ unsigned char cyl_hi_ex;
+ };
+ unsigned char features_ex;
+
+ unsigned char sect_count;
+ unsigned char sect_cnt_ex;
+ unsigned char res2;
+ unsigned char control;
+
+ unsigned int res3;
+};
+
+/* Command header structure. */
+struct mtip_cmd_hdr {
+ /*
+ * Command options.
+ * - Bits 31:16 Number of PRD entries.
+ * - Bits 15:8 Unused in this implementation.
+ * - Bit 7 Prefetch bit, informs the drive to prefetch PRD entries.
+ * - Bit 6 Write bit, should be set when writing data to the device.
+ * - Bit 5 Unused in this implementation.
+ * - Bits 4:0 Length of the command FIS in DWords (DWord = 4 bytes).
+ */
+ unsigned int opts;
+ /* This field is unsed when using NCQ. */
+ union {
+ unsigned int byte_count;
+ unsigned int status;
+ };
+ /*
+ * Lower 32 bits of the command table address associated with this
+ * header. The command table addresses must be 128 byte aligned.
+ */
+ unsigned int ctba;
+ /*
+ * If 64 bit addressing is used this field is the upper 32 bits
+ * of the command table address associated with this command.
+ */
+ unsigned int ctbau;
+ /* Reserved and unused. */
+ unsigned int res[4];
+};
+
+/* Command scatter gather structure (PRD). */
+struct mtip_cmd_sg {
+ /*
+ * Low 32 bits of the data buffer address. For P320 this
+ * address must be 8 byte aligned signified by bits 2:0 being
+ * set to 0.
+ */
+ unsigned int dba;
+ /*
+ * When 64 bit addressing is used this field is the upper
+ * 32 bits of the data buffer address.
+ */
+ unsigned int dba_upper;
+ /* Unused. */
+ unsigned int reserved;
+ /*
+ * Bit 31: interrupt when this data block has been transferred.
+ * Bits 30..22: reserved
+ * Bits 21..0: byte count (minus 1). For P320 the byte count must be
+ * 8 byte aligned signified by bits 2:0 being set to 1.
+ */
+ unsigned int info;
+};
+struct mtip_port;
+
+/* Structure used to describe a command. */
+struct mtip_cmd {
+
+ struct mtip_cmd_hdr *command_header; /* ptr to command header entry */
+
+ dma_addr_t command_header_dma; /* corresponding physical address */
+
+ void *command; /* ptr to command table entry */
+
+ dma_addr_t command_dma; /* corresponding physical address */
+
+ void *comp_data; /* data passed to completion function comp_func() */
+ /*
+ * Completion function called by the ISR upon completion of
+ * a command.
+ */
+ void (*comp_func)(struct mtip_port *port,
+ int tag,
+ void *data,
+ int status);
+ /* Additional callback function that may be called by comp_func() */
+ void (*async_callback)(void *data, int status);
+
+ void *async_data; /* Addl. data passed to async_callback() */
+
+ int scatter_ents; /* Number of scatter list entries used */
+
+ struct scatterlist sg[MTIP_MAX_SG]; /* Scatter list entries */
+
+ int retries; /* The number of retries left for this command. */
+
+ int direction; /* Data transfer direction */
+
+ unsigned long comp_time; /* command completion time, in jiffies */
+
+ atomic_t active; /* declares if this command sent to the drive. */
+};
+
+/* Structure used to describe a port. */
+struct mtip_port {
+ /* Pointer back to the driver data for this port. */
+ struct driver_data *dd;
+ /*
+ * Used to determine if the data pointed to by the
+ * identify field is valid.
+ */
+ unsigned long identify_valid;
+ /* Base address of the memory mapped IO for the port. */
+ void __iomem *mmio;
+ /* Array of pointers to the memory mapped s_active registers. */
+ void __iomem *s_active[MTIP_MAX_SLOT_GROUPS];
+ /* Array of pointers to the memory mapped completed registers. */
+ void __iomem *completed[MTIP_MAX_SLOT_GROUPS];
+ /* Array of pointers to the memory mapped Command Issue registers. */
+ void __iomem *cmd_issue[MTIP_MAX_SLOT_GROUPS];
+ /*
+ * Pointer to the beginning of the command header memory as used
+ * by the driver.
+ */
+ void *command_list;
+ /*
+ * Pointer to the beginning of the command header memory as used
+ * by the DMA.
+ */
+ dma_addr_t command_list_dma;
+ /*
+ * Pointer to the beginning of the RX FIS memory as used
+ * by the driver.
+ */
+ void *rxfis;
+ /*
+ * Pointer to the beginning of the RX FIS memory as used
+ * by the DMA.
+ */
+ dma_addr_t rxfis_dma;
+ /*
+ * Pointer to the beginning of the command table memory as used
+ * by the driver.
+ */
+ void *command_table;
+ /*
+ * Pointer to the beginning of the command table memory as used
+ * by the DMA.
+ */
+ dma_addr_t command_tbl_dma;
+ /*
+ * Pointer to the beginning of the identify data memory as used
+ * by the driver.
+ */
+ u16 *identify;
+ /*
+ * Pointer to the beginning of the identify data memory as used
+ * by the DMA.
+ */
+ dma_addr_t identify_dma;
+ /*
+ * Pointer to the beginning of a sector buffer that is used
+ * by the driver when issuing internal commands.
+ */
+ u16 *sector_buffer;
+ /*
+ * Pointer to the beginning of a sector buffer that is used
+ * by the DMA when the driver issues internal commands.
+ */
+ dma_addr_t sector_buffer_dma;
+ /*
+ * Bit significant, used to determine if a command slot has
+ * been allocated. i.e. the slot is in use. Bits are cleared
+ * when the command slot and all associated data structures
+ * are no longer needed.
+ */
+ unsigned long allocated[SLOTBITS_IN_LONGS];
+ /*
+ * used to queue commands when an internal command is in progress
+ * or error handling is active
+ */
+ unsigned long cmds_to_issue[SLOTBITS_IN_LONGS];
+ /*
+ * Array of command slots. Structure includes pointers to the
+ * command header and command table, and completion function and data
+ * pointers.
+ */
+ struct mtip_cmd commands[MTIP_MAX_COMMAND_SLOTS];
+ /* Used by mtip_service_thread to wait for an event */
+ wait_queue_head_t svc_wait;
+ /*
+ * indicates the state of the port. Also, helps the service thread
+ * to determine its action on wake up.
+ */
+ unsigned long flags;
+ /*
+ * Timer used to complete commands that have been active for too long.
+ */
+ struct timer_list cmd_timer;
+ /*
+ * Semaphore used to block threads if there are no
+ * command slots available.
+ */
+ struct semaphore cmd_slot;
+ /* Spinlock for working around command-issue bug. */
+ spinlock_t cmd_issue_lock;
+};
+
+/*
+ * Driver private data structure.
+ *
+ * One structure is allocated per probed device.
+ */
+struct driver_data {
+ void __iomem *mmio; /* Base address of the HBA registers. */
+
+ int major; /* Major device number. */
+
+ int instance; /* Instance number. First device probed is 0, ... */
+
+ struct gendisk *disk; /* Pointer to our gendisk structure. */
+
+ struct pci_dev *pdev; /* Pointer to the PCI device structure. */
+
+ struct request_queue *queue; /* Our request queue. */
+
+ struct mtip_port *port; /* Pointer to the port data structure. */
+
+ /* Tasklet used to process the bottom half of the ISR. */
+ struct tasklet_struct tasklet;
+
+ unsigned product_type; /* magic value declaring the product type */
+
+ unsigned slot_groups; /* number of slot groups the product supports */
+
+ atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
+
+ unsigned long index; /* Index to determine the disk name */
+
+ unsigned int ftlrebuildflag; /* FTL rebuild flag */
+
+ atomic_t resumeflag; /* Atomic variable to track suspend/resume */
+
+ atomic_t eh_active; /* Flag for error handling tracking */
+
+ struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
+};
+
+#endif
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
new file mode 100644
index 0000000..f4996b0
--- /dev/null
+++ b/drivers/block/nvme.c
@@ -0,0 +1,1745 @@
+/*
+ * NVM Express device driver
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/nvme.h>
+#include <linux/bio.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kdev_t.h>
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/poison.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#define NVME_Q_DEPTH 1024
+#define SQ_SIZE(depth) (depth * sizeof(struct nvme_command))
+#define CQ_SIZE(depth) (depth * sizeof(struct nvme_completion))
+#define NVME_MINORS 64
+#define NVME_IO_TIMEOUT (5 * HZ)
+#define ADMIN_TIMEOUT (60 * HZ)
+
+static int nvme_major;
+module_param(nvme_major, int, 0);
+
+static int use_threaded_interrupts;
+module_param(use_threaded_interrupts, int, 0);
+
+static DEFINE_SPINLOCK(dev_list_lock);
+static LIST_HEAD(dev_list);
+static struct task_struct *nvme_thread;
+
+/*
+ * Represents an NVM Express device. Each nvme_dev is a PCI function.
+ */
+struct nvme_dev {
+ struct list_head node;
+ struct nvme_queue **queues;
+ u32 __iomem *dbs;
+ struct pci_dev *pci_dev;
+ struct dma_pool *prp_page_pool;
+ struct dma_pool *prp_small_pool;
+ int instance;
+ int queue_count;
+ int db_stride;
+ u32 ctrl_config;
+ struct msix_entry *entry;
+ struct nvme_bar __iomem *bar;
+ struct list_head namespaces;
+ char serial[20];
+ char model[40];
+ char firmware_rev[8];
+};
+
+/*
+ * An NVM Express namespace is equivalent to a SCSI LUN
+ */
+struct nvme_ns {
+ struct list_head list;
+
+ struct nvme_dev *dev;
+ struct request_queue *queue;
+ struct gendisk *disk;
+
+ int ns_id;
+ int lba_shift;
+};
+
+/*
+ * An NVM Express queue. Each device has at least two (one for admin
+ * commands and one for I/O commands).
+ */
+struct nvme_queue {
+ struct device *q_dmadev;
+ struct nvme_dev *dev;
+ spinlock_t q_lock;
+ struct nvme_command *sq_cmds;
+ volatile struct nvme_completion *cqes;
+ dma_addr_t sq_dma_addr;
+ dma_addr_t cq_dma_addr;
+ wait_queue_head_t sq_full;
+ wait_queue_t sq_cong_wait;
+ struct bio_list sq_cong;
+ u32 __iomem *q_db;
+ u16 q_depth;
+ u16 cq_vector;
+ u16 sq_head;
+ u16 sq_tail;
+ u16 cq_head;
+ u16 cq_phase;
+ unsigned long cmdid_data[];
+};
+
+/*
+ * Check we didin't inadvertently grow the command struct
+ */
+static inline void _nvme_check_size(void)
+{
+ BUILD_BUG_ON(sizeof(struct nvme_rw_command) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_create_cq) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_features) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_command) != 64);
+ BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
+ BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
+ BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64);
+}
+
+typedef void (*nvme_completion_fn)(struct nvme_dev *, void *,
+ struct nvme_completion *);
+
+struct nvme_cmd_info {
+ nvme_completion_fn fn;
+ void *ctx;
+ unsigned long timeout;
+};
+
+static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq)
+{
+ return (void *)&nvmeq->cmdid_data[BITS_TO_LONGS(nvmeq->q_depth)];
+}
+
+/**
+ * alloc_cmdid() - Allocate a Command ID
+ * @nvmeq: The queue that will be used for this command
+ * @ctx: A pointer that will be passed to the handler
+ * @handler: The function to call on completion
+ *
+ * Allocate a Command ID for a queue. The data passed in will
+ * be passed to the completion handler. This is implemented by using
+ * the bottom two bits of the ctx pointer to store the handler ID.
+ * Passing in a pointer that's not 4-byte aligned will cause a BUG.
+ * We can change this if it becomes a problem.
+ *
+ * May be called with local interrupts disabled and the q_lock held,
+ * or with interrupts enabled and no locks held.
+ */
+static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx,
+ nvme_completion_fn handler, unsigned timeout)
+{
+ int depth = nvmeq->q_depth - 1;
+ struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+ int cmdid;
+
+ do {
+ cmdid = find_first_zero_bit(nvmeq->cmdid_data, depth);
+ if (cmdid >= depth)
+ return -EBUSY;
+ } while (test_and_set_bit(cmdid, nvmeq->cmdid_data));
+
+ info[cmdid].fn = handler;
+ info[cmdid].ctx = ctx;
+ info[cmdid].timeout = jiffies + timeout;
+ return cmdid;
+}
+
+static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
+ nvme_completion_fn handler, unsigned timeout)
+{
+ int cmdid;
+ wait_event_killable(nvmeq->sq_full,
+ (cmdid = alloc_cmdid(nvmeq, ctx, handler, timeout)) >= 0);
+ return (cmdid < 0) ? -EINTR : cmdid;
+}
+
+/* Special values must be less than 0x1000 */
+#define CMD_CTX_BASE ((void *)POISON_POINTER_DELTA)
+#define CMD_CTX_CANCELLED (0x30C + CMD_CTX_BASE)
+#define CMD_CTX_COMPLETED (0x310 + CMD_CTX_BASE)
+#define CMD_CTX_INVALID (0x314 + CMD_CTX_BASE)
+#define CMD_CTX_FLUSH (0x318 + CMD_CTX_BASE)
+
+static void special_completion(struct nvme_dev *dev, void *ctx,
+ struct nvme_completion *cqe)
+{
+ if (ctx == CMD_CTX_CANCELLED)
+ return;
+ if (ctx == CMD_CTX_FLUSH)
+ return;
+ if (ctx == CMD_CTX_COMPLETED) {
+ dev_warn(&dev->pci_dev->dev,
+ "completed id %d twice on queue %d\n",
+ cqe->command_id, le16_to_cpup(&cqe->sq_id));
+ return;
+ }
+ if (ctx == CMD_CTX_INVALID) {
+ dev_warn(&dev->pci_dev->dev,
+ "invalid id %d completed on queue %d\n",
+ cqe->command_id, le16_to_cpup(&cqe->sq_id));
+ return;
+ }
+
+ dev_warn(&dev->pci_dev->dev, "Unknown special completion %p\n", ctx);
+}
+
+/*
+ * Called with local interrupts disabled and the q_lock held. May not sleep.
+ */
+static void *free_cmdid(struct nvme_queue *nvmeq, int cmdid,
+ nvme_completion_fn *fn)
+{
+ void *ctx;
+ struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+
+ if (cmdid >= nvmeq->q_depth) {
+ *fn = special_completion;
+ return CMD_CTX_INVALID;
+ }
+ *fn = info[cmdid].fn;
+ ctx = info[cmdid].ctx;
+ info[cmdid].fn = special_completion;
+ info[cmdid].ctx = CMD_CTX_COMPLETED;
+ clear_bit(cmdid, nvmeq->cmdid_data);
+ wake_up(&nvmeq->sq_full);
+ return ctx;
+}
+
+static void *cancel_cmdid(struct nvme_queue *nvmeq, int cmdid,
+ nvme_completion_fn *fn)
+{
+ void *ctx;
+ struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+ if (fn)
+ *fn = info[cmdid].fn;
+ ctx = info[cmdid].ctx;
+ info[cmdid].fn = special_completion;
+ info[cmdid].ctx = CMD_CTX_CANCELLED;
+ return ctx;
+}
+
+static struct nvme_queue *get_nvmeq(struct nvme_dev *dev)
+{
+ return dev->queues[get_cpu() + 1];
+}
+
+static void put_nvmeq(struct nvme_queue *nvmeq)
+{
+ put_cpu();
+}
+
+/**
+ * nvme_submit_cmd() - Copy a command into a queue and ring the doorbell
+ * @nvmeq: The queue to use
+ * @cmd: The command to send
+ *
+ * Safe to use from interrupt context
+ */
+static int nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd)
+{
+ unsigned long flags;
+ u16 tail;
+ spin_lock_irqsave(&nvmeq->q_lock, flags);
+ tail = nvmeq->sq_tail;
+ memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
+ if (++tail == nvmeq->q_depth)
+ tail = 0;
+ writel(tail, nvmeq->q_db);
+ nvmeq->sq_tail = tail;
+ spin_unlock_irqrestore(&nvmeq->q_lock, flags);
+
+ return 0;
+}
+
+/*
+ * The nvme_iod describes the data in an I/O, including the list of PRP
+ * entries. You can't see it in this data structure because C doesn't let
+ * me express that. Use nvme_alloc_iod to ensure there's enough space
+ * allocated to store the PRP list.
+ */
+struct nvme_iod {
+ void *private; /* For the use of the submitter of the I/O */
+ int npages; /* In the PRP list. 0 means small pool in use */
+ int offset; /* Of PRP list */
+ int nents; /* Used in scatterlist */
+ int length; /* Of data, in bytes */
+ dma_addr_t first_dma;
+ struct scatterlist sg[0];
+};
+
+static __le64 **iod_list(struct nvme_iod *iod)
+{
+ return ((void *)iod) + iod->offset;
+}
+
+/*
+ * Will slightly overestimate the number of pages needed. This is OK
+ * as it only leads to a small amount of wasted memory for the lifetime of
+ * the I/O.
+ */
+static int nvme_npages(unsigned size)
+{
+ unsigned nprps = DIV_ROUND_UP(size + PAGE_SIZE, PAGE_SIZE);
+ return DIV_ROUND_UP(8 * nprps, PAGE_SIZE - 8);
+}
+
+static struct nvme_iod *
+nvme_alloc_iod(unsigned nseg, unsigned nbytes, gfp_t gfp)
+{
+ struct nvme_iod *iod = kmalloc(sizeof(struct nvme_iod) +
+ sizeof(__le64 *) * nvme_npages(nbytes) +
+ sizeof(struct scatterlist) * nseg, gfp);
+
+ if (iod) {
+ iod->offset = offsetof(struct nvme_iod, sg[nseg]);
+ iod->npages = -1;
+ iod->length = nbytes;
+ }
+
+ return iod;
+}
+
+static void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod)
+{
+ const int last_prp = PAGE_SIZE / 8 - 1;
+ int i;
+ __le64 **list = iod_list(iod);
+ dma_addr_t prp_dma = iod->first_dma;
+
+ if (iod->npages == 0)
+ dma_pool_free(dev->prp_small_pool, list[0], prp_dma);
+ for (i = 0; i < iod->npages; i++) {
+ __le64 *prp_list = list[i];
+ dma_addr_t next_prp_dma = le64_to_cpu(prp_list[last_prp]);
+ dma_pool_free(dev->prp_page_pool, prp_list, prp_dma);
+ prp_dma = next_prp_dma;
+ }
+ kfree(iod);
+}
+
+static void requeue_bio(struct nvme_dev *dev, struct bio *bio)
+{
+ struct nvme_queue *nvmeq = get_nvmeq(dev);
+ if (bio_list_empty(&nvmeq->sq_cong))
+ add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
+ bio_list_add(&nvmeq->sq_cong, bio);
+ put_nvmeq(nvmeq);
+ wake_up_process(nvme_thread);
+}
+
+static void bio_completion(struct nvme_dev *dev, void *ctx,
+ struct nvme_completion *cqe)
+{
+ struct nvme_iod *iod = ctx;
+ struct bio *bio = iod->private;
+ u16 status = le16_to_cpup(&cqe->status) >> 1;
+
+ dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
+ bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ nvme_free_iod(dev, iod);
+ if (status) {
+ bio_endio(bio, -EIO);
+ } else if (bio->bi_vcnt > bio->bi_idx) {
+ requeue_bio(dev, bio);
+ } else {
+ bio_endio(bio, 0);
+ }
+}
+
+/* length is in bytes. gfp flags indicates whether we may sleep. */
+static int nvme_setup_prps(struct nvme_dev *dev,
+ struct nvme_common_command *cmd, struct nvme_iod *iod,
+ int total_len, gfp_t gfp)
+{
+ struct dma_pool *pool;
+ int length = total_len;
+ struct scatterlist *sg = iod->sg;
+ int dma_len = sg_dma_len(sg);
+ u64 dma_addr = sg_dma_address(sg);
+ int offset = offset_in_page(dma_addr);
+ __le64 *prp_list;
+ __le64 **list = iod_list(iod);
+ dma_addr_t prp_dma;
+ int nprps, i;
+
+ cmd->prp1 = cpu_to_le64(dma_addr);
+ length -= (PAGE_SIZE - offset);
+ if (length <= 0)
+ return total_len;
+
+ dma_len -= (PAGE_SIZE - offset);
+ if (dma_len) {
+ dma_addr += (PAGE_SIZE - offset);
+ } else {
+ sg = sg_next(sg);
+ dma_addr = sg_dma_address(sg);
+ dma_len = sg_dma_len(sg);
+ }
+
+ if (length <= PAGE_SIZE) {
+ cmd->prp2 = cpu_to_le64(dma_addr);
+ return total_len;
+ }
+
+ nprps = DIV_ROUND_UP(length, PAGE_SIZE);
+ if (nprps <= (256 / 8)) {
+ pool = dev->prp_small_pool;
+ iod->npages = 0;
+ } else {
+ pool = dev->prp_page_pool;
+ iod->npages = 1;
+ }
+
+ prp_list = dma_pool_alloc(pool, gfp, &prp_dma);
+ if (!prp_list) {
+ cmd->prp2 = cpu_to_le64(dma_addr);
+ iod->npages = -1;
+ return (total_len - length) + PAGE_SIZE;
+ }
+ list[0] = prp_list;
+ iod->first_dma = prp_dma;
+ cmd->prp2 = cpu_to_le64(prp_dma);
+ i = 0;
+ for (;;) {
+ if (i == PAGE_SIZE / 8) {
+ __le64 *old_prp_list = prp_list;
+ prp_list = dma_pool_alloc(pool, gfp, &prp_dma);
+ if (!prp_list)
+ return total_len - length;
+ list[iod->npages++] = prp_list;
+ prp_list[0] = old_prp_list[i - 1];
+ old_prp_list[i - 1] = cpu_to_le64(prp_dma);
+ i = 1;
+ }
+ prp_list[i++] = cpu_to_le64(dma_addr);
+ dma_len -= PAGE_SIZE;
+ dma_addr += PAGE_SIZE;
+ length -= PAGE_SIZE;
+ if (length <= 0)
+ break;
+ if (dma_len > 0)
+ continue;
+ BUG_ON(dma_len < 0);
+ sg = sg_next(sg);
+ dma_addr = sg_dma_address(sg);
+ dma_len = sg_dma_len(sg);
+ }
+
+ return total_len;
+}
+
+/* NVMe scatterlists require no holes in the virtual address */
+#define BIOVEC_NOT_VIRT_MERGEABLE(vec1, vec2) ((vec2)->bv_offset || \
+ (((vec1)->bv_offset + (vec1)->bv_len) % PAGE_SIZE))
+
+static int nvme_map_bio(struct device *dev, struct nvme_iod *iod,
+ struct bio *bio, enum dma_data_direction dma_dir, int psegs)
+{
+ struct bio_vec *bvec, *bvprv = NULL;
+ struct scatterlist *sg = NULL;
+ int i, old_idx, length = 0, nsegs = 0;
+
+ sg_init_table(iod->sg, psegs);
+ old_idx = bio->bi_idx;
+ bio_for_each_segment(bvec, bio, i) {
+ if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) {
+ sg->length += bvec->bv_len;
+ } else {
+ if (bvprv && BIOVEC_NOT_VIRT_MERGEABLE(bvprv, bvec))
+ break;
+ sg = sg ? sg + 1 : iod->sg;
+ sg_set_page(sg, bvec->bv_page, bvec->bv_len,
+ bvec->bv_offset);
+ nsegs++;
+ }
+ length += bvec->bv_len;
+ bvprv = bvec;
+ }
+ bio->bi_idx = i;
+ iod->nents = nsegs;
+ sg_mark_end(sg);
+ if (dma_map_sg(dev, iod->sg, iod->nents, dma_dir) == 0) {
+ bio->bi_idx = old_idx;
+ return -ENOMEM;
+ }
+ return length;
+}
+
+static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns,
+ int cmdid)
+{
+ struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+
+ memset(cmnd, 0, sizeof(*cmnd));
+ cmnd->common.opcode = nvme_cmd_flush;
+ cmnd->common.command_id = cmdid;
+ cmnd->common.nsid = cpu_to_le32(ns->ns_id);
+
+ if (++nvmeq->sq_tail == nvmeq->q_depth)
+ nvmeq->sq_tail = 0;
+ writel(nvmeq->sq_tail, nvmeq->q_db);
+
+ return 0;
+}
+
+static int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns)
+{
+ int cmdid = alloc_cmdid(nvmeq, (void *)CMD_CTX_FLUSH,
+ special_completion, NVME_IO_TIMEOUT);
+ if (unlikely(cmdid < 0))
+ return cmdid;
+
+ return nvme_submit_flush(nvmeq, ns, cmdid);
+}
+
+/*
+ * Called with local interrupts disabled and the q_lock held. May not sleep.
+ */
+static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
+ struct bio *bio)
+{
+ struct nvme_command *cmnd;
+ struct nvme_iod *iod;
+ enum dma_data_direction dma_dir;
+ int cmdid, length, result = -ENOMEM;
+ u16 control;
+ u32 dsmgmt;
+ int psegs = bio_phys_segments(ns->queue, bio);
+
+ if ((bio->bi_rw & REQ_FLUSH) && psegs) {
+ result = nvme_submit_flush_data(nvmeq, ns);
+ if (result)
+ return result;
+ }
+
+ iod = nvme_alloc_iod(psegs, bio->bi_size, GFP_ATOMIC);
+ if (!iod)
+ goto nomem;
+ iod->private = bio;
+
+ result = -EBUSY;
+ cmdid = alloc_cmdid(nvmeq, iod, bio_completion, NVME_IO_TIMEOUT);
+ if (unlikely(cmdid < 0))
+ goto free_iod;
+
+ if ((bio->bi_rw & REQ_FLUSH) && !psegs)
+ return nvme_submit_flush(nvmeq, ns, cmdid);
+
+ control = 0;
+ if (bio->bi_rw & REQ_FUA)
+ control |= NVME_RW_FUA;
+ if (bio->bi_rw & (REQ_FAILFAST_DEV | REQ_RAHEAD))
+ control |= NVME_RW_LR;
+
+ dsmgmt = 0;
+ if (bio->bi_rw & REQ_RAHEAD)
+ dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH;
+
+ cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+
+ memset(cmnd, 0, sizeof(*cmnd));
+ if (bio_data_dir(bio)) {
+ cmnd->rw.opcode = nvme_cmd_write;
+ dma_dir = DMA_TO_DEVICE;
+ } else {
+ cmnd->rw.opcode = nvme_cmd_read;
+ dma_dir = DMA_FROM_DEVICE;
+ }
+
+ result = nvme_map_bio(nvmeq->q_dmadev, iod, bio, dma_dir, psegs);
+ if (result < 0)
+ goto free_iod;
+ length = result;
+
+ cmnd->rw.command_id = cmdid;
+ cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
+ length = nvme_setup_prps(nvmeq->dev, &cmnd->common, iod, length,
+ GFP_ATOMIC);
+ cmnd->rw.slba = cpu_to_le64(bio->bi_sector >> (ns->lba_shift - 9));
+ cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1);
+ cmnd->rw.control = cpu_to_le16(control);
+ cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
+
+ bio->bi_sector += length >> 9;
+
+ if (++nvmeq->sq_tail == nvmeq->q_depth)
+ nvmeq->sq_tail = 0;
+ writel(nvmeq->sq_tail, nvmeq->q_db);
+
+ return 0;
+
+ free_iod:
+ nvme_free_iod(nvmeq->dev, iod);
+ nomem:
+ return result;
+}
+
+/*
+ * NB: return value of non-zero would mean that we were a stacking driver.
+ * make_request must always succeed.
+ */
+static int nvme_make_request(struct request_queue *q, struct bio *bio)
+{
+ struct nvme_ns *ns = q->queuedata;
+ struct nvme_queue *nvmeq = get_nvmeq(ns->dev);
+ int result = -EBUSY;
+
+ spin_lock_irq(&nvmeq->q_lock);
+ if (bio_list_empty(&nvmeq->sq_cong))
+ result = nvme_submit_bio_queue(nvmeq, ns, bio);
+ if (unlikely(result)) {
+ if (bio_list_empty(&nvmeq->sq_cong))
+ add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
+ bio_list_add(&nvmeq->sq_cong, bio);
+ }
+
+ spin_unlock_irq(&nvmeq->q_lock);
+ put_nvmeq(nvmeq);
+
+ return 0;
+}
+
+static irqreturn_t nvme_process_cq(struct nvme_queue *nvmeq)
+{
+ u16 head, phase;
+
+ head = nvmeq->cq_head;
+ phase = nvmeq->cq_phase;
+
+ for (;;) {
+ void *ctx;
+ nvme_completion_fn fn;
+ struct nvme_completion cqe = nvmeq->cqes[head];
+ if ((le16_to_cpu(cqe.status) & 1) != phase)
+ break;
+ nvmeq->sq_head = le16_to_cpu(cqe.sq_head);
+ if (++head == nvmeq->q_depth) {
+ head = 0;
+ phase = !phase;
+ }
+
+ ctx = free_cmdid(nvmeq, cqe.command_id, &fn);
+ fn(nvmeq->dev, ctx, &cqe);
+ }
+
+ /* If the controller ignores the cq head doorbell and continuously
+ * writes to the queue, it is theoretically possible to wrap around
+ * the queue twice and mistakenly return IRQ_NONE. Linux only
+ * requires that 0.1% of your interrupts are handled, so this isn't
+ * a big problem.
+ */
+ if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
+ return IRQ_NONE;
+
+ writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride));
+ nvmeq->cq_head = head;
+ nvmeq->cq_phase = phase;
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t nvme_irq(int irq, void *data)
+{
+ irqreturn_t result;
+ struct nvme_queue *nvmeq = data;
+ spin_lock(&nvmeq->q_lock);
+ result = nvme_process_cq(nvmeq);
+ spin_unlock(&nvmeq->q_lock);
+ return result;
+}
+
+static irqreturn_t nvme_irq_check(int irq, void *data)
+{
+ struct nvme_queue *nvmeq = data;
+ struct nvme_completion cqe = nvmeq->cqes[nvmeq->cq_head];
+ if ((le16_to_cpu(cqe.status) & 1) != nvmeq->cq_phase)
+ return IRQ_NONE;
+ return IRQ_WAKE_THREAD;
+}
+
+static void nvme_abort_command(struct nvme_queue *nvmeq, int cmdid)
+{
+ spin_lock_irq(&nvmeq->q_lock);
+ cancel_cmdid(nvmeq, cmdid, NULL);
+ spin_unlock_irq(&nvmeq->q_lock);
+}
+
+struct sync_cmd_info {
+ struct task_struct *task;
+ u32 result;
+ int status;
+};
+
+static void sync_completion(struct nvme_dev *dev, void *ctx,
+ struct nvme_completion *cqe)
+{
+ struct sync_cmd_info *cmdinfo = ctx;
+ cmdinfo->result = le32_to_cpup(&cqe->result);
+ cmdinfo->status = le16_to_cpup(&cqe->status) >> 1;
+ wake_up_process(cmdinfo->task);
+}
+
+/*
+ * Returns 0 on success. If the result is negative, it's a Linux error code;
+ * if the result is positive, it's an NVM Express status code
+ */
+static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
+ struct nvme_command *cmd, u32 *result, unsigned timeout)
+{
+ int cmdid;
+ struct sync_cmd_info cmdinfo;
+
+ cmdinfo.task = current;
+ cmdinfo.status = -EINTR;
+
+ cmdid = alloc_cmdid_killable(nvmeq, &cmdinfo, sync_completion,
+ timeout);
+ if (cmdid < 0)
+ return cmdid;
+ cmd->common.command_id = cmdid;
+
+ set_current_state(TASK_KILLABLE);
+ nvme_submit_cmd(nvmeq, cmd);
+ schedule();
+
+ if (cmdinfo.status == -EINTR) {
+ nvme_abort_command(nvmeq, cmdid);
+ return -EINTR;
+ }
+
+ if (result)
+ *result = cmdinfo.result;
+
+ return cmdinfo.status;
+}
+
+static int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
+ u32 *result)
+{
+ return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT);
+}
+
+static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
+{
+ int status;
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+ c.delete_queue.opcode = opcode;
+ c.delete_queue.qid = cpu_to_le16(id);
+
+ status = nvme_submit_admin_cmd(dev, &c, NULL);
+ if (status)
+ return -EIO;
+ return 0;
+}
+
+static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid,
+ struct nvme_queue *nvmeq)
+{
+ int status;
+ struct nvme_command c;
+ int flags = NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED;
+
+ memset(&c, 0, sizeof(c));
+ c.create_cq.opcode = nvme_admin_create_cq;
+ c.create_cq.prp1 = cpu_to_le64(nvmeq->cq_dma_addr);
+ c.create_cq.cqid = cpu_to_le16(qid);
+ c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+ c.create_cq.cq_flags = cpu_to_le16(flags);
+ c.create_cq.irq_vector = cpu_to_le16(nvmeq->cq_vector);
+
+ status = nvme_submit_admin_cmd(dev, &c, NULL);
+ if (status)
+ return -EIO;
+ return 0;
+}
+
+static int adapter_alloc_sq(struct nvme_dev *dev, u16 qid,
+ struct nvme_queue *nvmeq)
+{
+ int status;
+ struct nvme_command c;
+ int flags = NVME_QUEUE_PHYS_CONTIG | NVME_SQ_PRIO_MEDIUM;
+
+ memset(&c, 0, sizeof(c));
+ c.create_sq.opcode = nvme_admin_create_sq;
+ c.create_sq.prp1 = cpu_to_le64(nvmeq->sq_dma_addr);
+ c.create_sq.sqid = cpu_to_le16(qid);
+ c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
+ c.create_sq.sq_flags = cpu_to_le16(flags);
+ c.create_sq.cqid = cpu_to_le16(qid);
+
+ status = nvme_submit_admin_cmd(dev, &c, NULL);
+ if (status)
+ return -EIO;
+ return 0;
+}
+
+static int adapter_delete_cq(struct nvme_dev *dev, u16 cqid)
+{
+ return adapter_delete_queue(dev, nvme_admin_delete_cq, cqid);
+}
+
+static int adapter_delete_sq(struct nvme_dev *dev, u16 sqid)
+{
+ return adapter_delete_queue(dev, nvme_admin_delete_sq, sqid);
+}
+
+static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
+ dma_addr_t dma_addr)
+{
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+ c.identify.opcode = nvme_admin_identify;
+ c.identify.nsid = cpu_to_le32(nsid);
+ c.identify.prp1 = cpu_to_le64(dma_addr);
+ c.identify.cns = cpu_to_le32(cns);
+
+ return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
+ unsigned dword11, dma_addr_t dma_addr)
+{
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+ c.features.opcode = nvme_admin_get_features;
+ c.features.prp1 = cpu_to_le64(dma_addr);
+ c.features.fid = cpu_to_le32(fid);
+ c.features.dword11 = cpu_to_le32(dword11);
+
+ return nvme_submit_admin_cmd(dev, &c, NULL);
+}
+
+static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
+ unsigned dword11, dma_addr_t dma_addr, u32 *result)
+{
+ struct nvme_command c;
+
+ memset(&c, 0, sizeof(c));
+ c.features.opcode = nvme_admin_set_features;
+ c.features.prp1 = cpu_to_le64(dma_addr);
+ c.features.fid = cpu_to_le32(fid);
+ c.features.dword11 = cpu_to_le32(dword11);
+
+ return nvme_submit_admin_cmd(dev, &c, result);
+}
+
+static void nvme_free_queue(struct nvme_dev *dev, int qid)
+{
+ struct nvme_queue *nvmeq = dev->queues[qid];
+ int vector = dev->entry[nvmeq->cq_vector].vector;
+
+ irq_set_affinity_hint(vector, NULL);
+ free_irq(vector, nvmeq);
+
+ /* Don't tell the adapter to delete the admin queue */
+ if (qid) {
+ adapter_delete_sq(dev, qid);
+ adapter_delete_cq(dev, qid);
+ }
+
+ dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+ (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+ dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+ nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+ kfree(nvmeq);
+}
+
+static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
+ int depth, int vector)
+{
+ struct device *dmadev = &dev->pci_dev->dev;
+ unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info));
+ struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL);
+ if (!nvmeq)
+ return NULL;
+
+ nvmeq->cqes = dma_alloc_coherent(dmadev, CQ_SIZE(depth),
+ &nvmeq->cq_dma_addr, GFP_KERNEL);
+ if (!nvmeq->cqes)
+ goto free_nvmeq;
+ memset((void *)nvmeq->cqes, 0, CQ_SIZE(depth));
+
+ nvmeq->sq_cmds = dma_alloc_coherent(dmadev, SQ_SIZE(depth),
+ &nvmeq->sq_dma_addr, GFP_KERNEL);
+ if (!nvmeq->sq_cmds)
+ goto free_cqdma;
+
+ nvmeq->q_dmadev = dmadev;
+ nvmeq->dev = dev;
+ spin_lock_init(&nvmeq->q_lock);
+ nvmeq->cq_head = 0;
+ nvmeq->cq_phase = 1;
+ init_waitqueue_head(&nvmeq->sq_full);
+ init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread);
+ bio_list_init(&nvmeq->sq_cong);
+ nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+ nvmeq->q_depth = depth;
+ nvmeq->cq_vector = vector;
+
+ return nvmeq;
+
+ free_cqdma:
+ dma_free_coherent(dmadev, CQ_SIZE(nvmeq->q_depth), (void *)nvmeq->cqes,
+ nvmeq->cq_dma_addr);
+ free_nvmeq:
+ kfree(nvmeq);
+ return NULL;
+}
+
+static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq,
+ const char *name)
+{
+ if (use_threaded_interrupts)
+ return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector,
+ nvme_irq_check, nvme_irq,
+ IRQF_DISABLED | IRQF_SHARED,
+ name, nvmeq);
+ return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq,
+ IRQF_DISABLED | IRQF_SHARED, name, nvmeq);
+}
+
+static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
+ int qid, int cq_size, int vector)
+{
+ int result;
+ struct nvme_queue *nvmeq = nvme_alloc_queue(dev, qid, cq_size, vector);
+
+ if (!nvmeq)
+ return ERR_PTR(-ENOMEM);
+
+ result = adapter_alloc_cq(dev, qid, nvmeq);
+ if (result < 0)
+ goto free_nvmeq;
+
+ result = adapter_alloc_sq(dev, qid, nvmeq);
+ if (result < 0)
+ goto release_cq;
+
+ result = queue_request_irq(dev, nvmeq, "nvme");
+ if (result < 0)
+ goto release_sq;
+
+ return nvmeq;
+
+ release_sq:
+ adapter_delete_sq(dev, qid);
+ release_cq:
+ adapter_delete_cq(dev, qid);
+ free_nvmeq:
+ dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+ (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+ dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+ nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+ kfree(nvmeq);
+ return ERR_PTR(result);
+}
+
+static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
+{
+ int result;
+ u32 aqa;
+ u64 cap;
+ unsigned long timeout;
+ struct nvme_queue *nvmeq;
+
+ dev->dbs = ((void __iomem *)dev->bar) + 4096;
+
+ nvmeq = nvme_alloc_queue(dev, 0, 64, 0);
+ if (!nvmeq)
+ return -ENOMEM;
+
+ aqa = nvmeq->q_depth - 1;
+ aqa |= aqa << 16;
+
+ dev->ctrl_config = NVME_CC_ENABLE | NVME_CC_CSS_NVM;
+ dev->ctrl_config |= (PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
+ dev->ctrl_config |= NVME_CC_ARB_RR | NVME_CC_SHN_NONE;
+ dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
+
+ writel(0, &dev->bar->cc);
+ writel(aqa, &dev->bar->aqa);
+ writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
+ writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
+ writel(dev->ctrl_config, &dev->bar->cc);
+
+ cap = readq(&dev->bar->cap);
+ timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+ dev->db_stride = NVME_CAP_STRIDE(cap);
+
+ while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
+ msleep(100);
+ if (fatal_signal_pending(current))
+ return -EINTR;
+ if (time_after(jiffies, timeout)) {
+ dev_err(&dev->pci_dev->dev,
+ "Device not ready; aborting initialisation\n");
+ return -ENODEV;
+ }
+ }
+
+ result = queue_request_irq(dev, nvmeq, "nvme admin");
+ dev->queues[0] = nvmeq;
+ return result;
+}
+
+static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
+ unsigned long addr, unsigned length)
+{
+ int i, err, count, nents, offset;
+ struct scatterlist *sg;
+ struct page **pages;
+ struct nvme_iod *iod;
+
+ if (addr & 3)
+ return ERR_PTR(-EINVAL);
+ if (!length)
+ return ERR_PTR(-EINVAL);
+
+ offset = offset_in_page(addr);
+ count = DIV_ROUND_UP(offset + length, PAGE_SIZE);
+ pages = kcalloc(count, sizeof(*pages), GFP_KERNEL);
+
+ err = get_user_pages_fast(addr, count, 1, pages);
+ if (err < count) {
+ count = err;
+ err = -EFAULT;
+ goto put_pages;
+ }
+
+ iod = nvme_alloc_iod(count, length, GFP_KERNEL);
+ sg = iod->sg;
+ sg_init_table(sg, count);
+ for (i = 0; i < count; i++) {
+ sg_set_page(&sg[i], pages[i],
+ min_t(int, length, PAGE_SIZE - offset), offset);
+ length -= (PAGE_SIZE - offset);
+ offset = 0;
+ }
+ sg_mark_end(&sg[i - 1]);
+ iod->nents = count;
+
+ err = -ENOMEM;
+ nents = dma_map_sg(&dev->pci_dev->dev, sg, count,
+ write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ if (!nents)
+ goto free_iod;
+
+ kfree(pages);
+ return iod;
+
+ free_iod:
+ kfree(iod);
+ put_pages:
+ for (i = 0; i < count; i++)
+ put_page(pages[i]);
+ kfree(pages);
+ return ERR_PTR(err);
+}
+
+static void nvme_unmap_user_pages(struct nvme_dev *dev, int write,
+ struct nvme_iod *iod)
+{
+ int i;
+
+ dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
+ write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+ for (i = 0; i < iod->nents; i++)
+ put_page(sg_page(&iod->sg[i]));
+}
+
+static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
+{
+ struct nvme_dev *dev = ns->dev;
+ struct nvme_queue *nvmeq;
+ struct nvme_user_io io;
+ struct nvme_command c;
+ unsigned length;
+ int status;
+ struct nvme_iod *iod;
+
+ if (copy_from_user(&io, uio, sizeof(io)))
+ return -EFAULT;
+ length = (io.nblocks + 1) << ns->lba_shift;
+
+ switch (io.opcode) {
+ case nvme_cmd_write:
+ case nvme_cmd_read:
+ case nvme_cmd_compare:
+ iod = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (IS_ERR(iod))
+ return PTR_ERR(iod);
+
+ memset(&c, 0, sizeof(c));
+ c.rw.opcode = io.opcode;
+ c.rw.flags = io.flags;
+ c.rw.nsid = cpu_to_le32(ns->ns_id);
+ c.rw.slba = cpu_to_le64(io.slba);
+ c.rw.length = cpu_to_le16(io.nblocks);
+ c.rw.control = cpu_to_le16(io.control);
+ c.rw.dsmgmt = cpu_to_le16(io.dsmgmt);
+ c.rw.reftag = io.reftag;
+ c.rw.apptag = io.apptag;
+ c.rw.appmask = io.appmask;
+ /* XXX: metadata */
+ length = nvme_setup_prps(dev, &c.common, iod, length, GFP_KERNEL);
+
+ nvmeq = get_nvmeq(dev);
+ /*
+ * Since nvme_submit_sync_cmd sleeps, we can't keep preemption
+ * disabled. We may be preempted at any point, and be rescheduled
+ * to a different CPU. That will cause cacheline bouncing, but no
+ * additional races since q_lock already protects against other CPUs.
+ */
+ put_nvmeq(nvmeq);
+ if (length != (io.nblocks + 1) << ns->lba_shift)
+ status = -ENOMEM;
+ else
+ status = nvme_submit_sync_cmd(nvmeq, &c, NULL, NVME_IO_TIMEOUT);
+
+ nvme_unmap_user_pages(dev, io.opcode & 1, iod);
+ nvme_free_iod(dev, iod);
+ return status;
+}
+
+static int nvme_user_admin_cmd(struct nvme_ns *ns,
+ struct nvme_admin_cmd __user *ucmd)
+{
+ struct nvme_dev *dev = ns->dev;
+ struct nvme_admin_cmd cmd;
+ struct nvme_command c;
+ int status, length;
+ struct nvme_iod *iod;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
+ return -EFAULT;
+
+ memset(&c, 0, sizeof(c));
+ c.common.opcode = cmd.opcode;
+ c.common.flags = cmd.flags;
+ c.common.nsid = cpu_to_le32(cmd.nsid);
+ c.common.cdw2[0] = cpu_to_le32(cmd.cdw2);
+ c.common.cdw2[1] = cpu_to_le32(cmd.cdw3);
+ c.common.cdw10[0] = cpu_to_le32(cmd.cdw10);
+ c.common.cdw10[1] = cpu_to_le32(cmd.cdw11);
+ c.common.cdw10[2] = cpu_to_le32(cmd.cdw12);
+ c.common.cdw10[3] = cpu_to_le32(cmd.cdw13);
+ c.common.cdw10[4] = cpu_to_le32(cmd.cdw14);
+ c.common.cdw10[5] = cpu_to_le32(cmd.cdw15);
+
+ length = cmd.data_len;
+ if (cmd.data_len) {
+ iod = nvme_map_user_pages(dev, cmd.opcode & 1, cmd.addr,
+ length);
+ if (IS_ERR(iod))
+ return PTR_ERR(iod);
+ length = nvme_setup_prps(dev, &c.common, iod, length,
+ GFP_KERNEL);
+ }
+
+ if (length != cmd.data_len)
+ status = -ENOMEM;
+ else
+ status = nvme_submit_admin_cmd(dev, &c, NULL);
+
+ if (cmd.data_len) {
+ nvme_unmap_user_pages(dev, cmd.opcode & 1, iod);
+ nvme_free_iod(dev, iod);
+ }
+ return status;
+}
+
+static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
+ unsigned long arg)
+{
+ struct nvme_ns *ns = bdev->bd_disk->private_data;
+
+ switch (cmd) {
+ case NVME_IOCTL_ID:
+ return ns->ns_id;
+ case NVME_IOCTL_ADMIN_CMD:
+ return nvme_user_admin_cmd(ns, (void __user *)arg);
+ case NVME_IOCTL_SUBMIT_IO:
+ return nvme_submit_io(ns, (void __user *)arg);
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct block_device_operations nvme_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = nvme_ioctl,
+ .compat_ioctl = nvme_ioctl,
+};
+
+static void nvme_timeout_ios(struct nvme_queue *nvmeq)
+{
+ int depth = nvmeq->q_depth - 1;
+ struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+ unsigned long now = jiffies;
+ int cmdid;
+
+ for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
+ void *ctx;
+ nvme_completion_fn fn;
+ static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, };
+
+ if (!time_after(now, info[cmdid].timeout))
+ continue;
+ dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid);
+ ctx = cancel_cmdid(nvmeq, cmdid, &fn);
+ fn(nvmeq->dev, ctx, &cqe);
+ }
+}
+
+static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
+{
+ while (bio_list_peek(&nvmeq->sq_cong)) {
+ struct bio *bio = bio_list_pop(&nvmeq->sq_cong);
+ struct nvme_ns *ns = bio->bi_bdev->bd_disk->private_data;
+ if (nvme_submit_bio_queue(nvmeq, ns, bio)) {
+ bio_list_add_head(&nvmeq->sq_cong, bio);
+ break;
+ }
+ if (bio_list_empty(&nvmeq->sq_cong))
+ remove_wait_queue(&nvmeq->sq_full,
+ &nvmeq->sq_cong_wait);
+ }
+}
+
+static int nvme_kthread(void *data)
+{
+ struct nvme_dev *dev;
+
+ while (!kthread_should_stop()) {
+ __set_current_state(TASK_RUNNING);
+ spin_lock(&dev_list_lock);
+ list_for_each_entry(dev, &dev_list, node) {
+ int i;
+ for (i = 0; i < dev->queue_count; i++) {
+ struct nvme_queue *nvmeq = dev->queues[i];
+ if (!nvmeq)
+ continue;
+ spin_lock_irq(&nvmeq->q_lock);
+ if (nvme_process_cq(nvmeq))
+ printk("process_cq did something\n");
+ nvme_timeout_ios(nvmeq);
+ nvme_resubmit_bios(nvmeq);
+ spin_unlock_irq(&nvmeq->q_lock);
+ }
+ }
+ spin_unlock(&dev_list_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+ return 0;
+}
+
+static DEFINE_IDA(nvme_index_ida);
+
+static int nvme_get_ns_idx(void)
+{
+ int index, error;
+
+ do {
+ if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL))
+ return -1;
+
+ spin_lock(&dev_list_lock);
+ error = ida_get_new(&nvme_index_ida, &index);
+ spin_unlock(&dev_list_lock);
+ } while (error == -EAGAIN);
+
+ if (error)
+ index = -1;
+ return index;
+}
+
+static void nvme_put_ns_idx(int index)
+{
+ spin_lock(&dev_list_lock);
+ ida_remove(&nvme_index_ida, index);
+ spin_unlock(&dev_list_lock);
+}
+
+static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
+ struct nvme_id_ns *id, struct nvme_lba_range_type *rt)
+{
+ struct nvme_ns *ns;
+ struct gendisk *disk;
+ int lbaf;
+
+ if (rt->attributes & NVME_LBART_ATTRIB_HIDE)
+ return NULL;
+
+ ns = kzalloc(sizeof(*ns), GFP_KERNEL);
+ if (!ns)
+ return NULL;
+ ns->queue = blk_alloc_queue(GFP_KERNEL);
+ if (!ns->queue)
+ goto out_free_ns;
+ ns->queue->queue_flags = QUEUE_FLAG_DEFAULT;
+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, ns->queue);
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, ns->queue);
+/* queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, ns->queue); */
+ blk_queue_make_request(ns->queue, nvme_make_request);
+ ns->dev = dev;
+ ns->queue->queuedata = ns;
+
+ disk = alloc_disk(NVME_MINORS);
+ if (!disk)
+ goto out_free_queue;
+ ns->ns_id = nsid;
+ ns->disk = disk;
+ lbaf = id->flbas & 0xf;
+ ns->lba_shift = id->lbaf[lbaf].ds;
+
+ disk->major = nvme_major;
+ disk->minors = NVME_MINORS;
+ disk->first_minor = NVME_MINORS * nvme_get_ns_idx();
+ disk->fops = &nvme_fops;
+ disk->private_data = ns;
+ disk->queue = ns->queue;
+ disk->driverfs_dev = &dev->pci_dev->dev;
+ sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
+ set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
+
+ return ns;
+
+ out_free_queue:
+ blk_cleanup_queue(ns->queue);
+ out_free_ns:
+ kfree(ns);
+ return NULL;
+}
+
+static void nvme_ns_free(struct nvme_ns *ns)
+{
+ int index = ns->disk->first_minor / NVME_MINORS;
+ put_disk(ns->disk);
+ nvme_put_ns_idx(index);
+ blk_cleanup_queue(ns->queue);
+ kfree(ns);
+}
+
+static int set_queue_count(struct nvme_dev *dev, int count)
+{
+ int status;
+ u32 result;
+ u32 q_count = (count - 1) | ((count - 1) << 16);
+
+ status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES, q_count, 0,
+ &result);
+ if (status)
+ return -EIO;
+ return min(result & 0xffff, result >> 16) + 1;
+}
+
+static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
+{
+ int result, cpu, i, nr_io_queues, db_bar_size;
+
+ nr_io_queues = num_online_cpus();
+ result = set_queue_count(dev, nr_io_queues);
+ if (result < 0)
+ return result;
+ if (result < nr_io_queues)
+ nr_io_queues = result;
+
+ /* Deregister the admin queue's interrupt */
+ free_irq(dev->entry[0].vector, dev->queues[0]);
+
+ db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
+ if (db_bar_size > 8192) {
+ iounmap(dev->bar);
+ dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0),
+ db_bar_size);
+ dev->dbs = ((void __iomem *)dev->bar) + 4096;
+ dev->queues[0]->q_db = dev->dbs;
+ }
+
+ for (i = 0; i < nr_io_queues; i++)
+ dev->entry[i].entry = i;
+ for (;;) {
+ result = pci_enable_msix(dev->pci_dev, dev->entry,
+ nr_io_queues);
+ if (result == 0) {
+ break;
+ } else if (result > 0) {
+ nr_io_queues = result;
+ continue;
+ } else {
+ nr_io_queues = 1;
+ break;
+ }
+ }
+
+ result = queue_request_irq(dev, dev->queues[0], "nvme admin");
+ /* XXX: handle failure here */
+
+ cpu = cpumask_first(cpu_online_mask);
+ for (i = 0; i < nr_io_queues; i++) {
+ irq_set_affinity_hint(dev->entry[i].vector, get_cpu_mask(cpu));
+ cpu = cpumask_next(cpu, cpu_online_mask);
+ }
+
+ for (i = 0; i < nr_io_queues; i++) {
+ dev->queues[i + 1] = nvme_create_queue(dev, i + 1,
+ NVME_Q_DEPTH, i);
+ if (IS_ERR(dev->queues[i + 1]))
+ return PTR_ERR(dev->queues[i + 1]);
+ dev->queue_count++;
+ }
+
+ for (; i < num_possible_cpus(); i++) {
+ int target = i % rounddown_pow_of_two(dev->queue_count - 1);
+ dev->queues[i + 1] = dev->queues[target + 1];
+ }
+
+ return 0;
+}
+
+static void nvme_free_queues(struct nvme_dev *dev)
+{
+ int i;
+
+ for (i = dev->queue_count - 1; i >= 0; i--)
+ nvme_free_queue(dev, i);
+}
+
+static int __devinit nvme_dev_add(struct nvme_dev *dev)
+{
+ int res, nn, i;
+ struct nvme_ns *ns, *next;
+ struct nvme_id_ctrl *ctrl;
+ struct nvme_id_ns *id_ns;
+ void *mem;
+ dma_addr_t dma_addr;
+
+ res = nvme_setup_io_queues(dev);
+ if (res)
+ return res;
+
+ mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr,
+ GFP_KERNEL);
+
+ res = nvme_identify(dev, 0, 1, dma_addr);
+ if (res) {
+ res = -EIO;
+ goto out_free;
+ }
+
+ ctrl = mem;
+ nn = le32_to_cpup(&ctrl->nn);
+ memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
+ memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
+ memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+
+ id_ns = mem;
+ for (i = 1; i <= nn; i++) {
+ res = nvme_identify(dev, i, 0, dma_addr);
+ if (res)
+ continue;
+
+ if (id_ns->ncap == 0)
+ continue;
+
+ res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i,
+ dma_addr + 4096);
+ if (res)
+ continue;
+
+ ns = nvme_alloc_ns(dev, i, mem, mem + 4096);
+ if (ns)
+ list_add_tail(&ns->list, &dev->namespaces);
+ }
+ list_for_each_entry(ns, &dev->namespaces, list)
+ add_disk(ns->disk);
+
+ goto out;
+
+ out_free:
+ list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+ list_del(&ns->list);
+ nvme_ns_free(ns);
+ }
+
+ out:
+ dma_free_coherent(&dev->pci_dev->dev, 8192, mem, dma_addr);
+ return res;
+}
+
+static int nvme_dev_remove(struct nvme_dev *dev)
+{
+ struct nvme_ns *ns, *next;
+
+ spin_lock(&dev_list_lock);
+ list_del(&dev->node);
+ spin_unlock(&dev_list_lock);
+
+ /* TODO: wait all I/O finished or cancel them */
+
+ list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+ list_del(&ns->list);
+ del_gendisk(ns->disk);
+ nvme_ns_free(ns);
+ }
+
+ nvme_free_queues(dev);
+
+ return 0;
+}
+
+static int nvme_setup_prp_pools(struct nvme_dev *dev)
+{
+ struct device *dmadev = &dev->pci_dev->dev;
+ dev->prp_page_pool = dma_pool_create("prp list page", dmadev,
+ PAGE_SIZE, PAGE_SIZE, 0);
+ if (!dev->prp_page_pool)
+ return -ENOMEM;
+
+ /* Optimisation for I/Os between 4k and 128k */
+ dev->prp_small_pool = dma_pool_create("prp list 256", dmadev,
+ 256, 256, 0);
+ if (!dev->prp_small_pool) {
+ dma_pool_destroy(dev->prp_page_pool);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void nvme_release_prp_pools(struct nvme_dev *dev)
+{
+ dma_pool_destroy(dev->prp_page_pool);
+ dma_pool_destroy(dev->prp_small_pool);
+}
+
+/* XXX: Use an ida or something to let remove / add work correctly */
+static void nvme_set_instance(struct nvme_dev *dev)
+{
+ static int instance;
+ dev->instance = instance++;
+}
+
+static void nvme_release_instance(struct nvme_dev *dev)
+{
+}
+
+static int __devinit nvme_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int bars, result = -ENOMEM;
+ struct nvme_dev *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->entry = kcalloc(num_possible_cpus(), sizeof(*dev->entry),
+ GFP_KERNEL);
+ if (!dev->entry)
+ goto free;
+ dev->queues = kcalloc(num_possible_cpus() + 1, sizeof(void *),
+ GFP_KERNEL);
+ if (!dev->queues)
+ goto free;
+
+ if (pci_enable_device_mem(pdev))
+ goto free;
+ pci_set_master(pdev);
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ if (pci_request_selected_regions(pdev, bars, "nvme"))
+ goto disable;
+
+ INIT_LIST_HEAD(&dev->namespaces);
+ dev->pci_dev = pdev;
+ pci_set_drvdata(pdev, dev);
+ dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+ nvme_set_instance(dev);
+ dev->entry[0].vector = pdev->irq;
+
+ result = nvme_setup_prp_pools(dev);
+ if (result)
+ goto disable_msix;
+
+ dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
+ if (!dev->bar) {
+ result = -ENOMEM;
+ goto disable_msix;
+ }
+
+ result = nvme_configure_admin_queue(dev);
+ if (result)
+ goto unmap;
+ dev->queue_count++;
+
+ spin_lock(&dev_list_lock);
+ list_add(&dev->node, &dev_list);
+ spin_unlock(&dev_list_lock);
+
+ result = nvme_dev_add(dev);
+ if (result)
+ goto delete;
+
+ return 0;
+
+ delete:
+ spin_lock(&dev_list_lock);
+ list_del(&dev->node);
+ spin_unlock(&dev_list_lock);
+
+ nvme_free_queues(dev);
+ unmap:
+ iounmap(dev->bar);
+ disable_msix:
+ pci_disable_msix(pdev);
+ nvme_release_instance(dev);
+ nvme_release_prp_pools(dev);
+ disable:
+ pci_disable_device(pdev);
+ pci_release_regions(pdev);
+ free:
+ kfree(dev->queues);
+ kfree(dev->entry);
+ kfree(dev);
+ return result;
+}
+
+static void __devexit nvme_remove(struct pci_dev *pdev)
+{
+ struct nvme_dev *dev = pci_get_drvdata(pdev);
+ nvme_dev_remove(dev);
+ pci_disable_msix(pdev);
+ iounmap(dev->bar);
+ nvme_release_instance(dev);
+ nvme_release_prp_pools(dev);
+ pci_disable_device(pdev);
+ pci_release_regions(pdev);
+ kfree(dev->queues);
+ kfree(dev->entry);
+ kfree(dev);
+}
+
+/* These functions are yet to be implemented */
+#define nvme_error_detected NULL
+#define nvme_dump_registers NULL
+#define nvme_link_reset NULL
+#define nvme_slot_reset NULL
+#define nvme_error_resume NULL
+#define nvme_suspend NULL
+#define nvme_resume NULL
+
+static struct pci_error_handlers nvme_err_handler = {
+ .error_detected = nvme_error_detected,
+ .mmio_enabled = nvme_dump_registers,
+ .link_reset = nvme_link_reset,
+ .slot_reset = nvme_slot_reset,
+ .resume = nvme_error_resume,
+};
+
+/* Move to pci_ids.h later */
+#define PCI_CLASS_STORAGE_EXPRESS 0x010802
+
+static DEFINE_PCI_DEVICE_TABLE(nvme_id_table) = {
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, nvme_id_table);
+
+static struct pci_driver nvme_driver = {
+ .name = "nvme",
+ .id_table = nvme_id_table,
+ .probe = nvme_probe,
+ .remove = __devexit_p(nvme_remove),
+ .suspend = nvme_suspend,
+ .resume = nvme_resume,
+ .err_handler = &nvme_err_handler,
+};
+
+static int __init nvme_init(void)
+{
+ int result = -EBUSY;
+
+ nvme_thread = kthread_run(nvme_kthread, NULL, "nvme");
+ if (IS_ERR(nvme_thread))
+ return PTR_ERR(nvme_thread);
+
+ nvme_major = register_blkdev(nvme_major, "nvme");
+ if (nvme_major <= 0)
+ goto kill_kthread;
+
+ result = pci_register_driver(&nvme_driver);
+ if (result)
+ goto unregister_blkdev;
+ return 0;
+
+ unregister_blkdev:
+ unregister_blkdev(nvme_major, "nvme");
+ kill_kthread:
+ kthread_stop(nvme_thread);
+ return result;
+}
+
+static void __exit nvme_exit(void)
+{
+ pci_unregister_driver(&nvme_driver);
+ unregister_blkdev(nvme_major, "nvme");
+ kthread_stop(nvme_thread);
+}
+
+MODULE_AUTHOR("Matthew Wilcox <willy@linux.intel.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.8");
+module_init(nvme_init);
+module_exit(nvme_exit);
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c
index ad12452..ec64e7f 100644
--- a/drivers/block/paride/bpck6.c
+++ b/drivers/block/paride/bpck6.c
@@ -20,9 +20,6 @@
*/
-/* PARAMETERS */
-static int verbose; /* set this to 1 to see debugging messages and whatnot */
-
#define BACKPACK_VERSION "2.0.2"
#include <linux/module.h>
@@ -36,6 +33,8 @@ static int verbose; /* set this to 1 to see debugging messages and whatnot */
#include "ppc6lnx.c"
#include "paride.h"
+/* PARAMETERS */
+static bool verbose; /* set this to 1 to see debugging messages and whatnot */
#define PPCSTRUCT(pi) ((Interface *)(pi->private))
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 46b8136..ba2b6b5 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -144,7 +144,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
static DEFINE_MUTEX(pcd_mutex);
static DEFINE_SPINLOCK(pcd_lock);
-module_param(verbose, bool, 0644);
+module_param(verbose, int, 0644);
module_param(major, int, 0);
module_param(name, charp, 0);
module_param(nice, int, 0);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 869e767..831e3ac 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -124,8 +124,9 @@
by default.
*/
+#include <linux/types.h>
-static int verbose = 0;
+static bool verbose = 0;
static int major = PD_MAJOR;
static char *name = PD_NAME;
static int cluster = 64;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index f21b520..ec8f9ed 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -118,13 +118,15 @@
#define PF_NAME "pf"
#define PF_UNITS 4
+#include <linux/types.h>
+
/* Here are things one can override from the insmod command.
Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
-static int verbose = 0;
+static bool verbose = 0;
static int major = PF_MAJOR;
static char *name = PF_NAME;
static int cluster = 64;
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index a79fb4f..4a27b1d 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -130,13 +130,14 @@
#define PI_PG 4
#endif
+#include <linux/types.h>
/* Here are things one can override from the insmod command.
Most are autoprobed by paride unless set here. Verbose is 0
by default.
*/
-static int verbose = 0;
+static bool verbose = 0;
static int major = PG_MAJOR;
static char *name = PG_NAME;
static int disable = 0;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 7179f79..2596042 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -109,13 +109,15 @@
#define PT_NAME "pt"
#define PT_UNITS 4
+#include <linux/types.h>
+
/* Here are things one can override from the insmod command.
Most are autoprobed by paride unless set here. Verbose is on
by default.
*/
-static int verbose = 0;
+static bool verbose = 0;
static int major = PT_MAJOR;
static char *name = PT_NAME;
static int disable = 0;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 148ab94..3fd31de 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2184,6 +2184,8 @@ static ssize_t rbd_add(struct bus_type *bus,
INIT_LIST_HEAD(&rbd_dev->node);
INIT_LIST_HEAD(&rbd_dev->snaps);
+ init_rwsem(&rbd_dev->header.snap_rwsem);
+
/* generate unique id: find highest unique id, add one */
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index b70f0fc..e7472f5 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -619,8 +619,10 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
host->state == HST_DEV_SCAN);
spin_unlock_irq(&host->lock);
- DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq);
+ DPRINTK("blk_execute_rq_nowait, tag == %u\n", idx);
+ crq->rq->cmd_type = REQ_TYPE_SPECIAL;
+ crq->rq->special = crq;
+ blk_execute_rq_nowait(host->oob_q, NULL, crq->rq, true, NULL);
return 0;
@@ -658,8 +660,10 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
BUG_ON(rc < 0);
crq->msg_bucket = (u32) rc;
- DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq);
+ DPRINTK("blk_execute_rq_nowait, tag == %u\n", idx);
+ crq->rq->cmd_type = REQ_TYPE_SPECIAL;
+ crq->rq->special = crq;
+ blk_execute_rq_nowait(host->oob_q, NULL, crq->rq, true, NULL);
return 0;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 0e376d4..7333b9e 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct gendisk *disk = bdev->bd_disk;
void __user *usermem = (void __user *) arg;
int ret;
mutex_lock(&ub_mutex);
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem);
mutex_unlock(&ub_mutex);
return ret;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 4d0b70a..c4a60ba 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -4,6 +4,7 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/virtio.h>
#include <linux/virtio_blk.h>
#include <linux/scatterlist.h>
@@ -36,6 +37,12 @@ struct virtio_blk
/* Process context for config space updates */
struct work_struct config_work;
+ /* Lock for config space updates */
+ struct mutex config_lock;
+
+ /* enable config space updates */
+ bool config_enable;
+
/* What host tells us, plus 2 for header & tailer. */
unsigned int sg_elems;
@@ -172,7 +179,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
}
}
- if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) {
+ if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr, GFP_ATOMIC)<0) {
mempool_free(vbr, vblk->pool);
return false;
}
@@ -243,8 +250,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
return -ENOTTY;
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
- (void __user *)data);
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd,
+ (void __user *)data);
}
/* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -318,6 +325,10 @@ static void virtblk_config_changed_work(struct work_struct *work)
char cap_str_2[10], cap_str_10[10];
u64 capacity, size;
+ mutex_lock(&vblk->config_lock);
+ if (!vblk->config_enable)
+ goto done;
+
/* Host must always specify the capacity. */
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
&capacity, sizeof(capacity));
@@ -340,6 +351,8 @@ static void virtblk_config_changed_work(struct work_struct *work)
cap_str_10, cap_str_2);
set_capacity(vblk->disk, capacity);
+done:
+ mutex_unlock(&vblk->config_lock);
}
static void virtblk_config_changed(struct virtio_device *vdev)
@@ -349,6 +362,18 @@ static void virtblk_config_changed(struct virtio_device *vdev)
queue_work(virtblk_wq, &vblk->config_work);
}
+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");
+ if (IS_ERR(vblk->vq))
+ err = PTR_ERR(vblk->vq);
+
+ return err;
+}
+
static int __devinit virtblk_probe(struct virtio_device *vdev)
{
struct virtio_blk *vblk;
@@ -388,14 +413,13 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
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;
- /* We expect one virtqueue, for output. */
- vblk->vq = virtio_find_single_vq(vdev, blk_done, "requests");
- if (IS_ERR(vblk->vq)) {
- err = PTR_ERR(vblk->vq);
+ err = init_vq(vblk);
+ if (err)
goto out_free_vblk;
- }
vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct virtblk_req));
if (!vblk->pool) {
@@ -542,7 +566,10 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
struct virtio_blk *vblk = vdev->priv;
int index = vblk->index;
- flush_work(&vblk->config_work);
+ /* Prevent config work handler from accessing the device. */
+ mutex_lock(&vblk->config_lock);
+ vblk->config_enable = false;
+ mutex_unlock(&vblk->config_lock);
/* Nothing should be pending. */
BUG_ON(!list_empty(&vblk->reqs));
@@ -550,6 +577,8 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
/* Stop all the virtqueues. */
vdev->config->reset(vdev);
+ flush_work(&vblk->config_work);
+
del_gendisk(vblk->disk);
blk_cleanup_queue(vblk->disk->queue);
put_disk(vblk->disk);
@@ -559,6 +588,46 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
ida_simple_remove(&vd_index_ida, index);
}
+#ifdef CONFIG_PM
+static int virtblk_freeze(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk = vdev->priv;
+
+ /* Ensure we don't receive any more interrupts */
+ vdev->config->reset(vdev);
+
+ /* Prevent config work handler from accessing the device. */
+ mutex_lock(&vblk->config_lock);
+ vblk->config_enable = false;
+ mutex_unlock(&vblk->config_lock);
+
+ flush_work(&vblk->config_work);
+
+ spin_lock_irq(vblk->disk->queue->queue_lock);
+ blk_stop_queue(vblk->disk->queue);
+ spin_unlock_irq(vblk->disk->queue->queue_lock);
+ blk_sync_queue(vblk->disk->queue);
+
+ vdev->config->del_vqs(vdev);
+ return 0;
+}
+
+static int virtblk_restore(struct virtio_device *vdev)
+{
+ struct virtio_blk *vblk = vdev->priv;
+ int ret;
+
+ vblk->config_enable = true;
+ ret = init_vq(vdev->priv);
+ if (!ret) {
+ spin_lock_irq(vblk->disk->queue->queue_lock);
+ blk_start_queue(vblk->disk->queue);
+ spin_unlock_irq(vblk->disk->queue->queue_lock);
+ }
+ return ret;
+}
+#endif
+
static const struct virtio_device_id id_table[] = {
{ VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID },
{ 0 },
@@ -584,6 +653,10 @@ static struct virtio_driver __refdata virtio_blk = {
.probe = virtblk_probe,
.remove = __devexit_p(virtblk_remove),
.config_changed = virtblk_config_changed,
+#ifdef CONFIG_PM
+ .freeze = virtblk_freeze,
+ .restore = virtblk_restore,
+#endif
};
static int __init init(void)
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 4abd2bc..51a9727 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -148,7 +148,7 @@ static volatile int xdc_busy;
static struct timer_list xd_watchdog_int;
static volatile u_char xd_error;
-static int nodma = XD_DONT_USE_DMA;
+static bool nodma = XD_DONT_USE_DMA;
static struct request_queue *xd_queue;
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 15ec4db..0088bf6 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -39,9 +39,6 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/freezer.h>
-#include <linux/loop.h>
-#include <linux/falloc.h>
-#include <linux/fs.h>
#include <xen/events.h>
#include <xen/page.h>
@@ -362,7 +359,7 @@ static int xen_blkbk_map(struct blkif_request *req,
{
struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
int i;
- int nseg = req->nr_segments;
+ int nseg = req->u.rw.nr_segments;
int ret = 0;
/*
@@ -416,30 +413,25 @@ static int xen_blkbk_map(struct blkif_request *req,
return ret;
}
-static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
+static int dispatch_discard_io(struct xen_blkif *blkif,
+ struct blkif_request *req)
{
int err = 0;
int status = BLKIF_RSP_OKAY;
struct block_device *bdev = blkif->vbd.bdev;
- if (blkif->blk_backend_type == BLKIF_BACKEND_PHY)
- /* just forward the discard request */
+ blkif->st_ds_req++;
+
+ xen_blkif_get(blkif);
+ if (blkif->blk_backend_type == BLKIF_BACKEND_PHY ||
+ blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
+ unsigned long secure = (blkif->vbd.discard_secure &&
+ (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
+ BLKDEV_DISCARD_SECURE : 0;
err = blkdev_issue_discard(bdev,
req->u.discard.sector_number,
req->u.discard.nr_sectors,
- GFP_KERNEL, 0);
- else if (blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
- /* punch a hole in the backing file */
- struct loop_device *lo = bdev->bd_disk->private_data;
- struct file *file = lo->lo_backing_file;
-
- if (file->f_op->fallocate)
- err = file->f_op->fallocate(file,
- FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
- req->u.discard.sector_number << 9,
- req->u.discard.nr_sectors << 9);
- else
- err = -EOPNOTSUPP;
+ GFP_KERNEL, secure);
} else
err = -EOPNOTSUPP;
@@ -449,7 +441,9 @@ static void xen_blk_discard(struct xen_blkif *blkif, struct blkif_request *req)
} else if (err)
status = BLKIF_RSP_ERROR;
- make_response(blkif, req->id, req->operation, status);
+ make_response(blkif, req->u.discard.id, req->operation, status);
+ xen_blkif_put(blkif);
+ return err;
}
static void xen_blk_drain_io(struct xen_blkif *blkif)
@@ -573,8 +567,11 @@ __do_block_io_op(struct xen_blkif *blkif)
/* Apply all sanity checks to /private copy/ of request. */
barrier();
-
- if (dispatch_rw_block_io(blkif, &req, pending_req))
+ if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+ free_req(pending_req);
+ if (dispatch_discard_io(blkif, &req))
+ break;
+ } else if (dispatch_rw_block_io(blkif, &req, pending_req))
break;
/* Yield point for this unbounded loop. */
@@ -633,10 +630,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
blkif->st_f_req++;
operation = WRITE_FLUSH;
break;
- case BLKIF_OP_DISCARD:
- blkif->st_ds_req++;
- operation = REQ_DISCARD;
- break;
default:
operation = 0; /* make gcc happy */
goto fail_response;
@@ -644,9 +637,9 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
}
/* Check that the number of segments is sane. */
- nseg = req->nr_segments;
- if (unlikely(nseg == 0 && operation != WRITE_FLUSH &&
- operation != REQ_DISCARD) ||
+ nseg = req->u.rw.nr_segments;
+
+ if (unlikely(nseg == 0 && operation != WRITE_FLUSH) ||
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
pr_debug(DRV_PFX "Bad number of segments in request (%d)\n",
nseg);
@@ -654,12 +647,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
goto fail_response;
}
- preq.dev = req->handle;
+ preq.dev = req->u.rw.handle;
preq.sector_number = req->u.rw.sector_number;
preq.nr_sects = 0;
pending_req->blkif = blkif;
- pending_req->id = req->id;
+ pending_req->id = req->u.rw.id;
pending_req->operation = req->operation;
pending_req->status = BLKIF_RSP_OKAY;
pending_req->nr_pages = nseg;
@@ -707,7 +700,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
* the hypercall to unmap the grants - that is all done in
* xen_blkbk_unmap.
*/
- if (operation != REQ_DISCARD && xen_blkbk_map(req, pending_req, seg))
+ if (xen_blkbk_map(req, pending_req, seg))
goto fail_flush;
/*
@@ -739,23 +732,16 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
/* This will be hit if the operation was a flush or discard. */
if (!bio) {
- BUG_ON(operation != WRITE_FLUSH && operation != REQ_DISCARD);
+ BUG_ON(operation != WRITE_FLUSH);
- if (operation == WRITE_FLUSH) {
- bio = bio_alloc(GFP_KERNEL, 0);
- if (unlikely(bio == NULL))
- goto fail_put_bio;
+ bio = bio_alloc(GFP_KERNEL, 0);
+ if (unlikely(bio == NULL))
+ goto fail_put_bio;
- biolist[nbio++] = bio;
- bio->bi_bdev = preq.bdev;
- bio->bi_private = pending_req;
- bio->bi_end_io = end_block_io_op;
- } else if (operation == REQ_DISCARD) {
- xen_blk_discard(blkif, req);
- xen_blkif_put(blkif);
- free_req(pending_req);
- return 0;
- }
+ biolist[nbio++] = bio;
+ bio->bi_bdev = preq.bdev;
+ bio->bi_private = pending_req;
+ bio->bi_end_io = end_block_io_op;
}
/*
@@ -784,7 +770,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
xen_blkbk_unmap(pending_req);
fail_response:
/* Haven't submitted any bio's yet. */
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ make_response(blkif, req->u.rw.id, req->operation, BLKIF_RSP_ERROR);
free_req(pending_req);
msleep(1); /* back off a bit */
return -EIO;
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index dfb1b3a..d0ee7ed 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -60,58 +60,66 @@ struct blkif_common_response {
char dummy;
};
-/* i386 protocol version */
-#pragma pack(push, 4)
-
struct blkif_x86_32_request_rw {
+ uint8_t nr_segments; /* number of segments */
+ blkif_vdev_t handle; /* only for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
struct blkif_x86_32_request_discard {
+ uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
+ blkif_vdev_t _pad1; /* was "handle" for read/write requests */
+ uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
- uint64_t nr_sectors;
-};
+ uint64_t nr_sectors;
+} __attribute__((__packed__));
struct blkif_x86_32_request {
uint8_t operation; /* BLKIF_OP_??? */
- uint8_t nr_segments; /* number of segments */
- blkif_vdev_t handle; /* only for read/write requests */
- uint64_t id; /* private guest value, echoed in resp */
union {
struct blkif_x86_32_request_rw rw;
struct blkif_x86_32_request_discard discard;
} u;
-};
+} __attribute__((__packed__));
+
+/* i386 protocol version */
+#pragma pack(push, 4)
struct blkif_x86_32_response {
uint64_t id; /* copied from request */
uint8_t operation; /* copied from request */
int16_t status; /* BLKIF_RSP_??? */
};
#pragma pack(pop)
-
/* x86_64 protocol version */
struct blkif_x86_64_request_rw {
+ uint8_t nr_segments; /* number of segments */
+ blkif_vdev_t handle; /* only for read/write requests */
+ uint32_t _pad1; /* offsetof(blkif_reqest..,u.rw.id)==8 */
+ uint64_t id;
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
-};
+} __attribute__((__packed__));
struct blkif_x86_64_request_discard {
+ uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
+ blkif_vdev_t _pad1; /* was "handle" for read/write requests */
+ uint32_t _pad2; /* offsetof(blkif_..,u.discard.id)==8 */
+ uint64_t id;
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
- uint64_t nr_sectors;
-};
+ uint64_t nr_sectors;
+} __attribute__((__packed__));
struct blkif_x86_64_request {
uint8_t operation; /* BLKIF_OP_??? */
- uint8_t nr_segments; /* number of segments */
- blkif_vdev_t handle; /* only for read/write requests */
- uint64_t __attribute__((__aligned__(8))) id;
union {
struct blkif_x86_64_request_rw rw;
struct blkif_x86_64_request_discard discard;
} u;
-};
+} __attribute__((__packed__));
+
struct blkif_x86_64_response {
uint64_t __attribute__((__aligned__(8))) id;
uint8_t operation; /* copied from request */
@@ -156,6 +164,7 @@ struct xen_vbd {
/* Cached size parameter. */
sector_t size;
bool flush_support;
+ bool discard_secure;
};
struct backend_info;
@@ -237,22 +246,23 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
{
int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
dst->operation = src->operation;
- dst->nr_segments = src->nr_segments;
- dst->handle = src->handle;
- dst->id = src->id;
switch (src->operation) {
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
case BLKIF_OP_FLUSH_DISKCACHE:
+ dst->u.rw.nr_segments = src->u.rw.nr_segments;
+ dst->u.rw.handle = src->u.rw.handle;
+ dst->u.rw.id = src->u.rw.id;
dst->u.rw.sector_number = src->u.rw.sector_number;
barrier();
- if (n > dst->nr_segments)
- n = dst->nr_segments;
+ if (n > dst->u.rw.nr_segments)
+ n = dst->u.rw.nr_segments;
for (i = 0; i < n; i++)
dst->u.rw.seg[i] = src->u.rw.seg[i];
break;
case BLKIF_OP_DISCARD:
+ dst->u.discard.flag = src->u.discard.flag;
dst->u.discard.sector_number = src->u.discard.sector_number;
dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
break;
@@ -266,22 +276,23 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
{
int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
dst->operation = src->operation;
- dst->nr_segments = src->nr_segments;
- dst->handle = src->handle;
- dst->id = src->id;
switch (src->operation) {
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
case BLKIF_OP_WRITE_BARRIER:
case BLKIF_OP_FLUSH_DISKCACHE:
+ dst->u.rw.nr_segments = src->u.rw.nr_segments;
+ dst->u.rw.handle = src->u.rw.handle;
+ dst->u.rw.id = src->u.rw.id;
dst->u.rw.sector_number = src->u.rw.sector_number;
barrier();
- if (n > dst->nr_segments)
- n = dst->nr_segments;
+ if (n > dst->u.rw.nr_segments)
+ n = dst->u.rw.nr_segments;
for (i = 0; i < n; i++)
dst->u.rw.seg[i] = src->u.rw.seg[i];
break;
case BLKIF_OP_DISCARD:
+ dst->u.discard.flag = src->u.discard.flag;
dst->u.discard.sector_number = src->u.discard.sector_number;
dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
break;
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 37c794d..24a2fb5 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -338,6 +338,9 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
if (q && q->flush_flags)
vbd->flush_support = true;
+ if (q && blk_queue_secdiscard(q))
+ vbd->discard_secure = true;
+
DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
handle, blkif->domid);
return 0;
@@ -420,6 +423,15 @@ int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
state = 1;
blkif->blk_backend_type = BLKIF_BACKEND_PHY;
}
+ /* Optional. */
+ err = xenbus_printf(xbt, dev->nodename,
+ "discard-secure", "%d",
+ blkif->vbd.discard_secure);
+ if (err) {
+ xenbus_dev_fatal(dev, err,
+ "writting discard-secure");
+ goto kfree;
+ }
}
} else {
err = PTR_ERR(type);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 9fd3ee2..2f22874 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -98,7 +98,8 @@ struct blkfront_info
unsigned long shadow_free;
unsigned int feature_flush;
unsigned int flush_op;
- unsigned int feature_discard;
+ unsigned int feature_discard:1;
+ unsigned int feature_secdiscard:1;
unsigned int discard_granularity;
unsigned int discard_alignment;
int is_ready;
@@ -135,15 +136,15 @@ static int get_id_from_freelist(struct blkfront_info *info)
{
unsigned long free = info->shadow_free;
BUG_ON(free >= BLK_RING_SIZE);
- info->shadow_free = info->shadow[free].req.id;
- info->shadow[free].req.id = 0x0fffffee; /* debug */
+ info->shadow_free = info->shadow[free].req.u.rw.id;
+ info->shadow[free].req.u.rw.id = 0x0fffffee; /* debug */
return free;
}
static void add_id_to_freelist(struct blkfront_info *info,
unsigned long id)
{
- info->shadow[id].req.id = info->shadow_free;
+ info->shadow[id].req.u.rw.id = info->shadow_free;
info->shadow[id].request = NULL;
info->shadow_free = id;
}
@@ -156,7 +157,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr)
if (end > nr_minors) {
unsigned long *bitmap, *old;
- bitmap = kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap),
+ bitmap = kcalloc(BITS_TO_LONGS(end), sizeof(*bitmap),
GFP_KERNEL);
if (bitmap == NULL)
return -ENOMEM;
@@ -287,9 +288,9 @@ static int blkif_queue_request(struct request *req)
id = get_id_from_freelist(info);
info->shadow[id].request = req;
- ring_req->id = id;
+ ring_req->u.rw.id = id;
ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
- ring_req->handle = info->handle;
+ ring_req->u.rw.handle = info->handle;
ring_req->operation = rq_data_dir(req) ?
BLKIF_OP_WRITE : BLKIF_OP_READ;
@@ -305,16 +306,21 @@ static int blkif_queue_request(struct request *req)
ring_req->operation = info->flush_op;
}
- if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+ if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) {
/* id, sector_number and handle are set above. */
ring_req->operation = BLKIF_OP_DISCARD;
- ring_req->nr_segments = 0;
ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
+ if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
+ ring_req->u.discard.flag = BLKIF_DISCARD_SECURE;
+ else
+ ring_req->u.discard.flag = 0;
} else {
- ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
- BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ ring_req->u.rw.nr_segments = blk_rq_map_sg(req->q, req,
+ info->sg);
+ BUG_ON(ring_req->u.rw.nr_segments >
+ BLKIF_MAX_SEGMENTS_PER_REQUEST);
- for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+ for_each_sg(info->sg, sg, ring_req->u.rw.nr_segments, i) {
buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
fsect = sg->offset >> 9;
lsect = fsect + (sg->length >> 9) - 1;
@@ -424,6 +430,8 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
blk_queue_max_discard_sectors(rq, get_capacity(gd));
rq->limits.discard_granularity = info->discard_granularity;
rq->limits.discard_alignment = info->discard_alignment;
+ if (info->feature_secdiscard)
+ queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, rq);
}
/* Hard sector size and max sectors impersonate the equiv. hardware. */
@@ -705,7 +713,9 @@ static void blkif_free(struct blkfront_info *info, int suspend)
static void blkif_completion(struct blk_shadow *s)
{
int i;
- for (i = 0; i < s->req.nr_segments; i++)
+ /* Do not let BLKIF_OP_DISCARD as nr_segment is in the same place
+ * flag. */
+ for (i = 0; i < s->req.u.rw.nr_segments; i++)
gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
}
@@ -736,7 +746,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
id = bret->id;
req = info->shadow[id].request;
- blkif_completion(&info->shadow[id]);
+ if (bret->operation != BLKIF_OP_DISCARD)
+ blkif_completion(&info->shadow[id]);
add_id_to_freelist(info, id);
@@ -749,7 +760,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
info->gd->disk_name);
error = -EOPNOTSUPP;
info->feature_discard = 0;
+ info->feature_secdiscard = 0;
queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+ queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq);
}
__blk_end_request_all(req, error);
break;
@@ -763,7 +776,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
error = -EOPNOTSUPP;
}
if (unlikely(bret->status == BLKIF_RSP_ERROR &&
- info->shadow[id].req.nr_segments == 0)) {
+ info->shadow[id].req.u.rw.nr_segments == 0)) {
printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n",
info->flush_op == BLKIF_OP_WRITE_BARRIER ?
"barrier" : "flush disk cache",
@@ -984,8 +997,8 @@ static int blkfront_probe(struct xenbus_device *dev,
INIT_WORK(&info->work, blkif_restart_queue);
for (i = 0; i < BLK_RING_SIZE; i++)
- info->shadow[i].req.id = i+1;
- info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+ info->shadow[i].req.u.rw.id = i+1;
+ info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff;
/* Front end dir is a number, which is used as the id. */
info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0);
@@ -1019,9 +1032,9 @@ static int blkif_recover(struct blkfront_info *info)
/* Stage 2: Set up free list. */
memset(&info->shadow, 0, sizeof(info->shadow));
for (i = 0; i < BLK_RING_SIZE; i++)
- info->shadow[i].req.id = i+1;
+ info->shadow[i].req.u.rw.id = i+1;
info->shadow_free = info->ring.req_prod_pvt;
- info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+ info->shadow[BLK_RING_SIZE-1].req.u.rw.id = 0x0fffffff;
/* Stage 3: Find pending requests and requeue them. */
for (i = 0; i < BLK_RING_SIZE; i++) {
@@ -1034,17 +1047,19 @@ static int blkif_recover(struct blkfront_info *info)
*req = copy[i].req;
/* We get a new request id, and must reset the shadow state. */
- req->id = get_id_from_freelist(info);
- memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
+ req->u.rw.id = get_id_from_freelist(info);
+ memcpy(&info->shadow[req->u.rw.id], &copy[i], sizeof(copy[i]));
+ if (req->operation != BLKIF_OP_DISCARD) {
/* Rewrite any grant references invalidated by susp/resume. */
- for (j = 0; j < req->nr_segments; j++)
- gnttab_grant_foreign_access_ref(
- req->u.rw.seg[j].gref,
- info->xbdev->otherend_id,
- pfn_to_mfn(info->shadow[req->id].frame[j]),
- rq_data_dir(info->shadow[req->id].request));
- info->shadow[req->id].req = *req;
+ for (j = 0; j < req->u.rw.nr_segments; j++)
+ gnttab_grant_foreign_access_ref(
+ req->u.rw.seg[j].gref,
+ info->xbdev->otherend_id,
+ pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]),
+ rq_data_dir(info->shadow[req->u.rw.id].request));
+ }
+ info->shadow[req->u.rw.id].req = *req;
info->ring.req_prod_pvt++;
}
@@ -1135,11 +1150,13 @@ static void blkfront_setup_discard(struct blkfront_info *info)
char *type;
unsigned int discard_granularity;
unsigned int discard_alignment;
+ unsigned int discard_secure;
type = xenbus_read(XBT_NIL, info->xbdev->otherend, "type", NULL);
if (IS_ERR(type))
return;
+ info->feature_secdiscard = 0;
if (strncmp(type, "phy", 3) == 0) {
err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
"discard-granularity", "%u", &discard_granularity,
@@ -1150,6 +1167,12 @@ static void blkfront_setup_discard(struct blkfront_info *info)
info->discard_granularity = discard_granularity;
info->discard_alignment = discard_alignment;
}
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "discard-secure", "%d", &discard_secure,
+ NULL);
+ if (!err)
+ info->feature_secdiscard = discard_secure;
+
} else if (strncmp(type, "file", 4) == 0)
info->feature_discard = 1;
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index fb1975d..1a17e33 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -456,7 +456,7 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace)
{
dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
- if (ace->irq == NO_IRQ)
+ if (!ace->irq)
/* No IRQ assigned, so need to poll */
tasklet_schedule(&ace->fsm_tasklet);
ace->fsm_continue_flag = 0;
@@ -1034,12 +1034,12 @@ static int __devinit ace_setup(struct ace_device *ace)
ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
/* Now we can hook up the irq handler */
- if (ace->irq != NO_IRQ) {
+ if (ace->irq) {
rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
if (rc) {
/* Failure - fall back to polled mode */
dev_err(ace->dev, "request_irq failed\n");
- ace->irq = NO_IRQ;
+ ace->irq = 0;
}
}
@@ -1086,7 +1086,7 @@ static void __devexit ace_teardown(struct ace_device *ace)
tasklet_kill(&ace->fsm_tasklet);
- if (ace->irq != NO_IRQ)
+ if (ace->irq)
free_irq(ace->irq, ace);
iounmap(ace->baseaddr);
@@ -1156,7 +1156,7 @@ static int __devinit ace_probe(struct platform_device *dev)
resource_size_t physaddr = 0;
int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
u32 id = dev->id;
- int irq = NO_IRQ;
+ int irq = 0;
int i;
dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 55ac349..f00f596 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -37,13 +37,13 @@
#define VERSION "0.6"
-static int ignore_dga;
-static int ignore_csr;
-static int ignore_sniffer;
-static int disable_scofix;
-static int force_scofix;
+static bool ignore_dga;
+static bool ignore_csr;
+static bool ignore_sniffer;
+static bool disable_scofix;
+static bool force_scofix;
-static int reset = 1;
+static bool reset = 1;
static struct usb_driver btusb_driver;
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 9c5b2dc..a767d4de 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -49,8 +49,8 @@
#define VERSION "0.3"
-static int txcrc = 1;
-static int hciextn = 1;
+static bool txcrc = 1;
+static bool hciextn = 1;
#define BCSP_TXWINSIZE 4
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 48ad2a7..0711448 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -48,7 +48,7 @@
#define VERSION "2.2"
-static int reset = 0;
+static bool reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 2118211..55eaf47 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -285,17 +285,17 @@
#include <asm/uaccess.h>
/* used to tell the module to turn on full debugging messages */
-static int debug;
+static bool debug;
/* used to keep tray locked at all times */
static int keeplocked;
/* default compatibility mode */
-static int autoclose=1;
-static int autoeject;
-static int lockdoor = 1;
+static bool autoclose=1;
+static bool autoeject;
+static bool lockdoor = 1;
/* will we ever get to use this... sigh. */
-static int check_media_type;
+static bool check_media_type;
/* automatically restart mrw format */
-static int mrw_format_restart = 1;
+static bool mrw_format_restart = 1;
module_param(debug, bool, 0);
module_param(autoclose, bool, 0);
module_param(autoeject, bool, 0);
@@ -2746,12 +2746,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
{
void __user *argp = (void __user *)arg;
int ret;
- struct gendisk *disk = bdev->bd_disk;
/*
* Try the generic SCSI command ioctl's first.
*/
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
if (ret != -ENOTTY)
return ret;
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 780498d..444f8b6 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -33,7 +33,7 @@
#define ULI_X86_64_ENU_SCR_REG 0x54
static struct resource *aperture_resource;
-static int __initdata agp_try_unsupported = 1;
+static bool __initdata agp_try_unsupported = 1;
static int agp_bridges_found;
static void amd64_tlbflush(struct agp_memory *temp)
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 29aacd8..08704ae 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -17,7 +17,7 @@
#define PCI_DEVICE_ID_SI_662 0x0662
#define PCI_DEVICE_ID_SI_671 0x0671
-static int __devinitdata agp_sis_force_delay = 0;
+static bool __devinitdata agp_sis_force_delay = 0;
static int __devinitdata agp_sis_agp_spec = -1;
static int sis_fetch_size(void)
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 241df2e..f518b99 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -141,17 +141,7 @@ static struct platform_driver atmel_trng_driver = {
},
};
-static int __init atmel_trng_init(void)
-{
- return platform_driver_register(&atmel_trng_driver);
-}
-module_init(atmel_trng_init);
-
-static void __exit atmel_trng_exit(void)
-{
- platform_driver_unregister(&atmel_trng_driver);
-}
-module_exit(atmel_trng_exit);
+module_platform_driver(atmel_trng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index c3de70d..ebd48f0 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -770,15 +770,4 @@ static struct platform_driver n2rng_driver = {
.remove = __devexit_p(n2rng_remove),
};
-static int __init n2rng_init(void)
-{
- return platform_driver_register(&n2rng_driver);
-}
-
-static void __exit n2rng_exit(void)
-{
- platform_driver_unregister(&n2rng_driver);
-}
-
-module_init(n2rng_init);
-module_exit(n2rng_exit);
+module_platform_driver(n2rng_driver);
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 9cd0fec..0943edc 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -131,18 +131,7 @@ static struct platform_driver octeon_rng_driver = {
.remove = __exit_p(octeon_rng_remove),
};
-static int __init octeon_rng_mod_init(void)
-{
- return platform_driver_register(&octeon_rng_driver);
-}
-
-static void __exit octeon_rng_mod_exit(void)
-{
- platform_driver_unregister(&octeon_rng_driver);
-}
-
-module_init(octeon_rng_mod_init);
-module_exit(octeon_rng_mod_exit);
+module_platform_driver(octeon_rng_driver);
MODULE_AUTHOR("David Daney");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index 1d50481..3a63267 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -148,17 +148,7 @@ static struct platform_driver rng_driver = {
.remove = rng_remove,
};
-static int __init rng_init(void)
-{
- return platform_driver_register(&rng_driver);
-}
-module_init(rng_init);
-
-static void __exit rng_exit(void)
-{
- platform_driver_unregister(&rng_driver);
-}
-module_exit(rng_exit);
+module_platform_driver(rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
index 990d55a..97bd891 100644
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -191,17 +191,7 @@ static struct platform_driver picoxcell_trng_driver = {
},
};
-static int __init picoxcell_trng_init(void)
-{
- return platform_driver_register(&picoxcell_trng_driver);
-}
-module_init(picoxcell_trng_init);
-
-static void __exit picoxcell_trng_exit(void)
-{
- platform_driver_unregister(&picoxcell_trng_driver);
-}
-module_exit(picoxcell_trng_exit);
+module_platform_driver(picoxcell_trng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jamie Iles");
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index b8afa6a..c51762c 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -139,17 +139,7 @@ static struct platform_driver ppc4xx_rng_driver = {
.remove = ppc4xx_rng_remove,
};
-static int __init ppc4xx_rng_init(void)
-{
- return platform_driver_register(&ppc4xx_rng_driver);
-}
-module_init(ppc4xx_rng_init);
-
-static void __exit ppc4xx_rng_exit(void)
-{
- platform_driver_unregister(&ppc4xx_rng_driver);
-}
-module_exit(ppc4xx_rng_exit);
+module_platform_driver(ppc4xx_rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index a8428e6..f1a1618 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -149,18 +149,7 @@ static struct platform_driver timeriomem_rng_driver = {
.remove = __devexit_p(timeriomem_rng_remove),
};
-static int __init timeriomem_rng_init(void)
-{
- return platform_driver_register(&timeriomem_rng_driver);
-}
-
-static void __exit timeriomem_rng_exit(void)
-{
- platform_driver_unregister(&timeriomem_rng_driver);
-}
-
-module_init(timeriomem_rng_init);
-module_exit(timeriomem_rng_exit);
+module_platform_driver(timeriomem_rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index fd699cc..723725b 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -47,7 +47,7 @@ static void register_buffer(u8 *buf, size_t size)
sg_init_one(&sg, buf, size);
/* There should always be room for one buffer. */
- if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0)
+ if (virtqueue_add_buf(vq, &sg, 0, 1, buf, GFP_KERNEL) < 0)
BUG();
virtqueue_kick(vq);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 6e40072..40cc0cf2 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -69,19 +69,19 @@ MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
MODULE_LICENSE("GPL");
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force loading without checking for supported models");
-static int ignore_dmi;
+static bool ignore_dmi;
module_param(ignore_dmi, bool, 0);
MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
-static int restricted;
+static bool restricted;
module_param(restricted, bool, 0);
MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
-static int power_status;
+static bool power_status;
module_param(power_status, bool, 0600);
MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 9397ab4..50fcf9c 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1227,7 +1227,7 @@ static int smi_num; /* Used to sequence the SMIs */
#define DEFAULT_REGSPACING 1
#define DEFAULT_REGSIZE 1
-static int si_trydefaults = 1;
+static bool si_trydefaults = 1;
static char *si_type[SI_MAX_PARMS];
#define MAX_SI_TYPE_STR 30
static char si_type_str[MAX_SI_TYPE_STR];
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 97c3edb..f434856 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -829,7 +829,7 @@ static struct console lpcons = {
static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
static char *parport[LP_NO];
-static int reset;
+static bool reset;
module_param_array(parport, charp, NULL, 0);
module_param(reset, bool, 0);
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index a12f524..bf586ae 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -51,7 +51,7 @@ static int write_block(unsigned long p, const char __user *buf, int count);
#define KFLASH_ID 0x89A6 //Intel flash
#define KFLASH_ID4 0xB0D4 //Intel flash 4Meg
-static int flashdebug; //if set - we will display progress msgs
+static bool flashdebug; //if set - we will display progress msgs
static int gbWriteEnable;
static int gbWriteBase64Enable;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 1578139..07f6a5a 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -439,7 +439,7 @@ static int mgslpc_device_count = 0;
* .text section address and breakpoint on module load.
* This is useful for use with gdb and add-symbol-file command.
*/
-static int break_on_load=0;
+static bool break_on_load=0;
/*
* Driver major number, defaults to zero to get auto
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
index 7c7f42a1f8..9fec323 100644
--- a/drivers/char/ramoops.c
+++ b/drivers/char/ramoops.c
@@ -83,8 +83,7 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
struct timeval timestamp;
if (reason != KMSG_DUMP_OOPS &&
- reason != KMSG_DUMP_PANIC &&
- reason != KMSG_DUMP_KEXEC)
+ reason != KMSG_DUMP_PANIC)
return;
/* Only dump oopses if dump_oops is set */
@@ -126,8 +125,8 @@ static int __init ramoops_probe(struct platform_device *pdev)
goto fail3;
}
- rounddown_pow_of_two(pdata->mem_size);
- rounddown_pow_of_two(pdata->record_size);
+ pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
+ pdata->record_size = rounddown_pow_of_two(pdata->record_size);
/* Check for the minimum memory size */
if (pdata->mem_size < MIN_MEM_SIZE &&
@@ -148,14 +147,6 @@ static int __init ramoops_probe(struct platform_device *pdev)
cxt->phys_addr = pdata->mem_address;
cxt->record_size = pdata->record_size;
cxt->dump_oops = pdata->dump_oops;
- /*
- * Update the module parameter variables as well so they are visible
- * through /sys/module/ramoops/parameters/
- */
- mem_size = pdata->mem_size;
- mem_address = pdata->mem_address;
- record_size = pdata->record_size;
- dump_oops = pdata->dump_oops;
if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
pr_err("request mem region failed\n");
@@ -176,6 +167,15 @@ static int __init ramoops_probe(struct platform_device *pdev)
goto fail1;
}
+ /*
+ * Update the module parameter variables as well so they are visible
+ * through /sys/module/ramoops/parameters/
+ */
+ mem_size = pdata->mem_size;
+ mem_address = pdata->mem_address;
+ record_size = pdata->record_size;
+ dump_oops = pdata->dump_oops;
+
return 0;
fail1:
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 85da874..54ca8b2 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -387,7 +387,7 @@ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
static struct fasync_struct *fasync;
#if 0
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
#define DEBUG_ENT(fmt, arg...) do { \
if (debug) \
@@ -965,6 +965,7 @@ EXPORT_SYMBOL(get_random_bytes);
*/
static void init_std_data(struct entropy_store *r)
{
+ int i;
ktime_t now;
unsigned long flags;
@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r)
now = ktime_get_real();
mix_pool_bytes(r, &now, sizeof(now));
+ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
+ if (!arch_get_random_long(&flags))
+ break;
+ mix_pool_bytes(r, &flags, sizeof(flags));
+ }
mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
}
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index fa567f1..7fc75e4 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -27,6 +27,7 @@ if TCG_TPM
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface"
+ depends on X86
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -35,6 +36,7 @@ config TCG_TIS
config TCG_NSC
tristate "National Semiconductor TPM Interface"
+ depends on X86
---help---
If you have a TPM security chip from National Semiconductor
say Yes and it will be accessible from within Linux. To
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 361a1df..6a8771f 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/freezer.h>
#include "tpm.h"
@@ -440,7 +441,6 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define TPM_ERROR_SIZE 10
#define TPM_RET_CODE_IDX 6
enum tpm_capabilities {
@@ -469,12 +469,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
len = tpm_transmit(chip,(u8 *) cmd, len);
if (len < 0)
return len;
- if (len == TPM_ERROR_SIZE) {
- err = be32_to_cpu(cmd->header.out.return_code);
- dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
- return err;
- }
- return 0;
+ else if (len < TPM_HEADER_SIZE)
+ return -EFAULT;
+
+ err = be32_to_cpu(cmd->header.out.return_code);
+ if (err != 0)
+ dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+
+ return err;
}
#define TPM_INTERNAL_RESULT_SIZE 200
@@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
-void tpm_get_timeouts(struct tpm_chip *chip)
+int tpm_get_timeouts(struct tpm_chip *chip)
{
struct tpm_cmd_t tpm_cmd;
struct timeout_t *timeout_cap;
@@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
- return;
+ return -EINVAL;
timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
/* Don't overwrite default if value is 0 */
@@ -583,12 +585,12 @@ duration:
rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
"attempting to determine the durations");
if (rc)
- return;
+ return rc;
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
- return;
+ return -EINVAL;
duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] =
@@ -610,20 +612,36 @@ duration:
chip->vendor.duration_adjusted = true;
dev_info(chip->dev, "Adjusting TPM timeout parameters.");
}
+ return 0;
}
EXPORT_SYMBOL_GPL(tpm_get_timeouts);
-void tpm_continue_selftest(struct tpm_chip *chip)
+#define TPM_ORD_CONTINUE_SELFTEST 83
+#define CONTINUE_SELFTEST_RESULT_SIZE 10
+
+static struct tpm_input_header continue_selftest_header = {
+ .tag = TPM_TAG_RQU_COMMAND,
+ .length = cpu_to_be32(10),
+ .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
+};
+
+/**
+ * tpm_continue_selftest -- run TPM's selftest
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+static int tpm_continue_selftest(struct tpm_chip *chip)
{
- u8 data[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 10, /* length */
- 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
- };
+ int rc;
+ struct tpm_cmd_t cmd;
- tpm_transmit(chip, data, sizeof(data));
+ cmd.header.in = continue_selftest_header;
+ rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+ "continue selftest");
+ return rc;
}
-EXPORT_SYMBOL_GPL(tpm_continue_selftest);
ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
char *buf)
@@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = {
.ordinal = TPM_ORDINAL_PCRREAD
};
-int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
int rc;
struct tpm_cmd_t cmd;
@@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+/**
+ * tpm_do_selftest - have the TPM continue its selftest and wait until it
+ * can receive further commands
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+int tpm_do_selftest(struct tpm_chip *chip)
+{
+ int rc;
+ u8 digest[TPM_DIGEST_SIZE];
+ unsigned int loops;
+ unsigned int delay_msec = 1000;
+ unsigned long duration;
+
+ duration = tpm_calc_ordinal_duration(chip,
+ TPM_ORD_CONTINUE_SELFTEST);
+
+ loops = jiffies_to_msecs(duration) / delay_msec;
+
+ rc = tpm_continue_selftest(chip);
+ /* This may fail if there was no TPM driver during a suspend/resume
+ * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
+ */
+ if (rc)
+ return rc;
+
+ do {
+ rc = __tpm_pcr_read(chip, 0, digest);
+ if (rc != TPM_WARN_DOING_SELFTEST)
+ return rc;
+ msleep(delay_msec);
+ } while (--loops > 0);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_do_selftest);
+
int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
struct tpm_chip *chip;
@@ -1005,6 +1062,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
+int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ long rc;
+ u8 status;
+
+ /* check current status */
+ status = chip->vendor.status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ stop = jiffies + timeout;
+
+ if (chip->vendor.irq) {
+again:
+ timeout = stop - jiffies;
+ if ((long)timeout <= 0)
+ return -ETIME;
+ rc = wait_event_interruptible_timeout(*queue,
+ ((chip->vendor.status(chip)
+ & mask) == mask),
+ timeout);
+ if (rc > 0)
+ return 0;
+ if (rc == -ERESTARTSYS && freezing(current)) {
+ clear_thread_flag(TIF_SIGPENDING);
+ goto again;
+ }
+ } else {
+ do {
+ msleep(TPM_TIMEOUT);
+ status = chip->vendor.status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+ }
+ return -ETIME;
+}
+EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
/*
* Device file system interface to the TPM
*
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9c4163c..8c1df30 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -38,6 +38,8 @@ enum tpm_addr {
TPM_ADDR = 0x4E,
};
+#define TPM_WARN_DOING_SELFTEST 0x802
+#define TPM_HEADER_SIZE 10
extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
@@ -279,9 +281,9 @@ struct tpm_cmd_t {
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
-extern void tpm_get_timeouts(struct tpm_chip *);
+extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
-extern void tpm_continue_selftest(struct tpm_chip *);
+extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
@@ -294,7 +296,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *, pm_message_t);
extern int tpm_pm_resume(struct device *);
-
+extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
+ wait_queue_head_t *);
#ifdef CONFIG_ACPI
extern struct dentry ** tpm_bios_log_setup(char *);
extern void tpm_bios_log_teardown(struct dentry **);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 3f4051a..a174862 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -29,8 +29,6 @@
#include <linux/freezer.h>
#include "tpm.h"
-#define TPM_HEADER_SIZE 10
-
enum tis_access {
TPM_ACCESS_VALID = 0x80,
TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
@@ -193,54 +191,14 @@ static int get_burstcount(struct tpm_chip *chip)
return -EBUSY;
}
-static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
- wait_queue_head_t *queue)
-{
- unsigned long stop;
- long rc;
- u8 status;
-
- /* check current status */
- status = tpm_tis_status(chip);
- if ((status & mask) == mask)
- return 0;
-
- stop = jiffies + timeout;
-
- if (chip->vendor.irq) {
-again:
- timeout = stop - jiffies;
- if ((long)timeout <= 0)
- return -ETIME;
- rc = wait_event_interruptible_timeout(*queue,
- ((tpm_tis_status
- (chip) & mask) ==
- mask), timeout);
- if (rc > 0)
- return 0;
- if (rc == -ERESTARTSYS && freezing(current)) {
- clear_thread_flag(TIF_SIGPENDING);
- goto again;
- }
- } else {
- do {
- msleep(TPM_TIMEOUT);
- status = tpm_tis_status(chip);
- if ((status & mask) == mask)
- return 0;
- } while (time_before(jiffies, stop));
- }
- return -ETIME;
-}
-
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
{
int size = 0, burstcnt;
while (size < count &&
- wait_for_stat(chip,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- chip->vendor.timeout_c,
- &chip->vendor.read_queue)
+ wait_for_tpm_stat(chip,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue)
== 0) {
burstcnt = get_burstcount(chip);
for (; burstcnt > 0 && size < count; burstcnt--)
@@ -282,8 +240,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
goto out;
}
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(chip->dev, "Error left over data\n");
@@ -297,7 +255,7 @@ out:
return size;
}
-static int itpm;
+static bool itpm;
module_param(itpm, bool, 0444);
MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
@@ -317,7 +275,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
status = tpm_tis_status(chip);
if ((status & TPM_STS_COMMAND_READY) == 0) {
tpm_tis_ready(chip);
- if (wait_for_stat
+ if (wait_for_tpm_stat
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
&chip->vendor.int_queue) < 0) {
rc = -ETIME;
@@ -333,8 +291,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
count++;
}
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO;
@@ -345,8 +303,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
/* write last byte */
iowrite8(buf[count],
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if ((status & TPM_STS_DATA_EXPECT) != 0) {
rc = -EIO;
@@ -381,7 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
if (chip->vendor.irq) {
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
- if (wait_for_stat
+ if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
tpm_calc_ordinal_duration(chip, ordinal),
&chip->vendor.read_queue) < 0) {
@@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip)
out:
itpm = rem_itpm;
tpm_tis_ready(chip);
+ /* some TPMs need a break here otherwise they will not work
+ * correctly on the immediately subsequent command */
+ msleep(chip->vendor.timeout_b);
release_locality(chip, chip->vendor.locality, 0);
return rc;
@@ -539,7 +500,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
return IRQ_HANDLED;
}
-static int interrupts = 1;
+static bool interrupts = 1;
module_param(interrupts, bool, 0444);
MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
dev_dbg(dev, "\tData Avail Int Support\n");
/* get the timeouts before testing for irqs */
- tpm_get_timeouts(chip);
+ if (tpm_get_timeouts(chip)) {
+ dev_err(dev, "Could not get TPM timeouts and durations\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ if (tpm_do_selftest(chip)) {
+ dev_err(dev, "TPM self test failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
/* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue);
@@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
list_add(&chip->vendor.list, &tis_chips);
spin_unlock(&tis_lock);
- tpm_continue_selftest(chip);
return 0;
out_err:
@@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
ret = tpm_pm_resume(&dev->dev);
if (!ret)
- tpm_continue_selftest(chip);
+ tpm_do_selftest(chip);
return ret;
}
@@ -858,7 +828,7 @@ static struct platform_driver tis_drv = {
static struct platform_device *pdev;
-static int force;
+static bool force;
module_param(force, bool, 0444);
MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
static int __init init_tis(void)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8e3c46d..b58b561 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -392,7 +392,7 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf)
sg_init_one(sg, buf->buf, buf->size);
- ret = virtqueue_add_buf(vq, sg, 0, 1, buf);
+ ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC);
virtqueue_kick(vq);
return ret;
}
@@ -457,7 +457,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
vq = portdev->c_ovq;
sg_init_one(sg, &cpkt, sizeof(cpkt));
- if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) {
+ if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
virtqueue_kick(vq);
while (!virtqueue_get_buf(vq, &len))
cpu_relax();
@@ -506,7 +506,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);
+ ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf, GFP_ATOMIC);
/* Tell Host to go! */
virtqueue_kick(out_vq);
@@ -1271,6 +1271,20 @@ static void remove_port(struct kref *kref)
kfree(port);
}
+static void remove_port_data(struct port *port)
+{
+ struct port_buffer *buf;
+
+ /* Remove unused data this port might have received. */
+ discard_port_data(port);
+
+ reclaim_consumed_buffers(port);
+
+ /* Remove buffers we queued up for the Host to send us data in. */
+ while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
+ free_buf(buf);
+}
+
/*
* Port got unplugged. Remove port from portdev's list and drop the
* kref reference. If no userspace has this port opened, it will
@@ -1278,8 +1292,6 @@ static void remove_port(struct kref *kref)
*/
static void unplug_port(struct port *port)
{
- struct port_buffer *buf;
-
spin_lock_irq(&port->portdev->ports_lock);
list_del(&port->list);
spin_unlock_irq(&port->portdev->ports_lock);
@@ -1300,14 +1312,7 @@ static void unplug_port(struct port *port)
hvc_remove(port->cons.hvc);
}
- /* Remove unused data this port might have received. */
- discard_port_data(port);
-
- reclaim_consumed_buffers(port);
-
- /* Remove buffers we queued up for the Host to send us data in. */
- while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
- free_buf(buf);
+ remove_port_data(port);
/*
* We should just assume the device itself has gone off --
@@ -1659,6 +1664,28 @@ static const struct file_operations portdev_fops = {
.owner = THIS_MODULE,
};
+static void remove_vqs(struct ports_device *portdev)
+{
+ portdev->vdev->config->del_vqs(portdev->vdev);
+ kfree(portdev->in_vqs);
+ kfree(portdev->out_vqs);
+}
+
+static void remove_controlq_data(struct ports_device *portdev)
+{
+ struct port_buffer *buf;
+ unsigned int len;
+
+ if (!use_multiport(portdev))
+ return;
+
+ while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
+ free_buf(buf);
+
+ while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
+ free_buf(buf);
+}
+
/*
* Once we're further in boot, we get probed like any other virtio
* device.
@@ -1764,9 +1791,7 @@ free_vqs:
/* The host might want to notify mgmt sw about device add failure */
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 0);
- vdev->config->del_vqs(vdev);
- kfree(portdev->in_vqs);
- kfree(portdev->out_vqs);
+ remove_vqs(portdev);
free_chrdev:
unregister_chrdev(portdev->chr_major, "virtio-portsdev");
free:
@@ -1804,21 +1829,8 @@ static void virtcons_remove(struct virtio_device *vdev)
* have to just stop using the port, as the vqs are going
* away.
*/
- if (use_multiport(portdev)) {
- struct port_buffer *buf;
- unsigned int len;
-
- while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
- free_buf(buf);
-
- while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
- free_buf(buf);
- }
-
- vdev->config->del_vqs(vdev);
- kfree(portdev->in_vqs);
- kfree(portdev->out_vqs);
-
+ remove_controlq_data(portdev);
+ remove_vqs(portdev);
kfree(portdev);
}
@@ -1832,6 +1844,68 @@ static unsigned int features[] = {
VIRTIO_CONSOLE_F_MULTIPORT,
};
+#ifdef CONFIG_PM
+static int virtcons_freeze(struct virtio_device *vdev)
+{
+ struct ports_device *portdev;
+ struct port *port;
+
+ portdev = vdev->priv;
+
+ vdev->config->reset(vdev);
+
+ virtqueue_disable_cb(portdev->c_ivq);
+ cancel_work_sync(&portdev->control_work);
+ /*
+ * Once more: if control_work_handler() was running, it would
+ * enable the cb as the last step.
+ */
+ virtqueue_disable_cb(portdev->c_ivq);
+ remove_controlq_data(portdev);
+
+ list_for_each_entry(port, &portdev->ports, list) {
+ virtqueue_disable_cb(port->in_vq);
+ virtqueue_disable_cb(port->out_vq);
+ /*
+ * We'll ask the host later if the new invocation has
+ * the port opened or closed.
+ */
+ port->host_connected = false;
+ remove_port_data(port);
+ }
+ remove_vqs(portdev);
+
+ return 0;
+}
+
+static int virtcons_restore(struct virtio_device *vdev)
+{
+ struct ports_device *portdev;
+ struct port *port;
+ int ret;
+
+ portdev = vdev->priv;
+
+ ret = init_vqs(portdev);
+ if (ret)
+ return ret;
+
+ if (use_multiport(portdev))
+ fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+
+ list_for_each_entry(port, &portdev->ports, list) {
+ port->in_vq = portdev->in_vqs[port->id];
+ port->out_vq = portdev->out_vqs[port->id];
+
+ fill_queue(port->in_vq, &port->inbuf_lock);
+
+ /* Get port open/close status on the host */
+ send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
+ }
+ return 0;
+}
+#endif
+
static struct virtio_driver virtio_console = {
.feature_table = features,
.feature_table_size = ARRAY_SIZE(features),
@@ -1841,6 +1915,10 @@ static struct virtio_driver virtio_console = {
.probe = virtcons_probe,
.remove = virtcons_remove,
.config_changed = config_intr,
+#ifdef CONFIG_PM
+ .freeze = virtcons_freeze,
+ .restore = virtcons_restore,
+#endif
};
static int __init init(void)
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 72a0044..e0664fe 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -21,12 +21,19 @@ config ARM_S5PV210_CPUFREQ
If in doubt, say N.
+config ARM_EXYNOS_CPUFREQ
+ bool "SAMSUNG EXYNOS SoCs"
+ depends on ARCH_EXYNOS
+ select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210
+ default y
+ help
+ This adds the CPUFreq driver common part for Samsung
+ EXYNOS SoCs.
+
+ If in doubt, say N.
+
config ARM_EXYNOS4210_CPUFREQ
bool "Samsung EXYNOS4210"
- depends on CPU_EXYNOS4210
- default y
help
This adds the CPUFreq driver for Samsung EXYNOS4210
SoC (S5PV310 or S5PC210).
-
- If in doubt, say N.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index a48bc02..ac000fa 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -42,7 +42,9 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
+obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
+obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o
##################################################################################
# PowerPC platform drivers
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8c2df34..622013f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -204,8 +204,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
pr_debug("saving %lu as reference value for loops_per_jiffy; "
"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
}
- if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
- (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
+ if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
ci->new);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 3d679ee..c3e0652 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -713,11 +713,10 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
static int __init cpufreq_gov_dbs_init(void)
{
- cputime64_t wall;
u64 idle_time;
int cpu = get_cpu();
- idle_time = get_cpu_idle_time_us(cpu, &wall);
+ idle_time = get_cpu_idle_time_us(cpu, NULL);
put_cpu();
if (idle_time != -1ULL) {
/* Idle micro accounting is supported. Use finer thresholds */
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index f231015..bedac1a 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -47,9 +47,11 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if (!per_cpu(cpu_is_managed, freq->cpu))
return 0;
- pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
- freq->cpu, freq->new);
- per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
+ if (val == CPUFREQ_POSTCHANGE) {
+ pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+ freq->cpu, freq->new);
+ per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
+ }
return 0;
}
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
new file mode 100644
index 0000000..5467879
--- /dev/null
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - CPU frequency scaling support for EXYNOS series
+ *
+ * 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/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+#include <linux/suspend.h>
+
+#include <mach/cpufreq.h>
+
+#include <plat/cpu.h>
+
+static struct exynos_dvfs_info *exynos_info;
+
+static struct regulator *arm_regulator;
+static struct cpufreq_freqs freqs;
+
+static unsigned int locking_frequency;
+static bool frequency_locked;
+static DEFINE_MUTEX(cpufreq_lock);
+
+int exynos_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy,
+ exynos_info->freq_table);
+}
+
+unsigned int exynos_getspeed(unsigned int cpu)
+{
+ return clk_get_rate(exynos_info->cpu_clk) / 1000;
+}
+
+static int exynos_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int index, old_index;
+ unsigned int arm_volt, safe_arm_volt = 0;
+ int ret = 0;
+ struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
+ unsigned int *volt_table = exynos_info->volt_table;
+ unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
+
+ mutex_lock(&cpufreq_lock);
+
+ freqs.old = policy->cur;
+
+ if (frequency_locked && target_freq != locking_frequency) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ if (cpufreq_frequency_table_target(policy, freq_table,
+ freqs.old, relation, &old_index)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (cpufreq_frequency_table_target(policy, freq_table,
+ target_freq, relation, &index)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ freqs.new = freq_table[index].frequency;
+ freqs.cpu = policy->cpu;
+
+ /*
+ * ARM clock source will be changed APLL to MPLL temporary
+ * To support this level, need to control regulator for
+ * required voltage level
+ */
+ if (exynos_info->need_apll_change != NULL) {
+ if (exynos_info->need_apll_change(old_index, index) &&
+ (freq_table[index].frequency < mpll_freq_khz) &&
+ (freq_table[old_index].frequency < mpll_freq_khz))
+ safe_arm_volt = volt_table[exynos_info->pll_safe_idx];
+ }
+ arm_volt = volt_table[index];
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ /* When the new frequency is higher than current frequency */
+ if ((freqs.new > freqs.old) && !safe_arm_volt) {
+ /* Firstly, voltage up to increase frequency */
+ regulator_set_voltage(arm_regulator, arm_volt,
+ arm_volt);
+ }
+
+ if (safe_arm_volt)
+ regulator_set_voltage(arm_regulator, safe_arm_volt,
+ safe_arm_volt);
+ if (freqs.new != freqs.old)
+ exynos_info->set_freq(old_index, index);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ /* When the new frequency is lower than current frequency */
+ if ((freqs.new < freqs.old) ||
+ ((freqs.new > freqs.old) && safe_arm_volt)) {
+ /* down the voltage after frequency change */
+ regulator_set_voltage(arm_regulator, arm_volt,
+ arm_volt);
+ }
+
+out:
+ mutex_unlock(&cpufreq_lock);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+
+static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+#endif
+
+/**
+ * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
+ * context
+ * @notifier
+ * @pm_event
+ * @v
+ *
+ * While frequency_locked == true, target() ignores every frequency but
+ * locking_frequency. The locking_frequency value is the initial frequency,
+ * which is set by the bootloader. In order to eliminate possible
+ * inconsistency in clock values, we save and restore frequencies during
+ * suspend and resume and block CPUFREQ activities. Note that the standard
+ * suspend/resume cannot be used as they are too deep (syscore_ops) for
+ * regulator actions.
+ */
+static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event, void *v)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+ static unsigned int saved_frequency;
+ unsigned int temp;
+
+ mutex_lock(&cpufreq_lock);
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ if (frequency_locked)
+ goto out;
+
+ frequency_locked = true;
+
+ if (locking_frequency) {
+ saved_frequency = exynos_getspeed(0);
+
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency,
+ CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+ }
+ break;
+
+ case PM_POST_SUSPEND:
+ if (saved_frequency) {
+ /*
+ * While frequency_locked, only locking_frequency
+ * is valid for target(). In order to use
+ * saved_frequency while keeping frequency_locked,
+ * we temporarly overwrite locking_frequency.
+ */
+ temp = locking_frequency;
+ locking_frequency = saved_frequency;
+
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency,
+ CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+
+ locking_frequency = temp;
+ }
+ frequency_locked = false;
+ break;
+ }
+out:
+ mutex_unlock(&cpufreq_lock);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block exynos_cpufreq_nb = {
+ .notifier_call = exynos_cpufreq_pm_notifier,
+};
+
+static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
+
+ cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
+
+ /* set the transition latency value */
+ policy->cpuinfo.transition_latency = 100000;
+
+ /*
+ * EXYNOS4 multi-core processors has 2 cores
+ * that the frequency cannot be set independently.
+ * Each cpu is bound to the same speed.
+ * So the affected cpu is all of the cpus.
+ */
+ if (num_online_cpus() == 1) {
+ cpumask_copy(policy->related_cpus, cpu_possible_mask);
+ cpumask_copy(policy->cpus, cpu_online_mask);
+ } else {
+ cpumask_setall(policy->cpus);
+ }
+
+ return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+}
+
+static struct cpufreq_driver exynos_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = exynos_verify_speed,
+ .target = exynos_target,
+ .get = exynos_getspeed,
+ .init = exynos_cpufreq_cpu_init,
+ .name = "exynos_cpufreq",
+#ifdef CONFIG_PM
+ .suspend = exynos_cpufreq_suspend,
+ .resume = exynos_cpufreq_resume,
+#endif
+};
+
+static int __init exynos_cpufreq_init(void)
+{
+ int ret = -EINVAL;
+
+ exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
+ if (!exynos_info)
+ return -ENOMEM;
+
+ if (soc_is_exynos4210())
+ ret = exynos4210_cpufreq_init(exynos_info);
+ else
+ pr_err("%s: CPU type not found\n", __func__);
+
+ if (ret)
+ goto err_vdd_arm;
+
+ if (exynos_info->set_freq == NULL) {
+ pr_err("%s: No set_freq function (ERR)\n", __func__);
+ goto err_vdd_arm;
+ }
+
+ arm_regulator = regulator_get(NULL, "vdd_arm");
+ if (IS_ERR(arm_regulator)) {
+ pr_err("%s: failed to get resource vdd_arm\n", __func__);
+ goto err_vdd_arm;
+ }
+
+ register_pm_notifier(&exynos_cpufreq_nb);
+
+ if (cpufreq_register_driver(&exynos_driver)) {
+ pr_err("%s: failed to register cpufreq driver\n", __func__);
+ goto err_cpufreq;
+ }
+
+ return 0;
+err_cpufreq:
+ unregister_pm_notifier(&exynos_cpufreq_nb);
+
+ if (!IS_ERR(arm_regulator))
+ regulator_put(arm_regulator);
+err_vdd_arm:
+ kfree(exynos_info);
+ pr_debug("%s: failed initialization\n", __func__);
+ return -EINVAL;
+}
+late_initcall(exynos_cpufreq_init);
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index ab9741f..065da5b 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -2,61 +2,52 @@
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * EXYNOS4 - CPU frequency scaling support
+ * EXYNOS4210 - CPU frequency scaling support
*
* 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/types.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
-#include <linux/notifier.h>
-#include <linux/suspend.h>
-#include <mach/map.h>
#include <mach/regs-clock.h>
-#include <mach/regs-mem.h>
+#include <mach/cpufreq.h>
-#include <plat/clock.h>
-#include <plat/pm.h>
+#define CPUFREQ_LEVEL_END L5
+
+static int max_support_idx = L0;
+static int min_support_idx = (CPUFREQ_LEVEL_END - 1);
static struct clk *cpu_clk;
static struct clk *moutcore;
static struct clk *mout_mpll;
static struct clk *mout_apll;
-static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
-
-static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-static unsigned int locking_frequency;
-static bool frequency_locked;
-static DEFINE_MUTEX(cpufreq_lock);
-
-enum exynos4_memory_type {
- DDR2 = 4,
- LPDDR2,
- DDR3,
+struct cpufreq_clkdiv {
+ unsigned int index;
+ unsigned int clkdiv;
};
-enum cpufreq_level_index {
- L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+static unsigned int exynos4210_volt_table[CPUFREQ_LEVEL_END] = {
+ 1250000, 1150000, 1050000, 975000, 950000,
};
-static struct cpufreq_frequency_table exynos4_freq_table[] = {
- {L0, 1000*1000},
- {L1, 800*1000},
- {L2, 400*1000},
- {L3, 100*1000},
+
+static struct cpufreq_clkdiv exynos4210_clkdiv_table[CPUFREQ_LEVEL_END];
+
+static struct cpufreq_frequency_table exynos4210_freq_table[] = {
+ {L0, 1200*1000},
+ {L1, 1000*1000},
+ {L2, 800*1000},
+ {L3, 500*1000},
+ {L4, 200*1000},
{0, CPUFREQ_TABLE_END},
};
@@ -67,17 +58,20 @@ static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
* DIVATB, DIVPCLK_DBG, DIVAPLL }
*/
- /* ARM L0: 1000MHz */
- { 0, 3, 7, 3, 3, 0, 1 },
+ /* ARM L0: 1200MHz */
+ { 0, 3, 7, 3, 4, 1, 7 },
- /* ARM L1: 800MHz */
- { 0, 3, 7, 3, 3, 0, 1 },
+ /* ARM L1: 1000MHz */
+ { 0, 3, 7, 3, 4, 1, 7 },
- /* ARM L2: 400MHz */
- { 0, 1, 3, 1, 3, 0, 1 },
+ /* ARM L2: 800MHz */
+ { 0, 3, 7, 3, 3, 1, 7 },
- /* ARM L3: 100MHz */
- { 0, 0, 1, 0, 3, 1, 1 },
+ /* ARM L3: 500MHz */
+ { 0, 3, 7, 3, 3, 1, 7 },
+
+ /* ARM L4: 200MHz */
+ { 0, 1, 3, 1, 3, 1, 0 },
};
static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
@@ -86,147 +80,46 @@ static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
* { DIVCOPY, DIVHPM }
*/
- /* ARM L0: 1000MHz */
- { 3, 0 },
+ /* ARM L0: 1200MHz */
+ { 5, 0 },
- /* ARM L1: 800MHz */
- { 3, 0 },
+ /* ARM L1: 1000MHz */
+ { 4, 0 },
- /* ARM L2: 400MHz */
+ /* ARM L2: 800MHz */
{ 3, 0 },
- /* ARM L3: 100MHz */
+ /* ARM L3: 500MHz */
{ 3, 0 },
-};
-
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
- /*
- * Clock divider value for following
- * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
- * DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
- */
-
- /* DMC L0: 400MHz */
- { 3, 1, 1, 1, 1, 1, 3, 1 },
-
- /* DMC L1: 400MHz */
- { 3, 1, 1, 1, 1, 1, 3, 1 },
-
- /* DMC L2: 266.7MHz */
- { 7, 1, 1, 2, 1, 1, 3, 1 },
-
- /* DMC L3: 200MHz */
- { 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
- /*
- * Clock divider value for following
- * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
- */
- /* ACLK200 L0: 200MHz */
- { 3, 7, 4, 5, 1 },
-
- /* ACLK200 L1: 200MHz */
- { 3, 7, 4, 5, 1 },
-
- /* ACLK200 L2: 160MHz */
- { 4, 7, 5, 7, 1 },
-
- /* ACLK200 L3: 133.3MHz */
- { 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
- /*
- * Clock divider value for following
- * { DIVGDL/R, DIVGPL/R }
- */
-
- /* ACLK_GDL/R L0: 200MHz */
- { 3, 1 },
-
- /* ACLK_GDL/R L1: 200MHz */
- { 3, 1 },
-
- /* ACLK_GDL/R L2: 160MHz */
- { 4, 1 },
-
- /* ACLK_GDL/R L3: 133.3MHz */
- { 5, 1 },
-};
-
-struct cpufreq_voltage_table {
- unsigned int index; /* any */
- unsigned int arm_volt; /* uV */
- unsigned int int_volt;
+ /* ARM L4: 200MHz */
+ { 3, 0 },
};
-static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
- {
- .index = L0,
- .arm_volt = 1200000,
- .int_volt = 1100000,
- }, {
- .index = L1,
- .arm_volt = 1100000,
- .int_volt = 1100000,
- }, {
- .index = L2,
- .arm_volt = 1000000,
- .int_volt = 1000000,
- }, {
- .index = L3,
- .arm_volt = 900000,
- .int_volt = 1000000,
- },
-};
+static unsigned int exynos4210_apll_pms_table[CPUFREQ_LEVEL_END] = {
+ /* APLL FOUT L0: 1200MHz */
+ ((150 << 16) | (3 << 8) | 1),
-static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
- /* APLL FOUT L0: 1000MHz */
+ /* APLL FOUT L1: 1000MHz */
((250 << 16) | (6 << 8) | 1),
- /* APLL FOUT L1: 800MHz */
+ /* APLL FOUT L2: 800MHz */
((200 << 16) | (6 << 8) | 1),
- /* APLL FOUT L2 : 400MHz */
- ((200 << 16) | (6 << 8) | 2),
+ /* APLL FOUT L3: 500MHz */
+ ((250 << 16) | (6 << 8) | 2),
- /* APLL FOUT L3: 100MHz */
- ((200 << 16) | (6 << 8) | 4),
+ /* APLL FOUT L4: 200MHz */
+ ((200 << 16) | (6 << 8) | 3),
};
-static int exynos4_verify_speed(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
-}
-
-static unsigned int exynos4_getspeed(unsigned int cpu)
-{
- return clk_get_rate(cpu_clk) / 1000;
-}
-
-static void exynos4_set_clkdiv(unsigned int div_index)
+static void exynos4210_set_clkdiv(unsigned int div_index)
{
unsigned int tmp;
/* Change Divider - CPU0 */
- tmp = __raw_readl(S5P_CLKDIV_CPU);
-
- tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
- S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
- S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
- S5P_CLKDIV_CPU0_APLL_MASK);
-
- tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
- (clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
- (clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
- (clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
- (clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
- (clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
- (clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+ tmp = exynos4210_clkdiv_table[div_index].clkdiv;
__raw_writel(tmp, S5P_CLKDIV_CPU);
@@ -248,83 +141,9 @@ static void exynos4_set_clkdiv(unsigned int div_index)
do {
tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
} while (tmp & 0x11);
-
- /* Change Divider - DMC0 */
-
- tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
- tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
- S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
- S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
- S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
- tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
- (clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
- (clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
- (clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
- (clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
- (clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
- (clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
- (clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_DMC0);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
- } while (tmp & 0x11111111);
-
- /* Change Divider - TOP */
-
- tmp = __raw_readl(S5P_CLKDIV_TOP);
-
- tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
- S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
- S5P_CLKDIV_TOP_ONENAND_MASK);
-
- tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
- (clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
- (clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
- (clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
- (clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_TOP);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
- } while (tmp & 0x11111);
-
- /* Change Divider - LEFTBUS */
-
- tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
- tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
- tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
- (clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
- } while (tmp & 0x11);
-
- /* Change Divider - RIGHTBUS */
-
- tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
- tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
- tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
- (clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
- } while (tmp & 0x11);
}
-static void exynos4_set_apll(unsigned int index)
+static void exynos4210_set_apll(unsigned int index)
{
unsigned int tmp;
@@ -343,7 +162,7 @@ static void exynos4_set_apll(unsigned int index)
/* 3. Change PLL PMS values */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
- tmp |= exynos4_apll_pms_table[index];
+ tmp |= exynos4210_apll_pms_table[index];
__raw_writel(tmp, S5P_APLL_CON0);
/* 4. wait_lock_time */
@@ -360,328 +179,126 @@ static void exynos4_set_apll(unsigned int index)
} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
}
-static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
+bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
+{
+ unsigned int old_pm = (exynos4210_apll_pms_table[old_index] >> 8);
+ unsigned int new_pm = (exynos4210_apll_pms_table[new_index] >> 8);
+
+ return (old_pm == new_pm) ? 0 : 1;
+}
+
+static void exynos4210_set_frequency(unsigned int old_index,
+ unsigned int new_index)
{
unsigned int tmp;
if (old_index > new_index) {
- /* The frequency changing to L0 needs to change apll */
- if (freqs.new == exynos4_freq_table[L0].frequency) {
- /* 1. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
-
- /* 2. Change the apll m,p,s value */
- exynos4_set_apll(new_index);
- } else {
+ if (!exynos4210_pms_change(old_index, new_index)) {
/* 1. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
+ exynos4210_set_clkdiv(new_index);
/* 2. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~(0x7 << 0);
- tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+ tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
- }
- }
-
- else if (old_index < new_index) {
- /* The frequency changing from L0 needs to change apll */
- if (freqs.old == exynos4_freq_table[L0].frequency) {
- /* 1. Change the apll m,p,s value */
- exynos4_set_apll(new_index);
-
- /* 2. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
} else {
+ /* Clock Configuration Procedure */
+ /* 1. Change the system clock divider values */
+ exynos4210_set_clkdiv(new_index);
+ /* 2. Change the apll m,p,s value */
+ exynos4210_set_apll(new_index);
+ }
+ } else if (old_index < new_index) {
+ if (!exynos4210_pms_change(old_index, new_index)) {
/* 1. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~(0x7 << 0);
- tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+ tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
/* 2. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
+ exynos4210_set_clkdiv(new_index);
+ } else {
+ /* Clock Configuration Procedure */
+ /* 1. Change the apll m,p,s value */
+ exynos4210_set_apll(new_index);
+ /* 2. Change the system clock divider values */
+ exynos4210_set_clkdiv(new_index);
}
}
}
-static int exynos4_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- unsigned int index, old_index;
- unsigned int arm_volt, int_volt;
- int err = -EINVAL;
-
- freqs.old = exynos4_getspeed(policy->cpu);
-
- mutex_lock(&cpufreq_lock);
-
- if (frequency_locked && target_freq != locking_frequency) {
- err = -EAGAIN;
- goto out;
- }
-
- if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
- freqs.old, relation, &old_index))
- goto out;
-
- if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
- target_freq, relation, &index))
- goto out;
-
- err = 0;
-
- freqs.new = exynos4_freq_table[index].frequency;
- freqs.cpu = policy->cpu;
-
- if (freqs.new == freqs.old)
- goto out;
-
- /* get the voltage value */
- arm_volt = exynos4_volt_table[index].arm_volt;
- int_volt = exynos4_volt_table[index].int_volt;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* control regulator */
- if (freqs.new > freqs.old) {
- /* Voltage up */
- regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- regulator_set_voltage(int_regulator, int_volt, int_volt);
- }
-
- /* Clock Configuration Procedure */
- exynos4_set_frequency(old_index, index);
-
- /* control regulator */
- if (freqs.new < freqs.old) {
- /* Voltage down */
- regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- regulator_set_voltage(int_regulator, int_volt, int_volt);
- }
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-out:
- mutex_unlock(&cpufreq_lock);
- return err;
-}
-
-#ifdef CONFIG_PM
-/*
- * These suspend/resume are used as syscore_ops, it is already too
- * late to set regulator voltages at this stage.
- */
-static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
-{
- return 0;
-}
-
-static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
+int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
{
- return 0;
-}
-#endif
-
-/**
- * exynos4_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
- * context
- * @notifier
- * @pm_event
- * @v
- *
- * While frequency_locked == true, target() ignores every frequency but
- * locking_frequency. The locking_frequency value is the initial frequency,
- * which is set by the bootloader. In order to eliminate possible
- * inconsistency in clock values, we save and restore frequencies during
- * suspend and resume and block CPUFREQ activities. Note that the standard
- * suspend/resume cannot be used as they are too deep (syscore_ops) for
- * regulator actions.
- */
-static int exynos4_cpufreq_pm_notifier(struct notifier_block *notifier,
- unsigned long pm_event, void *v)
-{
- struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
- static unsigned int saved_frequency;
- unsigned int temp;
-
- mutex_lock(&cpufreq_lock);
- switch (pm_event) {
- case PM_SUSPEND_PREPARE:
- if (frequency_locked)
- goto out;
- frequency_locked = true;
-
- if (locking_frequency) {
- saved_frequency = exynos4_getspeed(0);
-
- mutex_unlock(&cpufreq_lock);
- exynos4_target(policy, locking_frequency,
- CPUFREQ_RELATION_H);
- mutex_lock(&cpufreq_lock);
- }
-
- break;
- case PM_POST_SUSPEND:
-
- if (saved_frequency) {
- /*
- * While frequency_locked, only locking_frequency
- * is valid for target(). In order to use
- * saved_frequency while keeping frequency_locked,
- * we temporarly overwrite locking_frequency.
- */
- temp = locking_frequency;
- locking_frequency = saved_frequency;
-
- mutex_unlock(&cpufreq_lock);
- exynos4_target(policy, locking_frequency,
- CPUFREQ_RELATION_H);
- mutex_lock(&cpufreq_lock);
-
- locking_frequency = temp;
- }
-
- frequency_locked = false;
- break;
- }
-out:
- mutex_unlock(&cpufreq_lock);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block exynos4_cpufreq_nb = {
- .notifier_call = exynos4_cpufreq_pm_notifier,
-};
-
-static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- int ret;
-
- policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
-
- cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
-
- /* set the transition latency value */
- policy->cpuinfo.transition_latency = 100000;
-
- /*
- * EXYNOS4 multi-core processors has 2 cores
- * that the frequency cannot be set independently.
- * Each cpu is bound to the same speed.
- * So the affected cpu is all of the cpus.
- */
- cpumask_setall(policy->cpus);
-
- ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
- if (ret)
- return ret;
-
- cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
-
- return 0;
-}
-
-static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
- cpufreq_frequency_table_put_attr(policy->cpu);
- return 0;
-}
-
-static struct freq_attr *exynos4_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver exynos4_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = exynos4_verify_speed,
- .target = exynos4_target,
- .get = exynos4_getspeed,
- .init = exynos4_cpufreq_cpu_init,
- .exit = exynos4_cpufreq_cpu_exit,
- .name = "exynos4_cpufreq",
- .attr = exynos4_cpufreq_attr,
-#ifdef CONFIG_PM
- .suspend = exynos4_cpufreq_suspend,
- .resume = exynos4_cpufreq_resume,
-#endif
-};
+ int i;
+ unsigned int tmp;
+ unsigned long rate;
-static int __init exynos4_cpufreq_init(void)
-{
cpu_clk = clk_get(NULL, "armclk");
if (IS_ERR(cpu_clk))
return PTR_ERR(cpu_clk);
- locking_frequency = exynos4_getspeed(0);
-
moutcore = clk_get(NULL, "moutcore");
if (IS_ERR(moutcore))
- goto out;
+ goto err_moutcore;
mout_mpll = clk_get(NULL, "mout_mpll");
if (IS_ERR(mout_mpll))
- goto out;
+ goto err_mout_mpll;
+
+ rate = clk_get_rate(mout_mpll) / 1000;
mout_apll = clk_get(NULL, "mout_apll");
if (IS_ERR(mout_apll))
- goto out;
+ goto err_mout_apll;
- arm_regulator = regulator_get(NULL, "vdd_arm");
- if (IS_ERR(arm_regulator)) {
- printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
- goto out;
- }
+ tmp = __raw_readl(S5P_CLKDIV_CPU);
- int_regulator = regulator_get(NULL, "vdd_int");
- if (IS_ERR(int_regulator)) {
- printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
- goto out;
+ for (i = L0; i < CPUFREQ_LEVEL_END; i++) {
+ tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK |
+ S5P_CLKDIV_CPU0_COREM0_MASK |
+ S5P_CLKDIV_CPU0_COREM1_MASK |
+ S5P_CLKDIV_CPU0_PERIPH_MASK |
+ S5P_CLKDIV_CPU0_ATB_MASK |
+ S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+ S5P_CLKDIV_CPU0_APLL_MASK);
+
+ tmp |= ((clkdiv_cpu0[i][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+ (clkdiv_cpu0[i][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+ (clkdiv_cpu0[i][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+ (clkdiv_cpu0[i][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+ (clkdiv_cpu0[i][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+ (clkdiv_cpu0[i][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+ (clkdiv_cpu0[i][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+ exynos4210_clkdiv_table[i].clkdiv = tmp;
}
- /*
- * Check DRAM type.
- * Because DVFS level is different according to DRAM type.
- */
- memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
- memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
- memtype &= S5P_DMC0_MEMTYPE_MASK;
-
- if ((memtype < DDR2) && (memtype > DDR3)) {
- printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
- goto out;
- } else {
- printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
- }
-
- register_pm_notifier(&exynos4_cpufreq_nb);
-
- return cpufreq_register_driver(&exynos4_driver);
-
-out:
- if (!IS_ERR(cpu_clk))
- clk_put(cpu_clk);
+ info->mpll_freq_khz = rate;
+ info->pm_lock_idx = L2;
+ info->pll_safe_idx = L2;
+ info->max_support_idx = max_support_idx;
+ info->min_support_idx = min_support_idx;
+ info->cpu_clk = cpu_clk;
+ info->volt_table = exynos4210_volt_table;
+ info->freq_table = exynos4210_freq_table;
+ info->set_freq = exynos4210_set_frequency;
+ info->need_apll_change = exynos4210_pms_change;
- if (!IS_ERR(moutcore))
- clk_put(moutcore);
+ return 0;
+err_mout_apll:
if (!IS_ERR(mout_mpll))
clk_put(mout_mpll);
+err_mout_mpll:
+ if (!IS_ERR(moutcore))
+ clk_put(moutcore);
+err_moutcore:
+ if (!IS_ERR(cpu_clk))
+ clk_put(cpu_clk);
- if (!IS_ERR(mout_apll))
- clk_put(mout_apll);
-
- if (!IS_ERR(arm_regulator))
- regulator_put(arm_regulator);
-
- if (!IS_ERR(int_regulator))
- regulator_put(int_regulator);
-
- printk(KERN_ERR "%s: failed initialization\n", __func__);
-
+ pr_debug("%s: failed initialization\n", __func__);
return -EINVAL;
}
-late_initcall(exynos4_cpufreq_init);
+EXPORT_SYMBOL(exynos4210_cpufreq_init);
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
new file mode 100644
index 0000000..5d04c57
--- /dev/null
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -0,0 +1,274 @@
+/*
+ * CPU frequency scaling for OMAP using OPP information
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
+ *
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/opp.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/smp_plat.h>
+#include <asm/cpu.h>
+
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+#include <plat/common.h>
+#include <plat/omap_device.h>
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_SMP
+struct lpj_info {
+ unsigned long ref;
+ unsigned int freq;
+};
+
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
+static struct lpj_info global_lpj_ref;
+#endif
+
+static struct cpufreq_frequency_table *freq_table;
+static atomic_t freq_table_users = ATOMIC_INIT(0);
+static struct clk *mpu_clk;
+static char *mpu_clk_name;
+static struct device *mpu_dev;
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ if (!freq_table)
+ return -EINVAL;
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static unsigned int omap_getspeed(unsigned int cpu)
+{
+ unsigned long rate;
+
+ if (cpu >= NR_CPUS)
+ return 0;
+
+ rate = clk_get_rate(mpu_clk) / 1000;
+ return rate;
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int i;
+ int ret = 0;
+ struct cpufreq_freqs freqs;
+
+ if (!freq_table) {
+ dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
+ policy->cpu);
+ return -EINVAL;
+ }
+
+ ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
+ relation, &i);
+ if (ret) {
+ dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
+ __func__, policy->cpu, target_freq, ret);
+ return ret;
+ }
+ freqs.new = freq_table[i].frequency;
+ if (!freqs.new) {
+ dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
+ policy->cpu, target_freq);
+ return -EINVAL;
+ }
+
+ freqs.old = omap_getspeed(policy->cpu);
+ freqs.cpu = policy->cpu;
+
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
+ return ret;
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
+#endif
+
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ freqs.new = omap_getspeed(policy->cpu);
+
+#ifdef CONFIG_SMP
+ /*
+ * Note that loops_per_jiffy is not updated on SMP systems in
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
+ * on frequency transition. We need to update all dependent CPUs.
+ */
+ for_each_cpu(i, policy->cpus) {
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
+ if (!lpj->freq) {
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
+ lpj->freq = freqs.old;
+ }
+
+ per_cpu(cpu_data, i).loops_per_jiffy =
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
+ }
+
+ /* And don't forget to adjust the global one */
+ if (!global_lpj_ref.freq) {
+ global_lpj_ref.ref = loops_per_jiffy;
+ global_lpj_ref.freq = freqs.old;
+ }
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
+ freqs.new);
+#endif
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
+ return ret;
+}
+
+static inline void freq_table_free(void)
+{
+ if (atomic_dec_and_test(&freq_table_users))
+ opp_free_cpufreq_table(mpu_dev, &freq_table);
+}
+
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+{
+ int result = 0;
+
+ mpu_clk = clk_get(NULL, mpu_clk_name);
+ if (IS_ERR(mpu_clk))
+ return PTR_ERR(mpu_clk);
+
+ if (policy->cpu >= NR_CPUS) {
+ result = -EINVAL;
+ goto fail_ck;
+ }
+
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
+
+ if (atomic_inc_return(&freq_table_users) == 1)
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ if (result) {
+ dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
+ __func__, policy->cpu, result);
+ goto fail_ck;
+ }
+
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (result)
+ goto fail_table;
+
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(policy->cpu);
+
+ /*
+ * On OMAP SMP configuartion, both processors share the voltage
+ * and clock. So both CPUs needs to be scaled together and hence
+ * needs software co-ordination. Use cpufreq affected_cpus
+ * interface to handle this scenario. Additional is_smp() check
+ * is to keep SMP_ON_UP build working.
+ */
+ if (is_smp()) {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+ cpumask_setall(policy->cpus);
+ }
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 300 * 1000;
+
+ return 0;
+
+fail_table:
+ freq_table_free();
+fail_ck:
+ clk_put(mpu_clk);
+ return result;
+}
+
+static int omap_cpu_exit(struct cpufreq_policy *policy)
+{
+ freq_table_free();
+ clk_put(mpu_clk);
+ return 0;
+}
+
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver omap_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = omap_verify_speed,
+ .target = omap_target,
+ .get = omap_getspeed,
+ .init = omap_cpu_init,
+ .exit = omap_cpu_exit,
+ .name = "omap",
+ .attr = omap_cpufreq_attr,
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ if (cpu_is_omap24xx())
+ mpu_clk_name = "virt_prcm_set";
+ else if (cpu_is_omap34xx())
+ mpu_clk_name = "dpll1_ck";
+ else if (cpu_is_omap44xx())
+ mpu_clk_name = "dpll_mpu_ck";
+
+ if (!mpu_clk_name) {
+ pr_err("%s: unsupported Silicon?\n", __func__);
+ return -EINVAL;
+ }
+
+ mpu_dev = omap_device_get_by_hwmod_name("mpu");
+ if (!mpu_dev) {
+ pr_warning("%s: unable to get the mpu device\n", __func__);
+ return -EINVAL;
+ }
+
+ return cpufreq_register_driver(&omap_driver);
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+}
+
+MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
+MODULE_LICENSE("GPL");
+module_init(omap_cpufreq_init);
+module_exit(omap_cpufreq_exit);
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index bce576d..8f9b2cee 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1,10 +1,11 @@
/*
- * (c) 2003-2010 Advanced Micro Devices, Inc.
+ * (c) 2003-2012 Advanced Micro Devices, Inc.
* Your use of this code is subject to the terms and conditions of the
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
- * Support : mark.langsdorf@amd.com
+ * Maintainer:
+ * Andreas Herrmann <andreas.herrmann3@amd.com>
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -16,12 +17,14 @@
* Valuable input gratefully received from Dave Jones, Pavel Machek,
* Dominik Brodowski, Jacob Shin, and others.
* Originally developed by Paul Devriendt.
- * Processor information obtained from Chapter 9 (Power and Thermal Management)
- * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
- * Opteron Processors" available for download from www.amd.com
*
- * Tables for specific CPUs can be inferred from
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
+ * Processor information obtained from Chapter 9 (Power and Thermal
+ * Management) of the "BIOS and Kernel Developer's Guide (BKDG) for
+ * the AMD Athlon 64 and AMD Opteron Processors" and section "2.x
+ * Power Management" in BKDGs for newer AMD CPU families.
+ *
+ * Tables for specific CPUs can be inferred from AMD's processor
+ * power and thermal data sheets, (e.g. 30417.pdf, 30430.pdf, 43375.pdf)
*/
#include <linux/kernel.h>
@@ -54,6 +57,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
static int cpu_family = CPU_OPTERON;
+/* array to map SW pstate number to acpi state */
+static u32 ps_to_as[8];
+
/* core performance boost */
static bool cpb_capable, cpb_enabled;
static struct msr __percpu *msrs;
@@ -80,9 +86,9 @@ static u32 find_khz_freq_from_fid(u32 fid)
}
static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
- u32 pstate)
+ u32 pstate)
{
- return data[pstate].frequency;
+ return data[ps_to_as[pstate]].frequency;
}
/* Return the vco fid for an input fid
@@ -926,23 +932,27 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
invalidate_entry(powernow_table, i);
continue;
}
- rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
- if (!(hi & HW_PSTATE_VALID_MASK)) {
- pr_debug("invalid pstate %d, ignoring\n", index);
- invalidate_entry(powernow_table, i);
- continue;
- }
- powernow_table[i].index = index;
+ ps_to_as[index] = i;
/* Frequency may be rounded for these */
if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
|| boot_cpu_data.x86 == 0x11) {
+
+ rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
+ if (!(hi & HW_PSTATE_VALID_MASK)) {
+ pr_debug("invalid pstate %d, ignoring\n", index);
+ invalidate_entry(powernow_table, i);
+ continue;
+ }
+
powernow_table[i].frequency =
freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
} else
powernow_table[i].frequency =
data->acpi_data.states[i].core_frequency * 1000;
+
+ powernow_table[i].index = index;
}
return 0;
}
@@ -1189,7 +1199,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
powernow_k8_acpi_pst_values(data, newstate);
if (cpu_family == CPU_HW_PSTATE)
- ret = transition_frequency_pstate(data, newstate);
+ ret = transition_frequency_pstate(data,
+ data->powernow_table[newstate].index);
else
ret = transition_frequency_fidvid(data, newstate);
if (ret) {
@@ -1202,7 +1213,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_pstate(data->powernow_table,
- newstate);
+ data->powernow_table[newstate].index);
else
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 3475f65..a5e72cb 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -8,6 +8,8 @@
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) "cpufreq: " fmt
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
@@ -91,7 +93,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
if (freqs.old == freqs.new)
return 0;
- pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
+ pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -101,7 +103,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
dvfs->vddarm_min,
dvfs->vddarm_max);
if (ret != 0) {
- pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+ pr_err("Failed to set VDDARM for %dkHz: %d\n",
freqs.new, ret);
goto err;
}
@@ -110,7 +112,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
ret = clk_set_rate(armclk, freqs.new * 1000);
if (ret < 0) {
- pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
+ pr_err("Failed to set rate %dkHz: %d\n",
freqs.new, ret);
goto err;
}
@@ -123,14 +125,14 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
dvfs->vddarm_min,
dvfs->vddarm_max);
if (ret != 0) {
- pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+ pr_err("Failed to set VDDARM for %dkHz: %d\n",
freqs.new, ret);
goto err_clk;
}
}
#endif
- pr_debug("cpufreq: Set actual frequency %lukHz\n",
+ pr_debug("Set actual frequency %lukHz\n",
clk_get_rate(armclk) / 1000);
return 0;
@@ -153,7 +155,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
count = regulator_count_voltages(vddarm);
if (count < 0) {
- pr_err("cpufreq: Unable to check supported voltages\n");
+ pr_err("Unable to check supported voltages\n");
}
freq = s3c64xx_freq_table;
@@ -171,7 +173,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
}
if (!found) {
- pr_debug("cpufreq: %dkHz unsupported by regulator\n",
+ pr_debug("%dkHz unsupported by regulator\n",
freq->frequency);
freq->frequency = CPUFREQ_ENTRY_INVALID;
}
@@ -194,13 +196,13 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
return -EINVAL;
if (s3c64xx_freq_table == NULL) {
- pr_err("cpufreq: No frequency information for this CPU\n");
+ pr_err("No frequency information for this CPU\n");
return -ENODEV;
}
armclk = clk_get(NULL, "armclk");
if (IS_ERR(armclk)) {
- pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
+ pr_err("Unable to obtain ARMCLK: %ld\n",
PTR_ERR(armclk));
return PTR_ERR(armclk);
}
@@ -209,12 +211,19 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
vddarm = regulator_get(NULL, "vddarm");
if (IS_ERR(vddarm)) {
ret = PTR_ERR(vddarm);
- pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
- pr_err("cpufreq: Only frequency scaling available\n");
+ pr_err("Failed to obtain VDDARM: %d\n", ret);
+ pr_err("Only frequency scaling available\n");
vddarm = NULL;
} else {
s3c64xx_cpufreq_config_regulator();
}
+
+ vddint = regulator_get(NULL, "vddint");
+ if (IS_ERR(vddint)) {
+ ret = PTR_ERR(vddint);
+ pr_err("Failed to obtain VDDINT: %d\n", ret);
+ vddint = NULL;
+ }
#endif
freq = s3c64xx_freq_table;
@@ -225,7 +234,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
r = clk_round_rate(armclk, freq->frequency * 1000);
r /= 1000;
if (r != freq->frequency) {
- pr_debug("cpufreq: %dkHz unsupported by clock\n",
+ pr_debug("%dkHz unsupported by clock\n",
freq->frequency);
freq->frequency = CPUFREQ_ENTRY_INVALID;
}
@@ -248,7 +257,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
if (ret != 0) {
- pr_err("cpufreq: Failed to configure frequency table: %d\n",
+ pr_err("Failed to configure frequency table: %d\n",
ret);
regulator_put(vddarm);
clk_put(armclk);
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 1d103f9..13f8e1a 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1292,18 +1292,7 @@ static struct platform_driver crypto4xx_driver = {
.remove = crypto4xx_remove,
};
-static int __init crypto4xx_init(void)
-{
- return platform_driver_register(&crypto4xx_driver);
-}
-
-static void __exit crypto4xx_exit(void)
-{
- platform_driver_unregister(&crypto4xx_driver);
-}
-
-module_init(crypto4xx_init);
-module_exit(crypto4xx_exit);
+module_platform_driver(crypto4xx_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>");
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 4159265..e73cf2e 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -113,7 +113,7 @@ static inline void append_dec_shr_done(u32 *desc)
jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
set_jump_tgt_here(desc, jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
/*
@@ -213,7 +213,7 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
static int aead_set_sh_desc(struct crypto_aead *aead)
@@ -310,7 +310,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
/* Only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* Class 2 operation */
@@ -683,7 +683,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
/* Load iv */
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
@@ -724,7 +724,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* For aead, only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* load IV */
@@ -1806,6 +1806,25 @@ struct caam_alg_template {
static struct caam_alg_template driver_algs[] = {
/* single-pass ipsec_esp descriptor */
{
+ .name = "authenc(hmac(md5),cbc(aes))",
+ .driver_name = "authenc-hmac-md5-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(aes))",
.driver_name = "authenc-hmac-sha1-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1865,6 +1884,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1924,6 +1962,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des))",
+ .driver_name = "authenc-hmac-md5-cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des))",
.driver_name = "authenc-hmac-sha1-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index d38f2af..a63bc65 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -28,6 +28,7 @@
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/sha.h>
+#include <crypto/md5.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 73988bb..8ae3ba2 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -52,8 +52,6 @@ static int caam_probe(struct platform_device *pdev)
struct caam_ctrl __iomem *ctrl;
struct caam_full __iomem *topregs;
struct caam_drv_private *ctrlpriv;
- struct caam_deco **deco;
- u32 deconum;
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
#endif
@@ -92,17 +90,6 @@ static int caam_probe(struct platform_device *pdev)
if (sizeof(dma_addr_t) == sizeof(u64))
dma_set_mask(dev, DMA_BIT_MASK(36));
- /* Find out how many DECOs are present */
- deconum = (rd_reg64(&topregs->ctrl.perfmon.cha_num) &
- CHA_NUM_DECONUM_MASK) >> CHA_NUM_DECONUM_SHIFT;
-
- ctrlpriv->deco = kmalloc(deconum * sizeof(struct caam_deco *),
- GFP_KERNEL);
-
- deco = (struct caam_deco __force **)&topregs->deco;
- for (d = 0; d < deconum; d++)
- ctrlpriv->deco[d] = deco[d];
-
/*
* Detect and enable JobRs
* First, find out how many ring spec'ed, allocate references
@@ -253,18 +240,7 @@ static struct platform_driver caam_driver = {
.remove = __devexit_p(caam_remove),
};
-static int __init caam_base_init(void)
-{
- return platform_driver_register(&caam_driver);
-}
-
-static void __exit caam_base_exit(void)
-{
- return platform_driver_unregister(&caam_driver);
-}
-
-module_init(caam_base_init);
-module_exit(caam_base_exit);
+module_platform_driver(caam_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("FSL CAAM request backend");
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 974a758..a17c295 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -9,7 +9,7 @@
#define DESC_H
/* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
-#define MAX_CAAM_DESCSIZE 64
+#define MAX_CAAM_DESCSIZE 64
/* Block size of any entity covered/uncovered with a KEK/TKEK */
#define KEK_BLOCKSIZE 16
@@ -18,38 +18,38 @@
* Supported descriptor command types as they show up
* inside a descriptor command word.
*/
-#define CMD_SHIFT 27
-#define CMD_MASK 0xf8000000
-
-#define CMD_KEY (0x00 << CMD_SHIFT)
-#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
-#define CMD_LOAD (0x02 << CMD_SHIFT)
-#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
-#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
-#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
-#define CMD_STORE (0x0a << CMD_SHIFT)
-#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
-#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
-#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
-#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
-#define CMD_MOVE (0x0f << CMD_SHIFT)
-#define CMD_OPERATION (0x10 << CMD_SHIFT)
-#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
-#define CMD_JUMP (0x14 << CMD_SHIFT)
-#define CMD_MATH (0x15 << CMD_SHIFT)
-#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
-#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
-#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
-#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
+#define CMD_SHIFT 27
+#define CMD_MASK 0xf8000000
+
+#define CMD_KEY (0x00 << CMD_SHIFT)
+#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
+#define CMD_LOAD (0x02 << CMD_SHIFT)
+#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
+#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
+#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
+#define CMD_STORE (0x0a << CMD_SHIFT)
+#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
+#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
+#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
+#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
+#define CMD_MOVE (0x0f << CMD_SHIFT)
+#define CMD_OPERATION (0x10 << CMD_SHIFT)
+#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
+#define CMD_JUMP (0x14 << CMD_SHIFT)
+#define CMD_MATH (0x15 << CMD_SHIFT)
+#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
+#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
+#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
+#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
/* General-purpose class selector for all commands */
-#define CLASS_SHIFT 25
-#define CLASS_MASK (0x03 << CLASS_SHIFT)
+#define CLASS_SHIFT 25
+#define CLASS_MASK (0x03 << CLASS_SHIFT)
-#define CLASS_NONE (0x00 << CLASS_SHIFT)
-#define CLASS_1 (0x01 << CLASS_SHIFT)
-#define CLASS_2 (0x02 << CLASS_SHIFT)
-#define CLASS_BOTH (0x03 << CLASS_SHIFT)
+#define CLASS_NONE (0x00 << CLASS_SHIFT)
+#define CLASS_1 (0x01 << CLASS_SHIFT)
+#define CLASS_2 (0x02 << CLASS_SHIFT)
+#define CLASS_BOTH (0x03 << CLASS_SHIFT)
/*
* Descriptor header command constructs
@@ -60,82 +60,82 @@
* Do Not Run - marks a descriptor inexecutable if there was
* a preceding error somewhere
*/
-#define HDR_DNR 0x01000000
+#define HDR_DNR 0x01000000
/*
* ONE - should always be set. Combination of ONE (always
* set) and ZRO (always clear) forms an endianness sanity check
*/
-#define HDR_ONE 0x00800000
-#define HDR_ZRO 0x00008000
+#define HDR_ONE 0x00800000
+#define HDR_ZRO 0x00008000
/* Start Index or SharedDesc Length */
-#define HDR_START_IDX_MASK 0x3f
-#define HDR_START_IDX_SHIFT 16
+#define HDR_START_IDX_MASK 0x3f
+#define HDR_START_IDX_SHIFT 16
/* If shared descriptor header, 6-bit length */
-#define HDR_DESCLEN_SHR_MASK 0x3f
+#define HDR_DESCLEN_SHR_MASK 0x3f
/* If non-shared header, 7-bit length */
-#define HDR_DESCLEN_MASK 0x7f
+#define HDR_DESCLEN_MASK 0x7f
/* This is a TrustedDesc (if not SharedDesc) */
-#define HDR_TRUSTED 0x00004000
+#define HDR_TRUSTED 0x00004000
/* Make into TrustedDesc (if not SharedDesc) */
-#define HDR_MAKE_TRUSTED 0x00002000
+#define HDR_MAKE_TRUSTED 0x00002000
/* Save context if self-shared (if SharedDesc) */
-#define HDR_SAVECTX 0x00001000
+#define HDR_SAVECTX 0x00001000
/* Next item points to SharedDesc */
-#define HDR_SHARED 0x00001000
+#define HDR_SHARED 0x00001000
/*
* Reverse Execution Order - execute JobDesc first, then
* execute SharedDesc (normally SharedDesc goes first).
*/
-#define HDR_REVERSE 0x00000800
+#define HDR_REVERSE 0x00000800
/* Propogate DNR property to SharedDesc */
-#define HDR_PROP_DNR 0x00000800
+#define HDR_PROP_DNR 0x00000800
/* JobDesc/SharedDesc share property */
-#define HDR_SD_SHARE_MASK 0x03
-#define HDR_SD_SHARE_SHIFT 8
-#define HDR_JD_SHARE_MASK 0x07
-#define HDR_JD_SHARE_SHIFT 8
+#define HDR_SD_SHARE_MASK 0x03
+#define HDR_SD_SHARE_SHIFT 8
+#define HDR_JD_SHARE_MASK 0x07
+#define HDR_JD_SHARE_SHIFT 8
-#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
/* JobDesc/SharedDesc descriptor length */
-#define HDR_JD_LENGTH_MASK 0x7f
-#define HDR_SD_LENGTH_MASK 0x3f
+#define HDR_JD_LENGTH_MASK 0x7f
+#define HDR_SD_LENGTH_MASK 0x3f
/*
* KEY/SEQ_KEY Command Constructs
*/
-/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
-#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
-#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
+/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
+#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
+#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define KEY_SGF 0x01000000
-#define KEY_VLF 0x01000000
+#define KEY_SGF 0x01000000
+#define KEY_VLF 0x01000000
/* Immediate - Key follows command in the descriptor */
-#define KEY_IMM 0x00800000
+#define KEY_IMM 0x00800000
/*
* Encrypted - Key is encrypted either with the KEK, or
* with the TDKEK if TK is set
*/
-#define KEY_ENC 0x00400000
+#define KEY_ENC 0x00400000
/*
* No Write Back - Do not allow key to be FIFO STOREd
@@ -156,16 +156,16 @@
* KDEST - Key Destination: 0 - class key register,
* 1 - PKHA 'e', 2 - AFHA Sbox, 3 - MDHA split-key
*/
-#define KEY_DEST_SHIFT 16
-#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_SHIFT 16
+#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
-#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
-#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
-#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
-#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
+#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
+#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
+#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
/* Length in bytes */
-#define KEY_LENGTH_MASK 0x000003ff
+#define KEY_LENGTH_MASK 0x000003ff
/*
* LOAD/SEQ_LOAD/STORE/SEQ_STORE Command Constructs
@@ -175,25 +175,25 @@
* Load/Store Destination: 0 = class independent CCB,
* 1 = class 1 CCB, 2 = class 2 CCB, 3 = DECO
*/
-#define LDST_CLASS_SHIFT 25
-#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_SHIFT 25
+#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define LDST_SGF 0x01000000
+#define LDST_SGF 0x01000000
#define LDST_VLF LDST_SGF
-/* Immediate - Key follows this command in descriptor */
-#define LDST_IMM_MASK 1
-#define LDST_IMM_SHIFT 23
-#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
+/* Immediate - Key follows this command in descriptor */
+#define LDST_IMM_MASK 1
+#define LDST_IMM_SHIFT 23
+#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
-/* SRC/DST - Destination for LOAD, Source for STORE */
-#define LDST_SRCDST_SHIFT 16
-#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
+/* SRC/DST - Destination for LOAD, Source for STORE */
+#define LDST_SRCDST_SHIFT 16
+#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_CONTEXT (0x20 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_KEY (0x40 << LDST_SRCDST_SHIFT)
@@ -205,64 +205,64 @@
#define LDST_SRCDST_WORD_DATASZ_REG (0x02 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_ICVSZ_REG (0x03 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CHACTRL (0x06 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_IRQCTRL (0x07 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CLRW (0x08 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_STAT (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
-
-/* Offset in source/destination */
-#define LDST_OFFSET_SHIFT 8
-#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
+
+/* Offset in source/destination */
+#define LDST_OFFSET_SHIFT 8
+#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
/* LDOFF definitions used when DST = LDST_SRCDST_WORD_DECOCTRL */
/* These could also be shifted by LDST_OFFSET_SHIFT - this reads better */
-#define LDOFF_CHG_SHARE_SHIFT 0
-#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_NO_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
-
-#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
-#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
-
-#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
-#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-
-#define LDOFF_CHG_SEQLIODN_SHIFT 6
-#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-
-/* Data length in bytes */
-#define LDST_LEN_SHIFT 0
-#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
+#define LDOFF_CHG_SHARE_SHIFT 0
+#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_NO_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
+
+#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
+#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
+
+#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
+#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+
+#define LDOFF_CHG_SEQLIODN_SHIFT 6
+#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+
+/* Data length in bytes */
+#define LDST_LEN_SHIFT 0
+#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
/* Special Length definitions when dst=deco-ctrl */
-#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
-#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
-#define LDLEN_RST_OFIFO (1 << 5)
-#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
-#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
-#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
-#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
+#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
+#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
+#define LDLEN_RST_OFIFO (1 << 5)
+#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
+#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
+#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
+#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
/*
* FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
@@ -274,808 +274,808 @@
* 1 = Load for Class1, 2 = Load for Class2, 3 = Load both
* Store Source: 0 = normal, 1 = Class1key, 2 = Class2key
*/
-#define FIFOLD_CLASS_SHIFT 25
-#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
-
-#define FIFOST_CLASS_SHIFT 25
-#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
+#define FIFOLD_CLASS_SHIFT 25
+#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
+
+#define FIFOST_CLASS_SHIFT 25
+#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
/*
* Scatter-Gather Table/Variable Length Field
* If set for FIFO_LOAD, refers to a SG table. Within
* SEQ_FIFO_LOAD, is variable input sequence
*/
-#define FIFOLDST_SGF_SHIFT 24
-#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF_SHIFT 24
+#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
/* Immediate - Data follows command in descriptor */
-#define FIFOLD_IMM_SHIFT 23
-#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
-#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM_SHIFT 23
+#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
/* Continue - Not the last FIFO store to come */
-#define FIFOST_CONT_SHIFT 23
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_SHIFT 23
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
/*
* Extended Length - use 32-bit extended length that
* follows the pointer field. Illegal with IMM set
*/
-#define FIFOLDST_EXT_SHIFT 22
-#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
-#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT_SHIFT 22
+#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
/* Input data type.*/
-#define FIFOLD_TYPE_SHIFT 16
-#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
-#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_SHIFT 16
+#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
+#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
/* PK types */
-#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_PK_TYPEMASK (0x0f << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
/* Other types. Need to OR in last/flush bits as desired */
-#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
/* Last/Flush bits for use with "other" types above */
-#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLDST_LEN_MASK 0xffff
-#define FIFOLDST_EXT_LEN_MASK 0xffffffff
+#define FIFOLDST_LEN_MASK 0xffff
+#define FIFOLDST_EXT_LEN_MASK 0xffffffff
/* Output data types */
-#define FIFOST_TYPE_SHIFT 16
-#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
-
-#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SHIFT 16
+#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
+
+#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_OUTFIFO_TKEK (0x29 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
/*
* OPERATION Command Constructs
*/
/* Operation type selectors - OP TYPE */
-#define OP_TYPE_SHIFT 24
-#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_SHIFT 24
+#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
-#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
-#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
-#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
-#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
+#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
+#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
+#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
/* ProtocolID selectors - PROTID */
-#define OP_PCLID_SHIFT 16
-#define OP_PCLID_MASK (0xff << 16)
+#define OP_PCLID_SHIFT 16
+#define OP_PCLID_MASK (0xff << 16)
/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
-#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
-#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
-#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
-#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
-#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
+#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
+#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
+#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
-#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
/*
* ProtocolInfo selectors
*/
-#define OP_PCLINFO_MASK 0xffff
+#define OP_PCLINFO_MASK 0xffff
/* for OP_PCLID_IPSEC */
-#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
-#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
-
-#define OP_PCL_IPSEC_DES_IV64 0x0100
-#define OP_PCL_IPSEC_DES 0x0200
-#define OP_PCL_IPSEC_3DES 0x0300
-#define OP_PCL_IPSEC_AES_CBC 0x0c00
-#define OP_PCL_IPSEC_AES_CTR 0x0d00
-#define OP_PCL_IPSEC_AES_XTS 0x1600
-#define OP_PCL_IPSEC_AES_CCM8 0x0e00
-#define OP_PCL_IPSEC_AES_CCM12 0x0f00
-#define OP_PCL_IPSEC_AES_CCM16 0x1000
-#define OP_PCL_IPSEC_AES_GCM8 0x1200
-#define OP_PCL_IPSEC_AES_GCM12 0x1300
-#define OP_PCL_IPSEC_AES_GCM16 0x1400
-
-#define OP_PCL_IPSEC_HMAC_NULL 0x0000
-#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
-#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
-#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
-#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
-#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
-#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
-#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
-#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
+#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
+#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
+
+#define OP_PCL_IPSEC_DES_IV64 0x0100
+#define OP_PCL_IPSEC_DES 0x0200
+#define OP_PCL_IPSEC_3DES 0x0300
+#define OP_PCL_IPSEC_AES_CBC 0x0c00
+#define OP_PCL_IPSEC_AES_CTR 0x0d00
+#define OP_PCL_IPSEC_AES_XTS 0x1600
+#define OP_PCL_IPSEC_AES_CCM8 0x0e00
+#define OP_PCL_IPSEC_AES_CCM12 0x0f00
+#define OP_PCL_IPSEC_AES_CCM16 0x1000
+#define OP_PCL_IPSEC_AES_GCM8 0x1200
+#define OP_PCL_IPSEC_AES_GCM12 0x1300
+#define OP_PCL_IPSEC_AES_GCM16 0x1400
+
+#define OP_PCL_IPSEC_HMAC_NULL 0x0000
+#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
+#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
+#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
+#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
+#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
+#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
+#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
+#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
/* For SRTP - OP_PCLID_SRTP */
-#define OP_PCL_SRTP_CIPHER_MASK 0xff00
-#define OP_PCL_SRTP_AUTH_MASK 0x00ff
+#define OP_PCL_SRTP_CIPHER_MASK 0xff00
+#define OP_PCL_SRTP_AUTH_MASK 0x00ff
-#define OP_PCL_SRTP_AES_CTR 0x0d00
+#define OP_PCL_SRTP_AES_CTR 0x0d00
-#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
+#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
/* For SSL 3.0 - OP_PCLID_SSL30 */
-#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
-#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
-#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
-
-#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
-#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
-#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
-#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
-#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
-#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
-#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
-#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_SSL30_RC4_128_MD5 0x0024
-#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
-#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_SSL30_RC4_40_MD5 0x002b
-#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
-#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_SSL30_RC4_128_SHA 0x0020
-#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
-#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
-#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
-#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
-#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
-#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
-#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
-#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
-#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_SSL30_RC4_40_SHA 0x0028
+#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
+#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
+#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
+
+#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
+#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
+#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
+#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
+#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
+#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
+#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
+#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_SSL30_RC4_128_MD5 0x0024
+#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
+#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_SSL30_RC4_40_MD5 0x002b
+#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
+#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_SSL30_RC4_128_SHA 0x0020
+#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
+#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
+#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
+#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
+#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
+#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
+#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
+#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
+#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_SSL30_RC4_40_SHA 0x0028
/* For TLS 1.0 - OP_PCLID_TLS10 */
-#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS10_RC4_128_MD5 0x0024
-#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS10_RC4_40_MD5 0x002b
-#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS10_RC4_128_SHA 0x0020
-#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS10_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS10_RC4_128_MD5 0x0024
+#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS10_RC4_40_MD5 0x002b
+#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS10_RC4_128_SHA 0x0020
+#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS10_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
/* For TLS 1.1 - OP_PCLID_TLS11 */
-#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS11_RC4_128_MD5 0x0024
-#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS11_RC4_40_MD5 0x002b
-#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS11_RC4_128_SHA 0x0020
-#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS11_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS11_RC4_128_MD5 0x0024
+#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS11_RC4_40_MD5 0x002b
+#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS11_RC4_128_SHA 0x0020
+#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS11_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
/* For TLS 1.2 - OP_PCLID_TLS12 */
-#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS12_RC4_128_MD5 0x0024
-#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS12_RC4_40_MD5 0x002b
-#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS12_RC4_128_SHA 0x0020
-#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS12_RC4_40_SHA 0x0028
-
-/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
-
-/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
+#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS12_RC4_128_MD5 0x0024
+#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS12_RC4_40_MD5 0x002b
+#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS12_RC4_128_SHA 0x0020
+#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS12_RC4_40_SHA 0x0028
+
+/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
+
+/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
/* AEAD_AES_xxx_CCM/GCM remain to be defined... */
-#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
/* For DTLS - OP_PCLID_DTLS */
-#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
-#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
-#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
-
-#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
-#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
-#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
-#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
-#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
-#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
-#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
-#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
-
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
+#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
+#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
+
+#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
+#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
+#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
+#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
+#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
+#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
+#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
+#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
+
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
/* 802.16 WiMAX protinfos */
-#define OP_PCL_WIMAX_OFDM 0x0201
-#define OP_PCL_WIMAX_OFDMA 0x0231
+#define OP_PCL_WIMAX_OFDM 0x0201
+#define OP_PCL_WIMAX_OFDMA 0x0231
/* 802.11 WiFi protinfos */
-#define OP_PCL_WIFI 0xac04
+#define OP_PCL_WIFI 0xac04
/* MacSec protinfos */
-#define OP_PCL_MACSEC 0x0001
+#define OP_PCL_MACSEC 0x0001
/* PKI unidirectional protocol protinfo bits */
-#define OP_PCL_PKPROT_TEST 0x0008
-#define OP_PCL_PKPROT_DECRYPT 0x0004
-#define OP_PCL_PKPROT_ECC 0x0002
-#define OP_PCL_PKPROT_F2M 0x0001
+#define OP_PCL_PKPROT_TEST 0x0008
+#define OP_PCL_PKPROT_DECRYPT 0x0004
+#define OP_PCL_PKPROT_ECC 0x0002
+#define OP_PCL_PKPROT_F2M 0x0001
/* For non-protocol/alg-only op commands */
#define OP_ALG_TYPE_SHIFT 24
@@ -1181,114 +1181,114 @@
#define OP_ALG_ENCRYPT 1
/* PKHA algorithm type set */
-#define OP_ALG_PK 0x00800000
-#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
+#define OP_ALG_PK 0x00800000
+#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
/* PKHA mode clear memory functions */
-#define OP_ALG_PKMODE_A_RAM 0x80000
-#define OP_ALG_PKMODE_B_RAM 0x40000
-#define OP_ALG_PKMODE_E_RAM 0x20000
-#define OP_ALG_PKMODE_N_RAM 0x10000
-#define OP_ALG_PKMODE_CLEARMEM 0x00001
+#define OP_ALG_PKMODE_A_RAM 0x80000
+#define OP_ALG_PKMODE_B_RAM 0x40000
+#define OP_ALG_PKMODE_E_RAM 0x20000
+#define OP_ALG_PKMODE_N_RAM 0x10000
+#define OP_ALG_PKMODE_CLEARMEM 0x00001
/* PKHA mode modular-arithmetic functions */
-#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
-#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
-#define OP_ALG_PKMODE_MOD_F2M 0x20000
-#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
-#define OP_ALG_PKMODE_PRJECTV 0x00800
-#define OP_ALG_PKMODE_TIME_EQ 0x400
-#define OP_ALG_PKMODE_OUT_B 0x000
-#define OP_ALG_PKMODE_OUT_A 0x100
-#define OP_ALG_PKMODE_MOD_ADD 0x002
-#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
-#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
-#define OP_ALG_PKMODE_MOD_MULT 0x005
-#define OP_ALG_PKMODE_MOD_EXPO 0x006
-#define OP_ALG_PKMODE_MOD_REDUCT 0x007
-#define OP_ALG_PKMODE_MOD_INV 0x008
-#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
-#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
-#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
-#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
-#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
-#define OP_ALG_PKMODE_MOD_GCD 0x00e
-#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
+#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
+#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
+#define OP_ALG_PKMODE_MOD_F2M 0x20000
+#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
+#define OP_ALG_PKMODE_PRJECTV 0x00800
+#define OP_ALG_PKMODE_TIME_EQ 0x400
+#define OP_ALG_PKMODE_OUT_B 0x000
+#define OP_ALG_PKMODE_OUT_A 0x100
+#define OP_ALG_PKMODE_MOD_ADD 0x002
+#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
+#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
+#define OP_ALG_PKMODE_MOD_MULT 0x005
+#define OP_ALG_PKMODE_MOD_EXPO 0x006
+#define OP_ALG_PKMODE_MOD_REDUCT 0x007
+#define OP_ALG_PKMODE_MOD_INV 0x008
+#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
+#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
+#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
+#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
+#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
+#define OP_ALG_PKMODE_MOD_GCD 0x00e
+#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
/* PKHA mode copy-memory functions */
-#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
-#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_SHIFT 10
-#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
-#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
-#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-
-#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
-#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
+#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
+#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_SHIFT 10
+#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
+#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
+#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+
+#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
+#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
/*
* SEQ_IN_PTR Command Constructs
*/
/* Release Buffers */
-#define SQIN_RBS 0x04000000
+#define SQIN_RBS 0x04000000
/* Sequence pointer is really a descriptor */
-#define SQIN_INL 0x02000000
+#define SQIN_INL 0x02000000
/* Sequence pointer is a scatter-gather table */
-#define SQIN_SGF 0x01000000
+#define SQIN_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQIN_PRE 0x00800000
+#define SQIN_PRE 0x00800000
/* Use extended length following pointer */
-#define SQIN_EXT 0x00400000
+#define SQIN_EXT 0x00400000
/* Restore sequence with pointer/length */
-#define SQIN_RTO 0x00200000
+#define SQIN_RTO 0x00200000
/* Replace job descriptor */
-#define SQIN_RJD 0x00100000
+#define SQIN_RJD 0x00100000
-#define SQIN_LEN_SHIFT 0
-#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
+#define SQIN_LEN_SHIFT 0
+#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
/*
* SEQ_OUT_PTR Command Constructs
*/
/* Sequence pointer is a scatter-gather table */
-#define SQOUT_SGF 0x01000000
+#define SQOUT_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQOUT_PRE 0x00800000
+#define SQOUT_PRE 0x00800000
/* Restore sequence with pointer/length */
-#define SQOUT_RTO 0x00200000
+#define SQOUT_RTO 0x00200000
/* Use extended length following pointer */
-#define SQOUT_EXT 0x00400000
+#define SQOUT_EXT 0x00400000
-#define SQOUT_LEN_SHIFT 0
-#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
+#define SQOUT_LEN_SHIFT 0
+#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
/*
@@ -1296,196 +1296,196 @@
*/
/* TYPE field is all that's relevant */
-#define SIGN_TYPE_SHIFT 16
-#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_SHIFT 16
+#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_RESTORE (0x01 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_NONZERO (0x02 << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
/*
* MOVE Command Constructs
*/
-#define MOVE_AUX_SHIFT 25
-#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
-
-#define MOVE_WAITCOMP_SHIFT 24
-#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
-#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
-
-#define MOVE_SRC_SHIFT 20
-#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
-
-#define MOVE_DEST_SHIFT 16
-#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
-
-#define MOVE_OFFSET_SHIFT 8
-#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
-
-#define MOVE_LEN_SHIFT 0
-#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
-
-#define MOVELEN_MRSEL_SHIFT 0
-#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
+#define MOVE_AUX_SHIFT 25
+#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
+
+#define MOVE_WAITCOMP_SHIFT 24
+#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
+#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
+
+#define MOVE_SRC_SHIFT 20
+#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
+
+#define MOVE_DEST_SHIFT 16
+#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
+
+#define MOVE_OFFSET_SHIFT 8
+#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
+
+#define MOVE_LEN_SHIFT 0
+#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
+
+#define MOVELEN_MRSEL_SHIFT 0
+#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
/*
* MATH Command Constructs
*/
-#define MATH_IFB_SHIFT 26
-#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
-#define MATH_IFB (1 << MATH_IFB_SHIFT)
+#define MATH_IFB_SHIFT 26
+#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
+#define MATH_IFB (1 << MATH_IFB_SHIFT)
-#define MATH_NFU_SHIFT 25
-#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
-#define MATH_NFU (1 << MATH_NFU_SHIFT)
+#define MATH_NFU_SHIFT 25
+#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
+#define MATH_NFU (1 << MATH_NFU_SHIFT)
-#define MATH_STL_SHIFT 24
-#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
-#define MATH_STL (1 << MATH_STL_SHIFT)
+#define MATH_STL_SHIFT 24
+#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
+#define MATH_STL (1 << MATH_STL_SHIFT)
/* Function selectors */
-#define MATH_FUN_SHIFT 20
-#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
-#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
-#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
-#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
-#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
-#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
-#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
-#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
-#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
-#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
+#define MATH_FUN_SHIFT 20
+#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
+#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
+#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
+#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
+#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
+#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
+#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
+#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
+#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
+#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
/* Source 0 selectors */
-#define MATH_SRC0_SHIFT 16
-#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
-#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SHIFT 16
+#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
+#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
/* Source 1 selectors */
-#define MATH_SRC1_SHIFT 12
-#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
-#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
-#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
+#define MATH_SRC1_SHIFT 12
+#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
+#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
+#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
/* Destination selectors */
-#define MATH_DEST_SHIFT 8
-#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
-#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
-#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_SHIFT 8
+#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
+#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
/* Length selectors */
-#define MATH_LEN_SHIFT 0
-#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
-#define MATH_LEN_1BYTE 0x01
-#define MATH_LEN_2BYTE 0x02
-#define MATH_LEN_4BYTE 0x04
-#define MATH_LEN_8BYTE 0x08
+#define MATH_LEN_SHIFT 0
+#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
+#define MATH_LEN_1BYTE 0x01
+#define MATH_LEN_2BYTE 0x02
+#define MATH_LEN_4BYTE 0x04
+#define MATH_LEN_8BYTE 0x08
/*
* JUMP Command Constructs
*/
-#define JUMP_CLASS_SHIFT 25
+#define JUMP_CLASS_SHIFT 25
#define JUMP_CLASS_MASK (3 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_NONE 0
#define JUMP_CLASS_CLASS1 (1 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_CLASS2 (2 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_BOTH (3 << JUMP_CLASS_SHIFT)
-#define JUMP_JSL_SHIFT 24
-#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
-#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL_SHIFT 24
+#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
-#define JUMP_TYPE_SHIFT 22
-#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_SHIFT 22
+#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TEST_SHIFT 16
-#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_SHIFT 16
+#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
/* Condition codes. JSL bit is factored in */
-#define JUMP_COND_SHIFT 8
-#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
-
-#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
-
-#define JUMP_OFFSET_SHIFT 0
-#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
+#define JUMP_COND_SHIFT 8
+#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
+
+#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
+
+#define JUMP_OFFSET_SHIFT 0
+#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
/*
* NFIFO ENTRY
@@ -1500,20 +1500,20 @@
#define NFIFOENTRY_DEST_BOTH (3 << NFIFOENTRY_DEST_SHIFT)
#define NFIFOENTRY_LC2_SHIFT 29
-#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
-#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
#define NFIFOENTRY_LC1_SHIFT 28
-#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
-#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
#define NFIFOENTRY_FC2_SHIFT 27
-#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
-#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
#define NFIFOENTRY_FC1_SHIFT 26
-#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
-#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
#define NFIFOENTRY_STYPE_SHIFT 24
#define NFIFOENTRY_STYPE_MASK (3 << NFIFOENTRY_STYPE_SHIFT)
@@ -1525,60 +1525,59 @@
#define NFIFOENTRY_DTYPE_SHIFT 20
#define NFIFOENTRY_DTYPE_MASK (0xF << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
-
-#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
+
+#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
#define NFIFOENTRY_BND_SHIFT 19
-#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
-#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
#define NFIFOENTRY_PTYPE_SHIFT 16
#define NFIFOENTRY_PTYPE_MASK (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_OC_SHIFT 15
-#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC_SHIFT 15
+#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
#define NFIFOENTRY_AST_SHIFT 14
-#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_BM_SHIFT 11
-#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
-#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
-
-#define NFIFOENTRY_PS_SHIFT 10
-#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
-#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_BM_SHIFT 11
+#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_PS_SHIFT 10
+#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
#define NFIFOENTRY_DLEN_SHIFT 0
#define NFIFOENTRY_DLEN_MASK (0xFFF << NFIFOENTRY_DLEN_SHIFT)
@@ -1591,15 +1590,15 @@
*/
/* IPSec ESP CBC Encap/Decap Options */
-#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */
-#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */
-#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */
-#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */
-#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */
-#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */
-#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */
-#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */
-#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */
-#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */
+#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */
+#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */
+#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */
+#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */
+#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */
+#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */
+#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */
+#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */
+#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */
+#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */
#endif /* DESC_H */
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 0991323..348b882 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -18,9 +18,10 @@
#define PRINT_POS
#endif
-#define SET_OK_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
- LDST_SRCDST_WORD_DECOCTRL | \
- (LDOFF_CHG_SHARE_OK_PROP << LDST_OFFSET_SHIFT))
+#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+ LDST_SRCDST_WORD_DECOCTRL | \
+ (LDOFF_CHG_SHARE_OK_NO_PROP << \
+ LDST_OFFSET_SHIFT))
#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
LDST_SRCDST_WORD_DECOCTRL | \
(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index aee394e..e9f7a70 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -657,7 +657,6 @@ struct caam_full {
u64 rsvd[512];
struct caam_assurance assure;
struct caam_queue_if qi;
- struct caam_deco *deco;
};
#endif /* REGS_H */
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index dcd8bab..597235a 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -1128,17 +1128,7 @@ static struct platform_driver marvell_crypto = {
};
MODULE_ALIAS("platform:mv_crypto");
-static int __init mv_crypto_init(void)
-{
- return platform_driver_register(&marvell_crypto);
-}
-module_init(mv_crypto_init);
-
-static void __exit mv_crypto_exit(void)
-{
- platform_driver_unregister(&marvell_crypto);
-}
-module_exit(mv_crypto_exit);
+module_platform_driver(marvell_crypto);
MODULE_AUTHOR("Sebastian Andrzej Siewior <sebastian@breakpoint.cc>");
MODULE_DESCRIPTION("Support for Marvell's cryptographic engine");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index a2b553e..58480d0 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -873,7 +873,7 @@ static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
* request for any other size (192 bits) then we need to do a software
* fallback.
*/
- if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+ if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256 &&
ctx->sw_cipher) {
/*
* Set the fallback transform to use the same request flags as
@@ -886,7 +886,7 @@ static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
err = crypto_ablkcipher_setkey(ctx->sw_cipher, key, len);
if (err)
goto sw_setkey_failed;
- } else if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+ } else if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256 &&
!ctx->sw_cipher)
err = -EINVAL;
@@ -1854,17 +1854,7 @@ static struct platform_driver spacc_driver = {
.id_table = spacc_id_table,
};
-static int __init spacc_init(void)
-{
- return platform_driver_register(&spacc_driver);
-}
-module_init(spacc_init);
-
-static void __exit spacc_exit(void)
-{
- platform_driver_unregister(&spacc_driver);
-}
-module_exit(spacc_exit);
+module_platform_driver(spacc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jamie Iles");
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 8115417..3376bca 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -683,18 +683,7 @@ static struct platform_driver s5p_aes_crypto = {
},
};
-static int __init s5p_aes_mod_init(void)
-{
- return platform_driver_register(&s5p_aes_crypto);
-}
-
-static void __exit s5p_aes_mod_exit(void)
-{
- platform_driver_unregister(&s5p_aes_crypto);
-}
-
-module_init(s5p_aes_mod_init);
-module_exit(s5p_aes_mod_exit);
+module_platform_driver(s5p_aes_crypto);
MODULE_DESCRIPTION("S5PV210 AES hw acceleration support.");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index dbe76b5..2d8c789 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -99,6 +99,8 @@ struct talitos_request {
/* per-channel fifo management */
struct talitos_channel {
+ void __iomem *reg;
+
/* request fifo */
struct talitos_request *fifo;
@@ -120,7 +122,7 @@ struct talitos_private {
struct device *dev;
struct platform_device *ofdev;
void __iomem *reg;
- int irq;
+ int irq[2];
/* SEC version geometry (from device tree node) */
unsigned int num_channels;
@@ -144,7 +146,7 @@ struct talitos_private {
atomic_t last_chan ____cacheline_aligned;
/* request callback tasklet */
- struct tasklet_struct done_task;
+ struct tasklet_struct done_task[2];
/* list of registered algorithms */
struct list_head alg_list;
@@ -157,6 +159,7 @@ struct talitos_private {
#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002
#define TALITOS_FTR_SHA224_HWINIT 0x00000004
+#define TALITOS_FTR_HMAC_OK 0x00000008
static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr)
{
@@ -196,9 +199,9 @@ static int reset_channel(struct device *dev, int ch)
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
- setbits32(priv->reg + TALITOS_CCCR(ch), TALITOS_CCCR_RESET);
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
- while ((in_be32(priv->reg + TALITOS_CCCR(ch)) & TALITOS_CCCR_RESET)
+ while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
&& --timeout)
cpu_relax();
@@ -208,12 +211,12 @@ static int reset_channel(struct device *dev, int ch)
}
/* set 36-bit addressing, done writeback enable and done IRQ enable */
- setbits32(priv->reg + TALITOS_CCCR_LO(ch), TALITOS_CCCR_LO_EAE |
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
/* and ICCR writeback, if available */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->reg + TALITOS_CCCR_LO(ch),
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
TALITOS_CCCR_LO_IWSE);
return 0;
@@ -223,13 +226,19 @@ static int reset_device(struct device *dev)
{
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
+ u32 mcr = TALITOS_MCR_SWR;
- setbits32(priv->reg + TALITOS_MCR, TALITOS_MCR_SWR);
+ setbits32(priv->reg + TALITOS_MCR, mcr);
while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
&& --timeout)
cpu_relax();
+ if (priv->irq[1]) {
+ mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
+ setbits32(priv->reg + TALITOS_MCR, mcr);
+ }
+
if (timeout == 0) {
dev_err(dev, "failed to reset device\n");
return -EIO;
@@ -327,8 +336,9 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
/* GO! */
wmb();
- out_be32(priv->reg + TALITOS_FF(ch), upper_32_bits(request->dma_desc));
- out_be32(priv->reg + TALITOS_FF_LO(ch),
+ out_be32(priv->chan[ch].reg + TALITOS_FF,
+ upper_32_bits(request->dma_desc));
+ out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
lower_32_bits(request->dma_desc));
spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
@@ -397,21 +407,32 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
/*
* process completed requests for channels that have done status
*/
-static void talitos_done(unsigned long data)
-{
- struct device *dev = (struct device *)data;
- struct talitos_private *priv = dev_get_drvdata(dev);
- int ch;
-
- for (ch = 0; ch < priv->num_channels; ch++)
- flush_channel(dev, ch, 0, 0);
-
- /* At this point, all completed channels have been processed.
- * Unmask done interrupts for channels completed later on.
- */
- setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+#define DEF_TALITOS_DONE(name, ch_done_mask) \
+static void talitos_done_##name(unsigned long data) \
+{ \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ \
+ if (ch_done_mask & 1) \
+ flush_channel(dev, 0, 0, 0); \
+ if (priv->num_channels == 1) \
+ goto out; \
+ if (ch_done_mask & (1 << 2)) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & (1 << 4)) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & (1 << 6)) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+out: \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
+ setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
}
+DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
+DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
+DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
/*
* locate current (offending) descriptor
@@ -422,7 +443,7 @@ static u32 current_desc_hdr(struct device *dev, int ch)
int tail = priv->chan[ch].tail;
dma_addr_t cur_desc;
- cur_desc = in_be32(priv->reg + TALITOS_CDPR_LO(ch));
+ cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) {
tail = (tail + 1) & (priv->fifo_len - 1);
@@ -444,7 +465,7 @@ static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
int i;
if (!desc_hdr)
- desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+ desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
switch (desc_hdr & DESC_HDR_SEL0_MASK) {
case DESC_HDR_SEL0_AFEU:
@@ -506,16 +527,15 @@ static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
for (i = 0; i < 8; i++)
dev_err(dev, "DESCBUF 0x%08x_%08x\n",
- in_be32(priv->reg + TALITOS_DESCBUF(ch) + 8*i),
- in_be32(priv->reg + TALITOS_DESCBUF_LO(ch) + 8*i));
+ in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
+ in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
}
/*
* recover from error interrupts
*/
-static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
+static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
{
- struct device *dev = (struct device *)data;
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
int ch, error, reset_dev = 0, reset_ch = 0;
@@ -528,8 +548,8 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
error = -EINVAL;
- v = in_be32(priv->reg + TALITOS_CCPSR(ch));
- v_lo = in_be32(priv->reg + TALITOS_CCPSR_LO(ch));
+ v = in_be32(priv->chan[ch].reg + TALITOS_CCPSR);
+ v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
if (v_lo & TALITOS_CCPSR_LO_DOF) {
dev_err(dev, "double fetch fifo overflow error\n");
@@ -567,10 +587,10 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
if (reset_ch) {
reset_channel(dev, ch);
} else {
- setbits32(priv->reg + TALITOS_CCCR(ch),
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR,
TALITOS_CCCR_CONT);
- setbits32(priv->reg + TALITOS_CCCR_LO(ch), 0);
- while ((in_be32(priv->reg + TALITOS_CCCR(ch)) &
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
+ while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
TALITOS_CCCR_CONT) && --timeout)
cpu_relax();
if (timeout == 0) {
@@ -580,7 +600,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
}
}
}
- if (reset_dev || isr & ~TALITOS_ISR_CHERR || isr_lo) {
+ if (reset_dev || isr & ~TALITOS_ISR_4CHERR || isr_lo) {
dev_err(dev, "done overflow, internal time out, or rngu error: "
"ISR 0x%08x_%08x\n", isr, isr_lo);
@@ -593,30 +613,35 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
}
}
-static irqreturn_t talitos_interrupt(int irq, void *data)
-{
- struct device *dev = data;
- struct talitos_private *priv = dev_get_drvdata(dev);
- u32 isr, isr_lo;
-
- isr = in_be32(priv->reg + TALITOS_ISR);
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);
- /* Acknowledge interrupt */
- out_be32(priv->reg + TALITOS_ICR, isr);
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);
-
- if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo))
- talitos_error((unsigned long)data, isr, isr_lo);
- else
- if (likely(isr & TALITOS_ISR_CHDONE)) {
- /* mask further done interrupts. */
- clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE);
- /* done_task will unmask done interrupts at exit */
- tasklet_schedule(&priv->done_task);
- }
-
- return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE;
+#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+static irqreturn_t talitos_interrupt_##name(int irq, void *data) \
+{ \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ \
+ isr = in_be32(priv->reg + TALITOS_ISR); \
+ isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
+ out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
+ \
+ if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
+ talitos_error(dev, isr, isr_lo); \
+ else \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
+ IRQ_NONE; \
}
+DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0)
+DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0)
+DEF_TALITOS_INTERRUPT(ch1_3, TALITOS_ISR_CH_1_3_DONE, TALITOS_ISR_CH_1_3_ERR, 1)
/*
* hwrng
@@ -1874,6 +1899,97 @@ static int ahash_digest(struct ahash_request *areq)
return ahash_process_req(areq, areq->nbytes);
}
+struct keyhash_result {
+ struct completion completion;
+ int err;
+};
+
+static void keyhash_complete(struct crypto_async_request *req, int err)
+{
+ struct keyhash_result *res = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ res->err = err;
+ complete(&res->completion);
+}
+
+static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
+ u8 *hash)
+{
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+
+ struct scatterlist sg[1];
+ struct ahash_request *req;
+ struct keyhash_result hresult;
+ int ret;
+
+ init_completion(&hresult.completion);
+
+ req = ahash_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ /* Keep tfm keylen == 0 during hash of the long key */
+ ctx->keylen = 0;
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ keyhash_complete, &hresult);
+
+ sg_init_one(&sg[0], key, keylen);
+
+ ahash_request_set_crypt(req, sg, hash, keylen);
+ ret = crypto_ahash_digest(req);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &hresult.completion);
+ if (!ret)
+ ret = hresult.err;
+ break;
+ default:
+ break;
+ }
+ ahash_request_free(req);
+
+ return ret;
+}
+
+static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+ unsigned int blocksize =
+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+ unsigned int digestsize = crypto_ahash_digestsize(tfm);
+ unsigned int keysize = keylen;
+ u8 hash[SHA512_DIGEST_SIZE];
+ int ret;
+
+ if (keylen <= blocksize)
+ memcpy(ctx->key, key, keysize);
+ else {
+ /* Must get the hash of the long key */
+ ret = keyhash(tfm, key, keylen, hash);
+
+ if (ret) {
+ crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+ keysize = digestsize;
+ memcpy(ctx->key, hash, digestsize);
+ }
+
+ ctx->keylen = keysize;
+
+ return 0;
+}
+
+
struct talitos_alg_template {
u32 type;
union {
@@ -2217,6 +2333,138 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_SEL0_MDEUB |
DESC_HDR_MODE0_MDEUB_SHA512,
},
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = MD5_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(md5)",
+ .cra_driver_name = "hmac-md5-talitos",
+ .cra_blocksize = MD5_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_MD5,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac-sha1-talitos",
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA1,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha224)",
+ .cra_driver_name = "hmac-sha224-talitos",
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA224,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac-sha256-talitos",
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA256,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac-sha384-talitos",
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUB |
+ DESC_HDR_MODE0_MDEUB_SHA384,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac-sha512-talitos",
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUB |
+ DESC_HDR_MODE0_MDEUB_SHA512,
+ }
};
struct talitos_crypto_alg {
@@ -2331,12 +2579,15 @@ static int talitos_remove(struct platform_device *ofdev)
kfree(priv->chan);
- if (priv->irq != NO_IRQ) {
- free_irq(priv->irq, dev);
- irq_dispose_mapping(priv->irq);
- }
+ for (i = 0; i < 2; i++)
+ if (priv->irq[i]) {
+ free_irq(priv->irq[i], dev);
+ irq_dispose_mapping(priv->irq[i]);
+ }
- tasklet_kill(&priv->done_task);
+ tasklet_kill(&priv->done_task[0]);
+ if (priv->irq[1])
+ tasklet_kill(&priv->done_task[1]);
iounmap(priv->reg);
@@ -2373,8 +2624,14 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
case CRYPTO_ALG_TYPE_AHASH:
alg = &t_alg->algt.alg.hash.halg.base;
alg->cra_init = talitos_cra_init_ahash;
+ if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
+ !strncmp(alg->cra_name, "hmac", 4)) {
+ kfree(t_alg);
+ return ERR_PTR(-ENOTSUPP);
+ }
if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
- !strcmp(alg->cra_name, "sha224")) {
+ (!strcmp(alg->cra_name, "sha224") ||
+ !strcmp(alg->cra_name, "hmac(sha224)"))) {
t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
t_alg->algt.desc_hdr_template =
DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2397,6 +2654,54 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
return t_alg;
}
+static int talitos_probe_irq(struct platform_device *ofdev)
+{
+ struct device *dev = &ofdev->dev;
+ struct device_node *np = ofdev->dev.of_node;
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ int err;
+
+ priv->irq[0] = irq_of_parse_and_map(np, 0);
+ if (!priv->irq[0]) {
+ dev_err(dev, "failed to map irq\n");
+ return -EINVAL;
+ }
+
+ priv->irq[1] = irq_of_parse_and_map(np, 1);
+
+ /* get the primary irq line */
+ if (!priv->irq[1]) {
+ err = request_irq(priv->irq[0], talitos_interrupt_4ch, 0,
+ dev_driver_string(dev), dev);
+ goto primary_out;
+ }
+
+ err = request_irq(priv->irq[0], talitos_interrupt_ch0_2, 0,
+ dev_driver_string(dev), dev);
+ if (err)
+ goto primary_out;
+
+ /* get the secondary irq line */
+ err = request_irq(priv->irq[1], talitos_interrupt_ch1_3, 0,
+ dev_driver_string(dev), dev);
+ if (err) {
+ dev_err(dev, "failed to request secondary irq\n");
+ irq_dispose_mapping(priv->irq[1]);
+ priv->irq[1] = 0;
+ }
+
+ return err;
+
+primary_out:
+ if (err) {
+ dev_err(dev, "failed to request primary irq\n");
+ irq_dispose_mapping(priv->irq[0]);
+ priv->irq[0] = 0;
+ }
+
+ return err;
+}
+
static int talitos_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
@@ -2413,28 +2718,22 @@ static int talitos_probe(struct platform_device *ofdev)
priv->ofdev = ofdev;
- tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev);
-
- INIT_LIST_HEAD(&priv->alg_list);
-
- priv->irq = irq_of_parse_and_map(np, 0);
-
- if (priv->irq == NO_IRQ) {
- dev_err(dev, "failed to map irq\n");
- err = -EINVAL;
+ err = talitos_probe_irq(ofdev);
+ if (err)
goto err_out;
- }
- /* get the irq line */
- err = request_irq(priv->irq, talitos_interrupt, 0,
- dev_driver_string(dev), dev);
- if (err) {
- dev_err(dev, "failed to request irq %d\n", priv->irq);
- irq_dispose_mapping(priv->irq);
- priv->irq = NO_IRQ;
- goto err_out;
+ if (!priv->irq[1]) {
+ tasklet_init(&priv->done_task[0], talitos_done_4ch,
+ (unsigned long)dev);
+ } else {
+ tasklet_init(&priv->done_task[0], talitos_done_ch0_2,
+ (unsigned long)dev);
+ tasklet_init(&priv->done_task[1], talitos_done_ch1_3,
+ (unsigned long)dev);
}
+ INIT_LIST_HEAD(&priv->alg_list);
+
priv->reg = of_iomap(np, 0);
if (!priv->reg) {
dev_err(dev, "failed to of_iomap\n");
@@ -2471,7 +2770,8 @@ static int talitos_probe(struct platform_device *ofdev)
if (of_device_is_compatible(np, "fsl,sec2.1"))
priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
- TALITOS_FTR_SHA224_HWINIT;
+ TALITOS_FTR_SHA224_HWINIT |
+ TALITOS_FTR_HMAC_OK;
priv->chan = kzalloc(sizeof(struct talitos_channel) *
priv->num_channels, GFP_KERNEL);
@@ -2482,6 +2782,12 @@ static int talitos_probe(struct platform_device *ofdev)
}
for (i = 0; i < priv->num_channels; i++) {
+ priv->chan[i].reg = priv->reg + TALITOS_CH_STRIDE * (i + 1);
+ if (!priv->irq[1] || !(i & 1))
+ priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
+ }
+
+ for (i = 0; i < priv->num_channels; i++) {
spin_lock_init(&priv->chan[i].head_lock);
spin_lock_init(&priv->chan[i].tail_lock);
}
@@ -2530,6 +2836,8 @@ static int talitos_probe(struct platform_device *ofdev)
t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
+ if (err == -ENOTSUPP)
+ continue;
goto err_out;
}
@@ -2551,12 +2859,13 @@ static int talitos_probe(struct platform_device *ofdev)
dev_err(dev, "%s alg registration failed\n",
name);
kfree(t_alg);
- } else {
+ } else
list_add_tail(&t_alg->entry, &priv->alg_list);
- dev_info(dev, "%s\n", name);
- }
}
}
+ if (!list_empty(&priv->alg_list))
+ dev_info(dev, "%s algorithms registered in /proc/crypto\n",
+ (char *)of_get_property(np, "compatible", NULL));
return 0;
@@ -2584,17 +2893,7 @@ static struct platform_driver talitos_driver = {
.remove = talitos_remove,
};
-static int __init talitos_init(void)
-{
- return platform_driver_register(&talitos_driver);
-}
-module_init(talitos_init);
-
-static void __exit talitos_exit(void)
-{
- platform_driver_unregister(&talitos_driver);
-}
-module_exit(talitos_exit);
+module_platform_driver(talitos_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h
index 0b746ac..3c17395 100644
--- a/drivers/crypto/talitos.h
+++ b/drivers/crypto/talitos.h
@@ -1,7 +1,7 @@
/*
* Freescale SEC (talitos) device register and descriptor header defines
*
- * Copyright (c) 2006-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2011 Freescale Semiconductor, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,28 +34,37 @@
/* global register offset addresses */
#define TALITOS_MCR 0x1030 /* master control register */
-#define TALITOS_MCR_LO 0x1038
+#define TALITOS_MCR_RCA0 (1 << 15) /* remap channel 0 */
+#define TALITOS_MCR_RCA1 (1 << 14) /* remap channel 1 */
+#define TALITOS_MCR_RCA2 (1 << 13) /* remap channel 2 */
+#define TALITOS_MCR_RCA3 (1 << 12) /* remap channel 3 */
#define TALITOS_MCR_SWR 0x1 /* s/w reset */
+#define TALITOS_MCR_LO 0x1034
#define TALITOS_IMR 0x1008 /* interrupt mask register */
#define TALITOS_IMR_INIT 0x100ff /* enable channel IRQs */
#define TALITOS_IMR_DONE 0x00055 /* done IRQs */
#define TALITOS_IMR_LO 0x100C
#define TALITOS_IMR_LO_INIT 0x20000 /* allow RNGU error IRQs */
#define TALITOS_ISR 0x1010 /* interrupt status register */
-#define TALITOS_ISR_CHERR 0xaa /* channel errors mask */
-#define TALITOS_ISR_CHDONE 0x55 /* channel done mask */
+#define TALITOS_ISR_4CHERR 0xaa /* 4 channel errors mask */
+#define TALITOS_ISR_4CHDONE 0x55 /* 4 channel done mask */
+#define TALITOS_ISR_CH_0_2_ERR 0x22 /* channels 0, 2 errors mask */
+#define TALITOS_ISR_CH_0_2_DONE 0x11 /* channels 0, 2 done mask */
+#define TALITOS_ISR_CH_1_3_ERR 0x88 /* channels 1, 3 errors mask */
+#define TALITOS_ISR_CH_1_3_DONE 0x44 /* channels 1, 3 done mask */
#define TALITOS_ISR_LO 0x1014
#define TALITOS_ICR 0x1018 /* interrupt clear register */
#define TALITOS_ICR_LO 0x101C
/* channel register address stride */
+#define TALITOS_CH_BASE_OFFSET 0x1000 /* default channel map base */
#define TALITOS_CH_STRIDE 0x100
/* channel configuration register */
-#define TALITOS_CCCR(ch) (ch * TALITOS_CH_STRIDE + 0x1108)
+#define TALITOS_CCCR 0x8
#define TALITOS_CCCR_CONT 0x2 /* channel continue */
#define TALITOS_CCCR_RESET 0x1 /* channel reset */
-#define TALITOS_CCCR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x110c)
+#define TALITOS_CCCR_LO 0xc
#define TALITOS_CCCR_LO_IWSE 0x80 /* chan. ICCR writeback enab. */
#define TALITOS_CCCR_LO_EAE 0x20 /* extended address enable */
#define TALITOS_CCCR_LO_CDWE 0x10 /* chan. done writeback enab. */
@@ -63,8 +72,8 @@
#define TALITOS_CCCR_LO_CDIE 0x2 /* channel done IRQ enable */
/* CCPSR: channel pointer status register */
-#define TALITOS_CCPSR(ch) (ch * TALITOS_CH_STRIDE + 0x1110)
-#define TALITOS_CCPSR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1114)
+#define TALITOS_CCPSR 0x10
+#define TALITOS_CCPSR_LO 0x14
#define TALITOS_CCPSR_LO_DOF 0x8000 /* double FF write oflow error */
#define TALITOS_CCPSR_LO_SOF 0x4000 /* single FF write oflow error */
#define TALITOS_CCPSR_LO_MDTE 0x2000 /* master data transfer error */
@@ -79,24 +88,24 @@
#define TALITOS_CCPSR_LO_SRL 0x0010 /* scatter return/length error */
/* channel fetch fifo register */
-#define TALITOS_FF(ch) (ch * TALITOS_CH_STRIDE + 0x1148)
-#define TALITOS_FF_LO(ch) (ch * TALITOS_CH_STRIDE + 0x114c)
+#define TALITOS_FF 0x48
+#define TALITOS_FF_LO 0x4c
/* current descriptor pointer register */
-#define TALITOS_CDPR(ch) (ch * TALITOS_CH_STRIDE + 0x1140)
-#define TALITOS_CDPR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1144)
+#define TALITOS_CDPR 0x40
+#define TALITOS_CDPR_LO 0x44
/* descriptor buffer register */
-#define TALITOS_DESCBUF(ch) (ch * TALITOS_CH_STRIDE + 0x1180)
-#define TALITOS_DESCBUF_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1184)
+#define TALITOS_DESCBUF 0x80
+#define TALITOS_DESCBUF_LO 0x84
/* gather link table */
-#define TALITOS_GATHER(ch) (ch * TALITOS_CH_STRIDE + 0x11c0)
-#define TALITOS_GATHER_LO(ch) (ch * TALITOS_CH_STRIDE + 0x11c4)
+#define TALITOS_GATHER 0xc0
+#define TALITOS_GATHER_LO 0xc4
/* scatter link table */
-#define TALITOS_SCATTER(ch) (ch * TALITOS_CH_STRIDE + 0x11e0)
-#define TALITOS_SCATTER_LO(ch) (ch * TALITOS_CH_STRIDE + 0x11e4)
+#define TALITOS_SCATTER 0xe0
+#define TALITOS_SCATTER_LO 0xe4
/* execution unit interrupt status registers */
#define TALITOS_DEUISR 0x2030 /* DES unit */
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 5a99bb3..f1a2749 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -124,7 +124,7 @@ config MV_XOR
config MX3_IPU
bool "MX3x Image Processing Unit support"
- depends on SOC_IMX31 || SOC_IMX35
+ depends on ARCH_MXC
select DMA_ENGINE
default y
help
@@ -187,6 +187,13 @@ config TIMB_DMA
help
Enable support for the Timberdale FPGA DMA engine.
+config SIRF_DMA
+ tristate "CSR SiRFprimaII DMA support"
+ depends on ARCH_PRIMA2
+ select DMA_ENGINE
+ help
+ Enable support for the CSR SiRFprimaII DMA engine.
+
config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
bool
@@ -201,26 +208,26 @@ config PL330_DMA
platform_data for a dma-pl330 device.
config PCH_DMA
- tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223) DMA support"
+ tristate "Intel EG20T PCH / LAPIS Semicon IOH(ML7213/ML7223/ML7831) DMA"
depends on PCI && X86
select DMA_ENGINE
help
Enable support for Intel EG20T PCH DMA engine.
- This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7213 and ML7223.
- ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
- for MP(Media Phone) use.
- ML7213/ML7223 is companion chip for Intel Atom E6xx series.
- ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+ This driver also can be used for LAPIS Semiconductor IOH(Input/
+ Output Hub), ML7213, ML7223 and ML7831.
+ ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
+ for MP(Media Phone) use and ML7831 IOH is for general purpose use.
+ ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
config IMX_SDMA
tristate "i.MX SDMA support"
- depends on ARCH_MX25 || SOC_IMX31 || SOC_IMX35 || ARCH_MX5
+ depends on ARCH_MXC
select DMA_ENGINE
help
Support the i.MX SDMA engine. This engine is integrated into
- Freescale i.MX25/31/35/51 chips.
+ Freescale i.MX25/31/35/51/53 chips.
config IMX_DMA
tristate "i.MX DMA support"
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 30cf3b1..009a222 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
obj-$(CONFIG_IMX_DMA) += imx-dma.o
obj-$(CONFIG_MXS_DMA) += mxs-dma.o
obj-$(CONFIG_TIMB_DMA) += timb_dma.o
+obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 0698695..8a28158 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -854,8 +854,10 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
int ret;
/* Check if we already have a channel */
- if (plchan->phychan)
- return 0;
+ if (plchan->phychan) {
+ ch = plchan->phychan;
+ goto got_channel;
+ }
ch = pl08x_get_phy_channel(pl08x, plchan);
if (!ch) {
@@ -880,21 +882,22 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
return -EBUSY;
}
ch->signal = ret;
-
- /* Assign the flow control signal to this channel */
- if (txd->direction == DMA_TO_DEVICE)
- txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
- else if (txd->direction == DMA_FROM_DEVICE)
- txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
}
+ plchan->phychan = ch;
dev_dbg(&pl08x->adev->dev, "allocated physical channel %d and signal %d for xfer on %s\n",
ch->id,
ch->signal,
plchan->name);
+got_channel:
+ /* Assign the flow control signal to this channel */
+ if (txd->direction == DMA_MEM_TO_DEV)
+ txd->ccfg |= ch->signal << PL080_CONFIG_DST_SEL_SHIFT;
+ else if (txd->direction == DMA_DEV_TO_MEM)
+ txd->ccfg |= ch->signal << PL080_CONFIG_SRC_SEL_SHIFT;
+
plchan->phychan_hold++;
- plchan->phychan = ch;
return 0;
}
@@ -1102,10 +1105,10 @@ static int dma_set_runtime_config(struct dma_chan *chan,
/* Transfer direction */
plchan->runtime_direction = config->direction;
- if (config->direction == DMA_TO_DEVICE) {
+ if (config->direction == DMA_MEM_TO_DEV) {
addr_width = config->dst_addr_width;
maxburst = config->dst_maxburst;
- } else if (config->direction == DMA_FROM_DEVICE) {
+ } else if (config->direction == DMA_DEV_TO_MEM) {
addr_width = config->src_addr_width;
maxburst = config->src_maxburst;
} else {
@@ -1136,7 +1139,7 @@ static int dma_set_runtime_config(struct dma_chan *chan,
cctl |= burst << PL080_CONTROL_SB_SIZE_SHIFT;
cctl |= burst << PL080_CONTROL_DB_SIZE_SHIFT;
- if (plchan->runtime_direction == DMA_FROM_DEVICE) {
+ if (plchan->runtime_direction == DMA_DEV_TO_MEM) {
plchan->src_addr = config->src_addr;
plchan->src_cctl = pl08x_cctl(cctl) | PL080_CONTROL_DST_INCR |
pl08x_select_bus(plchan->cd->periph_buses,
@@ -1152,7 +1155,7 @@ static int dma_set_runtime_config(struct dma_chan *chan,
"configured channel %s (%s) for %s, data width %d, "
"maxburst %d words, LE, CCTL=0x%08x\n",
dma_chan_name(chan), plchan->name,
- (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
+ (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX",
addr_width,
maxburst,
cctl);
@@ -1322,7 +1325,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
@@ -1354,10 +1357,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
*/
txd->direction = direction;
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
txd->cctl = plchan->dst_cctl;
slave_addr = plchan->dst_addr;
- } else if (direction == DMA_FROM_DEVICE) {
+ } else if (direction == DMA_DEV_TO_MEM) {
txd->cctl = plchan->src_cctl;
slave_addr = plchan->src_addr;
} else {
@@ -1368,10 +1371,10 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
}
if (plchan->cd->device_fc)
- tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER_PER :
+ tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER_PER :
PL080_FLOW_PER2MEM_PER;
else
- tmp = (direction == DMA_TO_DEVICE) ? PL080_FLOW_MEM2PER :
+ tmp = (direction == DMA_MEM_TO_DEV) ? PL080_FLOW_MEM2PER :
PL080_FLOW_PER2MEM;
txd->ccfg |= tmp << PL080_CONFIG_FLOW_CONTROL_SHIFT;
@@ -1387,7 +1390,7 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
list_add_tail(&dsg->node, &txd->dsg_list);
dsg->len = sg_dma_len(sg);
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
dsg->src_addr = sg_phys(sg);
dsg->dst_addr = slave_addr;
} else {
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index fcfa0a8..97f87b2 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -23,6 +23,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include "at_hdmac_regs.h"
@@ -660,7 +662,7 @@ err_desc_get:
*/
static struct dma_async_tx_descriptor *
atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct at_dma_chan *atchan = to_at_dma_chan(chan);
@@ -678,7 +680,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
dev_vdbg(chan2dev(chan), "prep_slave_sg (%d): %s f0x%lx\n",
sg_len,
- direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+ direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
flags);
if (unlikely(!atslave || !sg_len)) {
@@ -692,7 +694,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
ctrlb = ATC_IEN;
switch (direction) {
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
ctrla |= ATC_DST_WIDTH(reg_width);
ctrlb |= ATC_DST_ADDR_MODE_FIXED
| ATC_SRC_ADDR_MODE_INCR
@@ -725,7 +727,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
total_len += len;
}
break;
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
ctrla |= ATC_SRC_WIDTH(reg_width);
ctrlb |= ATC_DST_ADDR_MODE_INCR
| ATC_SRC_ADDR_MODE_FIXED
@@ -787,7 +789,7 @@ err_desc_get:
*/
static int
atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
if (period_len > (ATC_BTSIZE_MAX << reg_width))
goto err_out;
@@ -795,7 +797,7 @@ atc_dma_cyclic_check_values(unsigned int reg_width, dma_addr_t buf_addr,
goto err_out;
if (unlikely(buf_addr & ((1 << reg_width) - 1)))
goto err_out;
- if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE))))
+ if (unlikely(!(direction & (DMA_DEV_TO_MEM | DMA_MEM_TO_DEV))))
goto err_out;
return 0;
@@ -810,7 +812,7 @@ err_out:
static int
atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
unsigned int period_index, dma_addr_t buf_addr,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
u32 ctrla;
unsigned int reg_width = atslave->reg_width;
@@ -822,7 +824,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
| period_len >> reg_width;
switch (direction) {
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
desc->lli.saddr = buf_addr + (period_len * period_index);
desc->lli.daddr = atslave->tx_reg;
desc->lli.ctrla = ctrla;
@@ -833,7 +835,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
| ATC_DIF(AT_DMA_PER_IF);
break;
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
desc->lli.saddr = atslave->rx_reg;
desc->lli.daddr = buf_addr + (period_len * period_index);
desc->lli.ctrla = ctrla;
@@ -861,7 +863,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc,
*/
static struct dma_async_tx_descriptor *
atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
struct at_dma_chan *atchan = to_at_dma_chan(chan);
struct at_dma_slave *atslave = chan->private;
@@ -872,7 +874,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
unsigned int i;
dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n",
- direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+ direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
buf_addr,
periods, buf_len, period_len);
@@ -1175,6 +1177,56 @@ static void atc_free_chan_resources(struct dma_chan *chan)
/*-- Module Management -----------------------------------------------*/
+/* cap_mask is a multi-u32 bitfield, fill it with proper C code. */
+static struct at_dma_platform_data at91sam9rl_config = {
+ .nr_channels = 2,
+};
+static struct at_dma_platform_data at91sam9g45_config = {
+ .nr_channels = 8,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_dma_dt_ids[] = {
+ {
+ .compatible = "atmel,at91sam9rl-dma",
+ .data = &at91sam9rl_config,
+ }, {
+ .compatible = "atmel,at91sam9g45-dma",
+ .data = &at91sam9g45_config,
+ }, {
+ /* sentinel */
+ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_dma_dt_ids);
+#endif
+
+static const struct platform_device_id atdma_devtypes[] = {
+ {
+ .name = "at91sam9rl_dma",
+ .driver_data = (unsigned long) &at91sam9rl_config,
+ }, {
+ .name = "at91sam9g45_dma",
+ .driver_data = (unsigned long) &at91sam9g45_config,
+ }, {
+ /* sentinel */
+ }
+};
+
+static inline struct at_dma_platform_data * __init at_dma_get_driver_data(
+ struct platform_device *pdev)
+{
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(atmel_dma_dt_ids, pdev->dev.of_node);
+ if (match == NULL)
+ return NULL;
+ return match->data;
+ }
+ return (struct at_dma_platform_data *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
/**
* at_dma_off - disable DMA controller
* @atdma: the Atmel HDAMC device
@@ -1193,18 +1245,23 @@ static void at_dma_off(struct at_dma *atdma)
static int __init at_dma_probe(struct platform_device *pdev)
{
- struct at_dma_platform_data *pdata;
struct resource *io;
struct at_dma *atdma;
size_t size;
int irq;
int err;
int i;
+ struct at_dma_platform_data *plat_dat;
- /* get DMA Controller parameters from platform */
- pdata = pdev->dev.platform_data;
- if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
- return -EINVAL;
+ /* setup platform data for each SoC */
+ dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask);
+ dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask);
+ dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask);
+
+ /* get DMA parameters from controller type */
+ plat_dat = at_dma_get_driver_data(pdev);
+ if (!plat_dat)
+ return -ENODEV;
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!io)
@@ -1215,14 +1272,14 @@ static int __init at_dma_probe(struct platform_device *pdev)
return irq;
size = sizeof(struct at_dma);
- size += pdata->nr_channels * sizeof(struct at_dma_chan);
+ size += plat_dat->nr_channels * sizeof(struct at_dma_chan);
atdma = kzalloc(size, GFP_KERNEL);
if (!atdma)
return -ENOMEM;
- /* discover transaction capabilites from the platform data */
- atdma->dma_common.cap_mask = pdata->cap_mask;
- atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
+ /* discover transaction capabilities */
+ atdma->dma_common.cap_mask = plat_dat->cap_mask;
+ atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1;
size = resource_size(io);
if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
@@ -1268,7 +1325,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
/* initialize channels related values */
INIT_LIST_HEAD(&atdma->dma_common.channels);
- for (i = 0; i < pdata->nr_channels; i++) {
+ for (i = 0; i < plat_dat->nr_channels; i++) {
struct at_dma_chan *atchan = &atdma->chan[i];
atchan->chan_common.device = &atdma->dma_common;
@@ -1313,7 +1370,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "",
- pdata->nr_channels);
+ plat_dat->nr_channels);
dma_async_device_register(&atdma->dma_common);
@@ -1495,9 +1552,11 @@ static const struct dev_pm_ops at_dma_dev_pm_ops = {
static struct platform_driver at_dma_driver = {
.remove = __exit_p(at_dma_remove),
.shutdown = at_dma_shutdown,
+ .id_table = atdma_devtypes,
.driver = {
.name = "at_hdmac",
.pm = &at_dma_dev_pm_ops,
+ .of_match_table = of_match_ptr(atmel_dma_dt_ids),
},
};
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index aa4c9ae..dcaedfc 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -251,6 +251,7 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
/**
* struct at_dma - internal representation of an Atmel HDMA Controller
* @chan_common: common dmaengine dma_device object members
+ * @atdma_devtype: identifier of DMA controller compatibility
* @ch_regs: memory mapped register base
* @clk: dma controller clock
* @save_imr: interrupt mask register that is saved on suspend/resume cycle
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 4234f41..d65a718 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -39,7 +39,7 @@ struct coh901318_desc {
struct scatterlist *sg;
unsigned int sg_len;
struct coh901318_lli *lli;
- enum dma_data_direction dir;
+ enum dma_transfer_direction dir;
unsigned long flags;
u32 head_config;
u32 head_ctrl;
@@ -1034,7 +1034,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
static struct dma_async_tx_descriptor *
coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct coh901318_chan *cohc = to_coh901318_chan(chan);
@@ -1077,7 +1077,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
ctrl_last |= cohc->runtime_ctrl;
ctrl |= cohc->runtime_ctrl;
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
@@ -1085,7 +1085,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
ctrl_chained |= tx_flags;
ctrl_last |= tx_flags;
ctrl |= tx_flags;
- } else if (direction == DMA_FROM_DEVICE) {
+ } else if (direction == DMA_DEV_TO_MEM) {
u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
@@ -1274,11 +1274,11 @@ static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
int i = 0;
/* We only support mem to per or per to mem transfers */
- if (config->direction == DMA_FROM_DEVICE) {
+ if (config->direction == DMA_DEV_TO_MEM) {
addr = config->src_addr;
addr_width = config->src_addr_width;
maxburst = config->src_maxburst;
- } else if (config->direction == DMA_TO_DEVICE) {
+ } else if (config->direction == DMA_MEM_TO_DEV) {
addr = config->dst_addr;
addr_width = config->dst_addr_width;
maxburst = config->dst_maxburst;
diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c
index 9f7e0e6a..6c0e2d4 100644
--- a/drivers/dma/coh901318_lli.c
+++ b/drivers/dma/coh901318_lli.c
@@ -7,11 +7,10 @@
* Author: Per Friden <per.friden@stericsson.com>
*/
-#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <linux/dmapool.h>
#include <linux/memory.h>
#include <linux/gfp.h>
+#include <linux/dmapool.h>
#include <mach/coh901318.h>
#include "coh901318_lli.h"
@@ -177,18 +176,18 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
struct coh901318_lli *lli,
dma_addr_t buf, unsigned int size,
dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom,
- enum dma_data_direction dir)
+ enum dma_transfer_direction dir)
{
int s = size;
dma_addr_t src;
dma_addr_t dst;
- if (dir == DMA_TO_DEVICE) {
+ if (dir == DMA_MEM_TO_DEV) {
src = buf;
dst = dev_addr;
- } else if (dir == DMA_FROM_DEVICE) {
+ } else if (dir == DMA_DEV_TO_MEM) {
src = dev_addr;
dst = buf;
@@ -215,9 +214,9 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
lli = coh901318_lli_next(lli);
- if (dir == DMA_TO_DEVICE)
+ if (dir == DMA_MEM_TO_DEV)
src += block_size;
- else if (dir == DMA_FROM_DEVICE)
+ else if (dir == DMA_DEV_TO_MEM)
dst += block_size;
}
@@ -234,7 +233,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
struct scatterlist *sgl, unsigned int nents,
dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl,
u32 ctrl_last,
- enum dma_data_direction dir, u32 ctrl_irq_mask)
+ enum dma_transfer_direction dir, u32 ctrl_irq_mask)
{
int i;
struct scatterlist *sg;
@@ -249,9 +248,9 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
spin_lock(&pool->lock);
- if (dir == DMA_TO_DEVICE)
+ if (dir == DMA_MEM_TO_DEV)
dst = dev_addr;
- else if (dir == DMA_FROM_DEVICE)
+ else if (dir == DMA_DEV_TO_MEM)
src = dev_addr;
else
goto err;
@@ -269,7 +268,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
ctrl_sg = ctrl ? ctrl : ctrl_last;
- if (dir == DMA_TO_DEVICE)
+ if (dir == DMA_MEM_TO_DEV)
/* increment source address */
src = sg_phys(sg);
else
@@ -293,7 +292,7 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
lli->src_addr = src;
lli->dst_addr = dst;
- if (dir == DMA_FROM_DEVICE)
+ if (dir == DMA_DEV_TO_MEM)
dst += elem_size;
else
src += elem_size;
diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h
index 7a5c809..abff371 100644
--- a/drivers/dma/coh901318_lli.h
+++ b/drivers/dma/coh901318_lli.h
@@ -97,7 +97,7 @@ coh901318_lli_fill_single(struct coh901318_pool *pool,
struct coh901318_lli *lli,
dma_addr_t buf, unsigned int size,
dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_last,
- enum dma_data_direction dir);
+ enum dma_transfer_direction dir);
/**
* coh901318_lli_fill_single() - Prepares the lli:s for dma scatter list transfer
@@ -119,6 +119,6 @@ coh901318_lli_fill_sg(struct coh901318_pool *pool,
struct scatterlist *sg, unsigned int nents,
dma_addr_t dev_addr, u32 ctrl_chained,
u32 ctrl, u32 ctrl_last,
- enum dma_data_direction dir, u32 ctrl_irq_mask);
+ enum dma_transfer_direction dir, u32 ctrl_irq_mask);
#endif /* COH901318_LLI_H */
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index b48967b..a6c6051 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -693,12 +693,12 @@ int dma_async_device_register(struct dma_device *device)
!device->device_prep_dma_interrupt);
BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) &&
!device->device_prep_dma_sg);
- BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
- !device->device_prep_slave_sg);
BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) &&
!device->device_prep_dma_cyclic);
BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
!device->device_control);
+ BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) &&
+ !device->device_prep_interleaved_dma);
BUG_ON(!device->device_alloc_chan_resources);
BUG_ON(!device->device_free_chan_resources);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 9bfd6d3..9b592b0 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -166,6 +166,38 @@ dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
return cookie;
}
+static void dwc_initialize(struct dw_dma_chan *dwc)
+{
+ struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+ struct dw_dma_slave *dws = dwc->chan.private;
+ u32 cfghi = DWC_CFGH_FIFO_MODE;
+ u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
+
+ if (dwc->initialized == true)
+ return;
+
+ if (dws) {
+ /*
+ * We need controller-specific data to set up slave
+ * transfers.
+ */
+ BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
+
+ cfghi = dws->cfg_hi;
+ cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
+ }
+
+ channel_writel(dwc, CFG_LO, cfglo);
+ channel_writel(dwc, CFG_HI, cfghi);
+
+ /* Enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dwc->mask);
+ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+ dwc->initialized = true;
+}
+
/*----------------------------------------------------------------------*/
/* Called with dwc->lock held and bh disabled */
@@ -189,6 +221,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
return;
}
+ dwc_initialize(dwc);
+
channel_writel(dwc, LLP, first->txd.phys);
channel_writel(dwc, CTL_LO,
DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
@@ -696,7 +730,7 @@ err_desc_get:
static struct dma_async_tx_descriptor *
dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
@@ -720,7 +754,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
prev = first = NULL;
switch (direction) {
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
ctllo = (DWC_DEFAULT_CTLLO(chan->private)
| DWC_CTLL_DST_WIDTH(reg_width)
| DWC_CTLL_DST_FIX
@@ -777,7 +811,7 @@ slave_sg_todev_fill_desc:
goto slave_sg_todev_fill_desc;
}
break;
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
ctllo = (DWC_DEFAULT_CTLLO(chan->private)
| DWC_CTLL_SRC_WIDTH(reg_width)
| DWC_CTLL_DST_INC
@@ -959,10 +993,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct dw_dma *dw = to_dw_dma(chan->device);
struct dw_desc *desc;
- struct dw_dma_slave *dws;
int i;
- u32 cfghi;
- u32 cfglo;
unsigned long flags;
dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
@@ -975,26 +1006,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
dwc->completed = chan->cookie = 1;
- cfghi = DWC_CFGH_FIFO_MODE;
- cfglo = 0;
-
- dws = chan->private;
- if (dws) {
- /*
- * We need controller-specific data to set up slave
- * transfers.
- */
- BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
-
- cfghi = dws->cfg_hi;
- cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
- }
-
- cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority);
-
- channel_writel(dwc, CFG_LO, cfglo);
- channel_writel(dwc, CFG_HI, cfghi);
-
/*
* NOTE: some controllers may have additional features that we
* need to initialize here, like "scatter-gather" (which
@@ -1026,11 +1037,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
i = ++dwc->descs_allocated;
}
- /* Enable interrupts */
- channel_set_bit(dw, MASK.XFER, dwc->mask);
- channel_set_bit(dw, MASK.BLOCK, dwc->mask);
- channel_set_bit(dw, MASK.ERROR, dwc->mask);
-
spin_unlock_irqrestore(&dwc->lock, flags);
dev_dbg(chan2dev(chan),
@@ -1058,6 +1064,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
spin_lock_irqsave(&dwc->lock, flags);
list_splice_init(&dwc->free_list, &list);
dwc->descs_allocated = 0;
+ dwc->initialized = false;
/* Disable interrupts */
channel_clear_bit(dw, MASK.XFER, dwc->mask);
@@ -1165,7 +1172,7 @@ EXPORT_SYMBOL(dw_dma_cyclic_stop);
*/
struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
dma_addr_t buf_addr, size_t buf_len, size_t period_len,
- enum dma_data_direction direction)
+ enum dma_transfer_direction direction)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct dw_cyclic_desc *cdesc;
@@ -1206,7 +1213,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
goto out_err;
if (unlikely(buf_addr & ((1 << reg_width) - 1)))
goto out_err;
- if (unlikely(!(direction & (DMA_TO_DEVICE | DMA_FROM_DEVICE))))
+ if (unlikely(!(direction & (DMA_MEM_TO_DEV | DMA_DEV_TO_MEM))))
goto out_err;
retval = ERR_PTR(-ENOMEM);
@@ -1228,7 +1235,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
goto out_err_desc_get;
switch (direction) {
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
desc->lli.dar = dws->tx_reg;
desc->lli.sar = buf_addr + (period_len * i);
desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
@@ -1239,7 +1246,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
| DWC_CTLL_FC(dws->fc)
| DWC_CTLL_INT_EN);
break;
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
desc->lli.dar = buf_addr + (period_len * i);
desc->lli.sar = dws->rx_reg;
desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
@@ -1335,6 +1342,8 @@ EXPORT_SYMBOL(dw_dma_cyclic_free);
static void dw_dma_off(struct dw_dma *dw)
{
+ int i;
+
dma_writel(dw, CFG, 0);
channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
@@ -1345,6 +1354,9 @@ static void dw_dma_off(struct dw_dma *dw)
while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
cpu_relax();
+
+ for (i = 0; i < dw->dma.chancnt; i++)
+ dw->chan[i].initialized = false;
}
static int __init dw_probe(struct platform_device *pdev)
@@ -1533,6 +1545,7 @@ static int dw_suspend_noirq(struct device *dev)
dw_dma_off(platform_get_drvdata(pdev));
clk_disable(dw->clk);
+
return 0;
}
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index c341951..5eef694 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -140,6 +140,7 @@ struct dw_dma_chan {
u8 mask;
u8 priority;
bool paused;
+ bool initialized;
spinlock_t lock;
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index b47e2b8..59e7a96 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -246,6 +246,9 @@ static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
static struct ep93xx_dma_desc *
ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
{
+ if (list_empty(&edmac->active))
+ return NULL;
+
return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
}
@@ -263,16 +266,22 @@ ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
*/
static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
{
+ struct ep93xx_dma_desc *desc;
+
list_rotate_left(&edmac->active);
if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
return true;
+ desc = ep93xx_dma_get_active(edmac);
+ if (!desc)
+ return false;
+
/*
* If txd.cookie is set it means that we are back in the first
* descriptor in the chain and hence done with it.
*/
- return !ep93xx_dma_get_active(edmac)->txd.cookie;
+ return !desc->txd.cookie;
}
/*
@@ -327,10 +336,16 @@ static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
{
- struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+ struct ep93xx_dma_desc *desc;
u32 bus_addr;
- if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_TO_DEVICE)
+ desc = ep93xx_dma_get_active(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "M2P: empty descriptor list\n");
+ return;
+ }
+
+ if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV)
bus_addr = desc->src_addr;
else
bus_addr = desc->dst_addr;
@@ -443,7 +458,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
control = (5 << M2M_CONTROL_PWSC_SHIFT);
control |= M2M_CONTROL_NO_HDSK;
- if (data->direction == DMA_TO_DEVICE) {
+ if (data->direction == DMA_MEM_TO_DEV) {
control |= M2M_CONTROL_DAH;
control |= M2M_CONTROL_TM_TX;
control |= M2M_CONTROL_RSS_SSPTX;
@@ -459,11 +474,7 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
* This IDE part is totally untested. Values below are taken
* from the EP93xx Users's Guide and might not be correct.
*/
- control |= M2M_CONTROL_NO_HDSK;
- control |= M2M_CONTROL_RSS_IDE;
- control |= M2M_CONTROL_PW_16;
-
- if (data->direction == DMA_TO_DEVICE) {
+ if (data->direction == DMA_MEM_TO_DEV) {
/* Worst case from the UG */
control = (3 << M2M_CONTROL_PWSC_SHIFT);
control |= M2M_CONTROL_DAH;
@@ -473,6 +484,10 @@ static int m2m_hw_setup(struct ep93xx_dma_chan *edmac)
control |= M2M_CONTROL_SAH;
control |= M2M_CONTROL_TM_RX;
}
+
+ control |= M2M_CONTROL_NO_HDSK;
+ control |= M2M_CONTROL_RSS_IDE;
+ control |= M2M_CONTROL_PW_16;
break;
default:
@@ -491,7 +506,13 @@ static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)
static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
{
- struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
+ struct ep93xx_dma_desc *desc;
+
+ desc = ep93xx_dma_get_active(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac), "M2M: empty descriptor list\n");
+ return;
+ }
if (edmac->buffer == 0) {
writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
@@ -669,24 +690,30 @@ static void ep93xx_dma_tasklet(unsigned long data)
{
struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
struct ep93xx_dma_desc *desc, *d;
- dma_async_tx_callback callback;
- void *callback_param;
+ dma_async_tx_callback callback = NULL;
+ void *callback_param = NULL;
LIST_HEAD(list);
spin_lock_irq(&edmac->lock);
+ /*
+ * If dma_terminate_all() was called before we get to run, the active
+ * list has become empty. If that happens we aren't supposed to do
+ * anything more than call ep93xx_dma_advance_work().
+ */
desc = ep93xx_dma_get_active(edmac);
- if (desc->complete) {
- edmac->last_completed = desc->txd.cookie;
- list_splice_init(&edmac->active, &list);
+ if (desc) {
+ if (desc->complete) {
+ edmac->last_completed = desc->txd.cookie;
+ list_splice_init(&edmac->active, &list);
+ }
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
}
spin_unlock_irq(&edmac->lock);
/* Pick up the next descriptor from the queue */
ep93xx_dma_advance_work(edmac);
- callback = desc->txd.callback;
- callback_param = desc->txd.callback_param;
-
/* Now we can release all the chained descriptors */
list_for_each_entry_safe(desc, d, &list, node) {
/*
@@ -706,13 +733,22 @@ static void ep93xx_dma_tasklet(unsigned long data)
static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
{
struct ep93xx_dma_chan *edmac = dev_id;
+ struct ep93xx_dma_desc *desc;
irqreturn_t ret = IRQ_HANDLED;
spin_lock(&edmac->lock);
+ desc = ep93xx_dma_get_active(edmac);
+ if (!desc) {
+ dev_warn(chan2dev(edmac),
+ "got interrupt while active list is empty\n");
+ spin_unlock(&edmac->lock);
+ return IRQ_NONE;
+ }
+
switch (edmac->edma->hw_interrupt(edmac)) {
case INTERRUPT_DONE:
- ep93xx_dma_get_active(edmac)->complete = true;
+ desc->complete = true;
tasklet_schedule(&edmac->tasklet);
break;
@@ -803,8 +839,8 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan)
switch (data->port) {
case EP93XX_DMA_SSP:
case EP93XX_DMA_IDE:
- if (data->direction != DMA_TO_DEVICE &&
- data->direction != DMA_FROM_DEVICE)
+ if (data->direction != DMA_MEM_TO_DEV &&
+ data->direction != DMA_DEV_TO_MEM)
return -EINVAL;
break;
default:
@@ -952,7 +988,7 @@ fail:
*/
static struct dma_async_tx_descriptor *
ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction dir,
+ unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags)
{
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
@@ -988,7 +1024,7 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
goto fail;
}
- if (dir == DMA_TO_DEVICE) {
+ if (dir == DMA_MEM_TO_DEV) {
desc->src_addr = sg_dma_address(sg);
desc->dst_addr = edmac->runtime_addr;
} else {
@@ -1032,7 +1068,7 @@ fail:
static struct dma_async_tx_descriptor *
ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
size_t buf_len, size_t period_len,
- enum dma_data_direction dir)
+ enum dma_transfer_direction dir)
{
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
struct ep93xx_dma_desc *desc, *first;
@@ -1065,7 +1101,7 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
goto fail;
}
- if (dir == DMA_TO_DEVICE) {
+ if (dir == DMA_MEM_TO_DEV) {
desc->src_addr = dma_addr + offset;
desc->dst_addr = edmac->runtime_addr;
} else {
@@ -1133,12 +1169,12 @@ static int ep93xx_dma_slave_config(struct ep93xx_dma_chan *edmac,
return -EINVAL;
switch (config->direction) {
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
width = config->src_addr_width;
addr = config->src_addr;
break;
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
width = config->dst_addr_width;
addr = config->dst_addr;
break;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 8a78154..b98070c 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -772,7 +772,7 @@ fail:
*/
static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long flags)
+ enum dma_transfer_direction direction, unsigned long flags)
{
/*
* This operation is not supported on the Freescale DMA controller
@@ -819,7 +819,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
return -ENXIO;
/* we set the controller burst size depending on direction */
- if (config->direction == DMA_TO_DEVICE)
+ if (config->direction == DMA_MEM_TO_DEV)
size = config->dst_addr_width * config->dst_maxburst;
else
size = config->src_addr_width * config->src_maxburst;
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 4be55f9..e4383ee 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -107,7 +107,7 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
imx_dma_disable(imxdmac->imxdma_channel);
return 0;
case DMA_SLAVE_CONFIG:
- if (dmaengine_cfg->direction == DMA_FROM_DEVICE) {
+ if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
imxdmac->per_address = dmaengine_cfg->src_addr;
imxdmac->watermark_level = dmaengine_cfg->src_maxburst;
imxdmac->word_size = dmaengine_cfg->src_addr_width;
@@ -224,7 +224,7 @@ static void imxdma_free_chan_resources(struct dma_chan *chan)
static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
@@ -241,7 +241,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
dma_length += sg->length;
}
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
dmamode = DMA_MODE_READ;
else
dmamode = DMA_MODE_WRITE;
@@ -271,7 +271,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
struct imxdma_engine *imxdma = imxdmac->imxdma;
@@ -317,7 +317,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
imxdmac->sg_list[periods].page_link =
((unsigned long)imxdmac->sg_list | 0x01) & ~0x02;
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
dmamode = DMA_MODE_READ;
else
dmamode = DMA_MODE_WRITE;
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f993955..a8af379 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -247,7 +247,7 @@ struct sdma_engine;
struct sdma_channel {
struct sdma_engine *sdma;
unsigned int channel;
- enum dma_data_direction direction;
+ enum dma_transfer_direction direction;
enum sdma_peripheral_type peripheral_type;
unsigned int event_id0;
unsigned int event_id1;
@@ -268,6 +268,8 @@ struct sdma_channel {
struct dma_async_tx_descriptor desc;
dma_cookie_t last_completed;
enum dma_status status;
+ unsigned int chn_count;
+ unsigned int chn_real_count;
};
#define IMX_DMA_SG_LOOP (1 << 0)
@@ -503,6 +505,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd;
int i, error = 0;
+ sdmac->chn_real_count = 0;
/*
* non loop mode. Iterate over all descriptors, collect
* errors and call callback function
@@ -512,6 +515,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO;
+ sdmac->chn_real_count += bd->mode.count;
}
if (error)
@@ -519,9 +523,9 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
else
sdmac->status = DMA_SUCCESS;
+ sdmac->last_completed = sdmac->desc.cookie;
if (sdmac->desc.callback)
sdmac->desc.callback(sdmac->desc.callback_param);
- sdmac->last_completed = sdmac->desc.cookie;
}
static void mxc_sdma_handle_channel(struct sdma_channel *sdmac)
@@ -650,7 +654,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
int ret;
- if (sdmac->direction == DMA_FROM_DEVICE) {
+ if (sdmac->direction == DMA_DEV_TO_MEM) {
load_address = sdmac->pc_from_device;
} else {
load_address = sdmac->pc_to_device;
@@ -832,17 +836,18 @@ static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
{
+ unsigned long flags;
struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
struct sdma_engine *sdma = sdmac->sdma;
dma_cookie_t cookie;
- spin_lock_irq(&sdmac->lock);
+ spin_lock_irqsave(&sdmac->lock, flags);
cookie = sdma_assign_cookie(sdmac);
sdma_enable_channel(sdma, sdmac->channel);
- spin_unlock_irq(&sdmac->lock);
+ spin_unlock_irqrestore(&sdmac->lock, flags);
return cookie;
}
@@ -911,7 +916,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
@@ -941,6 +946,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
goto err_out;
}
+ sdmac->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
int param;
@@ -957,6 +963,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
}
bd->mode.count = count;
+ sdmac->chn_count += count;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL;
@@ -1008,7 +1015,7 @@ err_out:
static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
@@ -1093,7 +1100,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
sdma_disable_channel(sdmac);
return 0;
case DMA_SLAVE_CONFIG:
- if (dmaengine_cfg->direction == DMA_FROM_DEVICE) {
+ if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
sdmac->per_address = dmaengine_cfg->src_addr;
sdmac->watermark_level = dmaengine_cfg->src_maxburst;
sdmac->word_size = dmaengine_cfg->src_addr_width;
@@ -1102,6 +1109,7 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
}
+ sdmac->direction = dmaengine_cfg->direction;
return sdma_config_channel(sdmac);
default:
return -ENOSYS;
@@ -1119,7 +1127,8 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
last_used = chan->cookie;
- dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0);
+ dma_set_tx_state(txstate, sdmac->last_completed, last_used,
+ sdmac->chn_count - sdmac->chn_real_count);
return sdmac->status;
}
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 19a0c64..74f70aa 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -280,7 +280,8 @@ static void midc_dostart(struct intel_mid_dma_chan *midc,
* callbacks but must be called with the lock held.
*/
static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
- struct intel_mid_dma_desc *desc)
+ struct intel_mid_dma_desc *desc)
+ __releases(&midc->lock) __acquires(&midc->lock)
{
struct dma_async_tx_descriptor *txd = &desc->txd;
dma_async_tx_callback callback_txd = NULL;
@@ -311,6 +312,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
pci_pool_free(desc->lli_pool, desc->lli,
desc->lli_phys);
pci_pool_destroy(desc->lli_pool);
+ desc->lli = NULL;
}
list_move(&desc->desc_node, &midc->free_list);
midc->busy = false;
@@ -395,10 +397,10 @@ static int midc_lli_fill_sg(struct intel_mid_dma_chan *midc,
midc->dma->block_size);
/*Populate SAR and DAR values*/
sg_phy_addr = sg_phys(sg);
- if (desc->dirn == DMA_TO_DEVICE) {
+ if (desc->dirn == DMA_MEM_TO_DEV) {
lli_bloc_desc->sar = sg_phy_addr;
lli_bloc_desc->dar = mids->dma_slave.dst_addr;
- } else if (desc->dirn == DMA_FROM_DEVICE) {
+ } else if (desc->dirn == DMA_DEV_TO_MEM) {
lli_bloc_desc->sar = mids->dma_slave.src_addr;
lli_bloc_desc->dar = sg_phy_addr;
}
@@ -490,7 +492,9 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
ret = dma_async_is_complete(cookie, last_complete, last_used);
if (ret != DMA_SUCCESS) {
+ spin_lock_bh(&midc->lock);
midc_scan_descriptors(to_middma_device(chan->device), midc);
+ spin_unlock_bh(&midc->lock);
last_complete = midc->completed;
last_used = chan->cookie;
@@ -566,6 +570,7 @@ static int intel_mid_dma_device_control(struct dma_chan *chan,
pci_pool_free(desc->lli_pool, desc->lli,
desc->lli_phys);
pci_pool_destroy(desc->lli_pool);
+ desc->lli = NULL;
}
list_move(&desc->desc_node, &midc->free_list);
}
@@ -632,13 +637,13 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy(
if (midc->dma->pimr_mask) {
cfg_hi.cfgx.protctl = 0x0; /*default value*/
cfg_hi.cfgx.fifo_mode = 1;
- if (mids->dma_slave.direction == DMA_TO_DEVICE) {
+ if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
cfg_hi.cfgx.src_per = 0;
if (mids->device_instance == 0)
cfg_hi.cfgx.dst_per = 3;
if (mids->device_instance == 1)
cfg_hi.cfgx.dst_per = 1;
- } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) {
+ } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
if (mids->device_instance == 0)
cfg_hi.cfgx.src_per = 2;
if (mids->device_instance == 1)
@@ -682,11 +687,11 @@ static struct dma_async_tx_descriptor *intel_mid_dma_prep_memcpy(
ctl_lo.ctlx.sinc = 0;
ctl_lo.ctlx.dinc = 0;
} else {
- if (mids->dma_slave.direction == DMA_TO_DEVICE) {
+ if (mids->dma_slave.direction == DMA_MEM_TO_DEV) {
ctl_lo.ctlx.sinc = 0;
ctl_lo.ctlx.dinc = 2;
ctl_lo.ctlx.tt_fc = 1;
- } else if (mids->dma_slave.direction == DMA_FROM_DEVICE) {
+ } else if (mids->dma_slave.direction == DMA_DEV_TO_MEM) {
ctl_lo.ctlx.sinc = 2;
ctl_lo.ctlx.dinc = 0;
ctl_lo.ctlx.tt_fc = 2;
@@ -732,7 +737,7 @@ err_desc_get:
*/
static struct dma_async_tx_descriptor *intel_mid_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct intel_mid_dma_chan *midc = NULL;
@@ -868,7 +873,7 @@ static int intel_mid_dma_alloc_chan_resources(struct dma_chan *chan)
pm_runtime_get_sync(&mid->pdev->dev);
if (mid->state == SUSPENDED) {
- if (dma_resume(mid->pdev)) {
+ if (dma_resume(&mid->pdev->dev)) {
pr_err("ERR_MDMA: resume failed");
return -EFAULT;
}
@@ -1099,7 +1104,8 @@ static int mid_setup_dma(struct pci_dev *pdev)
LNW_PERIPHRAL_MASK_SIZE);
if (dma->mask_reg == NULL) {
pr_err("ERR_MDMA:Can't map periphral intr space !!\n");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_ioremap;
}
} else
dma->mask_reg = NULL;
@@ -1196,6 +1202,9 @@ static int mid_setup_dma(struct pci_dev *pdev)
err_engine:
free_irq(pdev->irq, dma);
err_irq:
+ if (dma->mask_reg)
+ iounmap(dma->mask_reg);
+err_ioremap:
pci_pool_destroy(dma->dma_pool);
err_dma_pool:
pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
@@ -1337,8 +1346,9 @@ static void __devexit intel_mid_dma_remove(struct pci_dev *pdev)
*
* This function is called by OS when a power event occurs
*/
-int dma_suspend(struct pci_dev *pci, pm_message_t state)
+static int dma_suspend(struct device *dev)
{
+ struct pci_dev *pci = to_pci_dev(dev);
int i;
struct middma_device *device = pci_get_drvdata(pci);
pr_debug("MDMA: dma_suspend called\n");
@@ -1362,8 +1372,9 @@ int dma_suspend(struct pci_dev *pci, pm_message_t state)
*
* This function is called by OS when a power event occurs
*/
-int dma_resume(struct pci_dev *pci)
+int dma_resume(struct device *dev)
{
+ struct pci_dev *pci = to_pci_dev(dev);
int ret;
struct middma_device *device = pci_get_drvdata(pci);
@@ -1429,6 +1440,8 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
.runtime_suspend = dma_runtime_suspend,
.runtime_resume = dma_runtime_resume,
.runtime_idle = dma_runtime_idle,
+ .suspend = dma_suspend,
+ .resume = dma_resume,
};
static struct pci_driver intel_mid_dma_pci_driver = {
@@ -1437,8 +1450,6 @@ static struct pci_driver intel_mid_dma_pci_driver = {
.probe = intel_mid_dma_probe,
.remove = __devexit_p(intel_mid_dma_remove),
#ifdef CONFIG_PM
- .suspend = dma_suspend,
- .resume = dma_resume,
.driver = {
.pm = &intel_mid_dma_pm,
},
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
index aea5ee8..c83d35b 100644
--- a/drivers/dma/intel_mid_dma_regs.h
+++ b/drivers/dma/intel_mid_dma_regs.h
@@ -262,7 +262,7 @@ struct intel_mid_dma_desc {
unsigned int lli_length;
unsigned int current_lli;
dma_addr_t next;
- enum dma_data_direction dirn;
+ enum dma_transfer_direction dirn;
enum dma_status status;
enum dma_slave_buswidth width; /*width of DMA txn*/
enum intel_mid_dma_mode cfg_mode; /*mode configuration*/
@@ -296,6 +296,6 @@ static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
}
-int dma_resume(struct pci_dev *pci);
+int dma_resume(struct device *dev);
#endif /*__INTEL_MID_DMAC_REGS_H__*/
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index e03f811..04be90b 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1735,8 +1735,6 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
spin_unlock_bh(&iop_chan->lock);
}
-MODULE_ALIAS("platform:iop-adma");
-
static struct platform_driver iop_adma_driver = {
.probe = iop_adma_probe,
.remove = __devexit_p(iop_adma_remove),
@@ -1746,19 +1744,9 @@ static struct platform_driver iop_adma_driver = {
},
};
-static int __init iop_adma_init (void)
-{
- return platform_driver_register(&iop_adma_driver);
-}
-
-static void __exit iop_adma_exit (void)
-{
- platform_driver_unregister(&iop_adma_driver);
- return;
-}
-module_exit(iop_adma_exit);
-module_init(iop_adma_init);
+module_platform_driver(iop_adma_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("IOP ADMA Engine Driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:iop-adma");
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index 0e5ef33..6212b16 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -312,7 +312,7 @@ static void ipu_ch_param_set_size(union chan_param_mem *params,
case IPU_PIX_FMT_RGB565:
params->ip.bpp = 2;
params->ip.pfs = 4;
- params->ip.npb = 7;
+ params->ip.npb = 15;
params->ip.sat = 2; /* SAT = 32-bit access */
params->ip.ofs0 = 0; /* Red bit offset */
params->ip.ofs1 = 5; /* Green bit offset */
@@ -422,12 +422,6 @@ static void ipu_ch_param_set_size(union chan_param_mem *params,
params->pp.nsb = 1;
}
-static void ipu_ch_param_set_burst_size(union chan_param_mem *params,
- uint16_t burst_pixels)
-{
- params->pp.npb = burst_pixels - 1;
-}
-
static void ipu_ch_param_set_buffer(union chan_param_mem *params,
dma_addr_t buf0, dma_addr_t buf1)
{
@@ -690,23 +684,6 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan,
ipu_ch_param_set_size(&params, pixel_fmt, width, height, stride_bytes);
ipu_ch_param_set_buffer(&params, phyaddr_0, phyaddr_1);
ipu_ch_param_set_rotation(&params, rot_mode);
- /* Some channels (rotation) have restriction on burst length */
- switch (channel) {
- case IDMAC_IC_7: /* Hangs with burst 8, 16, other values
- invalid - Table 44-30 */
-/*
- ipu_ch_param_set_burst_size(&params, 8);
- */
- break;
- case IDMAC_SDC_0:
- case IDMAC_SDC_1:
- /* In original code only IPU_PIX_FMT_RGB565 was setting burst */
- ipu_ch_param_set_burst_size(&params, 16);
- break;
- case IDMAC_IC_0:
- default:
- break;
- }
spin_lock_irqsave(&ipu->lock, flags);
@@ -1364,7 +1341,7 @@ static void ipu_gc_tasklet(unsigned long arg)
/* Allocate and initialise a transfer descriptor. */
static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan,
struct scatterlist *sgl, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long tx_flags)
+ enum dma_transfer_direction direction, unsigned long tx_flags)
{
struct idmac_channel *ichan = to_idmac_chan(chan);
struct idmac_tx_desc *desc = NULL;
@@ -1376,7 +1353,7 @@ static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan
chan->chan_id != IDMAC_IC_7)
return NULL;
- if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) {
+ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) {
dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction);
return NULL;
}
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 8ba4edc..4d6d4cf 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -835,17 +835,7 @@ static struct platform_driver mpc_dma_driver = {
},
};
-static int __init mpc_dma_init(void)
-{
- return platform_driver_register(&mpc_dma_driver);
-}
-module_init(mpc_dma_init);
-
-static void __exit mpc_dma_exit(void)
-{
- platform_driver_unregister(&mpc_dma_driver);
-}
-module_exit(mpc_dma_exit);
+module_platform_driver(mpc_dma_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index fc903c0..b06cd4c 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -44,7 +44,6 @@
#define HW_APBHX_CTRL0 0x000
#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29)
#define BM_APBH_CTRL0_APB_BURST_EN (1 << 28)
-#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8
#define BP_APBH_CTRL0_RESET_CHANNEL 16
#define HW_APBHX_CTRL1 0x010
#define HW_APBHX_CTRL2 0x020
@@ -111,6 +110,7 @@ struct mxs_dma_chan {
int chan_irq;
struct mxs_dma_ccw *ccw;
dma_addr_t ccw_phys;
+ int desc_count;
dma_cookie_t last_completed;
enum dma_status status;
unsigned int flags;
@@ -130,23 +130,6 @@ struct mxs_dma_engine {
struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
};
-static inline void mxs_dma_clkgate(struct mxs_dma_chan *mxs_chan, int enable)
-{
- struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
- int chan_id = mxs_chan->chan.chan_id;
- int set_clr = enable ? MXS_CLR_ADDR : MXS_SET_ADDR;
-
- /* enable apbh channel clock */
- if (dma_is_apbh()) {
- if (apbh_is_old())
- writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
- mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
- else
- writel(1 << chan_id,
- mxs_dma->base + HW_APBHX_CTRL0 + set_clr);
- }
-}
-
static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
{
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -165,9 +148,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id;
- /* clkgate needs to be enabled before writing other registers */
- mxs_dma_clkgate(mxs_chan, 1);
-
/* set cmd_addr up */
writel(mxs_chan->ccw_phys,
mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
@@ -178,9 +158,6 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
{
- /* disable apbh channel clock */
- mxs_dma_clkgate(mxs_chan, 0);
-
mxs_chan->status = DMA_SUCCESS;
}
@@ -268,7 +245,7 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
/*
* When both completion and error of termination bits set at the
* same time, we do not take it as an error. IOW, it only becomes
- * an error we need to handler here in case of ether it's (1) an bus
+ * an error we need to handle here in case of either it's (1) a bus
* error or (2) a termination error with no completion.
*/
stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */
@@ -338,10 +315,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto err_clk;
- /* clkgate needs to be enabled for reset to finish */
- mxs_dma_clkgate(mxs_chan, 1);
mxs_dma_reset_chan(mxs_chan);
- mxs_dma_clkgate(mxs_chan, 0);
dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
@@ -377,7 +351,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long append)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
@@ -386,7 +360,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
struct scatterlist *sg;
int i, j;
u32 *pio;
- static int idx;
+ int idx = append ? mxs_chan->desc_count : 0;
if (mxs_chan->status == DMA_IN_PROGRESS && !append)
return NULL;
@@ -417,7 +391,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
idx = 0;
}
- if (direction == DMA_NONE) {
+ if (direction == DMA_TRANS_NONE) {
ccw = &mxs_chan->ccw[idx++];
pio = (u32 *) sgl;
@@ -450,7 +424,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
ccw->bits |= CCW_CHAIN;
ccw->bits |= CCW_HALT_ON_TERM;
ccw->bits |= CCW_TERM_FLUSH;
- ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+ ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ?
MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ,
COMMAND);
@@ -462,6 +436,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
}
}
}
+ mxs_chan->desc_count = idx;
return &mxs_chan->desc;
@@ -472,7 +447,7 @@ err_out:
static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -515,7 +490,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_HALT_ON_TERM;
ccw->bits |= CCW_TERM_FLUSH;
- ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+ ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ?
MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
dma_addr += period_len;
@@ -523,6 +498,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
i++;
}
+ mxs_chan->desc_count = i;
return &mxs_chan->desc;
@@ -539,8 +515,8 @@ static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
switch (cmd) {
case DMA_TERMINATE_ALL:
- mxs_dma_disable_chan(mxs_chan);
mxs_dma_reset_chan(mxs_chan);
+ mxs_dma_disable_chan(mxs_chan);
break;
case DMA_PAUSE:
mxs_dma_pause_chan(mxs_chan);
@@ -580,7 +556,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
ret = clk_prepare_enable(mxs_dma->clk);
if (ret)
- goto err_out;
+ return ret;
ret = mxs_reset_block(mxs_dma->base);
if (ret)
@@ -604,11 +580,8 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
- clk_disable_unprepare(mxs_dma->clk);
-
- return 0;
-
err_out:
+ clk_disable_unprepare(mxs_dma->clk);
return ret;
}
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index a6d0e3d..823f581 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -1,7 +1,7 @@
/*
* Topcliff PCH DMA controller driver
* Copyright (c) 2010 Intel Corporation
- * Copyright (C) 2011 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS Semiconductor Co., 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
@@ -99,7 +99,7 @@ struct pch_dma_desc {
struct pch_dma_chan {
struct dma_chan chan;
void __iomem *membase;
- enum dma_data_direction dir;
+ enum dma_transfer_direction dir;
struct tasklet_struct tasklet;
unsigned long err_status;
@@ -224,7 +224,7 @@ static void pdc_set_dir(struct dma_chan *chan)
mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
(DMA_CTL0_BITS_PER_CH * chan->chan_id));
val &= mask_mode;
- if (pd_chan->dir == DMA_TO_DEVICE)
+ if (pd_chan->dir == DMA_MEM_TO_DEV)
val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
DMA_CTL0_DIR_SHIFT_BITS);
else
@@ -242,7 +242,7 @@ static void pdc_set_dir(struct dma_chan *chan)
mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
(DMA_CTL0_BITS_PER_CH * ch));
val &= mask_mode;
- if (pd_chan->dir == DMA_TO_DEVICE)
+ if (pd_chan->dir == DMA_MEM_TO_DEV)
val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch +
DMA_CTL0_DIR_SHIFT_BITS);
else
@@ -607,7 +607,7 @@ static void pd_issue_pending(struct dma_chan *chan)
static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
struct scatterlist *sgl, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long flags)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct pch_dma_chan *pd_chan = to_pd_chan(chan);
struct pch_dma_slave *pd_slave = chan->private;
@@ -623,9 +623,9 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
return NULL;
}
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
reg = pd_slave->rx_reg;
- else if (direction == DMA_TO_DEVICE)
+ else if (direction == DMA_MEM_TO_DEV)
reg = pd_slave->tx_reg;
else
return NULL;
@@ -1018,6 +1018,8 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev)
#define PCI_DEVICE_ID_ML7223_DMA2_4CH 0x800E
#define PCI_DEVICE_ID_ML7223_DMA3_4CH 0x8017
#define PCI_DEVICE_ID_ML7223_DMA4_4CH 0x803B
+#define PCI_DEVICE_ID_ML7831_DMA1_8CH 0x8810
+#define PCI_DEVICE_ID_ML7831_DMA2_4CH 0x8815
DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 },
@@ -1030,6 +1032,8 @@ DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA1_8CH), 8}, /* UART */
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA2_4CH), 4}, /* SPI */
{ 0, },
};
@@ -1057,7 +1061,7 @@ static void __exit pch_dma_exit(void)
module_init(pch_dma_init);
module_exit(pch_dma_exit);
-MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH "
+MODULE_DESCRIPTION("Intel EG20T PCH / LAPIS Semicon ML7213/ML7223/ML7831 IOH "
"DMA controller driver");
MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 09adcfc..b8ec03e 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -350,14 +350,14 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
case DMA_SLAVE_CONFIG:
slave_config = (struct dma_slave_config *)arg;
- if (slave_config->direction == DMA_TO_DEVICE) {
+ if (slave_config->direction == DMA_MEM_TO_DEV) {
if (slave_config->dst_addr)
pch->fifo_addr = slave_config->dst_addr;
if (slave_config->dst_addr_width)
pch->burst_sz = __ffs(slave_config->dst_addr_width);
if (slave_config->dst_maxburst)
pch->burst_len = slave_config->dst_maxburst;
- } else if (slave_config->direction == DMA_FROM_DEVICE) {
+ } else if (slave_config->direction == DMA_DEV_TO_MEM) {
if (slave_config->src_addr)
pch->fifo_addr = slave_config->src_addr;
if (slave_config->src_addr_width)
@@ -621,7 +621,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
- size_t period_len, enum dma_data_direction direction)
+ size_t period_len, enum dma_transfer_direction direction)
{
struct dma_pl330_desc *desc;
struct dma_pl330_chan *pch = to_pchan(chan);
@@ -636,14 +636,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
}
switch (direction) {
- case DMA_TO_DEVICE:
+ case DMA_MEM_TO_DEV:
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
desc->req.rqtype = MEMTODEV;
src = dma_addr;
dst = pch->fifo_addr;
break;
- case DMA_FROM_DEVICE:
+ case DMA_DEV_TO_MEM:
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
desc->req.rqtype = DEVTOMEM;
@@ -710,7 +710,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
static struct dma_async_tx_descriptor *
pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flg)
{
struct dma_pl330_desc *first, *desc = NULL;
@@ -759,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
else
list_add_tail(&desc->node, &first->node);
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
desc->req.rqtype = MEMTODEV;
@@ -834,17 +834,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, pdmac);
-#ifdef CONFIG_PM_RUNTIME
- /* to use the runtime PM helper functions */
- pm_runtime_enable(&adev->dev);
-
- /* enable the power domain */
- if (pm_runtime_get_sync(&adev->dev)) {
- dev_err(&adev->dev, "failed to get runtime pm\n");
- ret = -ENODEV;
- goto probe_err1;
- }
-#else
+#ifndef CONFIG_PM_RUNTIME
/* enable dma clk */
clk_enable(pdmac->clk);
#endif
@@ -977,10 +967,7 @@ static int __devexit pl330_remove(struct amba_device *adev)
res = &adev->res;
release_mem_region(res->start, resource_size(res));
-#ifdef CONFIG_PM_RUNTIME
- pm_runtime_put(&adev->dev);
- pm_runtime_disable(&adev->dev);
-#else
+#ifndef CONFIG_PM_RUNTIME
clk_disable(pdmac->clk);
#endif
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 81809c2..54043cd 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -23,7 +23,6 @@
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
#include <linux/delay.h>
-#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sh_dma.h>
@@ -57,6 +56,15 @@ static LIST_HEAD(sh_dmae_devices);
static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
+static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+ __raw_writel(data, shdev->chan_reg +
+ shdev->pdata->channel[sh_dc->id].chclr_offset);
+}
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
@@ -129,6 +137,15 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME);
+ if (shdev->pdata->chclr_present) {
+ int i;
+ for (i = 0; i < shdev->pdata->channel_num; i++) {
+ struct sh_dmae_chan *sh_chan = shdev->chan[i];
+ if (sh_chan)
+ chclr_write(sh_chan, 0);
+ }
+ }
+
dmaor_write(shdev, dmaor | shdev->pdata->dmaor_init);
dmaor = dmaor_read(shdev);
@@ -139,6 +156,10 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n");
return -EIO;
}
+ if (shdev->pdata->dmaor_init & ~dmaor)
+ dev_warn(shdev->common.dev,
+ "DMAOR=0x%x hasn't latched the initial value 0x%x.\n",
+ dmaor, shdev->pdata->dmaor_init);
return 0;
}
@@ -259,8 +280,6 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
return 0;
}
-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
-
static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
@@ -340,6 +359,8 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
sh_chan_xfer_ld_queue(sh_chan);
sh_chan->pm_state = DMAE_PM_ESTABLISHED;
}
+ } else {
+ sh_chan->pm_state = DMAE_PM_PENDING;
}
spin_unlock_irq(&sh_chan->desc_lock);
@@ -479,19 +500,19 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
* @sh_chan: DMA channel
* @flags: DMA transfer flags
* @dest: destination DMA address, incremented when direction equals
- * DMA_FROM_DEVICE or DMA_BIDIRECTIONAL
+ * DMA_DEV_TO_MEM
* @src: source DMA address, incremented when direction equals
- * DMA_TO_DEVICE or DMA_BIDIRECTIONAL
+ * DMA_MEM_TO_DEV
* @len: DMA transfer length
* @first: if NULL, set to the current descriptor and cookie set to -EBUSY
* @direction: needed for slave DMA to decide which address to keep constant,
- * equals DMA_BIDIRECTIONAL for MEMCPY
+ * equals DMA_MEM_TO_MEM for MEMCPY
* Returns 0 or an error
* Locks: called with desc_lock held
*/
static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
- struct sh_desc **first, enum dma_data_direction direction)
+ struct sh_desc **first, enum dma_transfer_direction direction)
{
struct sh_desc *new;
size_t copy_size;
@@ -531,9 +552,9 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
new->direction = direction;
*len -= copy_size;
- if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE)
+ if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
*src += copy_size;
- if (direction == DMA_BIDIRECTIONAL || direction == DMA_FROM_DEVICE)
+ if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
*dest += copy_size;
return new;
@@ -546,12 +567,12 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
* converted to scatter-gather to guarantee consistent locking and a correct
* list manipulation. For slave DMA direction carries the usual meaning, and,
* logically, the SG list is RAM and the addr variable contains slave address,
- * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_BIDIRECTIONAL
+ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
* and the SG list contains only one element and points at the source buffer.
*/
static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
- enum dma_data_direction direction, unsigned long flags)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct scatterlist *sg;
struct sh_desc *first = NULL, *new = NULL /* compiler... */;
@@ -592,7 +613,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_c
dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
i, sg, len, (unsigned long long)sg_addr);
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
new = sh_dmae_add_desc(sh_chan, flags,
&sg_addr, addr, &len, &first,
direction);
@@ -646,13 +667,13 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
sg_dma_address(&sg) = dma_src;
sg_dma_len(&sg) = len;
- return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_BIDIRECTIONAL,
+ return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM,
flags);
}
static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long flags)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct sh_dmae_slave *param;
struct sh_dmae_chan *sh_chan;
@@ -996,7 +1017,7 @@ static void dmae_do_tasklet(unsigned long data)
spin_lock_irq(&sh_chan->desc_lock);
list_for_each_entry(desc, &sh_chan->ld_queue, node) {
if (desc->mark == DESC_SUBMITTED &&
- ((desc->direction == DMA_FROM_DEVICE &&
+ ((desc->direction == DMA_DEV_TO_MEM &&
(desc->hw.dar + desc->hw.tcr) == dar_buf) ||
(desc->hw.sar + desc->hw.tcr) == sar_buf)) {
dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
@@ -1225,6 +1246,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, shdev);
+ shdev->common.dev = &pdev->dev;
+
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
@@ -1254,7 +1277,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
shdev->common.device_control = sh_dmae_control;
- shdev->common.dev = &pdev->dev;
/* Default transfer size of 32 bytes requires 32-byte alignment */
shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
@@ -1435,22 +1457,17 @@ static int sh_dmae_runtime_resume(struct device *dev)
#ifdef CONFIG_PM
static int sh_dmae_suspend(struct device *dev)
{
- struct sh_dmae_device *shdev = dev_get_drvdata(dev);
- int i;
-
- for (i = 0; i < shdev->pdata->channel_num; i++) {
- struct sh_dmae_chan *sh_chan = shdev->chan[i];
- if (sh_chan->descs_allocated)
- sh_chan->pm_error = pm_runtime_put_sync(dev);
- }
-
return 0;
}
static int sh_dmae_resume(struct device *dev)
{
struct sh_dmae_device *shdev = dev_get_drvdata(dev);
- int i;
+ int i, ret;
+
+ ret = sh_dmae_rst(shdev);
+ if (ret < 0)
+ dev_err(dev, "Failed to reset!\n");
for (i = 0; i < shdev->pdata->channel_num; i++) {
struct sh_dmae_chan *sh_chan = shdev->chan[i];
@@ -1459,9 +1476,6 @@ static int sh_dmae_resume(struct device *dev)
if (!sh_chan->descs_allocated)
continue;
- if (!sh_chan->pm_error)
- pm_runtime_get_sync(dev);
-
if (param) {
const struct sh_dmae_slave_config *cfg = param->config;
dmae_set_dmars(sh_chan, cfg->mid_rid);
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
new file mode 100644
index 0000000..2333810
--- /dev/null
+++ b/drivers/dma/sirf-dma.c
@@ -0,0 +1,707 @@
+/*
+ * DMA controller driver for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/sirfsoc_dma.h>
+
+#define SIRFSOC_DMA_DESCRIPTORS 16
+#define SIRFSOC_DMA_CHANNELS 16
+
+#define SIRFSOC_DMA_CH_ADDR 0x00
+#define SIRFSOC_DMA_CH_XLEN 0x04
+#define SIRFSOC_DMA_CH_YLEN 0x08
+#define SIRFSOC_DMA_CH_CTRL 0x0C
+
+#define SIRFSOC_DMA_WIDTH_0 0x100
+#define SIRFSOC_DMA_CH_VALID 0x140
+#define SIRFSOC_DMA_CH_INT 0x144
+#define SIRFSOC_DMA_INT_EN 0x148
+#define SIRFSOC_DMA_CH_LOOP_CTRL 0x150
+
+#define SIRFSOC_DMA_MODE_CTRL_BIT 4
+#define SIRFSOC_DMA_DIR_CTRL_BIT 5
+
+/* xlen and dma_width register is in 4 bytes boundary */
+#define SIRFSOC_DMA_WORD_LEN 4
+
+struct sirfsoc_dma_desc {
+ struct dma_async_tx_descriptor desc;
+ struct list_head node;
+
+ /* SiRFprimaII 2D-DMA parameters */
+
+ int xlen; /* DMA xlen */
+ int ylen; /* DMA ylen */
+ int width; /* DMA width */
+ int dir;
+ bool cyclic; /* is loop DMA? */
+ u32 addr; /* DMA buffer address */
+};
+
+struct sirfsoc_dma_chan {
+ struct dma_chan chan;
+ struct list_head free;
+ struct list_head prepared;
+ struct list_head queued;
+ struct list_head active;
+ struct list_head completed;
+ dma_cookie_t completed_cookie;
+ unsigned long happened_cyclic;
+ unsigned long completed_cyclic;
+
+ /* Lock for this structure */
+ spinlock_t lock;
+
+ int mode;
+};
+
+struct sirfsoc_dma {
+ struct dma_device dma;
+ struct tasklet_struct tasklet;
+ struct sirfsoc_dma_chan channels[SIRFSOC_DMA_CHANNELS];
+ void __iomem *base;
+ int irq;
+};
+
+#define DRV_NAME "sirfsoc_dma"
+
+/* Convert struct dma_chan to struct sirfsoc_dma_chan */
+static inline
+struct sirfsoc_dma_chan *dma_chan_to_sirfsoc_dma_chan(struct dma_chan *c)
+{
+ return container_of(c, struct sirfsoc_dma_chan, chan);
+}
+
+/* Convert struct dma_chan to struct sirfsoc_dma */
+static inline struct sirfsoc_dma *dma_chan_to_sirfsoc_dma(struct dma_chan *c)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(c);
+ return container_of(schan, struct sirfsoc_dma, channels[c->chan_id]);
+}
+
+/* Execute all queued DMA descriptors */
+static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
+{
+ struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
+ int cid = schan->chan.chan_id;
+ struct sirfsoc_dma_desc *sdesc = NULL;
+
+ /*
+ * lock has been held by functions calling this, so we don't hold
+ * lock again
+ */
+
+ sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
+ node);
+ /* Move the first queued descriptor to active list */
+ list_move_tail(&schan->queued, &schan->active);
+
+ /* Start the DMA transfer */
+ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
+ cid * 4);
+ writel_relaxed(cid | (schan->mode << SIRFSOC_DMA_MODE_CTRL_BIT) |
+ (sdesc->dir << SIRFSOC_DMA_DIR_CTRL_BIT),
+ sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_CTRL);
+ writel_relaxed(sdesc->xlen, sdma->base + cid * 0x10 +
+ SIRFSOC_DMA_CH_XLEN);
+ writel_relaxed(sdesc->ylen, sdma->base + cid * 0x10 +
+ SIRFSOC_DMA_CH_YLEN);
+ writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) |
+ (1 << cid), sdma->base + SIRFSOC_DMA_INT_EN);
+
+ /*
+ * writel has an implict memory write barrier to make sure data is
+ * flushed into memory before starting DMA
+ */
+ writel(sdesc->addr >> 2, sdma->base + cid * 0x10 + SIRFSOC_DMA_CH_ADDR);
+
+ if (sdesc->cyclic) {
+ writel((1 << cid) | 1 << (cid + 16) |
+ readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL),
+ sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
+ schan->happened_cyclic = schan->completed_cyclic = 0;
+ }
+}
+
+/* Interrupt handler */
+static irqreturn_t sirfsoc_dma_irq(int irq, void *data)
+{
+ struct sirfsoc_dma *sdma = data;
+ struct sirfsoc_dma_chan *schan;
+ struct sirfsoc_dma_desc *sdesc = NULL;
+ u32 is;
+ int ch;
+
+ is = readl(sdma->base + SIRFSOC_DMA_CH_INT);
+ while ((ch = fls(is) - 1) >= 0) {
+ is &= ~(1 << ch);
+ writel_relaxed(1 << ch, sdma->base + SIRFSOC_DMA_CH_INT);
+ schan = &sdma->channels[ch];
+
+ spin_lock(&schan->lock);
+
+ sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc,
+ node);
+ if (!sdesc->cyclic) {
+ /* Execute queued descriptors */
+ list_splice_tail_init(&schan->active, &schan->completed);
+ if (!list_empty(&schan->queued))
+ sirfsoc_dma_execute(schan);
+ } else
+ schan->happened_cyclic++;
+
+ spin_unlock(&schan->lock);
+ }
+
+ /* Schedule tasklet */
+ tasklet_schedule(&sdma->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+/* process completed descriptors */
+static void sirfsoc_dma_process_completed(struct sirfsoc_dma *sdma)
+{
+ dma_cookie_t last_cookie = 0;
+ struct sirfsoc_dma_chan *schan;
+ struct sirfsoc_dma_desc *sdesc;
+ struct dma_async_tx_descriptor *desc;
+ unsigned long flags;
+ unsigned long happened_cyclic;
+ LIST_HEAD(list);
+ int i;
+
+ for (i = 0; i < sdma->dma.chancnt; i++) {
+ schan = &sdma->channels[i];
+
+ /* Get all completed descriptors */
+ spin_lock_irqsave(&schan->lock, flags);
+ if (!list_empty(&schan->completed)) {
+ list_splice_tail_init(&schan->completed, &list);
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ /* Execute callbacks and run dependencies */
+ list_for_each_entry(sdesc, &list, node) {
+ desc = &sdesc->desc;
+
+ if (desc->callback)
+ desc->callback(desc->callback_param);
+
+ last_cookie = desc->cookie;
+ dma_run_dependencies(desc);
+ }
+
+ /* Free descriptors */
+ spin_lock_irqsave(&schan->lock, flags);
+ list_splice_tail_init(&list, &schan->free);
+ schan->completed_cookie = last_cookie;
+ spin_unlock_irqrestore(&schan->lock, flags);
+ } else {
+ /* for cyclic channel, desc is always in active list */
+ sdesc = list_first_entry(&schan->active, struct sirfsoc_dma_desc,
+ node);
+
+ if (!sdesc || (sdesc && !sdesc->cyclic)) {
+ /* without active cyclic DMA */
+ spin_unlock_irqrestore(&schan->lock, flags);
+ continue;
+ }
+
+ /* cyclic DMA */
+ happened_cyclic = schan->happened_cyclic;
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ desc = &sdesc->desc;
+ while (happened_cyclic != schan->completed_cyclic) {
+ if (desc->callback)
+ desc->callback(desc->callback_param);
+ schan->completed_cyclic++;
+ }
+ }
+ }
+}
+
+/* DMA Tasklet */
+static void sirfsoc_dma_tasklet(unsigned long data)
+{
+ struct sirfsoc_dma *sdma = (void *)data;
+
+ sirfsoc_dma_process_completed(sdma);
+}
+
+/* Submit descriptor to hardware */
+static dma_cookie_t sirfsoc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(txd->chan);
+ struct sirfsoc_dma_desc *sdesc;
+ unsigned long flags;
+ dma_cookie_t cookie;
+
+ sdesc = container_of(txd, struct sirfsoc_dma_desc, desc);
+
+ spin_lock_irqsave(&schan->lock, flags);
+
+ /* Move descriptor to queue */
+ list_move_tail(&sdesc->node, &schan->queued);
+
+ /* Update cookie */
+ cookie = schan->chan.cookie + 1;
+ if (cookie <= 0)
+ cookie = 1;
+
+ schan->chan.cookie = cookie;
+ sdesc->desc.cookie = cookie;
+
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ return cookie;
+}
+
+static int sirfsoc_dma_slave_config(struct sirfsoc_dma_chan *schan,
+ struct dma_slave_config *config)
+{
+ unsigned long flags;
+
+ if ((config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+ (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES))
+ return -EINVAL;
+
+ spin_lock_irqsave(&schan->lock, flags);
+ schan->mode = (config->src_maxburst == 4 ? 1 : 0);
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ return 0;
+}
+
+static int sirfsoc_dma_terminate_all(struct sirfsoc_dma_chan *schan)
+{
+ struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
+ int cid = schan->chan.chan_id;
+ unsigned long flags;
+
+ writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_INT_EN) &
+ ~(1 << cid), sdma->base + SIRFSOC_DMA_INT_EN);
+ writel_relaxed(1 << cid, sdma->base + SIRFSOC_DMA_CH_VALID);
+
+ writel_relaxed(readl_relaxed(sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL)
+ & ~((1 << cid) | 1 << (cid + 16)),
+ sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
+
+ spin_lock_irqsave(&schan->lock, flags);
+ list_splice_tail_init(&schan->active, &schan->free);
+ list_splice_tail_init(&schan->queued, &schan->free);
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ return 0;
+}
+
+static int sirfsoc_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct dma_slave_config *config;
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+
+ switch (cmd) {
+ case DMA_TERMINATE_ALL:
+ return sirfsoc_dma_terminate_all(schan);
+ case DMA_SLAVE_CONFIG:
+ config = (struct dma_slave_config *)arg;
+ return sirfsoc_dma_slave_config(schan, config);
+
+ default:
+ break;
+ }
+
+ return -ENOSYS;
+}
+
+/* Alloc channel resources */
+static int sirfsoc_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan);
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ struct sirfsoc_dma_desc *sdesc;
+ unsigned long flags;
+ LIST_HEAD(descs);
+ int i;
+
+ /* Alloc descriptors for this channel */
+ for (i = 0; i < SIRFSOC_DMA_DESCRIPTORS; i++) {
+ sdesc = kzalloc(sizeof(*sdesc), GFP_KERNEL);
+ if (!sdesc) {
+ dev_notice(sdma->dma.dev, "Memory allocation error. "
+ "Allocated only %u descriptors\n", i);
+ break;
+ }
+
+ dma_async_tx_descriptor_init(&sdesc->desc, chan);
+ sdesc->desc.flags = DMA_CTRL_ACK;
+ sdesc->desc.tx_submit = sirfsoc_dma_tx_submit;
+
+ list_add_tail(&sdesc->node, &descs);
+ }
+
+ /* Return error only if no descriptors were allocated */
+ if (i == 0)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&schan->lock, flags);
+
+ list_splice_tail_init(&descs, &schan->free);
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ return i;
+}
+
+/* Free channel resources */
+static void sirfsoc_dma_free_chan_resources(struct dma_chan *chan)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ struct sirfsoc_dma_desc *sdesc, *tmp;
+ unsigned long flags;
+ LIST_HEAD(descs);
+
+ spin_lock_irqsave(&schan->lock, flags);
+
+ /* Channel must be idle */
+ BUG_ON(!list_empty(&schan->prepared));
+ BUG_ON(!list_empty(&schan->queued));
+ BUG_ON(!list_empty(&schan->active));
+ BUG_ON(!list_empty(&schan->completed));
+
+ /* Move data */
+ list_splice_tail_init(&schan->free, &descs);
+
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ /* Free descriptors */
+ list_for_each_entry_safe(sdesc, tmp, &descs, node)
+ kfree(sdesc);
+}
+
+/* Send pending descriptor to hardware */
+static void sirfsoc_dma_issue_pending(struct dma_chan *chan)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&schan->lock, flags);
+
+ if (list_empty(&schan->active) && !list_empty(&schan->queued))
+ sirfsoc_dma_execute(schan);
+
+ spin_unlock_irqrestore(&schan->lock, flags);
+}
+
+/* Check request completion status */
+static enum dma_status
+sirfsoc_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ unsigned long flags;
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+
+ spin_lock_irqsave(&schan->lock, flags);
+ last_used = schan->chan.cookie;
+ last_complete = schan->completed_cookie;
+ spin_unlock_irqrestore(&schan->lock, flags);
+
+ dma_set_tx_state(txstate, last_complete, last_used, 0);
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
+ struct dma_chan *chan, struct dma_interleaved_template *xt,
+ unsigned long flags)
+{
+ struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(chan);
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ struct sirfsoc_dma_desc *sdesc = NULL;
+ unsigned long iflags;
+ int ret;
+
+ if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+ ret = -EINVAL;
+ goto err_dir;
+ }
+
+ /* Get free descriptor */
+ spin_lock_irqsave(&schan->lock, iflags);
+ if (!list_empty(&schan->free)) {
+ sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc,
+ node);
+ list_del(&sdesc->node);
+ }
+ spin_unlock_irqrestore(&schan->lock, iflags);
+
+ if (!sdesc) {
+ /* try to free completed descriptors */
+ sirfsoc_dma_process_completed(sdma);
+ ret = 0;
+ goto no_desc;
+ }
+
+ /* Place descriptor in prepared list */
+ spin_lock_irqsave(&schan->lock, iflags);
+
+ /*
+ * Number of chunks in a frame can only be 1 for prima2
+ * and ylen (number of frame - 1) must be at least 0
+ */
+ if ((xt->frame_size == 1) && (xt->numf > 0)) {
+ sdesc->cyclic = 0;
+ sdesc->xlen = xt->sgl[0].size / SIRFSOC_DMA_WORD_LEN;
+ sdesc->width = (xt->sgl[0].size + xt->sgl[0].icg) /
+ SIRFSOC_DMA_WORD_LEN;
+ sdesc->ylen = xt->numf - 1;
+ if (xt->dir == DMA_MEM_TO_DEV) {
+ sdesc->addr = xt->src_start;
+ sdesc->dir = 1;
+ } else {
+ sdesc->addr = xt->dst_start;
+ sdesc->dir = 0;
+ }
+
+ list_add_tail(&sdesc->node, &schan->prepared);
+ } else {
+ pr_err("sirfsoc DMA Invalid xfer\n");
+ ret = -EINVAL;
+ goto err_xfer;
+ }
+ spin_unlock_irqrestore(&schan->lock, iflags);
+
+ return &sdesc->desc;
+err_xfer:
+ spin_unlock_irqrestore(&schan->lock, iflags);
+no_desc:
+err_dir:
+ return ERR_PTR(ret);
+}
+
+static struct dma_async_tx_descriptor *
+sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
+ size_t buf_len, size_t period_len,
+ enum dma_transfer_direction direction)
+{
+ struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
+ struct sirfsoc_dma_desc *sdesc = NULL;
+ unsigned long iflags;
+
+ /*
+ * we only support cycle transfer with 2 period
+ * If the X-length is set to 0, it would be the loop mode.
+ * The DMA address keeps increasing until reaching the end of a loop
+ * area whose size is defined by (DMA_WIDTH x (Y_LENGTH + 1)). Then
+ * the DMA address goes back to the beginning of this area.
+ * In loop mode, the DMA data region is divided into two parts, BUFA
+ * and BUFB. DMA controller generates interrupts twice in each loop:
+ * when the DMA address reaches the end of BUFA or the end of the
+ * BUFB
+ */
+ if (buf_len != 2 * period_len)
+ return ERR_PTR(-EINVAL);
+
+ /* Get free descriptor */
+ spin_lock_irqsave(&schan->lock, iflags);
+ if (!list_empty(&schan->free)) {
+ sdesc = list_first_entry(&schan->free, struct sirfsoc_dma_desc,
+ node);
+ list_del(&sdesc->node);
+ }
+ spin_unlock_irqrestore(&schan->lock, iflags);
+
+ if (!sdesc)
+ return 0;
+
+ /* Place descriptor in prepared list */
+ spin_lock_irqsave(&schan->lock, iflags);
+ sdesc->addr = addr;
+ sdesc->cyclic = 1;
+ sdesc->xlen = 0;
+ sdesc->ylen = buf_len / SIRFSOC_DMA_WORD_LEN - 1;
+ sdesc->width = 1;
+ list_add_tail(&sdesc->node, &schan->prepared);
+ spin_unlock_irqrestore(&schan->lock, iflags);
+
+ return &sdesc->desc;
+}
+
+/*
+ * The DMA controller consists of 16 independent DMA channels.
+ * Each channel is allocated to a different function
+ */
+bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
+{
+ unsigned int ch_nr = (unsigned int) chan_id;
+
+ if (ch_nr == chan->chan_id +
+ chan->device->dev_id * SIRFSOC_DMA_CHANNELS)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(sirfsoc_dma_filter_id);
+
+static int __devinit sirfsoc_dma_probe(struct platform_device *op)
+{
+ struct device_node *dn = op->dev.of_node;
+ struct device *dev = &op->dev;
+ struct dma_device *dma;
+ struct sirfsoc_dma *sdma;
+ struct sirfsoc_dma_chan *schan;
+ struct resource res;
+ ulong regs_start, regs_size;
+ u32 id;
+ int ret, i;
+
+ sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
+ if (!sdma) {
+ dev_err(dev, "Memory exhausted!\n");
+ return -ENOMEM;
+ }
+
+ if (of_property_read_u32(dn, "cell-index", &id)) {
+ dev_err(dev, "Fail to get DMAC index\n");
+ ret = -ENODEV;
+ goto free_mem;
+ }
+
+ sdma->irq = irq_of_parse_and_map(dn, 0);
+ if (sdma->irq == NO_IRQ) {
+ dev_err(dev, "Error mapping IRQ!\n");
+ ret = -EINVAL;
+ goto free_mem;
+ }
+
+ ret = of_address_to_resource(dn, 0, &res);
+ if (ret) {
+ dev_err(dev, "Error parsing memory region!\n");
+ goto free_mem;
+ }
+
+ regs_start = res.start;
+ regs_size = resource_size(&res);
+
+ sdma->base = devm_ioremap(dev, regs_start, regs_size);
+ if (!sdma->base) {
+ dev_err(dev, "Error mapping memory region!\n");
+ ret = -ENOMEM;
+ goto irq_dispose;
+ }
+
+ ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME,
+ sdma);
+ if (ret) {
+ dev_err(dev, "Error requesting IRQ!\n");
+ ret = -EINVAL;
+ goto unmap_mem;
+ }
+
+ dma = &sdma->dma;
+ dma->dev = dev;
+ dma->chancnt = SIRFSOC_DMA_CHANNELS;
+
+ dma->device_alloc_chan_resources = sirfsoc_dma_alloc_chan_resources;
+ dma->device_free_chan_resources = sirfsoc_dma_free_chan_resources;
+ dma->device_issue_pending = sirfsoc_dma_issue_pending;
+ dma->device_control = sirfsoc_dma_control;
+ dma->device_tx_status = sirfsoc_dma_tx_status;
+ dma->device_prep_interleaved_dma = sirfsoc_dma_prep_interleaved;
+ dma->device_prep_dma_cyclic = sirfsoc_dma_prep_cyclic;
+
+ INIT_LIST_HEAD(&dma->channels);
+ dma_cap_set(DMA_SLAVE, dma->cap_mask);
+ dma_cap_set(DMA_CYCLIC, dma->cap_mask);
+ dma_cap_set(DMA_INTERLEAVE, dma->cap_mask);
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+ for (i = 0; i < dma->chancnt; i++) {
+ schan = &sdma->channels[i];
+
+ schan->chan.device = dma;
+ schan->chan.cookie = 1;
+ schan->completed_cookie = schan->chan.cookie;
+
+ INIT_LIST_HEAD(&schan->free);
+ INIT_LIST_HEAD(&schan->prepared);
+ INIT_LIST_HEAD(&schan->queued);
+ INIT_LIST_HEAD(&schan->active);
+ INIT_LIST_HEAD(&schan->completed);
+
+ spin_lock_init(&schan->lock);
+ list_add_tail(&schan->chan.device_node, &dma->channels);
+ }
+
+ tasklet_init(&sdma->tasklet, sirfsoc_dma_tasklet, (unsigned long)sdma);
+
+ /* Register DMA engine */
+ dev_set_drvdata(dev, sdma);
+ ret = dma_async_device_register(dma);
+ if (ret)
+ goto free_irq;
+
+ dev_info(dev, "initialized SIRFSOC DMAC driver\n");
+
+ return 0;
+
+free_irq:
+ devm_free_irq(dev, sdma->irq, sdma);
+irq_dispose:
+ irq_dispose_mapping(sdma->irq);
+unmap_mem:
+ iounmap(sdma->base);
+free_mem:
+ devm_kfree(dev, sdma);
+ return ret;
+}
+
+static int __devexit sirfsoc_dma_remove(struct platform_device *op)
+{
+ struct device *dev = &op->dev;
+ struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
+
+ dma_async_device_unregister(&sdma->dma);
+ devm_free_irq(dev, sdma->irq, sdma);
+ irq_dispose_mapping(sdma->irq);
+ iounmap(sdma->base);
+ devm_kfree(dev, sdma);
+ return 0;
+}
+
+static struct of_device_id sirfsoc_dma_match[] = {
+ { .compatible = "sirf,prima2-dmac", },
+ {},
+};
+
+static struct platform_driver sirfsoc_dma_driver = {
+ .probe = sirfsoc_dma_probe,
+ .remove = __devexit_p(sirfsoc_dma_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = sirfsoc_dma_match,
+ },
+};
+
+module_platform_driver(sirfsoc_dma_driver);
+
+MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
+ "Barry Song <baohua.song@csr.com>");
+MODULE_DESCRIPTION("SIRFSOC DMA control driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 13259ca..cc5ecbc 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/amba/bus.h>
@@ -32,6 +34,9 @@
/* Maximum iterations taken before giving up suspending a channel */
#define D40_SUSPEND_MAX_IT 500
+/* Milliseconds */
+#define DMA40_AUTOSUSPEND_DELAY 100
+
/* Hardware requirement on LCLA alignment */
#define LCLA_ALIGNMENT 0x40000
@@ -62,6 +67,55 @@ enum d40_command {
D40_DMA_SUSPENDED = 3
};
+/*
+ * These are the registers that has to be saved and later restored
+ * when the DMA hw is powered off.
+ * TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
+ */
+static u32 d40_backup_regs[] = {
+ D40_DREG_LCPA,
+ D40_DREG_LCLA,
+ D40_DREG_PRMSE,
+ D40_DREG_PRMSO,
+ D40_DREG_PRMOE,
+ D40_DREG_PRMOO,
+};
+
+#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs)
+
+/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */
+static u32 d40_backup_regs_v3[] = {
+ D40_DREG_PSEG1,
+ D40_DREG_PSEG2,
+ D40_DREG_PSEG3,
+ D40_DREG_PSEG4,
+ D40_DREG_PCEG1,
+ D40_DREG_PCEG2,
+ D40_DREG_PCEG3,
+ D40_DREG_PCEG4,
+ D40_DREG_RSEG1,
+ D40_DREG_RSEG2,
+ D40_DREG_RSEG3,
+ D40_DREG_RSEG4,
+ D40_DREG_RCEG1,
+ D40_DREG_RCEG2,
+ D40_DREG_RCEG3,
+ D40_DREG_RCEG4,
+};
+
+#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3)
+
+static u32 d40_backup_regs_chan[] = {
+ D40_CHAN_REG_SSCFG,
+ D40_CHAN_REG_SSELT,
+ D40_CHAN_REG_SSPTR,
+ D40_CHAN_REG_SSLNK,
+ D40_CHAN_REG_SDCFG,
+ D40_CHAN_REG_SDELT,
+ D40_CHAN_REG_SDPTR,
+ D40_CHAN_REG_SDLNK,
+};
+
/**
* struct d40_lli_pool - Structure for keeping LLIs in memory
*
@@ -96,7 +150,7 @@ struct d40_lli_pool {
* during a transfer.
* @node: List entry.
* @is_in_client_list: true if the client owns this descriptor.
- * the previous one.
+ * @cyclic: true if this is a cyclic job
*
* This descriptor is used for both logical and physical transfers.
*/
@@ -143,6 +197,7 @@ struct d40_lcla_pool {
* channels.
*
* @lock: A lock protection this entity.
+ * @reserved: True if used by secure world or otherwise.
* @num: The physical channel number of this entity.
* @allocated_src: Bit mapped to show which src event line's are mapped to
* this physical channel. Can also be free or physically allocated.
@@ -152,6 +207,7 @@ struct d40_lcla_pool {
*/
struct d40_phy_res {
spinlock_t lock;
+ bool reserved;
int num;
u32 allocated_src;
u32 allocated_dst;
@@ -185,7 +241,6 @@ struct d40_base;
* @src_def_cfg: Default cfg register setting for src.
* @dst_def_cfg: Default cfg register setting for dst.
* @log_def: Default logical channel settings.
- * @lcla: Space for one dst src pair for logical channel transfers.
* @lcpa: Pointer to dst and src lcpa settings.
* @runtime_addr: runtime configured address.
* @runtime_direction: runtime configured direction.
@@ -217,7 +272,7 @@ struct d40_chan {
struct d40_log_lli_full *lcpa;
/* Runtime reconfiguration */
dma_addr_t runtime_addr;
- enum dma_data_direction runtime_direction;
+ enum dma_transfer_direction runtime_direction;
};
/**
@@ -241,6 +296,7 @@ struct d40_chan {
* @dma_both: dma_device channels that can do both memcpy and slave transfers.
* @dma_slave: dma_device channels that can do only do slave transfers.
* @dma_memcpy: dma_device channels that can do only do memcpy transfers.
+ * @phy_chans: Room for all possible physical channels in system.
* @log_chans: Room for all possible logical channels in system.
* @lookup_log_chans: Used to map interrupt number to logical channel. Points
* to log_chans entries.
@@ -248,12 +304,20 @@ struct d40_chan {
* to phy_chans entries.
* @plat_data: Pointer to provided platform_data which is the driver
* configuration.
+ * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
* @phy_res: Vector containing all physical channels.
* @lcla_pool: lcla pool settings and data.
* @lcpa_base: The virtual mapped address of LCPA.
* @phy_lcpa: The physical address of the LCPA.
* @lcpa_size: The size of the LCPA area.
* @desc_slab: cache for descriptors.
+ * @reg_val_backup: Here the values of some hardware registers are stored
+ * before the DMA is powered off. They are restored when the power is back on.
+ * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and
+ * later.
+ * @reg_val_backup_chan: Backup data for standard channel parameter registers.
+ * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off.
+ * @initialized: true if the dma has been initialized
*/
struct d40_base {
spinlock_t interrupt_lock;
@@ -275,6 +339,7 @@ struct d40_base {
struct d40_chan **lookup_log_chans;
struct d40_chan **lookup_phy_chans;
struct stedma40_platform_data *plat_data;
+ struct regulator *lcpa_regulator;
/* Physical half channels */
struct d40_phy_res *phy_res;
struct d40_lcla_pool lcla_pool;
@@ -282,6 +347,11 @@ struct d40_base {
dma_addr_t phy_lcpa;
resource_size_t lcpa_size;
struct kmem_cache *desc_slab;
+ u32 reg_val_backup[BACKUP_REGS_SZ];
+ u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3];
+ u32 *reg_val_backup_chan;
+ u16 gcc_pwr_off_mask;
+ bool initialized;
};
/**
@@ -479,13 +549,14 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c)
struct d40_desc *d;
struct d40_desc *_d;
- list_for_each_entry_safe(d, _d, &d40c->client, node)
+ list_for_each_entry_safe(d, _d, &d40c->client, node) {
if (async_tx_test_ack(&d->txd)) {
d40_desc_remove(d);
desc = d;
memset(desc, 0, sizeof(*desc));
break;
}
+ }
}
if (!desc)
@@ -536,6 +607,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
bool cyclic = desc->cyclic;
int curr_lcla = -EINVAL;
int first_lcla = 0;
+ bool use_esram_lcla = chan->base->plat_data->use_esram_lcla;
bool linkback;
/*
@@ -608,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
&lli->src[lli_current],
next_lcla, flags);
- dma_sync_single_range_for_device(chan->base->dev,
- pool->dma_addr, lcla_offset,
- 2 * sizeof(struct d40_log_lli),
- DMA_TO_DEVICE);
-
+ /*
+ * Cache maintenance is not needed if lcla is
+ * mapped in esram
+ */
+ if (!use_esram_lcla) {
+ dma_sync_single_range_for_device(chan->base->dev,
+ pool->dma_addr, lcla_offset,
+ 2 * sizeof(struct d40_log_lli),
+ DMA_TO_DEVICE);
+ }
curr_lcla = next_lcla;
if (curr_lcla == -EINVAL || curr_lcla == first_lcla) {
@@ -740,7 +817,61 @@ static int d40_sg_2_dmalen(struct scatterlist *sgl, int sg_len,
return len;
}
-/* Support functions for logical channels */
+
+#ifdef CONFIG_PM
+static void dma40_backup(void __iomem *baseaddr, u32 *backup,
+ u32 *regaddr, int num, bool save)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ void __iomem *addr = baseaddr + regaddr[i];
+
+ if (save)
+ backup[i] = readl_relaxed(addr);
+ else
+ writel_relaxed(backup[i], addr);
+ }
+}
+
+static void d40_save_restore_registers(struct d40_base *base, bool save)
+{
+ int i;
+
+ /* Save/Restore channel specific registers */
+ for (i = 0; i < base->num_phy_chans; i++) {
+ void __iomem *addr;
+ int idx;
+
+ if (base->phy_res[i].reserved)
+ continue;
+
+ addr = base->virtbase + D40_DREG_PCBASE + i * D40_DREG_PCDELTA;
+ idx = i * ARRAY_SIZE(d40_backup_regs_chan);
+
+ dma40_backup(addr, &base->reg_val_backup_chan[idx],
+ d40_backup_regs_chan,
+ ARRAY_SIZE(d40_backup_regs_chan),
+ save);
+ }
+
+ /* Save/Restore global registers */
+ dma40_backup(base->virtbase, base->reg_val_backup,
+ d40_backup_regs, ARRAY_SIZE(d40_backup_regs),
+ save);
+
+ /* Save/Restore registers only existing on dma40 v3 and later */
+ if (base->rev >= 3)
+ dma40_backup(base->virtbase, base->reg_val_backup_v3,
+ d40_backup_regs_v3,
+ ARRAY_SIZE(d40_backup_regs_v3),
+ save);
+}
+#else
+static void d40_save_restore_registers(struct d40_base *base, bool save)
+{
+}
+#endif
static int d40_channel_execute_command(struct d40_chan *d40c,
enum d40_command command)
@@ -973,6 +1104,10 @@ static void d40_config_write(struct d40_chan *d40c)
/* Set LIDX for lcla */
writel(lidx, chanbase + D40_CHAN_REG_SSELT);
writel(lidx, chanbase + D40_CHAN_REG_SDELT);
+
+ /* Clear LNK which will be used by d40_chan_has_events() */
+ writel(0, chanbase + D40_CHAN_REG_SSLNK);
+ writel(0, chanbase + D40_CHAN_REG_SDLNK);
}
}
@@ -1013,6 +1148,7 @@ static int d40_pause(struct d40_chan *d40c)
if (!d40c->busy)
return 0;
+ pm_runtime_get_sync(d40c->base->dev);
spin_lock_irqsave(&d40c->lock, flags);
res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
@@ -1025,7 +1161,8 @@ static int d40_pause(struct d40_chan *d40c)
D40_DMA_RUN);
}
}
-
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
return res;
}
@@ -1039,7 +1176,7 @@ static int d40_resume(struct d40_chan *d40c)
return 0;
spin_lock_irqsave(&d40c->lock, flags);
-
+ pm_runtime_get_sync(d40c->base->dev);
if (d40c->base->rev == 0)
if (chan_is_logical(d40c)) {
res = d40_channel_execute_command(d40c,
@@ -1057,6 +1194,8 @@ static int d40_resume(struct d40_chan *d40c)
}
no_suspend:
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
return res;
}
@@ -1129,7 +1268,10 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
d40d = d40_first_queued(d40c);
if (d40d != NULL) {
- d40c->busy = true;
+ if (!d40c->busy)
+ d40c->busy = true;
+
+ pm_runtime_get_sync(d40c->base->dev);
/* Remove from queue */
d40_desc_remove(d40d);
@@ -1190,6 +1332,8 @@ static void dma_tc_handle(struct d40_chan *d40c)
if (d40_queue_start(d40c) == NULL)
d40c->busy = false;
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
}
d40c->pending_tx++;
@@ -1405,11 +1549,16 @@ static int d40_validate_conf(struct d40_chan *d40c,
return res;
}
-static bool d40_alloc_mask_set(struct d40_phy_res *phy, bool is_src,
- int log_event_line, bool is_log)
+static bool d40_alloc_mask_set(struct d40_phy_res *phy,
+ bool is_src, int log_event_line, bool is_log,
+ bool *first_user)
{
unsigned long flags;
spin_lock_irqsave(&phy->lock, flags);
+
+ *first_user = ((phy->allocated_src | phy->allocated_dst)
+ == D40_ALLOC_FREE);
+
if (!is_log) {
/* Physical interrupts are masked per physical full channel */
if (phy->allocated_src == D40_ALLOC_FREE &&
@@ -1490,7 +1639,7 @@ out:
return is_free;
}
-static int d40_allocate_channel(struct d40_chan *d40c)
+static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
{
int dev_type;
int event_group;
@@ -1526,7 +1675,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
for (i = 0; i < d40c->base->num_phy_chans; i++) {
if (d40_alloc_mask_set(&phys[i], is_src,
- 0, is_log))
+ 0, is_log,
+ first_phy_user))
goto found_phy;
}
} else
@@ -1536,7 +1686,8 @@ static int d40_allocate_channel(struct d40_chan *d40c)
if (d40_alloc_mask_set(&phys[i],
is_src,
0,
- is_log))
+ is_log,
+ first_phy_user))
goto found_phy;
}
}
@@ -1552,6 +1703,25 @@ found_phy:
/* Find logical channel */
for (j = 0; j < d40c->base->num_phy_chans; j += 8) {
int phy_num = j + event_group * 2;
+
+ if (d40c->dma_cfg.use_fixed_channel) {
+ i = d40c->dma_cfg.phy_channel;
+
+ if ((i != phy_num) && (i != phy_num + 1)) {
+ dev_err(chan2dev(d40c),
+ "invalid fixed phy channel %d\n", i);
+ return -EINVAL;
+ }
+
+ if (d40_alloc_mask_set(&phys[i], is_src, event_line,
+ is_log, first_phy_user))
+ goto found_log;
+
+ dev_err(chan2dev(d40c),
+ "could not allocate fixed phy channel %d\n", i);
+ return -EINVAL;
+ }
+
/*
* Spread logical channels across all available physical rather
* than pack every logical channel at the first available phy
@@ -1560,13 +1730,15 @@ found_phy:
if (is_src) {
for (i = phy_num; i < phy_num + 2; i++) {
if (d40_alloc_mask_set(&phys[i], is_src,
- event_line, is_log))
+ event_line, is_log,
+ first_phy_user))
goto found_log;
}
} else {
for (i = phy_num + 1; i >= phy_num; i--) {
if (d40_alloc_mask_set(&phys[i], is_src,
- event_line, is_log))
+ event_line, is_log,
+ first_phy_user))
goto found_log;
}
}
@@ -1643,10 +1815,11 @@ static int d40_free_dma(struct d40_chan *d40c)
return -EINVAL;
}
+ pm_runtime_get_sync(d40c->base->dev);
res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
if (res) {
chan_err(d40c, "suspend failed\n");
- return res;
+ goto out;
}
if (chan_is_logical(d40c)) {
@@ -1664,13 +1837,11 @@ static int d40_free_dma(struct d40_chan *d40c)
if (d40_chan_has_events(d40c)) {
res = d40_channel_execute_command(d40c,
D40_DMA_RUN);
- if (res) {
+ if (res)
chan_err(d40c,
"Executing RUN command\n");
- return res;
- }
}
- return 0;
+ goto out;
}
} else {
(void) d40_alloc_mask_free(phy, is_src, 0);
@@ -1680,13 +1851,23 @@ static int d40_free_dma(struct d40_chan *d40c)
res = d40_channel_execute_command(d40c, D40_DMA_STOP);
if (res) {
chan_err(d40c, "Failed to stop channel\n");
- return res;
+ goto out;
}
+
+ if (d40c->busy) {
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
+ }
+
+ d40c->busy = false;
d40c->phy_chan = NULL;
d40c->configured = false;
d40c->base->lookup_phy_chans[phy->num] = NULL;
+out:
- return 0;
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
+ return res;
}
static bool d40_is_paused(struct d40_chan *d40c)
@@ -1855,7 +2036,7 @@ err:
}
static dma_addr_t
-d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
+d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction)
{
struct stedma40_platform_data *plat = chan->base->plat_data;
struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
@@ -1864,9 +2045,9 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
if (chan->runtime_addr)
return chan->runtime_addr;
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
addr = plat->dev_rx[cfg->src_dev_type];
- else if (direction == DMA_TO_DEVICE)
+ else if (direction == DMA_MEM_TO_DEV)
addr = plat->dev_tx[cfg->dst_dev_type];
return addr;
@@ -1875,7 +2056,7 @@ d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
static struct dma_async_tx_descriptor *
d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
struct scatterlist *sg_dst, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long dma_flags)
+ enum dma_transfer_direction direction, unsigned long dma_flags)
{
struct d40_chan *chan = container_of(dchan, struct d40_chan, chan);
dma_addr_t src_dev_addr = 0;
@@ -1902,9 +2083,9 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
if (direction != DMA_NONE) {
dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
- if (direction == DMA_FROM_DEVICE)
+ if (direction == DMA_DEV_TO_MEM)
src_dev_addr = dev_addr;
- else if (direction == DMA_TO_DEVICE)
+ else if (direction == DMA_MEM_TO_DEV)
dst_dev_addr = dev_addr;
}
@@ -2011,14 +2192,15 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
goto fail;
}
}
- is_free_phy = (d40c->phy_chan == NULL);
- err = d40_allocate_channel(d40c);
+ err = d40_allocate_channel(d40c, &is_free_phy);
if (err) {
chan_err(d40c, "Failed to allocate channel\n");
+ d40c->configured = false;
goto fail;
}
+ pm_runtime_get_sync(d40c->base->dev);
/* Fill in basic CFG register values */
d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg,
&d40c->dst_def_cfg, chan_is_logical(d40c));
@@ -2038,6 +2220,12 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
}
+ dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
+ chan_is_logical(d40c) ? "logical" : "physical",
+ d40c->phy_chan->num,
+ d40c->dma_cfg.use_fixed_channel ? ", fixed" : "");
+
+
/*
* Only write channel configuration to the DMA if the physical
* resource is free. In case of multiple logical channels
@@ -2046,6 +2234,8 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
if (is_free_phy)
d40_config_write(d40c);
fail:
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
return err;
}
@@ -2108,10 +2298,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan,
static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
struct scatterlist *sgl,
unsigned int sg_len,
- enum dma_data_direction direction,
+ enum dma_transfer_direction direction,
unsigned long dma_flags)
{
- if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE)
+ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV)
return NULL;
return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags);
@@ -2120,7 +2310,7 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
static struct dma_async_tx_descriptor *
dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
size_t buf_len, size_t period_len,
- enum dma_data_direction direction)
+ enum dma_transfer_direction direction)
{
unsigned int periods = buf_len / period_len;
struct dma_async_tx_descriptor *txd;
@@ -2269,7 +2459,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
dst_addr_width = config->dst_addr_width;
dst_maxburst = config->dst_maxburst;
- if (config->direction == DMA_FROM_DEVICE) {
+ if (config->direction == DMA_DEV_TO_MEM) {
dma_addr_t dev_addr_rx =
d40c->base->plat_data->dev_rx[cfg->src_dev_type];
@@ -2292,7 +2482,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
if (dst_maxburst == 0)
dst_maxburst = src_maxburst;
- } else if (config->direction == DMA_TO_DEVICE) {
+ } else if (config->direction == DMA_MEM_TO_DEV) {
dma_addr_t dev_addr_tx =
d40c->base->plat_data->dev_tx[cfg->dst_dev_type];
@@ -2357,7 +2547,7 @@ static int d40_set_runtime_config(struct dma_chan *chan,
"configured channel %s for %s, data width %d/%d, "
"maxburst %d/%d elements, LE, no flow control\n",
dma_chan_name(chan),
- (config->direction == DMA_FROM_DEVICE) ? "RX" : "TX",
+ (config->direction == DMA_DEV_TO_MEM) ? "RX" : "TX",
src_addr_width, dst_addr_width,
src_maxburst, dst_maxburst);
@@ -2519,6 +2709,72 @@ failure1:
return err;
}
+/* Suspend resume functionality */
+#ifdef CONFIG_PM
+static int dma40_pm_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct d40_base *base = platform_get_drvdata(pdev);
+ int ret = 0;
+ if (!pm_runtime_suspended(dev))
+ return -EBUSY;
+
+ if (base->lcpa_regulator)
+ ret = regulator_disable(base->lcpa_regulator);
+ return ret;
+}
+
+static int dma40_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct d40_base *base = platform_get_drvdata(pdev);
+
+ d40_save_restore_registers(base, true);
+
+ /* Don't disable/enable clocks for v1 due to HW bugs */
+ if (base->rev != 1)
+ writel_relaxed(base->gcc_pwr_off_mask,
+ base->virtbase + D40_DREG_GCC);
+
+ return 0;
+}
+
+static int dma40_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct d40_base *base = platform_get_drvdata(pdev);
+
+ if (base->initialized)
+ d40_save_restore_registers(base, false);
+
+ writel_relaxed(D40_DREG_GCC_ENABLE_ALL,
+ base->virtbase + D40_DREG_GCC);
+ return 0;
+}
+
+static int dma40_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct d40_base *base = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (base->lcpa_regulator)
+ ret = regulator_enable(base->lcpa_regulator);
+
+ return ret;
+}
+
+static const struct dev_pm_ops dma40_pm_ops = {
+ .suspend = dma40_pm_suspend,
+ .runtime_suspend = dma40_runtime_suspend,
+ .runtime_resume = dma40_runtime_resume,
+ .resume = dma40_resume,
+};
+#define DMA40_PM_OPS (&dma40_pm_ops)
+#else
+#define DMA40_PM_OPS NULL
+#endif
+
/* Initialization functions. */
static int __init d40_phy_res_init(struct d40_base *base)
@@ -2527,6 +2783,7 @@ static int __init d40_phy_res_init(struct d40_base *base)
int num_phy_chans_avail = 0;
u32 val[2];
int odd_even_bit = -2;
+ int gcc = D40_DREG_GCC_ENA;
val[0] = readl(base->virtbase + D40_DREG_PRSME);
val[1] = readl(base->virtbase + D40_DREG_PRSMO);
@@ -2538,9 +2795,17 @@ static int __init d40_phy_res_init(struct d40_base *base)
/* Mark security only channels as occupied */
base->phy_res[i].allocated_src = D40_ALLOC_PHY;
base->phy_res[i].allocated_dst = D40_ALLOC_PHY;
+ base->phy_res[i].reserved = true;
+ gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i),
+ D40_DREG_GCC_SRC);
+ gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(i),
+ D40_DREG_GCC_DST);
+
+
} else {
base->phy_res[i].allocated_src = D40_ALLOC_FREE;
base->phy_res[i].allocated_dst = D40_ALLOC_FREE;
+ base->phy_res[i].reserved = false;
num_phy_chans_avail++;
}
spin_lock_init(&base->phy_res[i].lock);
@@ -2552,6 +2817,11 @@ static int __init d40_phy_res_init(struct d40_base *base)
base->phy_res[chan].allocated_src = D40_ALLOC_PHY;
base->phy_res[chan].allocated_dst = D40_ALLOC_PHY;
+ base->phy_res[chan].reserved = true;
+ gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan),
+ D40_DREG_GCC_SRC);
+ gcc |= D40_DREG_GCC_EVTGRP_ENA(D40_PHYS_TO_GROUP(chan),
+ D40_DREG_GCC_DST);
num_phy_chans_avail--;
}
@@ -2572,6 +2842,15 @@ static int __init d40_phy_res_init(struct d40_base *base)
val[0] = val[0] >> 2;
}
+ /*
+ * To keep things simple, Enable all clocks initially.
+ * The clocks will get managed later post channel allocation.
+ * The clocks for the event lines on which reserved channels exists
+ * are not managed here.
+ */
+ writel(D40_DREG_GCC_ENABLE_ALL, base->virtbase + D40_DREG_GCC);
+ base->gcc_pwr_off_mask = gcc;
+
return num_phy_chans_avail;
}
@@ -2699,10 +2978,15 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
goto failure;
}
- base->lcla_pool.alloc_map = kzalloc(num_phy_chans *
- sizeof(struct d40_desc *) *
- D40_LCLA_LINK_PER_EVENT_GRP,
+ base->reg_val_backup_chan = kmalloc(base->num_phy_chans *
+ sizeof(d40_backup_regs_chan),
GFP_KERNEL);
+ if (!base->reg_val_backup_chan)
+ goto failure;
+
+ base->lcla_pool.alloc_map =
+ kzalloc(num_phy_chans * sizeof(struct d40_desc *)
+ * D40_LCLA_LINK_PER_EVENT_GRP, GFP_KERNEL);
if (!base->lcla_pool.alloc_map)
goto failure;
@@ -2741,9 +3025,9 @@ failure:
static void __init d40_hw_init(struct d40_base *base)
{
- static const struct d40_reg_val dma_init_reg[] = {
+ static struct d40_reg_val dma_init_reg[] = {
/* Clock every part of the DMA block from start */
- { .reg = D40_DREG_GCC, .val = 0x0000ff01},
+ { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
/* Interrupts on all logical channels */
{ .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
@@ -2943,11 +3227,31 @@ static int __init d40_probe(struct platform_device *pdev)
d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
goto failure;
}
+ /* If lcla has to be located in ESRAM we don't need to allocate */
+ if (base->plat_data->use_esram_lcla) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "lcla_esram");
+ if (!res) {
+ ret = -ENOENT;
+ d40_err(&pdev->dev,
+ "No \"lcla_esram\" memory resource\n");
+ goto failure;
+ }
+ base->lcla_pool.base = ioremap(res->start,
+ resource_size(res));
+ if (!base->lcla_pool.base) {
+ ret = -ENOMEM;
+ d40_err(&pdev->dev, "Failed to ioremap LCLA region\n");
+ goto failure;
+ }
+ writel(res->start, base->virtbase + D40_DREG_LCLA);
- ret = d40_lcla_allocate(base);
- if (ret) {
- d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
- goto failure;
+ } else {
+ ret = d40_lcla_allocate(base);
+ if (ret) {
+ d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
+ goto failure;
+ }
}
spin_lock_init(&base->lcla_pool.lock);
@@ -2960,6 +3264,32 @@ static int __init d40_probe(struct platform_device *pdev)
goto failure;
}
+ pm_runtime_irq_safe(base->dev);
+ pm_runtime_set_autosuspend_delay(base->dev, DMA40_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(base->dev);
+ pm_runtime_enable(base->dev);
+ pm_runtime_resume(base->dev);
+
+ if (base->plat_data->use_esram_lcla) {
+
+ base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
+ if (IS_ERR(base->lcpa_regulator)) {
+ d40_err(&pdev->dev, "Failed to get lcpa_regulator\n");
+ base->lcpa_regulator = NULL;
+ goto failure;
+ }
+
+ ret = regulator_enable(base->lcpa_regulator);
+ if (ret) {
+ d40_err(&pdev->dev,
+ "Failed to enable lcpa_regulator\n");
+ regulator_put(base->lcpa_regulator);
+ base->lcpa_regulator = NULL;
+ goto failure;
+ }
+ }
+
+ base->initialized = true;
err = d40_dmaengine_init(base, num_reserved_chans);
if (err)
goto failure;
@@ -2976,6 +3306,11 @@ failure:
if (base->virtbase)
iounmap(base->virtbase);
+ if (base->lcla_pool.base && base->plat_data->use_esram_lcla) {
+ iounmap(base->lcla_pool.base);
+ base->lcla_pool.base = NULL;
+ }
+
if (base->lcla_pool.dma_addr)
dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
SZ_1K * base->num_phy_chans,
@@ -2998,6 +3333,11 @@ failure:
clk_put(base->clk);
}
+ if (base->lcpa_regulator) {
+ regulator_disable(base->lcpa_regulator);
+ regulator_put(base->lcpa_regulator);
+ }
+
kfree(base->lcla_pool.alloc_map);
kfree(base->lookup_log_chans);
kfree(base->lookup_phy_chans);
@@ -3013,6 +3353,7 @@ static struct platform_driver d40_driver = {
.driver = {
.owner = THIS_MODULE,
.name = D40_NAME,
+ .pm = DMA40_PM_OPS,
},
};
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index b44c4551..8d3d490 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -16,6 +16,8 @@
#define D40_TYPE_TO_GROUP(type) (type / 16)
#define D40_TYPE_TO_EVENT(type) (type % 16)
+#define D40_GROUP_SIZE 8
+#define D40_PHYS_TO_GROUP(phys) ((phys & (D40_GROUP_SIZE - 1)) / 2)
/* Most bits of the CFG register are the same in log as in phy mode */
#define D40_SREG_CFG_MST_POS 15
@@ -123,6 +125,15 @@
/* DMA Register Offsets */
#define D40_DREG_GCC 0x000
+#define D40_DREG_GCC_ENA 0x1
+/* This assumes that there are only 4 event groups */
+#define D40_DREG_GCC_ENABLE_ALL 0xff01
+#define D40_DREG_GCC_EVTGRP_POS 8
+#define D40_DREG_GCC_SRC 0
+#define D40_DREG_GCC_DST 1
+#define D40_DREG_GCC_EVTGRP_ENA(x, y) \
+ (1 << (D40_DREG_GCC_EVTGRP_POS + 2 * x + y))
+
#define D40_DREG_PRTYP 0x004
#define D40_DREG_PRSME 0x008
#define D40_DREG_PRSMO 0x00C
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index a4a398f..a6f9c16 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -90,7 +90,7 @@ struct timb_dma_chan {
struct list_head queue;
struct list_head free_list;
unsigned int bytes_per_line;
- enum dma_data_direction direction;
+ enum dma_transfer_direction direction;
unsigned int descs; /* Descriptors to allocate */
unsigned int desc_elems; /* number of elems per descriptor */
};
@@ -166,10 +166,10 @@ static void __td_unmap_desc(struct timb_dma_chan *td_chan, const u8 *dma_desc,
if (single)
dma_unmap_single(chan2dev(&td_chan->chan), addr, len,
- td_chan->direction);
+ DMA_TO_DEVICE);
else
dma_unmap_page(chan2dev(&td_chan->chan), addr, len,
- td_chan->direction);
+ DMA_TO_DEVICE);
}
static void __td_unmap_descs(struct timb_dma_desc *td_desc, bool single)
@@ -235,7 +235,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan)
"td_chan: %p, chan: %d, membase: %p\n",
td_chan, td_chan->chan.chan_id, td_chan->membase);
- if (td_chan->direction == DMA_FROM_DEVICE) {
+ if (td_chan->direction == DMA_DEV_TO_MEM) {
/* descriptor address */
iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_DHAR);
@@ -278,7 +278,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
txd->cookie);
/* make sure to stop the transfer */
- if (td_chan->direction == DMA_FROM_DEVICE)
+ if (td_chan->direction == DMA_DEV_TO_MEM)
iowrite32(0, td_chan->membase + TIMBDMA_OFFS_RX_ER);
/* Currently no support for stopping DMA transfers
else
@@ -558,7 +558,7 @@ static void td_issue_pending(struct dma_chan *chan)
static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan,
struct scatterlist *sgl, unsigned int sg_len,
- enum dma_data_direction direction, unsigned long flags)
+ enum dma_transfer_direction direction, unsigned long flags)
{
struct timb_dma_chan *td_chan =
container_of(chan, struct timb_dma_chan, chan);
@@ -606,7 +606,7 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan,
}
dma_sync_single_for_device(chan2dmadev(chan), td_desc->txd.phys,
- td_desc->desc_list_len, DMA_TO_DEVICE);
+ td_desc->desc_list_len, DMA_MEM_TO_DEV);
return &td_desc->txd;
}
@@ -775,8 +775,8 @@ static int __devinit td_probe(struct platform_device *pdev)
td_chan->descs = pchan->descriptors;
td_chan->desc_elems = pchan->descriptor_elements;
td_chan->bytes_per_line = pchan->bytes_per_line;
- td_chan->direction = pchan->rx ? DMA_FROM_DEVICE :
- DMA_TO_DEVICE;
+ td_chan->direction = pchan->rx ? DMA_DEV_TO_MEM :
+ DMA_MEM_TO_DEV;
td_chan->membase = td->membase +
(i / 2) * TIMBDMA_INSTANCE_OFFSET +
@@ -841,17 +841,7 @@ static struct platform_driver td_driver = {
.remove = __exit_p(td_remove),
};
-static int __init td_init(void)
-{
- return platform_driver_register(&td_driver);
-}
-module_init(td_init);
-
-static void __exit td_exit(void)
-{
- platform_driver_unregister(&td_driver);
-}
-module_exit(td_exit);
+module_platform_driver(td_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Timberdale DMA controller driver");
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index cbd83e36..6122c36 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -845,7 +845,7 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
static struct dma_async_tx_descriptor *
txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
- unsigned int sg_len, enum dma_data_direction direction,
+ unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags)
{
struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
@@ -860,9 +860,9 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
BUG_ON(!ds || !ds->reg_width);
if (ds->tx_reg)
- BUG_ON(direction != DMA_TO_DEVICE);
+ BUG_ON(direction != DMA_MEM_TO_DEV);
else
- BUG_ON(direction != DMA_FROM_DEVICE);
+ BUG_ON(direction != DMA_DEV_TO_MEM);
if (unlikely(!sg_len))
return NULL;
@@ -882,7 +882,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
mem = sg_dma_address(sg);
if (__is_dmac64(ddev)) {
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
desc->hwdesc.SAR = mem;
desc->hwdesc.DAR = ds->tx_reg;
} else {
@@ -891,7 +891,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
desc->hwdesc.CNTR = sg_dma_len(sg);
} else {
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
desc->hwdesc32.SAR = mem;
desc->hwdesc32.DAR = ds->tx_reg;
} else {
@@ -900,7 +900,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
desc->hwdesc32.CNTR = sg_dma_len(sg);
}
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
sai = ds->reg_width;
dai = 0;
} else {
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
index b153674..e294e1b 100644
--- a/drivers/edac/r82600_edac.c
+++ b/drivers/edac/r82600_edac.c
@@ -131,7 +131,7 @@ struct r82600_error_info {
u32 eapr;
};
-static unsigned int disable_hardware_scrub;
+static bool disable_hardware_scrub;
static struct edac_pci_ctl_info *r82600_pci;
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 68375bc..80e95aa 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -66,7 +66,7 @@
*
* Concurrent logins are useful together with cluster filesystems.
*/
-static int sbp2_param_exclusive_login = 1;
+static bool sbp2_param_exclusive_login = 1;
module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
"(default = Y, use N for concurrent initiators)");
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index efba163..9b00072 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,18 +145,6 @@ config ISCSI_IBFT
detect iSCSI boot parameters dynamically during system boot, say Y.
Otherwise, say N.
-config SIGMA
- tristate "SigmaStudio firmware loader"
- depends on I2C
- select CRC32
- default n
- help
- Enable helper functions for working with Analog Devices SigmaDSP
- parts and binary firmwares produced by Analog Devices SigmaStudio.
-
- If unsure, say N here. Drivers that need these helpers will select
- this option automatically.
-
source "drivers/firmware/google/Kconfig"
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 47338c9..5a7e273 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -12,6 +12,5 @@ obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
-obj-$(CONFIG_SIGMA) += sigma.o
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644
index 1eedb6f..0000000
--- a/drivers/firmware/sigma.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Load Analog Devices SigmaStudio firmware files
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/sigma.h>
-
-static size_t sigma_action_size(struct sigma_action *sa)
-{
- size_t payload = 0;
-
- switch (sa->instr) {
- case SIGMA_ACTION_WRITEXBYTES:
- case SIGMA_ACTION_WRITESINGLE:
- case SIGMA_ACTION_WRITESAFELOAD:
- payload = sigma_action_len(sa);
- break;
- default:
- break;
- }
-
- payload = ALIGN(payload, 2);
-
- return payload + sizeof(struct sigma_action);
-}
-
-/*
- * Returns a negative error value in case of an error, 0 if processing of
- * the firmware should be stopped after this action, 1 otherwise.
- */
-static int
-process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
-{
- size_t len = sigma_action_len(sa);
- int ret;
-
- pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
- sa->instr, sa->addr, len);
-
- switch (sa->instr) {
- case SIGMA_ACTION_WRITEXBYTES:
- case SIGMA_ACTION_WRITESINGLE:
- case SIGMA_ACTION_WRITESAFELOAD:
- ret = i2c_master_send(client, (void *)&sa->addr, len);
- if (ret < 0)
- return -EINVAL;
- break;
- case SIGMA_ACTION_DELAY:
- udelay(len);
- len = 0;
- break;
- case SIGMA_ACTION_END:
- return 0;
- default:
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int
-process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
- struct sigma_action *sa;
- size_t size;
- int ret;
-
- while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
- sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
-
- size = sigma_action_size(sa);
- ssfw->pos += size;
- if (ssfw->pos > ssfw->fw->size || size == 0)
- break;
-
- ret = process_sigma_action(client, sa);
-
- pr_debug("%s: action returned %i\n", __func__, ret);
-
- if (ret <= 0)
- return ret;
- }
-
- if (ssfw->pos != ssfw->fw->size)
- return -EINVAL;
-
- return 0;
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
- int ret;
- struct sigma_firmware_header *ssfw_head;
- struct sigma_firmware ssfw;
- const struct firmware *fw;
- u32 crc;
-
- pr_debug("%s: loading firmware %s\n", __func__, name);
-
- /* first load the blob */
- ret = request_firmware(&fw, name, &client->dev);
- if (ret) {
- pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
- return ret;
- }
- ssfw.fw = fw;
-
- /* then verify the header */
- ret = -EINVAL;
-
- /*
- * Reject too small or unreasonable large files. The upper limit has been
- * chosen a bit arbitrarily, but it should be enough for all practical
- * purposes and having the limit makes it easier to avoid integer
- * overflows later in the loading process.
- */
- if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
- goto done;
-
- ssfw_head = (void *)fw->data;
- if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
- goto done;
-
- crc = crc32(0, fw->data + sizeof(*ssfw_head),
- fw->size - sizeof(*ssfw_head));
- pr_debug("%s: crc=%x\n", __func__, crc);
- if (crc != le32_to_cpu(ssfw_head->crc))
- goto done;
-
- ssfw.pos = sizeof(*ssfw_head);
-
- /* finally process all of the actions */
- ret = process_sigma_actions(client, &ssfw);
-
- done:
- release_firmware(fw);
-
- pr_debug("%s: loaded %s\n", __func__, name);
-
- return ret;
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 573532f..37c4bd1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -138,6 +138,7 @@ config GPIO_MXS
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA
+ select GENERIC_IRQ_CHIP
help
Say yes here to support the PrimeCell PL061 GPIO device
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 62e641e..fa10df6 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -2,7 +2,7 @@
ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
-obj-$(CONFIG_GPIOLIB) += gpiolib.o
+obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
new file mode 100644
index 0000000..3dd2939
--- /dev/null
+++ b/drivers/gpio/devres.c
@@ -0,0 +1,90 @@
+/*
+ * drivers/gpio/devres.c - managed gpio resources
+ *
+ * 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.
+ *
+ * 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
+ *
+ * This file is based on kernel/irq/devres.c
+ *
+ * Copyright (c) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/gfp.h>
+
+static void devm_gpio_release(struct device *dev, void *res)
+{
+ unsigned *gpio = res;
+
+ gpio_free(*gpio);
+}
+
+static int devm_gpio_match(struct device *dev, void *res, void *data)
+{
+ unsigned *this = res, *gpio = data;
+
+ return *this == *gpio;
+}
+
+/**
+ * devm_gpio_request - request a gpio for a managed device
+ * @dev: device to request the gpio for
+ * @gpio: gpio to allocate
+ * @label: the name of the requested gpio
+ *
+ * Except for the extra @dev argument, this function takes the
+ * same arguments and performs the same function as
+ * gpio_request(). GPIOs requested with this function will be
+ * automatically freed on driver detach.
+ *
+ * If an GPIO allocated with this function needs to be freed
+ * separately, devm_gpio_free() must be used.
+ */
+
+int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
+{
+ unsigned *dr;
+ int rc;
+
+ dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ rc = gpio_request(gpio, label);
+ if (rc) {
+ devres_free(dr);
+ return rc;
+ }
+
+ *dr = gpio;
+ devres_add(dev, dr);
+
+ return 0;
+}
+EXPORT_SYMBOL(devm_gpio_request);
+
+/**
+ * devm_gpio_free - free an interrupt
+ * @dev: device to free gpio for
+ * @gpio: gpio to free
+ *
+ * Except for the extra @dev argument, this function takes the
+ * same arguments and performs the same function as gpio_free().
+ * This function instead of gpio_free() should be used to manually
+ * free GPIOs allocated with devm_gpio_request().
+ */
+void devm_gpio_free(struct device *dev, unsigned int gpio)
+{
+
+ WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match,
+ &gpio));
+ gpio_free(gpio);
+}
+EXPORT_SYMBOL(devm_gpio_free);
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 8f79c03..77c9cc7 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -12,7 +12,6 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/module.h>
-#include <linux/list.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
@@ -23,6 +22,8 @@
#include <linux/amba/bus.h>
#include <linux/amba/pl061.h>
#include <linux/slab.h>
+#include <linux/pm.h>
+#include <asm/mach/irq.h>
#define GPIODIR 0x400
#define GPIOIS 0x404
@@ -35,25 +36,33 @@
#define PL061_GPIO_NR 8
-struct pl061_gpio {
- /* We use a list of pl061_gpio structs for each trigger IRQ in the main
- * interrupts controller of the system. We need this to support systems
- * in which more that one PL061s are connected to the same IRQ. The ISR
- * interates through this list to find the source of the interrupt.
- */
- struct list_head list;
+#ifdef CONFIG_PM
+struct pl061_context_save_regs {
+ u8 gpio_data;
+ u8 gpio_dir;
+ u8 gpio_is;
+ u8 gpio_ibe;
+ u8 gpio_iev;
+ u8 gpio_ie;
+};
+#endif
+struct pl061_gpio {
/* Each of the two spinlocks protects a different set of hardware
* regiters and data structurs. This decouples the code of the IRQ from
* the GPIO code. This also makes the case of a GPIO routine call from
* the IRQ code simpler.
*/
spinlock_t lock; /* GPIO registers */
- spinlock_t irq_lock; /* IRQ registers */
void __iomem *base;
- unsigned irq_base;
+ int irq_base;
+ struct irq_chip_generic *irq_gc;
struct gpio_chip gc;
+
+#ifdef CONFIG_PM
+ struct pl061_context_save_regs csave_regs;
+#endif
};
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
@@ -118,46 +127,16 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- if (chip->irq_base == NO_IRQ)
+ if (chip->irq_base <= 0)
return -EINVAL;
return chip->irq_base + offset;
}
-/*
- * PL061 GPIO IRQ
- */
-static void pl061_irq_disable(struct irq_data *d)
-{
- struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
- int offset = d->irq - chip->irq_base;
- unsigned long flags;
- u8 gpioie;
-
- spin_lock_irqsave(&chip->irq_lock, flags);
- gpioie = readb(chip->base + GPIOIE);
- gpioie &= ~(1 << offset);
- writeb(gpioie, chip->base + GPIOIE);
- spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
-static void pl061_irq_enable(struct irq_data *d)
-{
- struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
- int offset = d->irq - chip->irq_base;
- unsigned long flags;
- u8 gpioie;
-
- spin_lock_irqsave(&chip->irq_lock, flags);
- gpioie = readb(chip->base + GPIOIE);
- gpioie |= 1 << offset;
- writeb(gpioie, chip->base + GPIOIE);
- spin_unlock_irqrestore(&chip->irq_lock, flags);
-}
-
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
{
- struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct pl061_gpio *chip = gc->private;
int offset = d->irq - chip->irq_base;
unsigned long flags;
u8 gpiois, gpioibe, gpioiev;
@@ -165,7 +144,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
if (offset < 0 || offset >= PL061_GPIO_NR)
return -EINVAL;
- spin_lock_irqsave(&chip->irq_lock, flags);
+ raw_spin_lock_irqsave(&gc->lock, flags);
gpioiev = readb(chip->base + GPIOIEV);
@@ -194,49 +173,54 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
writeb(gpioiev, chip->base + GPIOIEV);
- spin_unlock_irqrestore(&chip->irq_lock, flags);
+ raw_spin_unlock_irqrestore(&gc->lock, flags);
return 0;
}
-static struct irq_chip pl061_irqchip = {
- .name = "GPIO",
- .irq_enable = pl061_irq_enable,
- .irq_disable = pl061_irq_disable,
- .irq_set_type = pl061_irq_type,
-};
-
static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
{
- struct list_head *chip_list = irq_get_handler_data(irq);
- struct list_head *ptr;
- struct pl061_gpio *chip;
-
- desc->irq_data.chip->irq_ack(&desc->irq_data);
- list_for_each(ptr, chip_list) {
- unsigned long pending;
- int offset;
+ unsigned long pending;
+ int offset;
+ struct pl061_gpio *chip = irq_desc_get_handler_data(desc);
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
- chip = list_entry(ptr, struct pl061_gpio, list);
- pending = readb(chip->base + GPIOMIS);
- writeb(pending, chip->base + GPIOIC);
-
- if (pending == 0)
- continue;
+ chained_irq_enter(irqchip, desc);
+ pending = readb(chip->base + GPIOMIS);
+ writeb(pending, chip->base + GPIOIC);
+ if (pending) {
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(pl061_to_irq(&chip->gc, offset));
}
- desc->irq_data.chip->irq_unmask(&desc->irq_data);
+
+ chained_irq_exit(irqchip, desc);
+}
+
+static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
+{
+ struct irq_chip_type *ct;
+
+ chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
+ chip->base, handle_simple_irq);
+ chip->irq_gc->private = chip;
+
+ ct = chip->irq_gc->chip_types;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_set_type = pl061_irq_type;
+ ct->chip.irq_set_wake = irq_gc_set_wake;
+ ct->regs.mask = GPIOIE;
+
+ irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
+ IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
}
static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
{
struct pl061_platform_data *pdata;
struct pl061_gpio *chip;
- struct list_head *chip_list;
int ret, irq, i;
- static DECLARE_BITMAP(init_irq, NR_IRQS);
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -248,7 +232,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
chip->irq_base = pdata->irq_base;
} else if (dev->dev.of_node) {
chip->gc.base = -1;
- chip->irq_base = NO_IRQ;
+ chip->irq_base = 0;
} else {
ret = -ENODEV;
goto free_mem;
@@ -267,8 +251,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
}
spin_lock_init(&chip->lock);
- spin_lock_init(&chip->irq_lock);
- INIT_LIST_HEAD(&chip->list);
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
@@ -288,9 +270,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
* irq_chip support
*/
- if (chip->irq_base == NO_IRQ)
+ if (chip->irq_base <= 0)
return 0;
+ pl061_init_gc(chip, chip->irq_base);
+
writeb(0, chip->base + GPIOIE); /* disable irqs */
irq = dev->irq[0];
if (irq < 0) {
@@ -298,18 +282,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
goto iounmap;
}
irq_set_chained_handler(irq, pl061_irq_handler);
- if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
- chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
- if (chip_list == NULL) {
- clear_bit(irq, init_irq);
- ret = -ENOMEM;
- goto iounmap;
- }
- INIT_LIST_HEAD(chip_list);
- irq_set_handler_data(irq, chip_list);
- } else
- chip_list = irq_get_handler_data(irq);
- list_add(&chip->list, chip_list);
+ irq_set_handler_data(irq, chip);
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata) {
@@ -319,13 +292,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
else
pl061_direction_input(&chip->gc, i);
}
-
- irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
- handle_simple_irq);
- set_irq_flags(i+chip->irq_base, IRQF_VALID);
- irq_set_chip_data(i + chip->irq_base, chip);
}
+ amba_set_drvdata(dev, chip);
+
return 0;
iounmap:
@@ -338,6 +308,53 @@ free_mem:
return ret;
}
+#ifdef CONFIG_PM
+static int pl061_suspend(struct device *dev)
+{
+ struct pl061_gpio *chip = dev_get_drvdata(dev);
+ int offset;
+
+ chip->csave_regs.gpio_data = 0;
+ chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR);
+ chip->csave_regs.gpio_is = readb(chip->base + GPIOIS);
+ chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE);
+ chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV);
+ chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
+
+ for (offset = 0; offset < PL061_GPIO_NR; offset++) {
+ if (chip->csave_regs.gpio_dir & (1 << offset))
+ chip->csave_regs.gpio_data |=
+ pl061_get_value(&chip->gc, offset) << offset;
+ }
+
+ return 0;
+}
+
+static int pl061_resume(struct device *dev)
+{
+ struct pl061_gpio *chip = dev_get_drvdata(dev);
+ int offset;
+
+ for (offset = 0; offset < PL061_GPIO_NR; offset++) {
+ if (chip->csave_regs.gpio_dir & (1 << offset))
+ pl061_direction_output(&chip->gc, offset,
+ chip->csave_regs.gpio_data &
+ (1 << offset));
+ else
+ pl061_direction_input(&chip->gc, offset);
+ }
+
+ writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS);
+ writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE);
+ writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV);
+ writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume);
+#endif
+
static struct amba_id pl061_ids[] = {
{
.id = 0x00041061,
@@ -351,6 +368,9 @@ MODULE_DEVICE_TABLE(amba, pl061_ids);
static struct amba_driver pl061_gpio_driver = {
.drv = {
.name = "pl061_gpio",
+#ifdef CONFIG_PM
+ .pm = &pl061_dev_pm_ops,
+#endif
},
.id_table = pl061_ids,
.probe = pl061_probe,
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index b6c1f6d..7eecf69 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -47,12 +47,18 @@ static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int
return 0;
}
+static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return offset < 11 ? (IRQ_GPIO0 + offset) : (IRQ_GPIO11 - 11 + offset);
+}
+
static struct gpio_chip sa1100_gpio_chip = {
.label = "gpio",
.direction_input = sa1100_direction_input,
.direction_output = sa1100_direction_output,
.set = sa1100_gpio_set,
.get = sa1100_gpio_get,
+ .to_irq = sa1100_to_irq,
.base = 0,
.ngpio = GPIO_MAX + 1,
};
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 4c980b5..87a68a8 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -65,7 +65,14 @@ static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
u8 reg = stmpe->regs[which] - (offset / 8);
u8 mask = 1 << (offset % 8);
- stmpe_reg_write(stmpe, reg, mask);
+ /*
+ * Some variants have single register for gpio set/clear functionality.
+ * For them we need to write 0 to clear and 1 to set.
+ */
+ if (stmpe->regs[STMPE_IDX_GPSR_LSB] == stmpe->regs[STMPE_IDX_GPCR_LSB])
+ stmpe_set_bits(stmpe, reg, mask, val ? mask : 0);
+ else
+ stmpe_reg_write(stmpe, reg, mask);
}
static int stmpe_gpio_direction_output(struct gpio_chip *chip,
@@ -132,6 +139,10 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
return -EINVAL;
+ /* STMPE801 doesn't have RE and FE registers */
+ if (stmpe_gpio->stmpe->partnum == STMPE801)
+ return 0;
+
if (type == IRQ_TYPE_EDGE_RISING)
stmpe_gpio->regs[REG_RE][regoffset] |= mask;
else
@@ -165,6 +176,11 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
int i, j;
for (i = 0; i < CACHE_NR_REGS; i++) {
+ /* STMPE801 doesn't have RE and FE registers */
+ if ((stmpe->partnum == STMPE801) &&
+ (i != REG_IE))
+ continue;
+
for (j = 0; j < num_banks; j++) {
u8 old = stmpe_gpio->oldregs[i][j];
u8 new = stmpe_gpio->regs[i][j];
@@ -241,8 +257,11 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
}
stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
- stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
- status[i]);
+
+ /* Edge detect register is not present on 801 */
+ if (stmpe->partnum != STMPE801)
+ stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_GPEDR_MSB]
+ + i, status[i]);
}
return IRQ_HANDLED;
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 61044c8..bdc2937 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -361,14 +361,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res),
- dev_name(&pdev->dev))) {
- dev_err(&pdev->dev, "Couldn't request MEM resource\n");
- return -ENODEV;
- }
-
- regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ regs = devm_request_and_ioremap(&pdev->dev, res);
if (!regs) {
dev_err(&pdev->dev, "Couldn't ioremap regs\n");
return -ENODEV;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 6d0f10b..c100f3e9 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -66,6 +66,7 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct drm_psb_private *dev_priv = connector->dev->dev_private;
int max_clock = 0;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -82,6 +83,11 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
return MODE_PANEL;
+ /* We assume worst case scenario of 32 bpp here, since we don't know */
+ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
+ dev_priv->vram_stolen_size)
+ return MODE_MEM;
+
return MODE_OK;
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 50d7cfb..de25560 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -241,6 +241,7 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector)
static int cdv_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct drm_psb_private *dev_priv = connector->dev->dev_private;
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
@@ -255,14 +256,11 @@ static int cdv_hdmi_mode_valid(struct drm_connector *connector,
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
return MODE_NO_INTERLACE;
- /*
- * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
- * will go beyond the stolen memory size allocated to the framebuffer
- */
- if (mode->hdisplay > 1680)
- return MODE_PANEL;
- if (mode->vdisplay > 1050)
- return MODE_PANEL;
+ /* We assume worst case scenario of 32 bpp here, since we don't know */
+ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
+ dev_priv->vram_stolen_size)
+ return MODE_MEM;
+
return MODE_OK;
}
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 36878a6..025d309 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -506,6 +506,7 @@ int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct drm_psb_private *dev_priv = connector->dev->dev_private;
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
if (mode->clock < 20000)
@@ -514,6 +515,11 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
+ /* We assume worst case scenario of 32 bpp here, since we don't know */
+ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
+ dev_priv->vram_stolen_size)
+ return MODE_MEM;
+
return MODE_OK;
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 4882b29..88b4297 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1141,6 +1141,7 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
+ struct drm_psb_private *dev_priv = connector->dev->dev_private;
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -1160,6 +1161,11 @@ static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
return MODE_PANEL;
}
+ /* We assume worst case scenario of 32 bpp here, since we don't know */
+ if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
+ dev_priv->vram_stolen_size)
+ return MODE_MEM;
+
return MODE_OK;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 525744d..7814a76 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -18,12 +18,6 @@
#include <linux/vga_switcheroo.h>
-#define NOUVEAU_DSM_SUPPORTED 0x00
-#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00
-
-#define NOUVEAU_DSM_ACTIVE 0x01
-#define NOUVEAU_DSM_ACTIVE_QUERY 0x00
-
#define NOUVEAU_DSM_LED 0x02
#define NOUVEAU_DSM_LED_STATE 0x00
#define NOUVEAU_DSM_LED_OFF 0x10
@@ -35,6 +29,9 @@
#define NOUVEAU_DSM_POWER_SPEED 0x01
#define NOUVEAU_DSM_POWER_STAMINA 0x02
+#define NOUVEAU_DSM_OPTIMUS_FN 0x1A
+#define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001
+
static struct nouveau_dsm_priv {
bool dsm_detected;
bool optimus_detected;
@@ -61,7 +58,8 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *
struct acpi_object_list input;
union acpi_object params[4];
union acpi_object *obj;
- int err;
+ int i, err;
+ char args_buff[4];
input.count = 4;
input.pointer = params;
@@ -73,7 +71,11 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *
params[2].type = ACPI_TYPE_INTEGER;
params[2].integer.value = func;
params[3].type = ACPI_TYPE_BUFFER;
- params[3].buffer.length = 0;
+ params[3].buffer.length = 4;
+ /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */
+ for (i = 0; i < 4; i++)
+ args_buff[i] = (arg >> i * 8) & 0xFF;
+ params[3].buffer.pointer = args_buff;
err = acpi_evaluate_object(handle, "_DSM", &input, &output);
if (err) {
@@ -148,6 +150,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
return 0;
}
+/* Returns 1 if a DSM function is usable and 0 otherwise */
+static int nouveau_test_dsm(acpi_handle test_handle,
+ int (*dsm_func)(acpi_handle, int, int, uint32_t *),
+ int sfnc)
+{
+ u32 result = 0;
+
+ /* Function 0 returns a Buffer containing available functions. The args
+ * parameter is ignored for function 0, so just put 0 in it */
+ if (dsm_func(test_handle, 0, 0, &result))
+ return 0;
+
+ /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If
+ * the n-th bit is enabled, function n is supported */
+ return result & 1 && result & (1 << sfnc);
+}
+
static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
{
mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
@@ -168,6 +187,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
{
+ /* perhaps the _DSM functions are mutually exclusive, but prepare for
+ * the future */
+ if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected)
+ return 0;
if (id == VGA_SWITCHEROO_IGD)
return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA);
else
@@ -180,6 +203,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
if (id == VGA_SWITCHEROO_IGD)
return 0;
+ /* Optimus laptops have the card already disabled in
+ * nouveau_switcheroo_set_state */
+ if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected)
+ return 0;
+
return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
}
@@ -212,8 +240,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
{
acpi_handle dhandle, nvidia_handle;
acpi_status status;
- int ret, retval = 0;
- uint32_t result;
+ int retval = 0;
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
@@ -224,13 +251,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
return false;
}
- ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED,
- NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
- if (ret == 0)
+ if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
retval |= NOUVEAU_DSM_HAS_MUX;
- ret = nouveau_optimus_dsm(dhandle, 0, 0, &result);
- if (ret == 0)
+ if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm,
+ NOUVEAU_DSM_OPTIMUS_FN))
retval |= NOUVEAU_DSM_HAS_OPT;
if (retval)
@@ -269,15 +294,22 @@ static bool nouveau_dsm_detect(void)
}
if (vga_count == 2 && has_dsm && guid_valid) {
- acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
+ acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME,
+ &buffer);
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
- acpi_method_name);
+ acpi_method_name);
nouveau_dsm_priv.dsm_detected = true;
ret = true;
}
- if (has_optimus == 1)
+ if (has_optimus == 1) {
+ acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME,
+ &buffer);
+ printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n",
+ acpi_method_name);
nouveau_dsm_priv.optimus_detected = true;
+ ret = true;
+ }
return ret;
}
@@ -293,6 +325,17 @@ void nouveau_register_dsm_handler(void)
vga_switcheroo_register_handler(&nouveau_dsm_handler);
}
+/* Must be called for Optimus models before the card can be turned off */
+void nouveau_switcheroo_optimus_dsm(void)
+{
+ u32 result = 0;
+ if (!nouveau_dsm_priv.optimus_detected)
+ return;
+
+ nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FN,
+ NOUVEAU_DSM_OPTIMUS_ARGS, &result);
+}
+
void nouveau_unregister_dsm_handler(void)
{
vga_switcheroo_unregister_handler();
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 38134a9..b827098 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -1055,12 +1055,14 @@ extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
#if defined(CONFIG_ACPI)
void nouveau_register_dsm_handler(void);
void nouveau_unregister_dsm_handler(void);
+void nouveau_switcheroo_optimus_dsm(void);
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
int nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
#else
static inline void nouveau_register_dsm_handler(void) {}
static inline void nouveau_unregister_dsm_handler(void) {}
+static inline void nouveau_switcheroo_optimus_dsm(void) {}
static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; }
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index f5e9891..f80c5e0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -525,6 +525,7 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
drm_kms_helper_poll_disable(dev);
+ nouveau_switcheroo_optimus_dsm();
nouveau_pci_suspend(pdev, pmm);
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
}
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index f7442e6..8e8cd85 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -1793,10 +1793,12 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
ret = -EINVAL;
break;
case PACKET_TYPE2:
+ idx += 1;
break;
case PACKET_TYPE3:
pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt);
+ idx += pkt.count + 2;
break;
default:
dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
@@ -1805,7 +1807,6 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
}
if (ret)
break;
- idx += pkt.count + 2;
} while (idx < ib->length_dw);
return ret;
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 3ec81c3..bfd36ab 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2186,7 +2186,6 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
void r100_bm_disable(struct radeon_device *rdev)
{
u32 tmp;
- u16 tmp16;
/* disable bus mastering */
tmp = RREG32(R_000030_BUS_CNTL);
@@ -2197,8 +2196,7 @@ void r100_bm_disable(struct radeon_device *rdev)
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040);
tmp = RREG32(RADEON_BUS_CNTL);
mdelay(1);
- pci_read_config_word(rdev->pdev, 0x4, &tmp16);
- pci_write_config_word(rdev->pdev, 0x4, tmp16 & 0xFFFB);
+ pci_clear_master(rdev->pdev);
mdelay(1);
}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 31da622..8032f1f 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -145,7 +145,7 @@ module_param_named(vramlimit, radeon_vram_limit, int, 0600);
MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)");
module_param_named(agpmode, radeon_agpmode, int, 0444);
-MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32,64, etc)\n");
+MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32, 64, etc)");
module_param_named(gartsize, radeon_gart_size, int, 0600);
MODULE_PARM_DESC(benchmark, "Run benchmark");
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 803e0d3..ec46eb4 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -322,16 +322,6 @@ void rs600_hpd_fini(struct radeon_device *rdev)
}
}
-void rs600_bm_disable(struct radeon_device *rdev)
-{
- u16 tmp;
-
- /* disable bus mastering */
- pci_read_config_word(rdev->pdev, 0x4, &tmp);
- pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB);
- mdelay(1);
-}
-
int rs600_asic_reset(struct radeon_device *rdev)
{
struct rv515_mc_save save;
@@ -355,7 +345,8 @@ int rs600_asic_reset(struct radeon_device *rdev)
WREG32(RADEON_CP_RB_CNTL, tmp);
pci_save_state(rdev->pdev);
/* disable bus mastering */
- rs600_bm_disable(rdev);
+ pci_clear_master(rdev->pdev);
+ mdelay(1);
/* reset GA+VAP */
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
S_0000F0_SOFT_RESET_GA(1));
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index 37ead69..0c46d8c 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -952,10 +952,9 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev)
type = ttm_to_type(ttm->page_flags, ttm->caching_state);
pool = ttm_dma_find_pool(dev, type);
- if (!pool) {
- WARN_ON(!pool);
+ if (!pool)
return;
- }
+
is_cached = (ttm_dma_find_pool(pool->dev,
ttm_to_type(ttm->page_flags, tt_cached)) == pool);
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index f779009..b71b77a 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -90,7 +90,7 @@ static const char longname[] = "Prodikeys PC-MIDI Keyboard";
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
module_param_array(id, charp, NULL, 0444);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index f218348..b47e58b 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -49,12 +49,14 @@ static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
static enum power_supply_property wacom_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_CAPACITY
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SCOPE,
};
static enum power_supply_property wacom_ac_props[] = {
POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_ONLINE
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_SCOPE,
};
static int wacom_battery_get_property(struct power_supply *psy,
@@ -70,6 +72,9 @@ static int wacom_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_PRESENT:
val->intval = 1;
break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
case POWER_SUPPLY_PROP_CAPACITY:
/* show 100% battery capacity when charging */
if (power_state == 0)
@@ -101,6 +106,9 @@ static int wacom_ac_get_property(struct power_supply *psy,
else
val->intval = 0;
break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
default:
ret = -EINVAL;
break;
@@ -523,6 +531,8 @@ static int wacom_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&hdev->dev, &wdata->battery);
if (ret) {
hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
@@ -537,6 +547,8 @@ static int wacom_probe(struct hid_device *hdev,
wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
wdata->ac.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&hdev->dev, &wdata->ac);
if (ret) {
hid_warn(hdev,
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 61881b3..fc253b4 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -52,7 +52,8 @@ static __u16 wiiproto_keymap[] = {
};
static enum power_supply_property wiimote_battery_props[] = {
- POWER_SUPPLY_PROP_CAPACITY
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SCOPE,
};
static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
@@ -402,6 +403,11 @@ static int wiimote_battery_get_property(struct power_supply *psy,
int ret = 0, state;
unsigned long flags;
+ if (psp == POWER_SUPPLY_PROP_SCOPE) {
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ return 0;
+ }
+
ret = wiimote_cmd_acquire(wdata);
if (ret)
return ret;
@@ -1220,6 +1226,8 @@ static int wiimote_hid_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
if (ret) {
hid_err(hdev, "Cannot register battery device\n");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index cb351d3..0226040 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -474,8 +474,8 @@ config SENSORS_IT87
select HWMON_VID
help
If you say yes here you get support for ITE IT8705F, IT8712F,
- IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor
- chips, and the SiS960 clone.
+ IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
+ sensor chips, and the SiS960 clone.
This driver can also be built as a module. If so, the module
will be called it87.
@@ -515,11 +515,11 @@ config SENSORS_LINEAGE
will be called lineage-pem.
config SENSORS_LM63
- tristate "National Semiconductor LM63 and LM64"
+ tristate "National Semiconductor LM63 and compatibles"
depends on I2C
help
If you say yes here you get support for the National
- Semiconductor LM63 and LM64 remote diode digital temperature
+ Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
sensors with integrated fan control. Such chips are found
on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
others.
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 65a35cf..3b728e8 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -145,7 +145,7 @@ static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 };
/* Insmod parameters */
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Set to one to force detection.");
static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] = { -1, -1, -1, -1, -1,
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index d30855a..34a14a7 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -603,11 +603,11 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
/* Insmod parameters */
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Set to one to force detection.");
/* Default verbose is 1, since this driver is still in the testing phase */
-static int verbose = 1;
+static bool verbose = 1;
module_param(verbose, bool, 0644);
MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 522860a..554f046 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -58,7 +58,7 @@ ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);
#define POWER_ALARM_NAME "power1_alarm"
static int cap_in_hardware;
-static int force_cap_on;
+static bool force_cap_on;
static int can_cap_in_hardware(void)
{
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 1ad0a88..0158cc3 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -103,7 +103,7 @@ static int adm1021_remove(struct i2c_client *client);
static struct adm1021_data *adm1021_update_device(struct device *dev);
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
-static int read_only;
+static bool read_only;
static const struct i2c_device_id adm1021_id[] = {
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index e6291da..97e2cfb 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -155,7 +155,8 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
#define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \
(val) | 0x70 : (val))
-#define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
+#define FAN_FROM_REG(reg, div) ((reg) ? \
+ (11250 * 60) / ((reg) * (div)) : 0)
static int FAN_TO_REG(int reg, int div)
{
@@ -174,8 +175,8 @@ static int FAN_TO_REG(int reg, int div)
(((reg) & 0x1F) | (((val) << 5) & 0xe0))
#define AUTO_TEMP_MIN_TO_REG(val, reg) \
- ((((val)/500) & 0xf8)|((reg) & 0x7))
-#define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1<< ((reg)&0x7)))
+ ((((val) / 500) & 0xf8) | ((reg) & 0x7))
+#define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7)))
#define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2))
#define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2)
@@ -202,7 +203,7 @@ static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
/* FAN auto control */
#define GET_FAN_AUTO_BITFIELD(data, idx) \
- (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
+ (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
/* The tables below contains the possible values for the auto fan
* control bitfields. the index in the table is the register value.
@@ -230,7 +231,7 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = {
*/
static int
get_fan_auto_nearest(struct adm1031_data *data,
- int chan, u8 val, u8 reg, u8 * new_reg)
+ int chan, u8 val, u8 reg, u8 *new_reg)
{
int i;
int first_match = -1, exact_match = -1;
@@ -258,13 +259,13 @@ get_fan_auto_nearest(struct adm1031_data *data,
}
}
- if (exact_match >= 0) {
+ if (exact_match >= 0)
*new_reg = exact_match;
- } else if (first_match >= 0) {
+ else if (first_match >= 0)
*new_reg = first_match;
- } else {
+ else
return -EINVAL;
- }
+
return 0;
}
@@ -283,23 +284,28 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
+ long val;
u8 reg;
int ret;
u8 old_fan_mode;
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
+
old_fan_mode = data->conf1;
mutex_lock(&data->update_lock);
- if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
+ ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg);
+ if (ret) {
mutex_unlock(&data->update_lock);
return ret;
}
data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
(old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
- if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
+ if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
/* Switch to Auto Fan Mode
* Save PWM registers
* Set PWM registers to 33% Both */
@@ -350,7 +356,12 @@ set_auto_temp_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
mutex_lock(&data->update_lock);
data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
@@ -374,10 +385,16 @@ set_auto_temp_max(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
mutex_lock(&data->update_lock);
- data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
+ data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
+ data->pwm[nr]);
adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->temp_max[nr]);
mutex_unlock(&data->update_lock);
@@ -410,8 +427,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
- int reg;
+ long val;
+ int ret, reg;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
mutex_lock(&data->update_lock);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
@@ -449,9 +470,13 @@ static int trust_fan_readings(struct adm1031_data *data, int chan)
if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
switch (data->conf1 & 0x60) {
- case 0x00: /* remote temp1 controls fan1 remote temp2 controls fan2 */
+ case 0x00:
+ /*
+ * remote temp1 controls fan1,
+ * remote temp2 controls fan2
+ */
res = data->temp[chan+1] >=
- AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
+ AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
break;
case 0x20: /* remote temp1 controls both fans */
res =
@@ -515,7 +540,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
mutex_lock(&data->update_lock);
if (val) {
@@ -534,10 +564,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val = simple_strtol(buf, NULL, 10);
+ long val;
u8 tmp;
int old_div;
int new_min;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
tmp = val == 8 ? 0xc0 :
val == 4 ? 0x80 :
@@ -631,9 +666,13 @@ static ssize_t set_temp_offset(struct device *dev,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val;
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
- val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -15000, 15000);
mutex_lock(&data->update_lock);
data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
@@ -648,9 +687,13 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val;
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
- val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val);
@@ -665,9 +708,13 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val;
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
- val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val);
@@ -682,9 +729,13 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
- int val;
+ long val;
+ int ret;
+
+ ret = kstrtol(buf, 10, &val);
+ if (ret)
+ return ret;
- val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_crit[nr] = TEMP_TO_REG(val);
@@ -711,7 +762,8 @@ temp_reg(2);
temp_reg(3);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct adm1031_data *data = adm1031_update_device(dev);
return sprintf(buf, "%d\n", data->alarm);
@@ -919,12 +971,13 @@ static int adm1031_probe(struct i2c_client *client,
adm1031_init_client(client);
/* Register sysfs hooks */
- if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
+ err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
+ if (err)
goto exit_free;
if (data->chip_type == adm1031) {
- if ((err = sysfs_create_group(&client->dev.kobj,
- &adm1031_group_opt)))
+ err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
+ if (err)
goto exit_remove;
}
@@ -970,14 +1023,13 @@ static void adm1031_init_client(struct i2c_client *client)
}
/* Initialize the ADM1031 chip (enables fan speed reading ) */
read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
- if ((read_val | mask) != read_val) {
- adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
- }
+ if ((read_val | mask) != read_val)
+ adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
- adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
- ADM1031_CONF1_MONITOR_ENABLE);
+ adm1031_write_value(client, ADM1031_REG_CONF1,
+ read_val | ADM1031_CONF1_MONITOR_ENABLE);
}
/* Read the chip's update rate */
@@ -1024,8 +1076,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
/* oldh is actually newer */
if (newh != oldh)
dev_warn(&client->dev,
- "Remote temperature may be "
- "wrong.\n");
+ "Remote temperature may be wrong.\n");
#endif
}
data->temp[chan] = newh;
@@ -1052,22 +1103,24 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
- | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
- << 8);
- if (data->chip_type == adm1030) {
+ | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
+ if (data->chip_type == adm1030)
data->alarm &= 0xc0ff;
- }
- for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
+ for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
+ chan++) {
data->fan_div[chan] =
- adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_DIV(chan));
data->fan_min[chan] =
- adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_MIN(chan));
data->fan[chan] =
- adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
+ adm1031_read_value(client,
+ ADM1031_REG_FAN_SPEED(chan));
data->pwm[chan] =
- 0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
- (4*chan));
+ (adm1031_read_value(client,
+ ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
}
data->last_updated = jiffies;
data->valid = 1;
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index cfcc3b6..ed60242 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -48,8 +48,8 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
I2C_CLIENT_END };
/* Module parameters */
-static int se_input = 1; /* Default is SE, 0 == diff */
-static int int_vref = 1; /* Default is internal ref ON */
+static bool se_input = 1; /* Default is SE, 0 == diff */
+static bool int_vref = 1; /* Default is internal ref ON */
static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */
module_param(se_input, bool, S_IRUGO);
module_param(int_vref, bool, S_IRUGO);
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 1fdef88..a6c6ec3 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -190,7 +190,8 @@ static ssize_t show_temp(struct device *dev,
return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
}
-static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
+static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
+ struct device *dev)
{
/* The 100C is default for both mobile and non mobile CPUs */
@@ -284,7 +285,8 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return tjmax;
}
-static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
+static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
+ struct device *dev)
{
int err;
u32 eax, edx;
@@ -323,7 +325,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return adjust_tjmax(c, id, dev);
}
-static int create_name_attr(struct platform_data *pdata, struct device *dev)
+static int __devinit create_name_attr(struct platform_data *pdata,
+ struct device *dev)
{
sysfs_attr_init(&pdata->name_attr.attr);
pdata->name_attr.attr.name = "name";
@@ -332,8 +335,8 @@ static int create_name_attr(struct platform_data *pdata, struct device *dev)
return device_create_file(dev, &pdata->name_attr);
}
-static int create_core_attrs(struct temp_data *tdata, struct device *dev,
- int attr_no)
+static int __cpuinit create_core_attrs(struct temp_data *tdata,
+ struct device *dev, int attr_no)
{
int err, i;
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
@@ -383,7 +386,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu)
return 0;
}
-static struct platform_device *coretemp_get_pdev(unsigned int cpu)
+static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu)
{
u16 phys_proc_id = TO_PHYS_ID(cpu);
struct pdev_entry *p;
@@ -400,7 +403,8 @@ static struct platform_device *coretemp_get_pdev(unsigned int cpu)
return NULL;
}
-static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
+static struct temp_data __cpuinit *init_temp_data(unsigned int cpu,
+ int pkg_flag)
{
struct temp_data *tdata;
@@ -418,7 +422,7 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
return tdata;
}
-static int create_core_data(struct platform_device *pdev,
+static int __cpuinit create_core_data(struct platform_device *pdev,
unsigned int cpu, int pkg_flag)
{
struct temp_data *tdata;
@@ -489,7 +493,7 @@ exit_free:
return err;
}
-static void coretemp_add_core(unsigned int cpu, int pkg_flag)
+static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag)
{
struct platform_device *pdev = coretemp_get_pdev(cpu);
int err;
@@ -618,7 +622,7 @@ exit:
return err;
}
-static void coretemp_device_remove(unsigned int cpu)
+static void __cpuinit coretemp_device_remove(unsigned int cpu)
{
struct pdev_entry *p, *n;
u16 phys_proc_id = TO_PHYS_ID(cpu);
@@ -634,7 +638,7 @@ static void coretemp_device_remove(unsigned int cpu)
mutex_unlock(&pdev_list_mutex);
}
-static bool is_any_core_online(struct platform_data *pdata)
+static bool __cpuinit is_any_core_online(struct platform_data *pdata)
{
int i;
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index d980395..ffb229a 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -45,7 +45,7 @@
static struct platform_device *pdev;
/* Module load parameters */
-static int force_start;
+static bool force_start;
module_param(force_start, bool, 0);
MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs");
@@ -53,7 +53,7 @@ static unsigned short force_id;
module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID");
-static int probe_all_addr;
+static bool probe_all_addr;
module_param(probe_all_addr, bool, 0);
MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC "
"addresses");
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
index 848a2b0..8650639 100644
--- a/drivers/hwmon/emc2103.c
+++ b/drivers/hwmon/emc2103.c
@@ -55,7 +55,7 @@ static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 };
* it. Default is to leave the device in the state it's already in (-1).
* This parameter allows APD mode to be optionally forced on or off */
static int apd = -1;
-module_param(apd, bool, 0);
+module_param(apd, bint, 0);
MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode");
struct temperature {
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 38c0b87..0054d6f 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -17,6 +17,7 @@
* IT8720F Super I/O chip w/LPC interface
* IT8721F Super I/O chip w/LPC interface
* IT8726F Super I/O chip w/LPC interface
+ * IT8728F Super I/O chip w/LPC interface
* IT8758E Super I/O chip w/LPC interface
* Sis950 A clone of the IT8705F
*
@@ -58,7 +59,7 @@
#define DRVNAME "it87"
-enum chips { it87, it8712, it8716, it8718, it8720, it8721 };
+enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 };
static unsigned short force_id;
module_param(force_id, ushort, 0);
@@ -135,6 +136,7 @@ static inline void superio_exit(void)
#define IT8720F_DEVID 0x8720
#define IT8721F_DEVID 0x8721
#define IT8726F_DEVID 0x8726
+#define IT8728F_DEVID 0x8728
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
@@ -146,10 +148,10 @@ static inline void superio_exit(void)
#define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */
/* Update battery voltage after every reading if true */
-static int update_vbat;
+static bool update_vbat;
/* Not all BIOSes properly configure the PWM registers */
-static int fix_pwm_polarity;
+static bool fix_pwm_polarity;
/* Many IT87 constants specified below */
@@ -274,11 +276,31 @@ struct it87_data {
s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
};
+static inline int has_12mv_adc(const struct it87_data *data)
+{
+ /*
+ * IT8721F and later have a 12 mV ADC, also with internal scaling
+ * on selected inputs.
+ */
+ return data->type == it8721
+ || data->type == it8728;
+}
+
+static inline int has_newer_autopwm(const struct it87_data *data)
+{
+ /*
+ * IT8721F and later have separate registers for the temperature
+ * mapping and the manual duty cycle.
+ */
+ return data->type == it8721
+ || data->type == it8728;
+}
+
static u8 in_to_reg(const struct it87_data *data, int nr, long val)
{
long lsb;
- if (data->type == it8721) {
+ if (has_12mv_adc(data)) {
if (data->in_scaled & (1 << nr))
lsb = 24;
else
@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val)
static int in_from_reg(const struct it87_data *data, int nr, int val)
{
- if (data->type == it8721) {
+ if (has_12mv_adc(data)) {
if (data->in_scaled & (1 << nr))
return val * 24;
else
@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm)
static u8 pwm_to_reg(const struct it87_data *data, long val)
{
- if (data->type == it8721)
+ if (has_newer_autopwm(data))
return val;
else
return val >> 1;
@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val)
static int pwm_from_reg(const struct it87_data *data, u8 reg)
{
- if (data->type == it8721)
+ if (has_newer_autopwm(data))
return reg;
else
return (reg & 0x7f) << 1;
@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data)
|| data->type == it8716
|| data->type == it8718
|| data->type == it8720
- || data->type == it8721;
+ || data->type == it8721
+ || data->type == it8728;
}
static inline int has_old_autopwm(const struct it87_data *data)
@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev,
data->fan_main_ctrl);
} else {
if (val == 1) /* Manual mode */
- data->pwm_ctrl[nr] = data->type == it8721 ?
+ data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
data->pwm_temp_map[nr] :
data->pwm_duty[nr];
else /* Automatic mode */
@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
return -EINVAL;
mutex_lock(&data->update_lock);
- if (data->type == it8721) {
+ if (has_newer_autopwm(data)) {
/* If we are in automatic mode, the PWM duty cycle register
* is read-only so we can't write the value */
if (data->pwm_ctrl[nr] & 0x80) {
@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
struct it87_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(attr)->index;
- return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr]
- : labels[nr]);
+ return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
+ : labels[nr]);
}
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address,
case IT8721F_DEVID:
sio_data->type = it8721;
break;
+ case IT8728F_DEVID:
+ sio_data->type = it8728;
+ break;
case 0xffff: /* No device at all */
goto exit;
default:
@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address,
superio_select(GPIO);
reg = superio_inb(IT87_SIO_GPIO3_REG);
- if (sio_data->type == it8721) {
- /* The IT8721F/IT8758E doesn't have VID pins at all */
+ if (sio_data->type == it8721 || sio_data->type == it8728) {
+ /*
+ * The IT8721F/IT8758E doesn't have VID pins at all,
+ * not sure about the IT8728F.
+ */
sio_data->skip_vid = 1;
} else {
/* We need at least 4 VID pins */
@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address,
}
if (reg & (1 << 0))
sio_data->internal |= (1 << 0);
- if ((reg & (1 << 1)) || sio_data->type == it8721)
+ if ((reg & (1 << 1)) || sio_data->type == it8721 ||
+ sio_data->type == it8728)
sio_data->internal |= (1 << 1);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
"it8718",
"it8720",
"it8721",
+ "it8728",
};
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
enable_pwm_interface = it87_check_pwm(dev);
/* Starting with IT8721F, we handle scaling of internal voltages */
- if (data->type == it8721) {
+ if (has_12mv_adc(data)) {
if (sio_data->internal & (1 << 0))
data->in_scaled |= (1 << 3); /* in3 is AVCC */
if (sio_data->internal & (1 << 1))
@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
{
data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
- if (data->type == it8721) {
+ if (has_newer_autopwm(data)) {
data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
data->pwm_duty[nr] = it87_read_value(data,
IT87_REG_PWM_DUTY(nr));
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 508cb29..5e6457a 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -47,10 +47,14 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/types.h>
/*
* Addresses to scan
- * Address is fully defined internally and cannot be changed.
+ * Address is fully defined internally and cannot be changed except for
+ * LM64 which has one pin dedicated to address selection.
+ * LM63 and LM96163 have address 0x4c.
+ * LM64 can have address 0x18 or 0x4e.
*/
static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
@@ -60,6 +64,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
*/
#define LM63_REG_CONFIG1 0x03
+#define LM63_REG_CONVRATE 0x04
#define LM63_REG_CONFIG2 0xBF
#define LM63_REG_CONFIG_FAN 0x4A
@@ -70,6 +75,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
#define LM63_REG_PWM_VALUE 0x4C
#define LM63_REG_PWM_FREQ 0x4D
+#define LM63_REG_LUT_TEMP_HYST 0x4F
+#define LM63_REG_LUT_TEMP(nr) (0x50 + 2 * (nr))
+#define LM63_REG_LUT_PWM(nr) (0x51 + 2 * (nr))
#define LM63_REG_LOCAL_TEMP 0x00
#define LM63_REG_LOCAL_HIGH 0x05
@@ -91,6 +99,16 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
#define LM63_REG_MAN_ID 0xFE
#define LM63_REG_CHIP_ID 0xFF
+#define LM96163_REG_TRUTHERM 0x30
+#define LM96163_REG_REMOTE_TEMP_U_MSB 0x31
+#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32
+#define LM96163_REG_CONFIG_ENHANCED 0x45
+
+#define LM63_MAX_CONVRATE 9
+
+#define LM63_MAX_CONVRATE_HZ 32
+#define LM96163_MAX_CONVRATE_HZ 26
+
/*
* Conversions and various macros
* For tachometer counts, the LM63 uses 16-bit values.
@@ -112,15 +130,24 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
(val) >= 127000 ? 127 : \
(val) < 0 ? ((val) - 500) / 1000 : \
((val) + 500) / 1000)
+#define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \
+ (val) >= 255000 ? 255 : \
+ ((val) + 500) / 1000)
#define TEMP11_FROM_REG(reg) ((reg) / 32 * 125)
#define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \
(val) >= 127875 ? 0x7FE0 : \
(val) < 0 ? ((val) - 62) / 125 * 32 : \
((val) + 62) / 125 * 32)
+#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \
+ (val) >= 255875 ? 0xFFE0 : \
+ ((val) + 62) / 125 * 32)
#define HYST_TO_REG(val) ((val) <= 0 ? 0 : \
(val) >= 127000 ? 127 : \
((val) + 500) / 1000)
+#define UPDATE_INTERVAL(max, rate) \
+ ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
+
/*
* Functions declaration
*/
@@ -134,7 +161,7 @@ static struct lm63_data *lm63_update_device(struct device *dev);
static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
static void lm63_init_client(struct i2c_client *client);
-enum chips { lm63, lm64 };
+enum chips { lm63, lm64, lm96163 };
/*
* Driver data (common to all clients)
@@ -143,6 +170,7 @@ enum chips { lm63, lm64 };
static const struct i2c_device_id lm63_id[] = {
{ "lm63", lm63 },
{ "lm64", lm64 },
+ { "lm96163", lm96163 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm63_id);
@@ -167,26 +195,53 @@ struct lm63_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* zero until following fields are valid */
+ char lut_valid; /* zero until lut fields are valid */
unsigned long last_updated; /* in jiffies */
- int kind;
+ unsigned long lut_last_updated; /* in jiffies */
+ enum chips kind;
int temp2_offset;
+ int update_interval; /* in milliseconds */
+ int max_convrate_hz;
+ int lut_size; /* 8 or 12 */
+
/* registers values */
u8 config, config_fan;
u16 fan[2]; /* 0: input
1: low limit */
u8 pwm1_freq;
- u8 pwm1_value;
- s8 temp8[3]; /* 0: local input
+ u8 pwm1[13]; /* 0: current output
+ 1-12: lookup table */
+ s8 temp8[15]; /* 0: local input
1: local high limit
- 2: remote critical limit */
- s16 temp11[3]; /* 0: remote input
+ 2: remote critical limit
+ 3-14: lookup table */
+ s16 temp11[4]; /* 0: remote input
1: remote low limit
- 2: remote high limit */
+ 2: remote high limit
+ 3: remote offset */
+ u16 temp11u; /* remote input (unsigned) */
u8 temp2_crit_hyst;
+ u8 lut_temp_hyst;
u8 alarms;
+ bool pwm_highres;
+ bool lut_temp_highres;
+ bool remote_unsigned; /* true if unsigned remote upper limits */
+ bool trutherm;
};
+static inline int temp8_from_reg(struct lm63_data *data, int nr)
+{
+ if (data->remote_unsigned)
+ return TEMP8_FROM_REG((u8)data->temp8[nr]);
+ return TEMP8_FROM_REG(data->temp8[nr]);
+}
+
+static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
+{
+ return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
+}
+
/*
* Sysfs callback functions and files
*/
@@ -204,7 +259,12 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
- unsigned long val = simple_strtoul(buf, NULL, 10);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
mutex_lock(&data->update_lock);
data->fan[1] = FAN_TO_REG(val);
@@ -216,13 +276,22 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
return count;
}
-static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
char *buf)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
- 255 : (data->pwm1_value * 255 + data->pwm1_freq) /
- (2 * data->pwm1_freq));
+ int nr = attr->index;
+ int pwm;
+
+ if (data->pwm_highres)
+ pwm = data->pwm1[nr];
+ else
+ pwm = data->pwm1[nr] >= 2 * data->pwm1_freq ?
+ 255 : (data->pwm1[nr] * 255 + data->pwm1_freq) /
+ (2 * data->pwm1_freq);
+
+ return sprintf(buf, "%d\n", pwm);
}
static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
@@ -231,22 +300,26 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
unsigned long val;
-
+ int err;
+
if (!(data->config_fan & 0x20)) /* register is read-only */
return -EPERM;
- val = simple_strtoul(buf, NULL, 10);
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ val = SENSORS_LIMIT(val, 0, 255);
mutex_lock(&data->update_lock);
- data->pwm1_value = val <= 0 ? 0 :
- val >= 255 ? 2 * data->pwm1_freq :
- (val * data->pwm1_freq * 2 + 127) / 255;
- i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value);
+ data->pwm1[0] = data->pwm_highres ? val :
+ (val * data->pwm1_freq * 2 + 127) / 255;
+ i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
mutex_unlock(&data->update_lock);
return count;
}
-static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
- char *buf)
+static ssize_t show_pwm1_enable(struct device *dev,
+ struct device_attribute *dummy, char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
@@ -273,21 +346,47 @@ static ssize_t show_remote_temp8(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev);
- return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])
+ return sprintf(buf, "%d\n", temp8_from_reg(data, attr->index)
+ + data->temp2_offset);
+}
+
+static ssize_t show_lut_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm63_data *data = lm63_update_device(dev);
+ return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
+ data->temp2_offset);
}
-static ssize_t set_local_temp8(struct device *dev,
- struct device_attribute *dummy,
- const char *buf, size_t count)
+static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
+ int nr = attr->index;
+ int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH;
+ long val;
+ int err;
+ int temp;
+
+ err = kstrtol(buf, 10, &val);
+ if (err)
+ return err;
mutex_lock(&data->update_lock);
- data->temp8[1] = TEMP8_TO_REG(val);
- i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
+ if (nr == 2) {
+ if (data->remote_unsigned)
+ temp = TEMP8U_TO_REG(val - data->temp2_offset);
+ else
+ temp = TEMP8_TO_REG(val - data->temp2_offset);
+ } else {
+ temp = TEMP8_TO_REG(val);
+ }
+ data->temp8[nr] = temp;
+ i2c_smbus_write_byte_data(client, reg, temp);
mutex_unlock(&data->update_lock);
return count;
}
@@ -297,28 +396,56 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev);
- return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])
- + data->temp2_offset);
+ int nr = attr->index;
+ int temp;
+
+ if (!nr) {
+ /*
+ * Use unsigned temperature unless its value is zero.
+ * If it is zero, use signed temperature.
+ */
+ if (data->temp11u)
+ temp = TEMP11_FROM_REG(data->temp11u);
+ else
+ temp = TEMP11_FROM_REG(data->temp11[nr]);
+ } else {
+ if (data->remote_unsigned && nr == 2)
+ temp = TEMP11_FROM_REG((u16)data->temp11[nr]);
+ else
+ temp = TEMP11_FROM_REG(data->temp11[nr]);
+ }
+ return sprintf(buf, "%d\n", temp + data->temp2_offset);
}
static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
- static const u8 reg[4] = {
+ static const u8 reg[6] = {
LM63_REG_REMOTE_LOW_MSB,
LM63_REG_REMOTE_LOW_LSB,
LM63_REG_REMOTE_HIGH_MSB,
LM63_REG_REMOTE_HIGH_LSB,
+ LM63_REG_REMOTE_OFFSET_MSB,
+ LM63_REG_REMOTE_OFFSET_LSB,
};
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
+ long val;
+ int err;
int nr = attr->index;
+ err = kstrtol(buf, 10, &val);
+ if (err)
+ return err;
+
mutex_lock(&data->update_lock);
- data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
+ if (data->remote_unsigned && nr == 2)
+ data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset);
+ else
+ data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
+
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
@@ -327,35 +454,143 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
return count;
}
-/* Hysteresis register holds a relative value, while we want to present
- an absolute to user-space */
-static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
- char *buf)
+/*
+ * Hysteresis register holds a relative value, while we want to present
+ * an absolute to user-space
+ */
+static ssize_t show_temp2_crit_hyst(struct device *dev,
+ struct device_attribute *dummy, char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
- return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
+ return sprintf(buf, "%d\n", temp8_from_reg(data, 2)
+ data->temp2_offset
- TEMP8_FROM_REG(data->temp2_crit_hyst));
}
-/* And now the other way around, user-space provides an absolute
- hysteresis value and we have to store a relative one */
-static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+static ssize_t show_lut_temp_hyst(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm63_data *data = lm63_update_device(dev);
+
+ return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
+ + data->temp2_offset
+ - TEMP8_FROM_REG(data->lut_temp_hyst));
+}
+
+/*
+ * And now the other way around, user-space provides an absolute
+ * hysteresis value and we have to store a relative one
+ */
+static ssize_t set_temp2_crit_hyst(struct device *dev,
+ struct device_attribute *dummy,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
+ long val;
+ int err;
long hyst;
+ err = kstrtol(buf, 10, &val);
+ if (err)
+ return err;
+
mutex_lock(&data->update_lock);
- hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val;
+ hyst = temp8_from_reg(data, 2) + data->temp2_offset - val;
i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
HYST_TO_REG(hyst));
mutex_unlock(&data->update_lock);
return count;
}
+/*
+ * Set conversion rate.
+ * client->update_lock must be held when calling this function.
+ */
+static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
+ unsigned int interval)
+{
+ int i;
+ unsigned int update_interval;
+
+ /* Shift calculations to avoid rounding errors */
+ interval <<= 6;
+
+ /* find the nearest update rate */
+ update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
+ / data->max_convrate_hz;
+ for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
+ if (interval >= update_interval * 3 / 4)
+ break;
+
+ i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
+ data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
+}
+
+static ssize_t show_update_interval(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lm63_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", data->update_interval);
+}
+
+static ssize_t set_update_interval(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+ unsigned long val;
+ int err;
+
+ err = kstrtoul(buf, 10, &val);
+ if (err)
+ return err;
+
+ mutex_lock(&data->update_lock);
+ lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_type(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+
+ return sprintf(buf, data->trutherm ? "1\n" : "2\n");
+}
+
+static ssize_t set_type(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+ unsigned long val;
+ int ret;
+ u8 reg;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+ if (val != 1 && val != 2)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->trutherm = val == 1;
+ reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02;
+ i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM,
+ reg | (data->trutherm ? 0x02 : 0x00));
+ data->valid = 0;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
char *buf)
{
@@ -377,27 +612,87 @@ static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
set_fan, 1);
-static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
+ show_lut_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
+ show_lut_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
+ show_lut_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
+ show_lut_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
+ show_lut_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
+ show_lut_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
+ show_lut_temp, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
+ show_lut_temp, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO,
+ show_lut_temp, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO,
+ show_lut_temp, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO,
+ show_lut_temp, NULL, 13);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 13);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO,
+ show_lut_temp, NULL, 14);
+static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO,
+ show_lut_temp_hyst, NULL, 14);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
- set_local_temp8, 1);
+ set_temp8, 1);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 1);
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 2);
-/*
- * On LM63, temp2_crit can be set only once, which should be job
- * of the bootloader.
- */
+static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
+ set_temp11, 3);
static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
- NULL, 2);
+ set_temp8, 2);
static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
set_temp2_crit_hyst);
+static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type);
+
/* Individual alarm files */
static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
@@ -408,14 +703,43 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
/* Raw alarm file for compatibility */
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
+ set_update_interval);
+
static struct attribute *lm63_attributes[] = {
- &dev_attr_pwm1.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
&dev_attr_pwm1_enable.attr,
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point5_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point6_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point7_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point8_temp_hyst.dev_attr.attr,
+
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_min.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
+ &sensor_dev_attr_temp2_offset.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&dev_attr_temp2_crit_hyst.attr,
@@ -425,10 +749,54 @@ static struct attribute *lm63_attributes[] = {
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&dev_attr_alarms.attr,
+ &dev_attr_update_interval.attr,
NULL
};
+static struct attribute *lm63_attributes_extra_lut[] = {
+ &sensor_dev_attr_pwm1_auto_point9_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point9_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point9_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point10_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point10_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point10_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point11_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point11_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point11_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point12_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point12_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point12_temp_hyst.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group lm63_group_extra_lut = {
+ .attrs = lm63_attributes_extra_lut,
+};
+
+/*
+ * On LM63, temp2_crit can be set only once, which should be job
+ * of the bootloader.
+ * On LM64, temp2_crit can always be set.
+ * On LM96163, temp2_crit can be set if bit 1 of the configuration
+ * register is true.
+ */
+static umode_t lm63_attribute_mode(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+
+ if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr
+ && (data->kind == lm64 ||
+ (data->kind == lm96163 && (data->config & 0x02))))
+ return attr->mode | S_IWUSR;
+
+ return attr->mode;
+}
+
static const struct attribute_group lm63_group = {
+ .is_visible = lm63_attribute_mode,
.attrs = lm63_attributes,
};
@@ -487,6 +855,8 @@ static int lm63_detect(struct i2c_client *new_client,
strlcpy(info->type, "lm63", I2C_NAME_SIZE);
else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
strlcpy(info->type, "lm64", I2C_NAME_SIZE);
+ else if (chip_id == 0x49 && address == 0x4c)
+ strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
else
return -ENODEV;
@@ -518,12 +888,24 @@ static int lm63_probe(struct i2c_client *new_client,
lm63_init_client(new_client);
/* Register sysfs hooks */
- if ((err = sysfs_create_group(&new_client->dev.kobj,
- &lm63_group)))
+ err = sysfs_create_group(&new_client->dev.kobj, &lm63_group);
+ if (err)
goto exit_free;
if (data->config & 0x04) { /* tachometer enabled */
- if ((err = sysfs_create_group(&new_client->dev.kobj,
- &lm63_group_fan1)))
+ err = sysfs_create_group(&new_client->dev.kobj,
+ &lm63_group_fan1);
+ if (err)
+ goto exit_remove_files;
+ }
+ if (data->kind == lm96163) {
+ err = device_create_file(&new_client->dev,
+ &dev_attr_temp2_type);
+ if (err)
+ goto exit_remove_files;
+
+ err = sysfs_create_group(&new_client->dev.kobj,
+ &lm63_group_extra_lut);
+ if (err)
goto exit_remove_files;
}
@@ -538,17 +920,25 @@ static int lm63_probe(struct i2c_client *new_client,
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
+ if (data->kind == lm96163) {
+ device_remove_file(&new_client->dev, &dev_attr_temp2_type);
+ sysfs_remove_group(&new_client->dev.kobj,
+ &lm63_group_extra_lut);
+ }
exit_free:
kfree(data);
exit:
return err;
}
-/* Idealy we shouldn't have to initialize anything, since the BIOS
- should have taken care of everything */
+/*
+ * Ideally we shouldn't have to initialize anything, since the BIOS
+ * should have taken care of everything
+ */
static void lm63_init_client(struct i2c_client *client)
{
struct lm63_data *data = i2c_get_clientdata(client);
+ u8 convrate;
data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
data->config_fan = i2c_smbus_read_byte_data(client,
@@ -561,16 +951,57 @@ static void lm63_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
data->config);
}
+ /* Tachometer is always enabled on LM64 */
+ if (data->kind == lm64)
+ data->config |= 0x04;
/* We may need pwm1_freq before ever updating the client data */
data->pwm1_freq = i2c_smbus_read_byte_data(client, LM63_REG_PWM_FREQ);
if (data->pwm1_freq == 0)
data->pwm1_freq = 1;
+ switch (data->kind) {
+ case lm63:
+ case lm64:
+ data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
+ data->lut_size = 8;
+ break;
+ case lm96163:
+ data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
+ data->lut_size = 12;
+ data->trutherm
+ = i2c_smbus_read_byte_data(client,
+ LM96163_REG_TRUTHERM) & 0x02;
+ break;
+ }
+ convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
+ if (unlikely(convrate > LM63_MAX_CONVRATE))
+ convrate = LM63_MAX_CONVRATE;
+ data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
+ convrate);
+
+ /*
+ * For LM96163, check if high resolution PWM
+ * and unsigned temperature format is enabled.
+ */
+ if (data->kind == lm96163) {
+ u8 config_enhanced
+ = i2c_smbus_read_byte_data(client,
+ LM96163_REG_CONFIG_ENHANCED);
+ if (config_enhanced & 0x20)
+ data->lut_temp_highres = true;
+ if ((config_enhanced & 0x10)
+ && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
+ data->pwm_highres = true;
+ if (config_enhanced & 0x08)
+ data->remote_unsigned = true;
+ }
+
/* Show some debug info about the LM63 configuration */
- dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
- (data->config & 0x04) ? "tachometer input" :
- "alert output");
+ if (data->kind == lm63)
+ dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
+ (data->config & 0x04) ? "tachometer input" :
+ "alert output");
dev_dbg(&client->dev, "PWM clock %s kHz, output frequency %u Hz\n",
(data->config_fan & 0x08) ? "1.4" : "360",
((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq);
@@ -586,6 +1017,10 @@ static int lm63_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm63_group);
sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
+ if (data->kind == lm96163) {
+ device_remove_file(&client->dev, &dev_attr_temp2_type);
+ sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut);
+ }
kfree(data);
return 0;
@@ -595,10 +1030,15 @@ static struct lm63_data *lm63_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
+ unsigned long next_update;
+ int i;
mutex_lock(&data->update_lock);
- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+ next_update = data->last_updated
+ + msecs_to_jiffies(data->update_interval) + 1;
+
+ if (time_after(jiffies, next_update) || !data->valid) {
if (data->config & 0x04) { /* tachometer enabled */
/* order matters for fan1_input */
data->fan[0] = i2c_smbus_read_byte_data(client,
@@ -615,8 +1055,8 @@ static struct lm63_data *lm63_update_device(struct device *dev)
LM63_REG_PWM_FREQ);
if (data->pwm1_freq == 0)
data->pwm1_freq = 1;
- data->pwm1_value = i2c_smbus_read_byte_data(client,
- LM63_REG_PWM_VALUE);
+ data->pwm1[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_PWM_VALUE);
data->temp8[0] = i2c_smbus_read_byte_data(client,
LM63_REG_LOCAL_TEMP);
@@ -636,6 +1076,17 @@ static struct lm63_data *lm63_update_device(struct device *dev)
LM63_REG_REMOTE_HIGH_MSB) << 8)
| i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_HIGH_LSB);
+ data->temp11[3] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_OFFSET_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_OFFSET_LSB);
+
+ if (data->kind == lm96163)
+ data->temp11u = (i2c_smbus_read_byte_data(client,
+ LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM96163_REG_REMOTE_TEMP_U_LSB);
+
data->temp8[2] = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT);
data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
@@ -648,6 +1099,21 @@ static struct lm63_data *lm63_update_device(struct device *dev)
data->valid = 1;
}
+ if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
+ !data->lut_valid) {
+ for (i = 0; i < data->lut_size; i++) {
+ data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_PWM(i));
+ data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_TEMP(i));
+ }
+ data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
+ LM63_REG_LUT_TEMP_HYST);
+
+ data->lut_last_updated = jiffies;
+ data->lut_valid = 1;
+ }
+
mutex_unlock(&data->update_lock);
return data;
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index bdfd675..d2dd5f9 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -917,7 +917,7 @@ static ssize_t set_update_interval(struct device *dev,
return err;
mutex_lock(&data->update_lock);
- lm90_set_convrate(client, data, val);
+ lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
mutex_unlock(&data->update_lock);
return count;
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 3b43df4..8bd6c5c 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -151,12 +151,12 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
/* Insmod parameters */
-static int disable_block;
+static bool disable_block;
module_param(disable_block, bool, 0);
MODULE_PARM_DESC(disable_block,
"Set to non-zero to disable SMBus block data transactions.");
-static int init;
+static bool init;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to non-zero to force chip initialization.");
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index 84ef3a8..482ca90 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -106,11 +106,14 @@ static ssize_t show_adc(struct device *dev,
if (ret < 0)
return ret;
- return sprintf(buf, "%d\n", ret);
+ /* assume the reference voltage to be 2.048V, with an 8-bit sample,
+ * the LSB weight is 8mV
+ */
+ return sprintf(buf, "%d\n", ret * 8);
}
#define MAX1111_ADC_ATTR(_id) \
- SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id)
+ SENSOR_DEVICE_ATTR(in##_id##_input, S_IRUGO, show_adc, NULL, _id)
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static MAX1111_ADC_ATTR(0);
@@ -120,10 +123,10 @@ static MAX1111_ADC_ATTR(3);
static struct attribute *max1111_attributes[] = {
&dev_attr_name.attr,
- &sensor_dev_attr_adc0_in.dev_attr.attr,
- &sensor_dev_attr_adc1_in.dev_attr.attr,
- &sensor_dev_attr_adc2_in.dev_attr.attr,
- &sensor_dev_attr_adc3_in.dev_attr.attr,
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
NULL,
};
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index 6914195..88953f9 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -59,7 +59,7 @@ static unsigned short max1668_addr_list[] = {
#define DEV_ID_MAX1989 0xb
/* read only mode module parameter */
-static int read_only;
+static bool read_only;
module_param(read_only, bool, 0);
MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bde50e3..374118f 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -71,7 +71,7 @@ module_param(force_i2c, byte, 0);
MODULE_PARM_DESC(force_i2c,
"Initialize the i2c address of the sensors");
-static int init = 1;
+static bool init = 1;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 65b685e..17a8fa2 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -67,11 +67,11 @@ module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
-static int reset;
+static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
-static int init = 1;
+static bool init = 1;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 6e5d0ae..35aa514 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -58,11 +58,11 @@ module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
-static int reset;
+static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset");
-static int init;
+static bool init;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to one to force extra software initialization");
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 9ded133..d3100ea 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -56,7 +56,7 @@ module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
-static int init;
+static bool init;
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to one to force chip initialization");
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 3cc6fef..45ec7e7 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -61,7 +61,7 @@ module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
-static int reset;
+static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index 3ee398d..aa58b25 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -42,7 +42,7 @@ static const unsigned short normal_i2c[] = {
};
-static int reset;
+static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 0254e18..063bd95 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -39,7 +39,7 @@ static const unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END };
/* Insmod parameters */
-static int reset;
+static bool reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a3afac4..cbe7a2f 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -299,11 +299,11 @@ config I2C_AT91
unless your system can cope with those limitations.
config I2C_AU1550
- tristate "Au1550/Au1200 SMBus interface"
+ tristate "Au1550/Au1200/Au1300 SMBus interface"
depends on MIPS_ALCHEMY
help
If you say yes to this option, support will be included for the
- Au1550 and Au1200 SMBus interface.
+ Au1550/Au1200/Au1300 SMBus interface.
This driver can also be built as a module. If so, the module
will be called i2c-au1550.
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index b6807db..e66d248 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -132,7 +132,8 @@
#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */
static struct pci_driver ali1535_driver;
-static unsigned short ali1535_smba;
+static unsigned long ali1535_smba;
+static unsigned short ali1535_offset;
/* Detect whether a ALI1535 can be found, and initialize it, where necessary.
Note the differences between kernels with the old PCI BIOS interface and
@@ -140,7 +141,7 @@ static unsigned short ali1535_smba;
defined to make the transition easier. */
static int __devinit ali1535_setup(struct pci_dev *dev)
{
- int retval = -ENODEV;
+ int retval;
unsigned char temp;
/* Check the following things:
@@ -149,15 +150,28 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
- We can use the addresses
*/
+ retval = pci_enable_device(dev);
+ if (retval) {
+ dev_err(&dev->dev, "ALI1535_smb can't enable device\n");
+ goto exit;
+ }
+
/* Determine the address of the SMBus area */
- pci_read_config_word(dev, SMBBA, &ali1535_smba);
- ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1));
- if (ali1535_smba == 0) {
+ pci_read_config_word(dev, SMBBA, &ali1535_offset);
+ dev_dbg(&dev->dev, "ALI1535_smb is at offset 0x%04x\n", ali1535_offset);
+ ali1535_offset &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1));
+ if (ali1535_offset == 0) {
dev_warn(&dev->dev,
"ALI1535_smb region uninitialized - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit;
}
+ if (pci_resource_flags(dev, 0) & IORESOURCE_IO)
+ ali1535_smba = pci_resource_start(dev, 0) + ali1535_offset;
+ else
+ ali1535_smba = ali1535_offset;
+
retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name);
if (retval)
@@ -165,8 +179,9 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
ali1535_driver.name)) {
- dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
+ dev_err(&dev->dev, "ALI1535_smb region 0x%lx already in use!\n",
ali1535_smba);
+ retval = -EBUSY;
goto exit;
}
@@ -174,6 +189,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
pci_read_config_byte(dev, SMBCFG, &temp);
if ((temp & ALI1535_SMBIO_EN) == 0) {
dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit_free;
}
@@ -181,6 +197,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
pci_read_config_byte(dev, SMBHSTCFG, &temp);
if ((temp & 1) == 0) {
dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit_free;
}
@@ -196,14 +213,13 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
*/
pci_read_config_byte(dev, SMBREV, &temp);
dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
- dev_dbg(&dev->dev, "ALI1535_smba = 0x%X\n", ali1535_smba);
+ dev_dbg(&dev->dev, "ALI1535_smba = 0x%lx\n", ali1535_smba);
- retval = 0;
-exit:
- return retval;
+ return 0;
exit_free:
release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
+exit:
return retval;
}
@@ -498,7 +514,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
ali1535_adapter.dev.parent = &dev->dev;
snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
- "SMBus ALI1535 adapter at %04x", ali1535_smba);
+ "SMBus ALI1535 adapter at %04x", ali1535_offset);
return i2c_add_adapter(&ali1535_adapter);
}
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index a409cfc..47ae009 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -417,7 +417,7 @@ static void __devexit ali1563_remove(struct pci_dev * dev)
ali1563_shutdown(dev);
}
-static const struct pci_device_id ali1563_id_table[] __devinitconst = {
+static DEFINE_PCI_DEVICE_TABLE(ali1563_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },
{},
};
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 83e8a60..087ea9c 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -477,7 +477,7 @@ static struct i2c_adapter ali15x3_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id ali15x3_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 03bcd07..eb778bf1 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -308,7 +308,7 @@ static const char* chipname[] = {
"nVidia nForce", "AMD8111",
};
-static const struct pci_device_id amd756_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
.driver_data = AMD756 },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 6b6a6b1..e5ac53b 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -415,7 +415,7 @@ static const struct i2c_algorithm smbus_algorithm = {
};
-static const struct pci_device_id amd8111_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 305c075..1679dee 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -295,9 +295,6 @@ static int at91_i2c_resume(struct platform_device *pdev)
#define at91_i2c_resume NULL
#endif
-/* work with "modprobe at91_i2c" from hotplugging or coldplugging */
-MODULE_ALIAS("platform:at91_i2c");
-
static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe,
.remove = __devexit_p(at91_i2c_remove),
@@ -309,19 +306,9 @@ static struct platform_driver at91_i2c_driver = {
},
};
-static int __init at91_i2c_init(void)
-{
- return platform_driver_register(&at91_i2c_driver);
-}
-
-static void __exit at91_i2c_exit(void)
-{
- platform_driver_unregister(&at91_i2c_driver);
-}
-
-module_init(at91_i2c_init);
-module_exit(at91_i2c_exit);
+module_platform_driver(at91_i2c_driver);
MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at91_i2c");
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index f314d7f..582d616 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -426,20 +426,9 @@ static struct platform_driver au1xpsc_smbus_driver = {
.remove = __devexit_p(i2c_au1550_remove),
};
-static int __init i2c_au1550_init(void)
-{
- return platform_driver_register(&au1xpsc_smbus_driver);
-}
-
-static void __exit i2c_au1550_exit(void)
-{
- platform_driver_unregister(&au1xpsc_smbus_driver);
-}
+module_platform_driver(au1xpsc_smbus_driver);
MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:au1xpsc_smbus");
-
-module_init (i2c_au1550_init);
-module_exit (i2c_au1550_exit);
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index b1d9cd2..c1e1096 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -724,18 +724,7 @@ static struct platform_driver cpm_i2c_driver = {
},
};
-static int __init cpm_i2c_init(void)
-{
- return platform_driver_register(&cpm_i2c_driver);
-}
-
-static void __exit cpm_i2c_exit(void)
-{
- platform_driver_unregister(&cpm_i2c_driver);
-}
-
-module_init(cpm_i2c_init);
-module_exit(cpm_i2c_exit);
+module_platform_driver(cpm_i2c_driver);
MODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards");
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 9e89e73..37f4211 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -349,7 +349,7 @@ static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("i2c_designware-pci");
-DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
+static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = {
/* Moorestown */
{ PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
{ PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 18936ac..3ef3557 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -185,7 +185,7 @@ static DEFINE_MUTEX(pch_mutex);
#define PCI_DEVICE_ID_ML7213_I2C 0x802D
#define PCI_DEVICE_ID_ML7223_I2C 0x8010
-static struct pci_device_id __devinitdata pch_pcidev_id[] = {
+static DEFINE_PCI_DEVICE_TABLE(pch_pcidev_id) = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, },
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 63bb1cc..19515df 100644
--- a/drivers/i2c/busses/i2c-highlander.c
+++ b/drivers/i2c/busses/i2c-highlander.c
@@ -52,7 +52,7 @@ struct highlander_i2c_dev {
size_t buf_len;
};
-static int iic_force_poll, iic_force_normal;
+static bool iic_force_poll, iic_force_normal;
static int iic_timeout = 1000, iic_read_delay;
static inline void highlander_i2c_irq_enable(struct highlander_i2c_dev *dev)
@@ -468,18 +468,7 @@ static struct platform_driver highlander_i2c_driver = {
.remove = __devexit_p(highlander_i2c_remove),
};
-static int __init highlander_i2c_init(void)
-{
- return platform_driver_register(&highlander_i2c_driver);
-}
-
-static void __exit highlander_i2c_exit(void)
-{
- platform_driver_unregister(&highlander_i2c_driver);
-}
-
-module_init(highlander_i2c_init);
-module_exit(highlander_i2c_exit);
+module_platform_driver(highlander_i2c_driver);
MODULE_AUTHOR("Paul Mundt");
MODULE_DESCRIPTION("Renesas Highlander FPGA I2C/SMBus adapter");
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 9ff1695..c527de1 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -105,7 +105,7 @@ static struct i2c_adapter hydra_adap = {
.algo_data = &hydra_bit_data,
};
-static const struct pci_device_id hydra_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ab26840d..5d2e281 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -609,7 +609,7 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = i801_func,
};
-static const struct pci_device_id i801_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 3c110fb..806e225 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -51,11 +51,11 @@
MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
MODULE_LICENSE("GPL");
-static int iic_force_poll;
+static bool iic_force_poll;
module_param(iic_force_poll, bool, 0);
MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
-static int iic_force_fast;
+static bool iic_force_fast;
module_param(iic_force_fast, bool, 0);
MODULE_PARM_DESC(iic_force_fast, "Force fast mode (400 kHz)");
@@ -815,15 +815,4 @@ static struct platform_driver ibm_iic_driver = {
.remove = __devexit_p(iic_remove),
};
-static int __init iic_init(void)
-{
- return platform_driver_register(&ibm_iic_driver);
-}
-
-static void __exit iic_exit(void)
-{
- platform_driver_unregister(&ibm_iic_driver);
-}
-
-module_init(iic_init);
-module_exit(iic_exit);
+module_platform_driver(ibm_iic_driver);
diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c
index e828ac8..365bad5 100644
--- a/drivers/i2c/busses/i2c-intel-mid.c
+++ b/drivers/i2c/busses/i2c-intel-mid.c
@@ -1093,7 +1093,7 @@ static void __devexit intel_mid_i2c_remove(struct pci_dev *dev)
pci_release_region(dev, 0);
}
-static struct pci_device_id intel_mid_i2c_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(intel_mid_i2c_ids) = {
/* Moorestown */
{ PCI_VDEVICE(INTEL, 0x0802), 0 },
{ PCI_VDEVICE(INTEL, 0x0803), 1 },
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index f09c931..93f147a 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -523,21 +523,7 @@ static struct platform_driver iop3xx_i2c_driver = {
},
};
-static int __init
-i2c_iop3xx_init (void)
-{
- return platform_driver_register(&iop3xx_i2c_driver);
-}
-
-static void __exit
-i2c_iop3xx_exit (void)
-{
- platform_driver_unregister(&iop3xx_i2c_driver);
- return;
-}
-
-module_init (i2c_iop3xx_init);
-module_exit (i2c_iop3xx_exit);
+module_platform_driver(iop3xx_i2c_driver);
MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index 0682f8f..6561d27 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -306,20 +306,9 @@ static struct platform_driver smbus_sch_driver = {
.remove = __devexit_p(smbus_sch_remove),
};
-static int __init i2c_sch_init(void)
-{
- return platform_driver_register(&smbus_sch_driver);
-}
-
-static void __exit i2c_sch_exit(void)
-{
- platform_driver_unregister(&smbus_sch_driver);
-}
+module_platform_driver(smbus_sch_driver);
MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
MODULE_DESCRIPTION("Intel SCH SMBus driver");
MODULE_LICENSE("GPL");
-
-module_init(i2c_sch_init);
-module_exit(i2c_sch_exit);
MODULE_ALIAS("platform:isch_smbus");
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index c01e951..5d263f90 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -148,18 +148,7 @@ static struct platform_driver ixp2000_i2c_driver = {
},
};
-static int __init ixp2000_i2c_init(void)
-{
- return platform_driver_register(&ixp2000_i2c_driver);
-}
-
-static void __exit ixp2000_i2c_exit(void)
-{
- platform_driver_unregister(&ixp2000_i2c_driver);
-}
-
-module_init(ixp2000_i2c_init);
-module_exit(ixp2000_i2c_exit);
+module_platform_driver(ixp2000_i2c_driver);
MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 107397a..a8ebb84 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -715,18 +715,7 @@ static struct platform_driver mpc_i2c_driver = {
},
};
-static int __init fsl_i2c_init(void)
-{
- return platform_driver_register(&mpc_i2c_driver);
-}
-
-static void __exit fsl_i2c_exit(void)
-{
- platform_driver_unregister(&mpc_i2c_driver);
-}
-
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
+module_platform_driver(mpc_i2c_driver);
MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a9941c6..4f44a33 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -611,20 +611,7 @@ static struct platform_driver mv64xxx_i2c_driver = {
},
};
-static int __init
-mv64xxx_i2c_init(void)
-{
- return platform_driver_register(&mv64xxx_i2c_driver);
-}
-
-static void __exit
-mv64xxx_i2c_exit(void)
-{
- platform_driver_unregister(&mv64xxx_i2c_driver);
-}
-
-module_init(mv64xxx_i2c_init);
-module_exit(mv64xxx_i2c_exit);
+module_platform_driver(mv64xxx_i2c_driver);
MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver");
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index ff1e127..43a96a1 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -309,7 +309,7 @@ static struct i2c_algorithm smbus_algorithm = {
};
-static const struct pci_device_id nforce2_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
@@ -356,7 +356,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
error = acpi_check_region(smbus->base, smbus->size,
nforce2_driver.name);
if (error)
- return -1;
+ return error;
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 1b46a9d..18068de 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -394,9 +394,6 @@ static struct of_device_id ocores_i2c_match[] = {
};
MODULE_DEVICE_TABLE(of, ocores_i2c_match);
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:ocores-i2c");
-
static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove),
@@ -409,19 +406,9 @@ static struct platform_driver ocores_i2c_driver = {
},
};
-static int __init ocores_i2c_init(void)
-{
- return platform_driver_register(&ocores_i2c_driver);
-}
-
-static void __exit ocores_i2c_exit(void)
-{
- platform_driver_unregister(&ocores_i2c_driver);
-}
-
-module_init(ocores_i2c_init);
-module_exit(ocores_i2c_exit);
+module_platform_driver(ocores_i2c_driver);
MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
MODULE_DESCRIPTION("OpenCores I2C bus driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ocores-i2c");
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 56dbe54..ee139a5 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -629,24 +629,10 @@ static struct platform_driver octeon_i2c_driver = {
},
};
-static int __init octeon_i2c_init(void)
-{
- int rv;
-
- rv = platform_driver_register(&octeon_i2c_driver);
- return rv;
-}
-
-static void __exit octeon_i2c_exit(void)
-{
- platform_driver_unregister(&octeon_i2c_driver);
-}
+module_platform_driver(octeon_i2c_driver);
MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_NAME);
-
-module_init(octeon_i2c_init);
-module_exit(octeon_i2c_exit);
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 837b8c1..eaaea73 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -401,7 +401,7 @@ static void __devexit pasemi_smb_remove(struct pci_dev *dev)
kfree(smbus);
}
-static const struct pci_device_id pasemi_smb_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(pasemi_smb_ids) = {
{ PCI_DEVICE(0x1959, 0xa003) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index ace6799..2adbf1a 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -286,20 +286,8 @@ static struct platform_driver i2c_pca_pf_driver = {
},
};
-static int __init i2c_pca_pf_init(void)
-{
- return platform_driver_register(&i2c_pca_pf_driver);
-}
-
-static void __exit i2c_pca_pf_exit(void)
-{
- platform_driver_unregister(&i2c_pca_pf_driver);
-}
+module_platform_driver(i2c_pca_pf_driver);
MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver");
MODULE_LICENSE("GPL");
-
-module_init(i2c_pca_pf_init);
-module_exit(i2c_pca_pf_exit);
-
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d14ac2..c14d48d 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -472,7 +472,7 @@ static struct i2c_adapter piix4_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id piix4_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) },
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 127051b..07b7447 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -627,9 +627,6 @@ static struct i2c_adapter pmcmsptwi_adapter = {
.name = DRV_NAME,
};
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:" DRV_NAME);
-
static struct platform_driver pmcmsptwi_driver = {
.probe = pmcmsptwi_probe,
.remove = __devexit_p(pmcmsptwi_remove),
@@ -639,18 +636,8 @@ static struct platform_driver pmcmsptwi_driver = {
},
};
-static int __init pmcmsptwi_init(void)
-{
- return platform_driver_register(&pmcmsptwi_driver);
-}
-
-static void __exit pmcmsptwi_exit(void)
-{
- platform_driver_unregister(&pmcmsptwi_driver);
-}
+module_platform_driver(pmcmsptwi_driver);
MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
MODULE_LICENSE("GPL");
-
-module_init(pmcmsptwi_init);
-module_exit(pmcmsptwi_exit);
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index b289ec9..7b397c6 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -312,10 +312,6 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
return rc;
}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:i2c-powermac");
-
static struct platform_driver i2c_powermac_driver = {
.probe = i2c_powermac_probe,
.remove = __devexit_p(i2c_powermac_remove),
@@ -325,17 +321,6 @@ static struct platform_driver i2c_powermac_driver = {
},
};
-static int __init i2c_powermac_init(void)
-{
- platform_driver_register(&i2c_powermac_driver);
- return 0;
-}
+module_platform_driver(i2c_powermac_driver);
-
-static void __exit i2c_powermac_cleanup(void)
-{
- platform_driver_unregister(&i2c_powermac_driver);
-}
-
-module_init(i2c_powermac_init);
-module_exit(i2c_powermac_cleanup);
+MODULE_ALIAS("platform:i2c-powermac");
diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
index fac6739..93709fb 100644
--- a/drivers/i2c/busses/i2c-puv3.c
+++ b/drivers/i2c/busses/i2c-puv3.c
@@ -276,8 +276,6 @@ static int puv3_i2c_resume(struct platform_device *dev)
#define puv3_i2c_resume NULL
#endif
-MODULE_ALIAS("platform:puv3_i2c");
-
static struct platform_driver puv3_i2c_driver = {
.probe = puv3_i2c_probe,
.remove = __devexit_p(puv3_i2c_remove),
@@ -289,18 +287,8 @@ static struct platform_driver puv3_i2c_driver = {
}
};
-static int __init puv3_i2c_init(void)
-{
- return platform_driver_register(&puv3_i2c_driver);
-}
-
-static void __exit puv3_i2c_exit(void)
-{
- platform_driver_unregister(&puv3_i2c_driver);
-}
-
-module_init(puv3_i2c_init);
-module_exit(puv3_i2c_exit);
+module_platform_driver(puv3_i2c_driver);
MODULE_DESCRIPTION("PKUnity v3 I2C driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:puv3_i2c");
diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
index 632e088..a058179 100644
--- a/drivers/i2c/busses/i2c-pxa-pci.c
+++ b/drivers/i2c/busses/i2c-pxa-pci.c
@@ -150,7 +150,7 @@ static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
kfree(sds);
}
-static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
+static DEFINE_PCI_DEVICE_TABLE(ce4100_i2c_devices) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
{ },
};
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index a67132b..c0c9dff 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -560,18 +560,7 @@ static struct platform_driver sh7760_i2c_drv = {
.remove = __devexit_p(sh7760_i2c_remove),
};
-static int __init sh7760_i2c_init(void)
-{
- return platform_driver_register(&sh7760_i2c_drv);
-}
-
-static void __exit sh7760_i2c_exit(void)
-{
- platform_driver_unregister(&sh7760_i2c_drv);
-}
-
-module_init(sh7760_i2c_init);
-module_exit(sh7760_i2c_exit);
+module_platform_driver(sh7760_i2c_drv);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 I2C bus driver");
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
index 2fc08fb..4fc87e7 100644
--- a/drivers/i2c/busses/i2c-simtec.c
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -156,12 +156,8 @@ static int simtec_i2c_remove(struct platform_device *dev)
return 0;
}
-
/* device driver */
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:simtec-i2c");
-
static struct platform_driver simtec_i2c_driver = {
.driver = {
.name = "simtec-i2c",
@@ -171,19 +167,9 @@ static struct platform_driver simtec_i2c_driver = {
.remove = simtec_i2c_remove,
};
-static int __init i2c_adap_simtec_init(void)
-{
- return platform_driver_register(&simtec_i2c_driver);
-}
-
-static void __exit i2c_adap_simtec_exit(void)
-{
- platform_driver_unregister(&simtec_i2c_driver);
-}
-
-module_init(i2c_adap_simtec_init);
-module_exit(i2c_adap_simtec_exit);
+module_platform_driver(simtec_i2c_driver);
MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:simtec-i2c");
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 4375866..87e5126 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -147,7 +147,7 @@ static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
u16 a;
u8 val;
int *i;
- int retval = -ENODEV;
+ int retval;
/* Look for imposters */
for (i = blacklist; *i != 0; i++) {
@@ -223,7 +223,7 @@ static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
error:
release_region(sis5595_base + SMB_INDEX, 2);
- return retval;
+ return -ENODEV;
}
static int sis5595_transaction(struct i2c_adapter *adap)
@@ -369,7 +369,7 @@ static struct i2c_adapter sis5595_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id sis5595_ids[] __devinitconst = {
+static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index e6f539e..15cf78f 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -93,8 +93,8 @@
static struct pci_driver sis630_driver;
/* insmod parameters */
-static int high_clock;
-static int force;
+static bool high_clock;
+static bool force;
module_param(high_clock, bool, 0);
MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
module_param(force, bool, 0);
@@ -393,7 +393,7 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
{
unsigned char b;
struct pci_dev *dummy = NULL;
- int retval = -ENODEV, i;
+ int retval, i;
/* check for supported SiS devices */
for (i=0; supported[i] > 0 ; i++) {
@@ -418,18 +418,21 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
*/
if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
+ retval = -ENODEV;
goto exit;
}
/* if ACPI already enabled , do nothing */
if (!(b & 0x80) &&
pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
+ retval = -ENODEV;
goto exit;
}
/* Determine the ACPI base address */
if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
+ retval = -ENODEV;
goto exit;
}
@@ -445,6 +448,7 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
sis630_driver.name)) {
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
+ retval = -EBUSY;
goto exit;
}
@@ -468,7 +472,7 @@ static struct i2c_adapter sis630_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id sis630_ids[] __devinitconst = {
+static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
{ 0, }
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 86837f0..cc5d149 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -245,7 +245,7 @@ static struct i2c_adapter sis96x_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id sis96x_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 7799fe5..713d31a 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -89,7 +89,7 @@ static struct i2c_adapter vt586b_adapter = {
};
-static const struct pci_device_id vt586b_ids[] __devinitconst = {
+static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 0b012f1..333011c 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -91,7 +91,7 @@ static unsigned short SMBHSTCFG = 0xD2;
/* If force is set to anything different from 0, we forcibly enable the
VT596. DANGEROUS! */
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
@@ -324,7 +324,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
unsigned char temp;
- int error = -ENODEV;
+ int error;
/* Determine the address of the SMBus areas */
if (force_addr) {
@@ -390,6 +390,7 @@ found:
dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
"controller not enabled! - upgrade BIOS or "
"use force=1\n");
+ error = -ENODEV;
goto release_region;
}
}
@@ -422,9 +423,11 @@ found:
"SMBus Via Pro adapter at %04x", vt596_smba);
vt596_pdev = pci_dev_get(pdev);
- if (i2c_add_adapter(&vt596_adapter)) {
+ error = i2c_add_adapter(&vt596_adapter);
+ if (error) {
pci_dev_put(vt596_pdev);
vt596_pdev = NULL;
+ goto release_region;
}
/* Always return failure here. This is to allow other drivers to bind
@@ -438,7 +441,7 @@ release_region:
return error;
}
-static const struct pci_device_id vt596_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(vt596_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
.driver_data = SMBBA1 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index ac083a2..2bded76 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -795,10 +795,6 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev)
return 0;
}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:"DRIVER_NAME);
-
static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe,
.remove = __devexit_p(xiic_i2c_remove),
@@ -808,19 +804,9 @@ static struct platform_driver xiic_i2c_driver = {
},
};
-static int __init xiic_i2c_init(void)
-{
- return platform_driver_register(&xiic_i2c_driver);
-}
-
-static void __exit xiic_i2c_exit(void)
-{
- platform_driver_unregister(&xiic_i2c_driver);
-}
-
-module_init(xiic_i2c_init);
-module_exit(xiic_i2c_exit);
+module_platform_driver(xiic_i2c_driver);
MODULE_AUTHOR("info@mocean-labs.com");
MODULE_DESCRIPTION("Xilinx I2C bus driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:"DRIVER_NAME);
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 91e349c..2eacb77 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -559,7 +559,7 @@ static struct platform_driver scx200_pci_driver = {
.remove = __devexit_p(scx200_remove),
};
-static const struct pci_device_id scx200_isa[] __initconst = {
+static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
{ 0, }
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 57a45ce8..10e7f1e 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -251,15 +251,10 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
- rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);
- if (!rdwr_pa)
- return -ENOMEM;
-
- if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
- rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
- kfree(rdwr_pa);
- return -EFAULT;
- }
+ rdwr_pa = memdup_user(rdwr_arg.msgs,
+ rdwr_arg.nmsgs * sizeof(struct i2c_msg));
+ if (IS_ERR(rdwr_pa))
+ return PTR_ERR(rdwr_pa);
data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
diff --git a/drivers/i2c/muxes/gpio-i2cmux.c b/drivers/i2c/muxes/gpio-i2cmux.c
index 7b6ce62..e5fa695 100644
--- a/drivers/i2c/muxes/gpio-i2cmux.c
+++ b/drivers/i2c/muxes/gpio-i2cmux.c
@@ -165,18 +165,7 @@ static struct platform_driver gpiomux_driver = {
},
};
-static int __init gpiomux_init(void)
-{
- return platform_driver_register(&gpiomux_driver);
-}
-
-static void __exit gpiomux_exit(void)
-{
- platform_driver_unregister(&gpiomux_driver);
-}
-
-module_init(gpiomux_init);
-module_exit(gpiomux_exit);
+module_platform_driver(gpiomux_driver);
MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver");
MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>");
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index 25b9fe3..d3be99f 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -221,7 +221,7 @@ static int __init ali14xx_probe(void)
return ide_legacy_device_add(&ali14xx_port_info, 0);
}
-static int probe_ali14xx;
+static bool probe_ali14xx;
module_param_named(probe, probe_ali14xx, bool, 0);
MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index a81bd75..1471730 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -111,7 +111,7 @@
#define DRV_NAME "cmd640"
-static int cmd640_vlb;
+static bool cmd640_vlb;
/*
* CMD640 specific registers definition.
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 6929f7f..46af474 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -130,7 +130,7 @@ static int __init dtc2278_probe(void)
return ide_legacy_device_add(&dtc2278_port_info, 0);
}
-static int probe_dtc2278;
+static bool probe_dtc2278;
module_param_named(probe, probe_dtc2278, bool, 0);
MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 3feaa26..51beb85 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -50,7 +50,7 @@
GAYLE_NUM_HWIFS-1)
#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
-static int ide_doubler;
+static bool ide_doubler;
module_param_named(doubler, ide_doubler, bool, 0);
MODULE_PARM_DESC(doubler, "enable support for IDE doublers");
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 808bcdc..986f251 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -317,7 +317,7 @@ static void __init ht6560b_init_dev(ide_drive_t *drive)
ide_set_drivedata(drive, (void *)t);
}
-static int probe_ht6560b;
+static bool probe_ht6560b;
module_param_named(probe, probe_ht6560b, bool, 0);
MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
diff --git a/drivers/ide/ide-4drives.c b/drivers/ide/ide-4drives.c
index 979d342..547d7cf 100644
--- a/drivers/ide/ide-4drives.c
+++ b/drivers/ide/ide-4drives.c
@@ -6,7 +6,7 @@
#define DRV_NAME "ide-4drives"
-static int probe_4drives;
+static bool probe_4drives;
module_param_named(probe, probe_4drives, bool, 0);
MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index f22edc6..f1a6796b 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -53,15 +53,15 @@ struct ide_acpi_hwif_link {
#define DEBPRINT(fmt, args...) do {} while (0)
#endif /* DEBUGGING */
-static int ide_noacpi;
+static bool ide_noacpi;
module_param_named(noacpi, ide_noacpi, bool, 0);
MODULE_PARM_DESC(noacpi, "disable IDE ACPI support");
-static int ide_acpigtf;
+static bool ide_acpigtf;
module_param_named(acpigtf, ide_acpigtf, bool, 0);
MODULE_PARM_DESC(acpigtf, "enable IDE ACPI _GTF support");
-static int ide_acpionboot;
+static bool ide_acpionboot;
module_param_named(acpionboot, ide_acpionboot, bool, 0);
MODULE_PARM_DESC(acpionboot, "call IDE ACPI methods on boot");
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index d267b7a..a22ca84 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
* and CDROM_SEND_PACKET (legacy) ioctls
*/
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk,
- mode, cmd, argp);
+ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
if (err == -ENOTTY)
err = generic_ide_ioctl(drive, bdev, cmd, arg);
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c
index a743e68..7f56b73 100644
--- a/drivers/ide/ide-pci-generic.c
+++ b/drivers/ide/ide-pci-generic.c
@@ -28,7 +28,7 @@
#define DRV_NAME "ide_pci_generic"
-static int ide_generic_all; /* Set to claim all devices */
+static bool ide_generic_all; /* Set to claim all devices */
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index 3f0244f..8bbfe55 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -417,7 +417,7 @@ static int __init qd_probe(int base)
return rc;
}
-static int probe_qd65xx;
+static bool probe_qd65xx;
module_param_named(probe, probe_qd65xx, bool, 0);
MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index 47adcd0..5cfb781 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -160,7 +160,7 @@ static int __init umc8672_probe(void)
return ide_legacy_device_add(&umc8672_port_info, 0);
}
-static int probe_umc8672;
+static bool probe_umc8672;
module_param_named(probe, probe_umc8672, bool, 0);
MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index aaf6023..f08f6ea 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -379,8 +379,8 @@ extern spinlock_t shca_list_lock;
extern int ehca_static_rate;
extern int ehca_port_act_time;
-extern int ehca_use_hp_mr;
-extern int ehca_scaling_code;
+extern bool ehca_use_hp_mr;
+extern bool ehca_scaling_code;
extern int ehca_lock_hcalls;
extern int ehca_nr_ports;
extern int ehca_max_cq;
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c240e99..832e7a7 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -59,16 +59,16 @@ MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
MODULE_VERSION(HCAD_VERSION);
-static int ehca_open_aqp1 = 0;
+static bool ehca_open_aqp1 = 0;
static int ehca_hw_level = 0;
-static int ehca_poll_all_eqs = 1;
+static bool ehca_poll_all_eqs = 1;
int ehca_debug_level = 0;
int ehca_nr_ports = -1;
-int ehca_use_hp_mr = 0;
+bool ehca_use_hp_mr = 0;
int ehca_port_act_time = 30;
int ehca_static_rate = -1;
-int ehca_scaling_code = 0;
+bool ehca_scaling_code = 0;
int ehca_lock_hcalls = -1;
int ehca_max_cq = -1;
int ehca_max_qp = -1;
@@ -82,7 +82,7 @@ module_param_named(port_act_time, ehca_port_act_time, int, S_IRUGO);
module_param_named(poll_all_eqs, ehca_poll_all_eqs, bool, S_IRUGO);
module_param_named(static_rate, ehca_static_rate, int, S_IRUGO);
module_param_named(scaling_code, ehca_scaling_code, bool, S_IRUGO);
-module_param_named(lock_hcalls, ehca_lock_hcalls, bool, S_IRUGO);
+module_param_named(lock_hcalls, ehca_lock_hcalls, bint, S_IRUGO);
module_param_named(number_of_cqs, ehca_max_cq, int, S_IRUGO);
module_param_named(number_of_qps, ehca_max_qp, int, S_IRUGO);
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 5965b3d..7013da5 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -96,7 +96,7 @@ unsigned int wqm_quanta = 0x10000;
module_param(wqm_quanta, int, 0644);
MODULE_PARM_DESC(wqm_quanta, "WQM quanta");
-static unsigned int limit_maxrdreqsz;
+static bool limit_maxrdreqsz;
module_param(limit_maxrdreqsz, bool, 0644);
MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes");
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 32bbd4c..fd7a0d5 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -98,15 +98,15 @@
#define XTYPE_XBOX360W 2
#define XTYPE_UNKNOWN 3
-static int dpad_to_buttons;
+static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
-static int triggers_to_buttons;
+static bool triggers_to_buttons;
module_param(triggers_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads");
-static int sticks_to_null;
+static bool sticks_to_null;
module_param(sticks_to_null, bool, S_IRUGO);
MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 6df5f6a..79172af 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -259,6 +259,19 @@ static struct platform_driver amikbd_driver = {
.owner = THIS_MODULE,
},
};
-module_platform_driver(amikbd_driver);
+
+static int __init amikbd_init(void)
+{
+ return platform_driver_probe(&amikbd_driver, amikbd_probe);
+}
+
+module_init(amikbd_init);
+
+static void __exit amikbd_exit(void)
+{
+ platform_driver_unregister(&amikbd_driver);
+}
+
+module_exit(amikbd_exit);
MODULE_ALIAS("platform:amiga-keyboard");
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index 4698252..9d82b3a 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -328,7 +328,18 @@ static struct platform_driver davinci_ks_driver = {
},
.remove = __devexit_p(davinci_ks_remove),
};
-module_platform_driver(davinci_ks_driver);
+
+static int __init davinci_ks_init(void)
+{
+ return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe);
+}
+module_init(davinci_ks_init);
+
+static void __exit davinci_ks_exit(void)
+{
+ platform_driver_unregister(&davinci_ks_driver);
+}
+module_exit(davinci_ks_exit);
MODULE_AUTHOR("Miguel Aguilar");
MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index 5a71e55..e35566a 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -390,7 +390,18 @@ static struct platform_driver ske_keypad_driver = {
.probe = ske_keypad_probe,
.remove = __devexit_p(ske_keypad_remove),
};
-module_platform_driver(ske_keypad_driver);
+
+static int __init ske_keypad_init(void)
+{
+ return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
+}
+module_init(ske_keypad_init);
+
+static void __exit ske_keypad_exit(void)
+{
+ platform_driver_unregister(&ske_keypad_driver);
+}
+module_exit(ske_keypad_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index 79d9016..350fd0c 100644
--- a/drivers/input/misc/ab8500-ponkey.c
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -12,7 +12,7 @@
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/interrupt.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/slab.h>
/**
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
index 19a6882..38e4b50 100644
--- a/drivers/input/misc/twl4030-pwrbutton.c
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -107,14 +107,25 @@ static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev)
}
static struct platform_driver twl4030_pwrbutton_driver = {
- .probe = twl4030_pwrbutton_probe,
.remove = __exit_p(twl4030_pwrbutton_remove),
.driver = {
.name = "twl4030_pwrbutton",
.owner = THIS_MODULE,
},
};
-module_platform_driver(twl4030_pwrbutton_driver);
+
+static int __init twl4030_pwrbutton_init(void)
+{
+ return platform_driver_probe(&twl4030_pwrbutton_driver,
+ twl4030_pwrbutton_probe);
+}
+module_init(twl4030_pwrbutton_init);
+
+static void __exit twl4030_pwrbutton_exit(void)
+{
+ platform_driver_unregister(&twl4030_pwrbutton_driver);
+}
+module_exit(twl4030_pwrbutton_exit);
MODULE_ALIAS("platform:twl4030_pwrbutton");
MODULE_DESCRIPTION("Triton2 Power Button");
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 52b4193..e2bdfd4 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -48,7 +48,7 @@ MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.3");
-static int force; /* = 0; */
+static bool force; /* = 0; */
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Load even if computer is not in database");
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 39be7b8..ff5f61a 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -140,13 +140,25 @@ static int __exit amimouse_remove(struct platform_device *pdev)
}
static struct platform_driver amimouse_driver = {
- .probe = amimouse_probe,
.remove = __exit_p(amimouse_remove),
.driver = {
.name = "amiga-mouse",
.owner = THIS_MODULE,
},
};
-module_platform_driver(amimouse_driver);
+
+static int __init amimouse_init(void)
+{
+ return platform_driver_probe(&amimouse_driver, amimouse_probe);
+}
+
+module_init(amimouse_init);
+
+static void __exit amimouse_exit(void)
+{
+ platform_driver_unregister(&amimouse_driver);
+}
+
+module_exit(amimouse_exit);
MODULE_ALIAS("platform:amiga-mouse");
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index cf87f8b..927e479 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -433,6 +433,9 @@ static void setup_events_to_report(struct input_dev *input_dev,
__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
+ if (cfg->caps & HAS_INTEGRATED_BUTTON)
+ __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
+
input_set_events_per_packet(input_dev, 60);
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index de7e8bc..e6c9931 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -60,7 +60,7 @@ static unsigned int psmouse_rate = 100;
module_param_named(rate, psmouse_rate, uint, 0644);
MODULE_PARM_DESC(rate, "Report rate, in reports per second.");
-static unsigned int psmouse_smartscroll = 1;
+static bool psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 4b755cb..1c58aaf 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -185,17 +185,17 @@
#define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4)
/* Control touchpad's No Deceleration option */
-static int no_decel = 1;
+static bool no_decel = 1;
module_param(no_decel, bool, 0644);
MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)");
/* Control touchpad's Reduced Reporting option */
-static int reduce_report;
+static bool reduce_report;
module_param(reduce_report, bool, 0644);
MODULE_PARM_DESC(reduce_report, "Reduced Reporting. Default = 0 (off)");
/* Control touchpad's No Filter option */
-static int no_filter;
+static bool no_filter;
module_param(no_filter, bool, 0644);
MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)");
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
index 421a744..95280f9 100644
--- a/drivers/input/serio/at32psif.c
+++ b/drivers/input/serio/at32psif.c
@@ -358,7 +358,19 @@ static struct platform_driver psif_driver = {
.suspend = psif_suspend,
.resume = psif_resume,
};
-module_platform_driver(psif_driver);
+
+static int __init psif_init(void)
+{
+ return platform_driver_probe(&psif_driver, psif_probe);
+}
+
+static void __exit psif_exit(void)
+{
+ platform_driver_unregister(&psif_driver);
+}
+
+module_init(psif_init);
+module_exit(psif_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 979c443..be33160 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -105,7 +105,7 @@ EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
-static unsigned int hp_sdc_disabled;
+static bool hp_sdc_disabled;
module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 4d4cd14..8250299 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -220,11 +220,11 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
goto out;
}
written++;
- };
+ }
out:
mutex_unlock(&serio_raw_mutex);
- return written;
+ return written ?: retval;
}
static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
@@ -237,9 +237,9 @@ static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
if (serio_raw->head != serio_raw->tail)
- return POLLIN | POLLRDNORM;
+ mask |= POLLIN | POLLRDNORM;
- return 0;
+ return mask;
}
static const struct file_operations serio_raw_fops = {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 127c391..d96d4c2 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -253,7 +253,7 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
}
/* Get IRQ for the device */
- if (of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq) == NO_IRQ) {
+ if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) {
dev_err(dev, "no IRQ found\n");
return -ENODEV;
}
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
index d016cb2..8034cbb 100644
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ b/drivers/input/touchscreen/atmel-wm97xx.c
@@ -429,7 +429,18 @@ static struct platform_driver atmel_wm97xx_driver = {
.suspend = atmel_wm97xx_suspend,
.resume = atmel_wm97xx_resume,
};
-module_platform_driver(atmel_wm97xx_driver);
+
+static int __init atmel_wm97xx_init(void)
+{
+ return platform_driver_probe(&atmel_wm97xx_driver, atmel_wm97xx_probe);
+}
+module_init(atmel_wm97xx_init);
+
+static void __exit atmel_wm97xx_exit(void)
+{
+ platform_driver_unregister(&atmel_wm97xx_driver);
+}
+module_exit(atmel_wm97xx_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 7f8f538..1df19bb 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -35,11 +35,11 @@
#include <linux/input/eeti_ts.h>
#include <linux/slab.h>
-static int flip_x;
+static bool flip_x;
module_param(flip_x, bool, 0644);
MODULE_PARM_DESC(flip_x, "flip x coordinate");
-static int flip_y;
+static bool flip_y;
module_param(flip_y, bool, 0644);
MODULE_PARM_DESC(flip_y, "flip y coordinate");
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
index 81e3386..d13143b 100644
--- a/drivers/input/touchscreen/htcpen.c
+++ b/drivers/input/touchscreen/htcpen.c
@@ -40,10 +40,10 @@ MODULE_LICENSE("GPL");
#define X_AXIS_MAX 2040
#define Y_AXIS_MAX 2040
-static int invert_x;
+static bool invert_x;
module_param(invert_x, bool, 0644);
MODULE_PARM_DESC(invert_x, "If set, X axis is inverted");
-static int invert_y;
+static bool invert_y;
module_param(invert_y, bool, 0644);
MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted");
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index 68f86f7..ede0274 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -240,7 +240,18 @@ static struct platform_driver mc13783_ts_driver = {
.name = MC13783_TS_NAME,
},
};
-module_platform_driver(mc13783_ts_driver);
+
+static int __init mc13783_ts_init(void)
+{
+ return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
+}
+module_init(mc13783_ts_init);
+
+static void __exit mc13783_ts_exit(void)
+{
+ platform_driver_unregister(&mc13783_ts_driver);
+}
+module_exit(mc13783_ts_exit);
MODULE_DESCRIPTION("MC13783 input touchscreen driver");
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index d2b5753..46e83ad 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -30,7 +30,7 @@
#define UCB1400_TS_POLL_PERIOD 10 /* ms */
-static int adcsync;
+static bool adcsync;
static int ts_delay = 55; /* us */
static int ts_delay_pressure; /* us */
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 06cef3c..3a5ebf4 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -60,11 +60,11 @@
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver"
-static int swap_xy;
+static bool swap_xy;
module_param(swap_xy, bool, 0644);
MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
-static int hwcalib_xy;
+static bool hwcalib_xy;
module_param(hwcalib_xy, bool, 0644);
MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available");
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 9c8d7aa0..a0ed668 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -40,7 +40,7 @@ MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
-static int suppress_pollack = 0;
+static bool suppress_pollack = 0;
module_param(suppress_pollack, bool, 0);
/* ------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index d3530f6..9743b24 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -40,7 +40,7 @@ static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
-static int suppress_pollack;
+static bool suppress_pollack;
static struct pci_device_id c4_pci_tbl[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 },
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 9c6650e..2302fbe 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -6,7 +6,7 @@ if ISDN_I4L
config ISDN_PPP
bool "Support synchronous PPP"
- depends on INET
+ depends on INET && NETDEVICES
select SLHC
help
Over digital connections such as ISDN, there is no need to
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index ca710ab..023de78 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -30,7 +30,7 @@ static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCo
static unsigned int io[] = {0,0,0,0};
static unsigned char irq[] = {0,0,0,0};
static unsigned long ram[] = {0,0,0,0};
-static int do_reset = 0;
+static bool do_reset = 0;
module_param_array(io, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 1b75a56..c957c34 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -388,6 +388,21 @@ config LEDS_RENESAS_TPU
pin function. The latter to support brightness control.
Brightness control is supported but hardware blinking is not.
+config LEDS_TCA6507
+ tristate "LED Support for TCA6507 I2C chip"
+ depends on LEDS_CLASS && I2C
+ help
+ This option enables support for LEDs connected to TC6507
+ LED driver chips accessed via the I2C bus.
+ Driver support brightness control and hardware-assisted blinking.
+
+config LEDS_MAX8997
+ tristate "LED support for MAX8997 PMIC"
+ depends on LEDS_CLASS && MFD_MAX8997
+ help
+ This option enables support for on-chip LED drivers on
+ MAXIM MAX8997 PMIC.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e4f6bf5..b8a9723 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
+obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
@@ -43,6 +44,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o
obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o
+obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 0810604..4ca0062 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = {
.remove = pm860x_led_remove,
};
-static int __devinit pm860x_led_init(void)
-{
- return platform_driver_register(&pm860x_led_driver);
-}
-module_init(pm860x_led_init);
-
-static void __devexit pm860x_led_exit(void)
-{
- platform_driver_unregister(&pm860x_led_driver);
-}
-module_exit(pm860x_led_exit);
+module_platform_driver(pm860x_led_driver);
MODULE_DESCRIPTION("LED driver for Marvell PM860x");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index 7ba4c7b..b1400db 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = {
.remove = __devexit_p(adp5520_led_remove),
};
-static int __init adp5520_led_init(void)
-{
- return platform_driver_register(&adp5520_led_driver);
-}
-module_init(adp5520_led_init);
-
-static void __exit adp5520_led_exit(void)
-{
- platform_driver_unregister(&adp5520_led_driver);
-}
-module_exit(adp5520_led_exit);
+module_platform_driver(adp5520_led_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
index 8c00937..0742835 100644
--- a/drivers/leds/leds-ams-delta.c
+++ b/drivers/leds/leds-ams-delta.c
@@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = {
},
};
-static int __init ams_delta_led_init(void)
-{
- return platform_driver_register(&ams_delta_led_driver);
-}
-
-static void __exit ams_delta_led_exit(void)
-{
- platform_driver_unregister(&ams_delta_led_driver);
-}
-
-module_init(ams_delta_led_init);
-module_exit(ams_delta_led_exit);
+module_platform_driver(ams_delta_led_driver);
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
MODULE_DESCRIPTION("Amstrad Delta LED driver");
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index 48d9fe6..525a924 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = {
},
};
-MODULE_ALIAS("platform:leds-asic3");
-
-static int __init asic3_led_init(void)
-{
- return platform_driver_register(&asic3_led_driver);
-}
-
-static void __exit asic3_led_exit(void)
-{
- platform_driver_unregister(&asic3_led_driver);
-}
-
-module_init(asic3_led_init);
-module_exit(asic3_led_exit);
+module_platform_driver(asic3_led_driver);
MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
MODULE_DESCRIPTION("HTC ASIC3 LED driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-asic3");
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 109c875..800243b 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev)
return 0;
}
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:leds-atmel-pwm");
-
static struct platform_driver pwmled_driver = {
.driver = {
.name = "leds-atmel-pwm",
.owner = THIS_MODULE,
},
/* REVISIT add suspend() and resume() methods */
+ .probe = pwmled_probe,
.remove = __exit_p(pwmled_remove),
};
-static int __init modinit(void)
-{
- return platform_driver_probe(&pwmled_driver, pwmled_probe);
-}
-module_init(modinit);
-
-static void __exit modexit(void)
-{
- platform_driver_unregister(&pwmled_driver);
-}
-module_exit(modexit);
+module_platform_driver(pwmled_driver);
MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-atmel-pwm");
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index ea21855..591cbdf5 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
i2c_set_clientdata(client, led);
/* Configure RESET GPIO (L: RESET, H: RESET cancel) */
- gpio_request(pdata->reset_gpio, "RGB_RESETB");
- gpio_direction_output(pdata->reset_gpio, 1);
+ gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB");
/* Tacss = min 0.1ms */
udelay(100);
@@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = {
.id_table = bd2802_id,
};
-static int __init bd2802_init(void)
-{
- return i2c_add_driver(&bd2802_i2c_driver);
-}
-module_init(bd2802_init);
-
-static void __exit bd2802_exit(void)
-{
- i2c_del_driver(&bd2802_i2c_driver);
-}
-module_exit(bd2802_exit);
+module_i2c_driver(bd2802_i2c_driver);
MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
MODULE_DESCRIPTION("BD2802 LED driver");
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index a498135..1ed1677 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -18,7 +18,7 @@ MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
MODULE_DESCRIPTION("Clevo mail LED driver");
MODULE_LICENSE("GPL");
-static unsigned int __initdata nodetect;
+static bool __initdata nodetect;
module_param_named(nodetect, nodetect, bool, 0);
MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index da5fb01..6a8725cc 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
return 0;
}
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:cobalt-qube-leds");
-
static struct platform_driver cobalt_qube_led_driver = {
.probe = cobalt_qube_led_probe,
.remove = __devexit_p(cobalt_qube_led_remove),
@@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = {
},
};
-static int __init cobalt_qube_led_init(void)
-{
- return platform_driver_register(&cobalt_qube_led_driver);
-}
-
-static void __exit cobalt_qube_led_exit(void)
-{
- platform_driver_unregister(&cobalt_qube_led_driver);
-}
-
-module_init(cobalt_qube_led_init);
-module_exit(cobalt_qube_led_exit);
+module_platform_driver(cobalt_qube_led_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Front LED support for Cobalt Server");
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_ALIAS("platform:cobalt-qube-leds");
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index f28931c..d9cd73e 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = {
.remove = __devexit_p(da903x_led_remove),
};
-static int __init da903x_led_init(void)
-{
- return platform_driver_register(&da903x_led_driver);
-}
-module_init(da903x_led_init);
-
-static void __exit da903x_led_exit(void)
-{
- platform_driver_unregister(&da903x_led_driver);
-}
-module_exit(da903x_led_exit);
+module_platform_driver(da903x_led_driver);
MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index 31cf0d6..d56c142 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = {
},
};
-static int __init dac124s085_leds_init(void)
-{
- return spi_register_driver(&dac124s085_driver);
-}
-
-static void __exit dac124s085_leds_exit(void)
-{
- spi_unregister_driver(&dac124s085_driver);
-}
-
-module_init(dac124s085_leds_init);
-module_exit(dac124s085_leds_exit);
+module_spi_driver(dac124s085_driver);
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
MODULE_DESCRIPTION("DAC124S085 LED driver");
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index 49aceff..b9053fa 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = {
},
};
-
-static int __init fsg_led_init(void)
-{
- return platform_driver_register(&fsg_led_driver);
-}
-
-static void __exit fsg_led_exit(void)
-{
- platform_driver_unregister(&fsg_led_driver);
-}
-
-
-module_init(fsg_led_init);
-module_exit(fsg_led_exit);
+module_platform_driver(fsg_led_driver);
MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 399a86f..7df74cb 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = {
},
};
-MODULE_ALIAS("platform:leds-gpio");
-
-static int __init gpio_led_init(void)
-{
- return platform_driver_register(&gpio_led_driver);
-}
-
-static void __exit gpio_led_exit(void)
-{
- platform_driver_unregister(&gpio_led_driver);
-}
-
-module_init(gpio_led_init);
-module_exit(gpio_led_exit);
+module_platform_driver(gpio_led_driver);
MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
MODULE_DESCRIPTION("GPIO LED driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-gpio");
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index bcfbd3a..366b605 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev)
return 0;
}
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:hp6xx-led");
-
static struct platform_driver hp6xxled_driver = {
.probe = hp6xxled_probe,
.remove = hp6xxled_remove,
@@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = {
},
};
-static int __init hp6xxled_init(void)
-{
- return platform_driver_register(&hp6xxled_driver);
-}
-
-static void __exit hp6xxled_exit(void)
-{
- platform_driver_unregister(&hp6xxled_driver);
-}
-
-module_init(hp6xxled_init);
-module_exit(hp6xxled_exit);
+module_platform_driver(hp6xxled_driver);
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hp6xx-led");
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 0630e4f..45e6878 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = {
},
};
-static int __init lm3530_init(void)
-{
- return i2c_add_driver(&lm3530_i2c_driver);
-}
-
-static void __exit lm3530_exit(void)
-{
- i2c_del_driver(&lm3530_i2c_driver);
-}
-
-module_init(lm3530_init);
-module_exit(lm3530_exit);
+module_i2c_driver(lm3530_i2c_driver);
MODULE_DESCRIPTION("Back Light driver for LM3530");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 9010c05..b8f9f0a 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = {
.id_table = lp3944_id,
};
-static int __init lp3944_module_init(void)
-{
- return i2c_add_driver(&lp3944_driver);
-}
-
-static void __exit lp3944_module_exit(void)
-{
- i2c_del_driver(&lp3944_driver);
-}
-
-module_init(lp3944_module_init);
-module_exit(lp3944_module_exit);
+module_i2c_driver(lp3944_driver);
MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("LP3944 Fun Light Chip");
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index cb641f1..d62a798 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = {
.id_table = lp5521_id,
};
-static int __init lp5521_init(void)
-{
- int ret;
-
- ret = i2c_add_driver(&lp5521_driver);
-
- if (ret < 0)
- printk(KERN_ALERT "Adding lp5521 driver failed\n");
-
- return ret;
-}
-
-static void __exit lp5521_exit(void)
-{
- i2c_del_driver(&lp5521_driver);
-}
-
-module_init(lp5521_init);
-module_exit(lp5521_exit);
+module_i2c_driver(lp5521_driver);
MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
MODULE_DESCRIPTION("LP5521 LED engine");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 5971e309..73e791a 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
return 0;
}
-static struct i2c_driver lp5523_driver;
-
static int __devinit lp5523_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = {
.id_table = lp5523_id,
};
-static int __init lp5523_init(void)
-{
- int ret;
-
- ret = i2c_add_driver(&lp5523_driver);
-
- if (ret < 0)
- printk(KERN_ALERT "Adding lp5523 driver failed\n");
-
- return ret;
-}
-
-static void __exit lp5523_exit(void)
-{
- i2c_del_driver(&lp5523_driver);
-}
-
-module_init(lp5523_init);
-module_exit(lp5523_exit);
+module_i2c_driver(lp5523_driver);
MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
MODULE_DESCRIPTION("LP5523 LED engine");
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 53f67b8..e311a96c 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = {
},
};
-MODULE_ALIAS("platform:leds-lt3593");
-
-static int __init lt3593_led_init(void)
-{
- return platform_driver_register(&lt3593_led_driver);
-}
-
-static void __exit lt3593_led_exit(void)
-{
- platform_driver_unregister(&lt3593_led_driver);
-}
-
-module_init(lt3593_led_init);
-module_exit(lt3593_led_exit);
+module_platform_driver(lt3593_led_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("LED driver for LT3593 controllers");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-lt3593");
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
new file mode 100644
index 0000000..f4c0e37
--- /dev/null
+++ b/drivers/leds/leds-max8997.c
@@ -0,0 +1,372 @@
+/*
+ * leds-max8997.c - LED class driver for MAX8997 LEDs.
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * Donggeun Kim <dg77.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+#include <linux/platform_device.h>
+
+#define MAX8997_LED_FLASH_SHIFT 3
+#define MAX8997_LED_FLASH_CUR_MASK 0xf8
+#define MAX8997_LED_MOVIE_SHIFT 4
+#define MAX8997_LED_MOVIE_CUR_MASK 0xf0
+
+#define MAX8997_LED_FLASH_MAX_BRIGHTNESS 0x1f
+#define MAX8997_LED_MOVIE_MAX_BRIGHTNESS 0xf
+#define MAX8997_LED_NONE_MAX_BRIGHTNESS 0
+
+#define MAX8997_LED0_FLASH_MASK 0x1
+#define MAX8997_LED0_FLASH_PIN_MASK 0x5
+#define MAX8997_LED0_MOVIE_MASK 0x8
+#define MAX8997_LED0_MOVIE_PIN_MASK 0x28
+
+#define MAX8997_LED1_FLASH_MASK 0x2
+#define MAX8997_LED1_FLASH_PIN_MASK 0x6
+#define MAX8997_LED1_MOVIE_MASK 0x10
+#define MAX8997_LED1_MOVIE_PIN_MASK 0x30
+
+#define MAX8997_LED_BOOST_ENABLE_MASK (1 << 6)
+
+struct max8997_led {
+ struct max8997_dev *iodev;
+ struct led_classdev cdev;
+ bool enabled;
+ int id;
+ enum max8997_led_mode led_mode;
+ struct mutex mutex;
+};
+
+static void max8997_led_clear_mode(struct max8997_led *led,
+ enum max8997_led_mode mode)
+{
+ struct i2c_client *client = led->iodev->i2c;
+ u8 val = 0, mask = 0;
+ int ret;
+
+ switch (mode) {
+ case MAX8997_FLASH_MODE:
+ mask = led->id ?
+ MAX8997_LED1_FLASH_MASK : MAX8997_LED0_FLASH_MASK;
+ break;
+ case MAX8997_MOVIE_MODE:
+ mask = led->id ?
+ MAX8997_LED1_MOVIE_MASK : MAX8997_LED0_MOVIE_MASK;
+ break;
+ case MAX8997_FLASH_PIN_CONTROL_MODE:
+ mask = led->id ?
+ MAX8997_LED1_FLASH_PIN_MASK : MAX8997_LED0_FLASH_PIN_MASK;
+ break;
+ case MAX8997_MOVIE_PIN_CONTROL_MODE:
+ mask = led->id ?
+ MAX8997_LED1_MOVIE_PIN_MASK : MAX8997_LED0_MOVIE_PIN_MASK;
+ break;
+ default:
+ break;
+ }
+
+ if (mask) {
+ ret = max8997_update_reg(client,
+ MAX8997_REG_LEN_CNTL, val, mask);
+ if (ret)
+ dev_err(led->iodev->dev,
+ "failed to update register(%d)\n", ret);
+ }
+}
+
+static void max8997_led_set_mode(struct max8997_led *led,
+ enum max8997_led_mode mode)
+{
+ int ret;
+ struct i2c_client *client = led->iodev->i2c;
+ u8 mask = 0;
+
+ /* First, clear the previous mode */
+ max8997_led_clear_mode(led, led->led_mode);
+
+ switch (mode) {
+ case MAX8997_FLASH_MODE:
+ mask = led->id ?
+ MAX8997_LED1_FLASH_MASK : MAX8997_LED0_FLASH_MASK;
+ led->cdev.max_brightness = MAX8997_LED_FLASH_MAX_BRIGHTNESS;
+ break;
+ case MAX8997_MOVIE_MODE:
+ mask = led->id ?
+ MAX8997_LED1_MOVIE_MASK : MAX8997_LED0_MOVIE_MASK;
+ led->cdev.max_brightness = MAX8997_LED_MOVIE_MAX_BRIGHTNESS;
+ break;
+ case MAX8997_FLASH_PIN_CONTROL_MODE:
+ mask = led->id ?
+ MAX8997_LED1_FLASH_PIN_MASK : MAX8997_LED0_FLASH_PIN_MASK;
+ led->cdev.max_brightness = MAX8997_LED_FLASH_MAX_BRIGHTNESS;
+ break;
+ case MAX8997_MOVIE_PIN_CONTROL_MODE:
+ mask = led->id ?
+ MAX8997_LED1_MOVIE_PIN_MASK : MAX8997_LED0_MOVIE_PIN_MASK;
+ led->cdev.max_brightness = MAX8997_LED_MOVIE_MAX_BRIGHTNESS;
+ break;
+ default:
+ led->cdev.max_brightness = MAX8997_LED_NONE_MAX_BRIGHTNESS;
+ break;
+ }
+
+ if (mask) {
+ ret = max8997_update_reg(client,
+ MAX8997_REG_LEN_CNTL, mask, mask);
+ if (ret)
+ dev_err(led->iodev->dev,
+ "failed to update register(%d)\n", ret);
+ }
+
+ led->led_mode = mode;
+}
+
+static void max8997_led_enable(struct max8997_led *led, bool enable)
+{
+ int ret;
+ struct i2c_client *client = led->iodev->i2c;
+ u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;
+
+ if (led->enabled == enable)
+ return;
+
+ val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;
+
+ ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
+ if (ret)
+ dev_err(led->iodev->dev,
+ "failed to update register(%d)\n", ret);
+
+ led->enabled = enable;
+}
+
+static void max8997_led_set_current(struct max8997_led *led,
+ enum led_brightness value)
+{
+ int ret;
+ struct i2c_client *client = led->iodev->i2c;
+ u8 val = 0, mask = 0, reg = 0;
+
+ switch (led->led_mode) {
+ case MAX8997_FLASH_MODE:
+ case MAX8997_FLASH_PIN_CONTROL_MODE:
+ val = value << MAX8997_LED_FLASH_SHIFT;
+ mask = MAX8997_LED_FLASH_CUR_MASK;
+ reg = led->id ? MAX8997_REG_FLASH2_CUR : MAX8997_REG_FLASH1_CUR;
+ break;
+ case MAX8997_MOVIE_MODE:
+ case MAX8997_MOVIE_PIN_CONTROL_MODE:
+ val = value << MAX8997_LED_MOVIE_SHIFT;
+ mask = MAX8997_LED_MOVIE_CUR_MASK;
+ reg = MAX8997_REG_MOVIE_CUR;
+ break;
+ default:
+ break;
+ }
+
+ if (mask) {
+ ret = max8997_update_reg(client, reg, val, mask);
+ if (ret)
+ dev_err(led->iodev->dev,
+ "failed to update register(%d)\n", ret);
+ }
+}
+
+static void max8997_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct max8997_led *led =
+ container_of(led_cdev, struct max8997_led, cdev);
+
+ if (value) {
+ max8997_led_set_current(led, value);
+ max8997_led_enable(led, true);
+ } else {
+ max8997_led_set_current(led, value);
+ max8997_led_enable(led, false);
+ }
+}
+
+static ssize_t max8997_led_show_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct max8997_led *led =
+ container_of(led_cdev, struct max8997_led, cdev);
+ ssize_t ret = 0;
+
+ mutex_lock(&led->mutex);
+
+ switch (led->led_mode) {
+ case MAX8997_FLASH_MODE:
+ ret += sprintf(buf, "FLASH\n");
+ break;
+ case MAX8997_MOVIE_MODE:
+ ret += sprintf(buf, "MOVIE\n");
+ break;
+ case MAX8997_FLASH_PIN_CONTROL_MODE:
+ ret += sprintf(buf, "FLASH_PIN_CONTROL\n");
+ break;
+ case MAX8997_MOVIE_PIN_CONTROL_MODE:
+ ret += sprintf(buf, "MOVIE_PIN_CONTROL\n");
+ break;
+ default:
+ ret += sprintf(buf, "NONE\n");
+ break;
+ }
+
+ mutex_unlock(&led->mutex);
+
+ return ret;
+}
+
+static ssize_t max8997_led_store_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct max8997_led *led =
+ container_of(led_cdev, struct max8997_led, cdev);
+ enum max8997_led_mode mode;
+
+ mutex_lock(&led->mutex);
+
+ if (!strncmp(buf, "FLASH_PIN_CONTROL", 17))
+ mode = MAX8997_FLASH_PIN_CONTROL_MODE;
+ else if (!strncmp(buf, "MOVIE_PIN_CONTROL", 17))
+ mode = MAX8997_MOVIE_PIN_CONTROL_MODE;
+ else if (!strncmp(buf, "FLASH", 5))
+ mode = MAX8997_FLASH_MODE;
+ else if (!strncmp(buf, "MOVIE", 5))
+ mode = MAX8997_MOVIE_MODE;
+ else
+ mode = MAX8997_NONE;
+
+ max8997_led_set_mode(led, mode);
+
+ mutex_unlock(&led->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
+
+static int __devinit max8997_led_probe(struct platform_device *pdev)
+{
+ struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_led *led;
+ char name[20];
+ int ret = 0;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -ENODEV;
+ }
+
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
+ if (led == NULL) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ led->id = pdev->id;
+ snprintf(name, sizeof(name), "max8997-led%d", pdev->id);
+
+ led->cdev.name = name;
+ led->cdev.brightness_set = max8997_led_brightness_set;
+ led->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led->cdev.brightness = 0;
+ led->iodev = iodev;
+
+ /* initialize mode and brightness according to platform_data */
+ if (pdata->led_pdata) {
+ u8 mode = 0, brightness = 0;
+
+ mode = pdata->led_pdata->mode[led->id];
+ brightness = pdata->led_pdata->brightness[led->id];
+
+ max8997_led_set_mode(led, pdata->led_pdata->mode[led->id]);
+
+ if (brightness > led->cdev.max_brightness)
+ brightness = led->cdev.max_brightness;
+ max8997_led_set_current(led, brightness);
+ led->cdev.brightness = brightness;
+ } else {
+ max8997_led_set_mode(led, MAX8997_NONE);
+ max8997_led_set_current(led, 0);
+ }
+
+ mutex_init(&led->mutex);
+
+ platform_set_drvdata(pdev, led);
+
+ ret = led_classdev_register(&pdev->dev, &led->cdev);
+ if (ret < 0)
+ goto err_led;
+
+ ret = device_create_file(led->cdev.dev, &dev_attr_mode);
+ if (ret != 0) {
+ dev_err(&pdev->dev,
+ "failed to create file: %d\n", ret);
+ goto err_file;
+ }
+
+ return 0;
+
+err_file:
+ led_classdev_unregister(&led->cdev);
+err_led:
+ kfree(led);
+err_mem:
+ return ret;
+}
+
+static int __devexit max8997_led_remove(struct platform_device *pdev)
+{
+ struct max8997_led *led = platform_get_drvdata(pdev);
+
+ device_remove_file(led->cdev.dev, &dev_attr_mode);
+ led_classdev_unregister(&led->cdev);
+ kfree(led);
+
+ return 0;
+}
+
+static struct platform_driver max8997_led_driver = {
+ .driver = {
+ .name = "max8997-led",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8997_led_probe,
+ .remove = __devexit_p(max8997_led_remove),
+};
+
+static int __init max8997_led_init(void)
+{
+ return platform_driver_register(&max8997_led_driver);
+}
+module_init(max8997_led_init);
+
+static void __exit max8997_led_exit(void)
+{
+ platform_driver_unregister(&max8997_led_driver);
+}
+module_exit(max8997_led_exit);
+
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_DESCRIPTION("MAX8997 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:max8997-led");
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index b3393a9..8bc4915 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) {
+ if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) {
dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
return -EINVAL;
}
@@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = {
.remove = __devexit_p(mc13783_led_remove),
};
-static int __init mc13783_led_init(void)
-{
- return platform_driver_register(&mc13783_led_driver);
-}
-module_init(mc13783_led_init);
-
-static void __exit mc13783_led_exit(void)
-{
- platform_driver_unregister(&mc13783_led_driver);
-}
-module_exit(mc13783_led_exit);
+module_platform_driver(mc13783_led_driver);
MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index f2e51c1..d8433f2 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
/* Configure address GPIOs. */
for (i = 0; i < gpio_ext->num_addr; i++) {
- err = gpio_request(gpio_ext->addr[i], "GPIO extension addr");
+ err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW,
+ "GPIO extension addr");
if (err)
goto err_free_addr;
- err = gpio_direction_output(gpio_ext->addr[i], 0);
- if (err) {
- gpio_free(gpio_ext->addr[i]);
- goto err_free_addr;
- }
}
/* Configure data GPIOs. */
for (i = 0; i < gpio_ext->num_data; i++) {
- err = gpio_request(gpio_ext->data[i], "GPIO extension data");
+ err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW,
+ "GPIO extension data");
if (err)
goto err_free_data;
- err = gpio_direction_output(gpio_ext->data[i], 0);
- if (err) {
- gpio_free(gpio_ext->data[i]);
- goto err_free_data;
- }
}
/* Configure "enable select" GPIO. */
- err = gpio_request(gpio_ext->enable, "GPIO extension enable");
+ err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW,
+ "GPIO extension enable");
if (err)
goto err_free_data;
- err = gpio_direction_output(gpio_ext->enable, 0);
- if (err) {
- gpio_free(gpio_ext->enable);
- goto err_free_data;
- }
return 0;
@@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = {
.owner = THIS_MODULE,
},
};
-MODULE_ALIAS("platform:leds-netxbig");
-static int __init netxbig_led_init(void)
-{
- return platform_driver_register(&netxbig_led_driver);
-}
-
-static void __exit netxbig_led_exit(void)
-{
- platform_driver_unregister(&netxbig_led_driver);
-}
-
-module_init(netxbig_led_init);
-module_exit(netxbig_led_exit);
+module_platform_driver(netxbig_led_driver);
MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-netxbig");
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 37b7d0c..2f0a144 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = {
.owner = THIS_MODULE,
},
};
-MODULE_ALIAS("platform:leds-ns2");
-
-static int __init ns2_led_init(void)
-{
- return platform_driver_register(&ns2_led_driver);
-}
-static void __exit ns2_led_exit(void)
-{
- platform_driver_unregister(&ns2_led_driver);
-}
-
-module_init(ns2_led_init);
-module_exit(ns2_led_exit);
+module_platform_driver(ns2_led_driver);
MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
MODULE_DESCRIPTION("Network Space v2 LED driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ns2");
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index a2c8746..ceccab4 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client)
return 0;
}
-static int __init pca9532_init(void)
-{
- return i2c_add_driver(&pca9532_driver);
-}
-
-static void __exit pca9532_exit(void)
-{
- i2c_del_driver(&pca9532_driver);
-}
+module_i2c_driver(pca9532_driver);
MODULE_AUTHOR("Riku Voipio");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCA 9532 LED dimmer");
-
-module_init(pca9532_init);
-module_exit(pca9532_exit);
-
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 66aa3e8..dcc3bc3 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = {
.id_table = pca955x_id,
};
-static int __init pca955x_leds_init(void)
-{
- return i2c_add_driver(&pca955x_driver);
-}
-
-static void __exit pca955x_leds_exit(void)
-{
- i2c_del_driver(&pca955x_driver);
-}
-
-module_init(pca955x_leds_init);
-module_exit(pca955x_leds_exit);
+module_i2c_driver(pca955x_driver);
MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
MODULE_DESCRIPTION("PCA955x LED driver");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 666daf7..3ed92f3 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = {
},
};
-static int __init led_pwm_init(void)
-{
- return platform_driver_register(&led_pwm_driver);
-}
-
-static void __exit led_pwm_exit(void)
-{
- platform_driver_unregister(&led_pwm_driver);
-}
-
-module_init(led_pwm_init);
-module_exit(led_pwm_exit);
+module_platform_driver(led_pwm_driver);
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
MODULE_DESCRIPTION("PWM LED driver for PXA");
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
index c3525f3..a7815b6 100644
--- a/drivers/leds/leds-rb532.c
+++ b/drivers/leds/leds-rb532.c
@@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = {
},
};
-static int __init rb532_led_init(void)
-{
- return platform_driver_register(&rb532_led_driver);
-}
-
-static void __exit rb532_led_exit(void)
-{
- platform_driver_unregister(&rb532_led_driver);
-}
-
-module_init(rb532_led_init);
-module_exit(rb532_led_exit);
-
-MODULE_ALIAS("platform:rb532-led");
+module_platform_driver(rb532_led_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("User LED support for Routerboard532");
MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
+MODULE_ALIAS("platform:rb532-led");
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 8497f56..df7e963 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = {
.remove = __devexit_p(regulator_led_remove),
};
-static int __init regulator_led_init(void)
-{
- return platform_driver_register(&regulator_led_driver);
-}
-module_init(regulator_led_init);
-
-static void __exit regulator_led_exit(void)
-{
- platform_driver_unregister(&regulator_led_driver);
-}
-module_exit(regulator_led_exit);
+module_platform_driver(regulator_led_driver);
MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("Regulator driven LED driver");
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index 3ee540e..32fe337 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = {
}
};
-static int __init r_tpu_init(void)
-{
- return platform_driver_register(&r_tpu_device_driver);
-}
-
-static void __exit r_tpu_exit(void)
-{
- platform_driver_unregister(&r_tpu_device_driver);
-}
-
-module_init(r_tpu_init);
-module_exit(r_tpu_exit);
+module_platform_driver(r_tpu_device_driver);
MODULE_AUTHOR("Magnus Damm");
MODULE_DESCRIPTION("Renesas TPU LED Driver");
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 29f8b0f..bd0a5ed 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = {
},
};
-static int __init s3c24xx_led_init(void)
-{
- return platform_driver_register(&s3c24xx_led_driver);
-}
-
-static void __exit s3c24xx_led_exit(void)
-{
- platform_driver_unregister(&s3c24xx_led_driver);
-}
-
-module_init(s3c24xx_led_init);
-module_exit(s3c24xx_led_exit);
+module_platform_driver(s3c24xx_led_driver);
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C24XX LED driver");
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 614ebeb..57371e1 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -79,7 +79,7 @@ static int __init ss4200_led_dmi_callback(const struct dmi_system_id *id)
return 1;
}
-static unsigned int __initdata nodetect;
+static bool __initdata nodetect;
module_param_named(nodetect, nodetect, bool, 0);
MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
new file mode 100644
index 0000000..133f89f
--- /dev/null
+++ b/drivers/leds/leds-tca6507.c
@@ -0,0 +1,779 @@
+/*
+ * leds-tca6507
+ *
+ * The TCA6507 is a programmable LED controller that can drive 7
+ * separate lines either by holding them low, or by pulsing them
+ * with modulated width.
+ * The modulation can be varied in a simple pattern to produce a blink or
+ * double-blink.
+ *
+ * This driver can configure each line either as a 'GPIO' which is out-only
+ * (no pull-up) or as an LED with variable brightness and hardware-assisted
+ * blinking.
+ *
+ * Apart from OFF and ON there are three programmable brightness levels which
+ * can be programmed from 0 to 15 and indicate how many 500usec intervals in
+ * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and
+ * BANK1.
+ *
+ * There are two different blink rates that can be programmed, each with
+ * separate time for rise, on, fall, off and second-off. Thus if 3 or more
+ * different non-trivial rates are required, software must be used for the extra
+ * rates. The two different blink rates must align with the two levels BANK0 and
+ * BANK1.
+ * This driver does not support double-blink so 'second-off' always matches
+ * 'off'.
+ *
+ * Only 16 different times can be programmed in a roughly logarithmic scale from
+ * 64ms to 16320ms. To be precise the possible times are:
+ * 0, 64, 128, 192, 256, 384, 512, 768,
+ * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
+ *
+ * Times that cannot be closely matched with these must be
+ * handled in software. This driver allows 12.5% error in matching.
+ *
+ * This driver does not allow rise/fall rates to be set explicitly. When trying
+ * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
+ * 'hold' times are chosen to get a close match. If the target delay is even,
+ * the 'change' number will be the smaller; if odd, the 'hold' number will be
+ * the smaller.
+
+ * Choosing pairs of delays with 12.5% errors allows us to match delays in the
+ * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
+ * 26% of the achievable sums can be matched by multiple pairings. For example
+ * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the
+ * pairing with the least maximum - 768+768 in this case. Other pairings are
+ * not available.
+ *
+ * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
+ * Access can be shared by multiple leds if they have the same level and
+ * either same blink rates, or some don't blink.
+ * When a led changes, it relinquishes access and tries again, so it might
+ * lose access to hardware blink.
+ * If a blink engine cannot be allocated, software blink is used.
+ * If the desired brightness cannot be allocated, the closest available non-zero
+ * brightness is used. As 'full' is always available, the worst case would be
+ * to have two different blink rates at '1', with Max at '2', then other leds
+ * will have to choose between '2' and '16'. Hopefully this is not likely.
+ *
+ * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
+ * and LEDs using the blink. It can only be reprogrammed when the appropriate
+ * counter is zero. The MASTER level has a single usage count.
+ *
+ * Each Led has programmable 'on' and 'off' time as milliseconds. With each
+ * there is a flag saying if it was explicitly requested or defaulted.
+ * Similarly the banks know if each time was explicit or a default. Defaults
+ * are permitted to be changed freely - they are not recognised when matching.
+ *
+ *
+ * An led-tca6507 device must be provided with platform data. This data
+ * lists for each output: the name, default trigger, and whether the signal
+ * is being used as a GPiO rather than an led. 'struct led_plaform_data'
+ * is used for this. If 'name' is NULL, the output isn't used. If 'flags'
+ * is TCA6507_MAKE_CPIO, the output is a GPO.
+ * The "struct led_platform_data" can be embedded in a
+ * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
+ * and a 'setup' callback which is called once the GPiOs are available.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/leds-tca6507.h>
+
+/* LED select registers determine the source that drives LED outputs */
+#define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */
+#define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */
+#define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */
+#define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */
+#define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */
+#define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */
+#define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */
+#define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */
+
+enum {
+ BANK0,
+ BANK1,
+ MASTER,
+};
+static int bank_source[3] = {
+ TCA6507_LS_LED_PWM0,
+ TCA6507_LS_LED_PWM1,
+ TCA6507_LS_LED_MIR,
+};
+static int blink_source[2] = {
+ TCA6507_LS_BLINK0,
+ TCA6507_LS_BLINK1,
+};
+
+/* PWM registers */
+#define TCA6507_REG_CNT 11
+
+/*
+ * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output
+ * owns one bit in each register
+ */
+#define TCA6507_FADE_ON 0x03
+#define TCA6507_FULL_ON 0x04
+#define TCA6507_FADE_OFF 0x05
+#define TCA6507_FIRST_OFF 0x06
+#define TCA6507_SECOND_OFF 0x07
+#define TCA6507_MAX_INTENSITY 0x08
+#define TCA6507_MASTER_INTENSITY 0x09
+#define TCA6507_INITIALIZE 0x0A
+
+#define INIT_CODE 0x8
+
+#define TIMECODES 16
+static int time_codes[TIMECODES] = {
+ 0, 64, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
+};
+
+/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */
+static inline int TO_LEVEL(int brightness)
+{
+ return brightness >> 4;
+}
+
+/* ...and convert back */
+static inline int TO_BRIGHT(int level)
+{
+ if (level)
+ return (level << 4) | 0xf;
+ return 0;
+}
+
+#define NUM_LEDS 7
+struct tca6507_chip {
+ int reg_set; /* One bit per register where
+ * a '1' means the register
+ * should be written */
+ u8 reg_file[TCA6507_REG_CNT];
+ /* Bank 2 is Master Intensity and doesn't use times */
+ struct bank {
+ int level;
+ int ontime, offtime;
+ int on_dflt, off_dflt;
+ int time_use, level_use;
+ } bank[3];
+ struct i2c_client *client;
+ struct work_struct work;
+ spinlock_t lock;
+
+ struct tca6507_led {
+ struct tca6507_chip *chip;
+ struct led_classdev led_cdev;
+ int num;
+ int ontime, offtime;
+ int on_dflt, off_dflt;
+ int bank; /* Bank used, or -1 */
+ int blink; /* Set if hardware-blinking */
+ } leds[NUM_LEDS];
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio;
+ const char *gpio_name[NUM_LEDS];
+ int gpio_map[NUM_LEDS];
+#endif
+};
+
+static const struct i2c_device_id tca6507_id[] = {
+ { "tca6507" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tca6507_id);
+
+static int choose_times(int msec, int *c1p, int *c2p)
+{
+ /*
+ * Choose two timecodes which add to 'msec' as near as possible.
+ * The first returned is the 'on' or 'off' time. The second is to be
+ * used as a 'fade-on' or 'fade-off' time. If 'msec' is even,
+ * the first will not be smaller than the second. If 'msec' is odd,
+ * the first will not be larger than the second.
+ * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
+ * otherwise return the sum that was achieved, plus 1 if the first is
+ * smaller.
+ * If two possibilities are equally good (e.g. 512+0, 256+256), choose
+ * the first pair so there is more change-time visible (i.e. it is
+ * softer).
+ */
+ int c1, c2;
+ int tmax = msec * 9 / 8;
+ int tmin = msec * 7 / 8;
+ int diff = 65536;
+
+ /* We start at '1' to ensure we never even think of choosing a
+ * total time of '0'.
+ */
+ for (c1 = 1; c1 < TIMECODES; c1++) {
+ int t = time_codes[c1];
+ if (t*2 < tmin)
+ continue;
+ if (t > tmax)
+ break;
+ for (c2 = 0; c2 <= c1; c2++) {
+ int tt = t + time_codes[c2];
+ int d;
+ if (tt < tmin)
+ continue;
+ if (tt > tmax)
+ break;
+ /* This works! */
+ d = abs(msec - tt);
+ if (d >= diff)
+ continue;
+ /* Best yet */
+ *c1p = c1;
+ *c2p = c2;
+ diff = d;
+ if (d == 0)
+ return msec;
+ }
+ }
+ if (diff < 65536) {
+ int actual;
+ if (msec & 1) {
+ c1 = *c2p;
+ *c2p = *c1p;
+ *c1p = c1;
+ }
+ actual = time_codes[*c1p] + time_codes[*c2p];
+ if (*c1p < *c2p)
+ return actual + 1;
+ else
+ return actual;
+ }
+ /* No close match */
+ return -EINVAL;
+}
+
+/*
+ * Update the register file with the appropriate 3-bit state for
+ * the given led.
+ */
+static void set_select(struct tca6507_chip *tca, int led, int val)
+{
+ int mask = (1 << led);
+ int bit;
+
+ for (bit = 0; bit < 3; bit++) {
+ int n = tca->reg_file[bit] & ~mask;
+ if (val & (1 << bit))
+ n |= mask;
+ if (tca->reg_file[bit] != n) {
+ tca->reg_file[bit] = n;
+ tca->reg_set |= (1 << bit);
+ }
+ }
+}
+
+/* Update the register file with the appropriate 4-bit code for
+ * one bank or other. This can be used for timers, for levels, or
+ * for initialisation.
+ */
+static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
+{
+ int mask = 0xF;
+ int n;
+ if (bank) {
+ mask <<= 4;
+ new <<= 4;
+ }
+ n = tca->reg_file[reg] & ~mask;
+ n |= new;
+ if (tca->reg_file[reg] != n) {
+ tca->reg_file[reg] = n;
+ tca->reg_set |= 1 << reg;
+ }
+}
+
+/* Update brightness level. */
+static void set_level(struct tca6507_chip *tca, int bank, int level)
+{
+ switch (bank) {
+ case BANK0:
+ case BANK1:
+ set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
+ break;
+ case MASTER:
+ set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
+ break;
+ }
+ tca->bank[bank].level = level;
+}
+
+/* Record all relevant time code for a given bank */
+static void set_times(struct tca6507_chip *tca, int bank)
+{
+ int c1, c2;
+ int result;
+
+ result = choose_times(tca->bank[bank].ontime, &c1, &c2);
+ dev_dbg(&tca->client->dev,
+ "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+ c2, time_codes[c2], tca->bank[bank].ontime);
+ set_code(tca, TCA6507_FADE_ON, bank, c2);
+ set_code(tca, TCA6507_FULL_ON, bank, c1);
+ tca->bank[bank].ontime = result;
+
+ result = choose_times(tca->bank[bank].offtime, &c1, &c2);
+ dev_dbg(&tca->client->dev,
+ "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+ c2, time_codes[c2], tca->bank[bank].offtime);
+ set_code(tca, TCA6507_FADE_OFF, bank, c2);
+ set_code(tca, TCA6507_FIRST_OFF, bank, c1);
+ set_code(tca, TCA6507_SECOND_OFF, bank, c1);
+ tca->bank[bank].offtime = result;
+
+ set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
+}
+
+/* Write all needed register of tca6507 */
+
+static void tca6507_work(struct work_struct *work)
+{
+ struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
+ work);
+ struct i2c_client *cl = tca->client;
+ int set;
+ u8 file[TCA6507_REG_CNT];
+ int r;
+
+ spin_lock_irq(&tca->lock);
+ set = tca->reg_set;
+ memcpy(file, tca->reg_file, TCA6507_REG_CNT);
+ tca->reg_set = 0;
+ spin_unlock_irq(&tca->lock);
+
+ for (r = 0; r < TCA6507_REG_CNT; r++)
+ if (set & (1<<r))
+ i2c_smbus_write_byte_data(cl, r, file[r]);
+}
+
+static void led_release(struct tca6507_led *led)
+{
+ /* If led owns any resource, release it. */
+ struct tca6507_chip *tca = led->chip;
+ if (led->bank >= 0) {
+ struct bank *b = tca->bank + led->bank;
+ if (led->blink)
+ b->time_use--;
+ b->level_use--;
+ }
+ led->blink = 0;
+ led->bank = -1;
+}
+
+static int led_prepare(struct tca6507_led *led)
+{
+ /* Assign this led to a bank, configuring that bank if necessary. */
+ int level = TO_LEVEL(led->led_cdev.brightness);
+ struct tca6507_chip *tca = led->chip;
+ int c1, c2;
+ int i;
+ struct bank *b;
+ int need_init = 0;
+
+ led->led_cdev.brightness = TO_BRIGHT(level);
+ if (level == 0) {
+ set_select(tca, led->num, TCA6507_LS_LED_OFF);
+ return 0;
+ }
+
+ if (led->ontime == 0 || led->offtime == 0) {
+ /*
+ * Just set the brightness, choosing first usable bank.
+ * If none perfect, choose best.
+ * Count backwards so we check MASTER bank first
+ * to avoid wasting a timer.
+ */
+ int best = -1;/* full-on */
+ int diff = 15-level;
+
+ if (level == 15) {
+ set_select(tca, led->num, TCA6507_LS_LED_ON);
+ return 0;
+ }
+
+ for (i = MASTER; i >= BANK0; i--) {
+ int d;
+ if (tca->bank[i].level == level ||
+ tca->bank[i].level_use == 0) {
+ best = i;
+ break;
+ }
+ d = abs(level - tca->bank[i].level);
+ if (d < diff) {
+ diff = d;
+ best = i;
+ }
+ }
+ if (best == -1) {
+ /* Best brightness is full-on */
+ set_select(tca, led->num, TCA6507_LS_LED_ON);
+ led->led_cdev.brightness = LED_FULL;
+ return 0;
+ }
+
+ if (!tca->bank[best].level_use)
+ set_level(tca, best, level);
+
+ tca->bank[best].level_use++;
+ led->bank = best;
+ set_select(tca, led->num, bank_source[best]);
+ led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
+ return 0;
+ }
+
+ /*
+ * We have on/off time so we need to try to allocate a timing bank.
+ * First check if times are compatible with hardware and give up if
+ * not.
+ */
+ if (choose_times(led->ontime, &c1, &c2) < 0)
+ return -EINVAL;
+ if (choose_times(led->offtime, &c1, &c2) < 0)
+ return -EINVAL;
+
+ for (i = BANK0; i <= BANK1; i++) {
+ if (tca->bank[i].level_use == 0)
+ /* not in use - it is ours! */
+ break;
+ if (tca->bank[i].level != level)
+ /* Incompatible level - skip */
+ /* FIX: if timer matches we maybe should consider
+ * this anyway...
+ */
+ continue;
+
+ if (tca->bank[i].time_use == 0)
+ /* Timer not in use, and level matches - use it */
+ break;
+
+ if (!(tca->bank[i].on_dflt ||
+ led->on_dflt ||
+ tca->bank[i].ontime == led->ontime))
+ /* on time is incompatible */
+ continue;
+
+ if (!(tca->bank[i].off_dflt ||
+ led->off_dflt ||
+ tca->bank[i].offtime == led->offtime))
+ /* off time is incompatible */
+ continue;
+
+ /* looks like a suitable match */
+ break;
+ }
+
+ if (i > BANK1)
+ /* Nothing matches - how sad */
+ return -EINVAL;
+
+ b = &tca->bank[i];
+ if (b->level_use == 0)
+ set_level(tca, i, level);
+ b->level_use++;
+ led->bank = i;
+
+ if (b->on_dflt ||
+ !led->on_dflt ||
+ b->time_use == 0) {
+ b->ontime = led->ontime;
+ b->on_dflt = led->on_dflt;
+ need_init = 1;
+ }
+
+ if (b->off_dflt ||
+ !led->off_dflt ||
+ b->time_use == 0) {
+ b->offtime = led->offtime;
+ b->off_dflt = led->off_dflt;
+ need_init = 1;
+ }
+
+ if (need_init)
+ set_times(tca, i);
+
+ led->ontime = b->ontime;
+ led->offtime = b->offtime;
+
+ b->time_use++;
+ led->blink = 1;
+ led->led_cdev.brightness = TO_BRIGHT(b->level);
+ set_select(tca, led->num, blink_source[i]);
+ return 0;
+}
+
+static int led_assign(struct tca6507_led *led)
+{
+ struct tca6507_chip *tca = led->chip;
+ int err;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tca->lock, flags);
+ led_release(led);
+ err = led_prepare(led);
+ if (err) {
+ /*
+ * Can only fail on timer setup. In that case we need to
+ * re-establish as steady level.
+ */
+ led->ontime = 0;
+ led->offtime = 0;
+ led_prepare(led);
+ }
+ spin_unlock_irqrestore(&tca->lock, flags);
+
+ if (tca->reg_set)
+ schedule_work(&tca->work);
+ return err;
+}
+
+static void tca6507_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
+ led_cdev);
+ led->led_cdev.brightness = brightness;
+ led->ontime = 0;
+ led->offtime = 0;
+ led_assign(led);
+}
+
+static int tca6507_blink_set(struct led_classdev *led_cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
+ led_cdev);
+
+ if (*delay_on == 0)
+ led->on_dflt = 1;
+ else if (delay_on != &led_cdev->blink_delay_on)
+ led->on_dflt = 0;
+ led->ontime = *delay_on;
+
+ if (*delay_off == 0)
+ led->off_dflt = 1;
+ else if (delay_off != &led_cdev->blink_delay_off)
+ led->off_dflt = 0;
+ led->offtime = *delay_off;
+
+ if (led->ontime == 0)
+ led->ontime = 512;
+ if (led->offtime == 0)
+ led->offtime = 512;
+
+ if (led->led_cdev.brightness == LED_OFF)
+ led->led_cdev.brightness = LED_FULL;
+ if (led_assign(led) < 0) {
+ led->ontime = 0;
+ led->offtime = 0;
+ led->led_cdev.brightness = LED_OFF;
+ return -EINVAL;
+ }
+ *delay_on = led->ontime;
+ *delay_off = led->offtime;
+ return 0;
+}
+
+#ifdef CONFIG_GPIOLIB
+static void tca6507_gpio_set_value(struct gpio_chip *gc,
+ unsigned offset, int val)
+{
+ struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tca->lock, flags);
+ /*
+ * 'OFF' is floating high, and 'ON' is pulled down, so it has the
+ * inverse sense of 'val'.
+ */
+ set_select(tca, tca->gpio_map[offset],
+ val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
+ spin_unlock_irqrestore(&tca->lock, flags);
+ if (tca->reg_set)
+ schedule_work(&tca->work);
+}
+
+static int tca6507_gpio_direction_output(struct gpio_chip *gc,
+ unsigned offset, int val)
+{
+ tca6507_gpio_set_value(gc, offset, val);
+ return 0;
+}
+
+static int tca6507_probe_gpios(struct i2c_client *client,
+ struct tca6507_chip *tca,
+ struct tca6507_platform_data *pdata)
+{
+ int err;
+ int i = 0;
+ int gpios = 0;
+
+ for (i = 0; i < NUM_LEDS; i++)
+ if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
+ /* Configure as a gpio */
+ tca->gpio_name[gpios] = pdata->leds.leds[i].name;
+ tca->gpio_map[gpios] = i;
+ gpios++;
+ }
+
+ if (!gpios)
+ return 0;
+
+ tca->gpio.label = "gpio-tca6507";
+ tca->gpio.names = tca->gpio_name;
+ tca->gpio.ngpio = gpios;
+ tca->gpio.base = pdata->gpio_base;
+ tca->gpio.owner = THIS_MODULE;
+ tca->gpio.direction_output = tca6507_gpio_direction_output;
+ tca->gpio.set = tca6507_gpio_set_value;
+ tca->gpio.dev = &client->dev;
+ err = gpiochip_add(&tca->gpio);
+ if (err) {
+ tca->gpio.ngpio = 0;
+ return err;
+ }
+ if (pdata->setup)
+ pdata->setup(tca->gpio.base, tca->gpio.ngpio);
+ return 0;
+}
+
+static void tca6507_remove_gpio(struct tca6507_chip *tca)
+{
+ if (tca->gpio.ngpio) {
+ int err = gpiochip_remove(&tca->gpio);
+ dev_err(&tca->client->dev, "%s failed, %d\n",
+ "gpiochip_remove()", err);
+ }
+}
+#else /* CONFIG_GPIOLIB */
+static int tca6507_probe_gpios(struct i2c_client *client,
+ struct tca6507_chip *tca,
+ struct tca6507_platform_data *pdata)
+{
+ return 0;
+}
+static void tca6507_remove_gpio(struct tca6507_chip *tca)
+{
+}
+#endif /* CONFIG_GPIOLIB */
+
+static int __devinit tca6507_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tca6507_chip *tca;
+ struct i2c_adapter *adapter;
+ struct tca6507_platform_data *pdata;
+ int err;
+ int i = 0;
+
+ adapter = to_i2c_adapter(client->dev.parent);
+ pdata = client->dev.platform_data;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return -EIO;
+
+ if (!pdata || pdata->leds.num_leds != NUM_LEDS) {
+ dev_err(&client->dev, "Need %d entries in platform-data list\n",
+ NUM_LEDS);
+ return -ENODEV;
+ }
+ err = -ENOMEM;
+ tca = kzalloc(sizeof(*tca), GFP_KERNEL);
+ if (!tca)
+ goto exit;
+
+ tca->client = client;
+ INIT_WORK(&tca->work, tca6507_work);
+ spin_lock_init(&tca->lock);
+ i2c_set_clientdata(client, tca);
+
+ for (i = 0; i < NUM_LEDS; i++) {
+ struct tca6507_led *l = tca->leds + i;
+
+ l->chip = tca;
+ l->num = i;
+ if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
+ l->led_cdev.name = pdata->leds.leds[i].name;
+ l->led_cdev.default_trigger
+ = pdata->leds.leds[i].default_trigger;
+ l->led_cdev.brightness_set = tca6507_brightness_set;
+ l->led_cdev.blink_set = tca6507_blink_set;
+ l->bank = -1;
+ err = led_classdev_register(&client->dev,
+ &l->led_cdev);
+ if (err < 0)
+ goto exit;
+ }
+ }
+ err = tca6507_probe_gpios(client, tca, pdata);
+ if (err)
+ goto exit;
+ /* set all registers to known state - zero */
+ tca->reg_set = 0x7f;
+ schedule_work(&tca->work);
+
+ return 0;
+exit:
+ while (i--)
+ if (tca->leds[i].led_cdev.name)
+ led_classdev_unregister(&tca->leds[i].led_cdev);
+ cancel_work_sync(&tca->work);
+ i2c_set_clientdata(client, NULL);
+ kfree(tca);
+ return err;
+}
+
+static int __devexit tca6507_remove(struct i2c_client *client)
+{
+ int i;
+ struct tca6507_chip *tca = i2c_get_clientdata(client);
+ struct tca6507_led *tca_leds = tca->leds;
+
+ for (i = 0; i < NUM_LEDS; i++) {
+ if (tca_leds[i].led_cdev.name)
+ led_classdev_unregister(&tca_leds[i].led_cdev);
+ }
+ tca6507_remove_gpio(tca);
+ cancel_work_sync(&tca->work);
+ i2c_set_clientdata(client, NULL);
+ kfree(tca);
+
+ return 0;
+}
+
+static struct i2c_driver tca6507_driver = {
+ .driver = {
+ .name = "leds-tca6507",
+ .owner = THIS_MODULE,
+ },
+ .probe = tca6507_probe,
+ .remove = __devexit_p(tca6507_remove),
+ .id_table = tca6507_id,
+};
+
+static int __init tca6507_leds_init(void)
+{
+ return i2c_add_driver(&tca6507_driver);
+}
+
+static void __exit tca6507_leds_exit(void)
+{
+ i2c_del_driver(&tca6507_driver);
+}
+
+module_init(tca6507_leds_init);
+module_exit(tca6507_leds_exit);
+
+MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
+MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index b1eb34c..74a24cf 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev)
goto err;
}
- drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL);
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
+ GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, drvdata);
@@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
err_led:
led_classdev_unregister(&drvdata->cdev);
- kfree(drvdata);
err:
return ret;
}
@@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev)
device_remove_file(drvdata->cdev.dev, &dev_attr_src);
led_classdev_unregister(&drvdata->cdev);
- kfree(drvdata);
return 0;
}
@@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = {
.remove = wm831x_status_remove,
};
-static int __devinit wm831x_status_init(void)
-{
- return platform_driver_register(&wm831x_status_driver);
-}
-module_init(wm831x_status_init);
-
-static void wm831x_status_exit(void)
-{
- platform_driver_unregister(&wm831x_status_driver);
-}
-module_exit(wm831x_status_exit);
+module_platform_driver(wm831x_status_driver);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("WM831x status LED driver");
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 4a12765..918d4ba 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
goto err_isink;
}
- led = kzalloc(sizeof(*led), GFP_KERNEL);
+ led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
if (led == NULL) {
ret = -ENOMEM;
goto err_dcdc;
@@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev)
ret = led_classdev_register(&pdev->dev, &led->cdev);
if (ret < 0)
- goto err_led;
+ goto err_dcdc;
return 0;
- err_led:
- kfree(led);
err_dcdc:
regulator_put(dcdc);
err_isink:
@@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
wm8350_led_disable(led);
regulator_put(led->dcdc);
regulator_put(led->isink);
- kfree(led);
return 0;
}
@@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = {
.shutdown = wm8350_led_shutdown,
};
-static int __devinit wm8350_led_init(void)
-{
- return platform_driver_register(&wm8350_led_driver);
-}
-module_init(wm8350_led_init);
-
-static void wm8350_led_exit(void)
-{
- platform_driver_unregister(&wm8350_led_driver);
-}
-module_exit(wm8350_led_exit);
+module_platform_driver(wm8350_led_driver);
MODULE_AUTHOR("Mark Brown");
MODULE_DESCRIPTION("WM8350 LED driver");
diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
index 8ac947c..c419750 100644
--- a/drivers/lguest/Makefile
+++ b/drivers/lguest/Makefile
@@ -18,7 +18,7 @@ Mastery: PREFIX=M
Beer:
@for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}"
Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery:
- @sh ../../Documentation/virtual/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
+ @sh ../../tools/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
Puppy:
@clear
@printf " __ \n (___()'\`;\n /, /\`\n \\\\\\\"--\\\\\\ \n"
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 595d731..9e8388e 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -241,7 +241,7 @@ static void lg_notify(struct virtqueue *vq)
}
/* An extern declaration inside a C file is bad form. Don't do it. */
-extern void lguest_setup_irq(unsigned int irq);
+extern int lguest_setup_irq(unsigned int irq);
/*
* This routine finds the Nth virtqueue described in the configuration of
@@ -292,17 +292,21 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
/*
* OK, tell virtio_ring.c to set up a virtqueue now we know its size
- * and we've got a pointer to its pages.
+ * and we've got a pointer to its pages. Note that we set weak_barriers
+ * 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, lvq->pages, lg_notify, callback, name);
+ vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, vdev,
+ true, lvq->pages, lg_notify, callback, name);
if (!vq) {
err = -ENOMEM;
goto unmap;
}
/* Make sure the interrupt is allocated. */
- lguest_setup_irq(lvq->config.irq);
+ err = lguest_setup_irq(lvq->config.irq);
+ if (err)
+ goto destroy_vring;
/*
* Tell the interrupt for this virtqueue to go to the virtio_ring
@@ -315,7 +319,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
dev_name(&vdev->dev), vq);
if (err)
- goto destroy_vring;
+ goto free_desc;
/*
* Last of all we hook up our 'struct lguest_vq_info" to the
@@ -324,6 +328,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
vq->priv = lvq;
return vq;
+free_desc:
+ irq_free_desc(lvq->config.irq);
destroy_vring:
vring_del_virtqueue(vq);
unmap:
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index ede4658..c4fb424 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -81,8 +81,8 @@ static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
* sometimes careless and leaves this as 0, even though it's
* running at privilege level 1. If so, we fix it here.
*/
- if ((cpu->arch.gdt[i].b & 0x00006000) == 0)
- cpu->arch.gdt[i].b |= (GUEST_PL << 13);
+ if (cpu->arch.gdt[i].dpl == 0)
+ cpu->arch.gdt[i].dpl |= GUEST_PL;
/*
* Each descriptor has an "accessed" bit. If we don't set it
@@ -90,7 +90,7 @@ static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
* that entry into a segment register. But the GDT isn't
* writable by the Guest, so bad things can happen.
*/
- cpu->arch.gdt[i].b |= 0x00000100;
+ cpu->arch.gdt[i].type |= 0x1;
}
}
@@ -114,13 +114,19 @@ void setup_default_gdt_entries(struct lguest_ro_state *state)
/*
* The TSS segment refers to the TSS entry for this particular CPU.
- * Forgive the magic flags: the 0x8900 means the entry is Present, it's
- * privilege level 0 Available 386 TSS system segment, and the 0x67
- * means Saturn is eclipsed by Mercury in the twelfth house.
*/
- gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
- gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
- | ((tss >> 16) & 0x000000FF);
+ gdt[GDT_ENTRY_TSS].a = 0;
+ gdt[GDT_ENTRY_TSS].b = 0;
+
+ gdt[GDT_ENTRY_TSS].limit0 = 0x67;
+ gdt[GDT_ENTRY_TSS].base0 = tss & 0xFFFF;
+ gdt[GDT_ENTRY_TSS].base1 = (tss >> 16) & 0xFF;
+ gdt[GDT_ENTRY_TSS].base2 = tss >> 24;
+ gdt[GDT_ENTRY_TSS].type = 0x9; /* 32-bit TSS (available) */
+ gdt[GDT_ENTRY_TSS].p = 0x1; /* Entry is present */
+ gdt[GDT_ENTRY_TSS].dpl = 0x0; /* Privilege level 0 */
+ gdt[GDT_ENTRY_TSS].s = 0x0; /* system segment */
+
}
/*
@@ -135,8 +141,8 @@ void setup_guest_gdt(struct lg_cpu *cpu)
*/
cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
- cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
- cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].dpl |= GUEST_PL;
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].dpl |= GUEST_PL;
}
/*H:650
diff --git a/drivers/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c
index 399beb16..5c6a2d8 100644
--- a/drivers/macintosh/ams/ams-core.c
+++ b/drivers/macintosh/ams/ams-core.c
@@ -31,7 +31,7 @@
/* There is only one motion sensor per machine */
struct ams ams_info;
-static unsigned int verbose;
+static bool verbose;
module_param(verbose, bool, 0644);
MODULE_PARM_DESC(verbose, "Show free falls and shocks in kernel output");
diff --git a/drivers/macintosh/ams/ams-input.c b/drivers/macintosh/ams/ams-input.c
index 8a71239..b27e530 100644
--- a/drivers/macintosh/ams/ams-input.c
+++ b/drivers/macintosh/ams/ams-input.c
@@ -19,11 +19,11 @@
#include "ams.h"
-static unsigned int joystick;
+static bool joystick;
module_param(joystick, bool, S_IRUGO);
MODULE_PARM_DESC(joystick, "Enable the input class device on module load");
-static unsigned int invert;
+static bool invert;
module_param(invert, bool, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 0236730..c60d025 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -52,7 +52,7 @@ static const char *sensor_location[3];
static int limit_adjust;
static int fan_speed = -1;
-static int verbose;
+static bool verbose;
MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index f84c080..9fb18c1 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -368,8 +368,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
{
struct flakey_c *fc = ti->private;
+ struct dm_dev *dev = fc->dev;
+ int r = 0;
- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (fc->start ||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3921e3b..9728839 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct linear_c *lc = (struct linear_c *) ti->private;
- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
+ struct dm_dev *dev = lc->dev;
+ int r = 0;
+
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (lc->start ||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5e0090e..801d92d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1520,6 +1520,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
spin_unlock_irqrestore(&m->lock, flags);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 8e91321..63cc542 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -699,7 +699,7 @@ static int validate_hardware_logical_block_alignment(struct dm_table *table,
while (i < dm_table_get_num_targets(table)) {
ti = dm_table_get_target(table, i++);
- blk_set_default_limits(&ti_limits);
+ blk_set_stacking_limits(&ti_limits);
/* combine all target devices' limits */
if (ti->type->iterate_devices)
@@ -1221,10 +1221,10 @@ int dm_calculate_queue_limits(struct dm_table *table,
struct queue_limits ti_limits;
unsigned i = 0;
- blk_set_default_limits(limits);
+ blk_set_stacking_limits(limits);
while (i < dm_table_get_num_targets(table)) {
- blk_set_default_limits(&ti_limits);
+ blk_set_stacking_limits(&ti_limits);
ti = dm_table_get_target(table, i++);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ca8527f..9417ae2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4666,6 +4666,7 @@ static int md_alloc(dev_t dev, char *name)
mddev->queue->queuedata = mddev;
blk_queue_make_request(mddev->queue, md_make_request);
+ blk_set_stacking_limits(&mddev->queue->limits);
disk = alloc_disk(1 << shift);
if (!disk) {
@@ -7382,6 +7383,7 @@ static int remove_and_add_spares(struct mddev *mddev)
{
struct md_rdev *rdev;
int spares = 0;
+ int removed = 0;
mddev->curr_resync_completed = 0;
@@ -7395,8 +7397,13 @@ static int remove_and_add_spares(struct mddev *mddev)
mddev, rdev) == 0) {
sysfs_unlink_rdev(mddev, rdev);
rdev->raid_disk = -1;
+ removed++;
}
}
+ if (removed)
+ sysfs_notify(&mddev->kobj, NULL,
+ "degraded");
+
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index cc24f0c..a368db2 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -531,8 +531,17 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
if (test_bit(WriteMostly, &rdev->flags)) {
/* Don't balance among write-mostly, just
* use the first as a last resort */
- if (best_disk < 0)
+ if (best_disk < 0) {
+ if (is_badblock(rdev, this_sector, sectors,
+ &first_bad, &bad_sectors)) {
+ if (first_bad < this_sector)
+ /* Cannot use this */
+ continue;
+ best_good_sectors = first_bad - this_sector;
+ } else
+ best_good_sectors = sectors;
best_disk = disk;
+ }
continue;
}
/* This is a reasonable device to use. It might
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 996302a..4a6d5ce 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -26,7 +26,7 @@ config MEDIA_TUNER
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
+ select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
@@ -116,6 +116,13 @@ config MEDIA_TUNER_MT2060
help
A driver for the silicon IF tuner MT2060 from Microtune.
+config MEDIA_TUNER_MT2063
+ tristate "Microtune MT2063 silicon IF tuner"
+ depends on VIDEO_MEDIA && I2C
+ default m if MEDIA_TUNER_CUSTOMISE
+ help
+ A driver for the silicon IF tuner MT2063 from Microtune.
+
config MEDIA_TUNER_MT2266
tristate "Microtune MT2266 silicon tuner"
depends on VIDEO_MEDIA && I2C
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
index 196c12a..8295854 100644
--- a/drivers/media/common/tuners/Makefile
+++ b/drivers/media/common/tuners/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c
index 9883617..cb2c98f 100644
--- a/drivers/media/common/tuners/max2165.c
+++ b/drivers/media/common/tuners/max2165.c
@@ -151,7 +151,7 @@ static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw)
{
u8 val;
- if (bw == BANDWIDTH_8_MHZ)
+ if (bw == 8000000)
val = priv->bb_filter_8mhz_cfg;
else
val = priv->bb_filter_7mhz_cfg;
@@ -257,39 +257,28 @@ static void max2165_debug_status(struct max2165_priv *priv)
dprintk("VCO: %d, VCO Sub-band: %d, ADC: %d\n", vco, vco_sub_band, adc);
}
-static int max2165_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int max2165_set_params(struct dvb_frontend *fe)
{
struct max2165_priv *priv = fe->tuner_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
- dprintk("%s() frequency=%d (Hz)\n", __func__, params->frequency);
- if (fe->ops.info.type == FE_ATSC) {
- return -EINVAL;
- } else if (fe->ops.info.type == FE_OFDM) {
- dprintk("%s() OFDM\n", __func__);
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- return -EINVAL;
- case BANDWIDTH_7_MHZ:
- case BANDWIDTH_8_MHZ:
- priv->frequency = params->frequency;
- priv->bandwidth = params->u.ofdm.bandwidth;
- break;
- default:
- printk(KERN_ERR "MAX2165 bandwidth not set!\n");
- return -EINVAL;
- }
- } else {
- printk(KERN_ERR "MAX2165 modulation type not supported!\n");
+ switch (c->bandwidth_hz) {
+ case 7000000:
+ case 8000000:
+ priv->frequency = c->frequency;
+ break;
+ default:
+ printk(KERN_INFO "MAX2165: bandwidth %d Hz not supported.\n",
+ c->bandwidth_hz);
return -EINVAL;
}
- dprintk("%s() frequency=%d\n", __func__, priv->frequency);
+ dprintk("%s() frequency=%d\n", __func__, c->frequency);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- max2165_set_bandwidth(priv, priv->bandwidth);
+ max2165_set_bandwidth(priv, c->bandwidth_hz);
ret = max2165_set_rf(priv, priv->frequency);
mdelay(50);
max2165_debug_status(priv);
@@ -370,7 +359,7 @@ static int max2165_init(struct dvb_frontend *fe)
max2165_read_rom_table(priv);
- max2165_set_bandwidth(priv, BANDWIDTH_8_MHZ);
+ max2165_set_bandwidth(priv, 8000000);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
diff --git a/drivers/media/common/tuners/mc44s803.c b/drivers/media/common/tuners/mc44s803.c
index fe5c4b8..5ddce7e 100644
--- a/drivers/media/common/tuners/mc44s803.c
+++ b/drivers/media/common/tuners/mc44s803.c
@@ -214,22 +214,22 @@ exit:
return err;
}
-static int mc44s803_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int mc44s803_set_params(struct dvb_frontend *fe)
{
struct mc44s803_priv *priv = fe->tuner_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 r1, r2, n1, n2, lo1, lo2, freq, val;
int err;
- priv->frequency = params->frequency;
+ priv->frequency = c->frequency;
r1 = MC44S803_OSC / 1000000;
r2 = MC44S803_OSC / 100000;
- n1 = (params->frequency + MC44S803_IF1 + 500000) / 1000000;
+ n1 = (c->frequency + MC44S803_IF1 + 500000) / 1000000;
freq = MC44S803_OSC / r1 * n1;
lo1 = ((60 * n1) + (r1 / 2)) / r1;
- freq = freq - params->frequency;
+ freq = freq - c->frequency;
n2 = (freq - MC44S803_IF2 + 50000) / 100000;
lo2 = ((60 * n2) + (r2 / 2)) / r2;
diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c
index 2d0e768..13381de 100644
--- a/drivers/media/common/tuners/mt2060.c
+++ b/drivers/media/common/tuners/mt2060.c
@@ -153,8 +153,9 @@ static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
#define IF2 36150 // IF2 frequency = 36.150 MHz
#define FREF 16000 // Quartz oscillator 16 MHz
-static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int mt2060_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct mt2060_priv *priv;
int ret=0;
int i=0;
@@ -176,8 +177,7 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
mt2060_writeregs(priv,b,2);
- freq = params->frequency / 1000; // Hz -> kHz
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+ freq = c->frequency / 1000; /* Hz -> kHz */
f_lo1 = freq + if1 * 1000;
f_lo1 = (f_lo1 / 250) * 250;
@@ -293,10 +293,9 @@ static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+static int mt2060_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct mt2060_priv *priv = fe->tuner_priv;
- *bandwidth = priv->bandwidth;
+ *frequency = IF2 * 1000;
return 0;
}
@@ -356,7 +355,7 @@ static const struct dvb_tuner_ops mt2060_tuner_ops = {
.set_params = mt2060_set_params,
.get_frequency = mt2060_get_frequency,
- .get_bandwidth = mt2060_get_bandwidth
+ .get_if_frequency = mt2060_get_if_frequency,
};
/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
diff --git a/drivers/media/common/tuners/mt2060_priv.h b/drivers/media/common/tuners/mt2060_priv.h
index 5eaccde..2b60de6 100644
--- a/drivers/media/common/tuners/mt2060_priv.h
+++ b/drivers/media/common/tuners/mt2060_priv.h
@@ -97,7 +97,6 @@ struct mt2060_priv {
struct i2c_adapter *i2c;
u32 frequency;
- u32 bandwidth;
u16 if1_freq;
u8 fmfreq;
};
diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/common/tuners/mt2063.c
new file mode 100644
index 0000000..c89af3c
--- /dev/null
+++ b/drivers/media/common/tuners/mt2063.c
@@ -0,0 +1,2307 @@
+/*
+ * Driver for mt2063 Micronas tuner
+ *
+ * Copyright (c) 2011 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * This driver came from a driver originally written by:
+ * Henry Wang <Henry.wang@AzureWave.com>
+ * Made publicly available by Terratec, at:
+ * 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()
+ *
+ * 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 under version 2 of the License.
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/videodev2.h>
+
+#include "mt2063.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Set Verbosity level");
+
+#define dprintk(level, fmt, arg...) do { \
+if (debug >= level) \
+ printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg); \
+} while (0)
+
+
+/* positive error codes used internally */
+
+/* Info: Unavoidable LO-related spur may be present in the output */
+#define MT2063_SPUR_PRESENT_ERR (0x00800000)
+
+/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
+#define MT2063_SPUR_CNT_MASK (0x001f0000)
+#define MT2063_SPUR_SHIFT (16)
+
+/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
+#define MT2063_UPC_RANGE (0x04000000)
+
+/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
+#define MT2063_DNC_RANGE (0x08000000)
+
+/*
+ * Constant defining the version of the following structure
+ * and therefore the API for this code.
+ *
+ * When compiling the tuner driver, the preprocessor will
+ * check against this version number to make sure that
+ * it matches the version that the tuner driver knows about.
+ */
+
+/* DECT Frequency Avoidance */
+#define MT2063_DECT_AVOID_US_FREQS 0x00000001
+
+#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
+
+#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
+
+#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
+
+enum MT2063_DECT_Avoid_Type {
+ MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
+ MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
+ MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
+ MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
+};
+
+#define MT2063_MAX_ZONES 48
+
+struct MT2063_ExclZone_t {
+ u32 min_;
+ u32 max_;
+ struct MT2063_ExclZone_t *next_;
+};
+
+/*
+ * Structure of data needed for Spur Avoidance
+ */
+struct MT2063_AvoidSpursData_t {
+ u32 f_ref;
+ u32 f_in;
+ u32 f_LO1;
+ u32 f_if1_Center;
+ u32 f_if1_Request;
+ u32 f_if1_bw;
+ u32 f_LO2;
+ u32 f_out;
+ u32 f_out_bw;
+ u32 f_LO1_Step;
+ u32 f_LO2_Step;
+ u32 f_LO1_FracN_Avoid;
+ u32 f_LO2_FracN_Avoid;
+ u32 f_zif_bw;
+ u32 f_min_LO_Separation;
+ u32 maxH1;
+ u32 maxH2;
+ enum MT2063_DECT_Avoid_Type avoidDECT;
+ u32 bSpurPresent;
+ u32 bSpurAvoided;
+ u32 nSpursFound;
+ u32 nZones;
+ struct MT2063_ExclZone_t *freeZones;
+ struct MT2063_ExclZone_t *usedZones;
+ struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
+};
+
+/*
+ * Parameter for function MT2063_SetPowerMask that specifies the power down
+ * of various sections of the MT2063.
+ */
+enum MT2063_Mask_Bits {
+ MT2063_REG_SD = 0x0040, /* Shutdown regulator */
+ MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
+ MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
+ MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
+ MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
+ MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
+ MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
+ MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
+ MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
+ MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
+ MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
+ MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
+ MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
+ MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
+ MT2063_NONE_SD = 0x0000 /* No shutdown bits */
+};
+
+/*
+ * Possible values for MT2063_DNC_OUTPUT
+ */
+enum MT2063_DNC_Output_Enable {
+ MT2063_DNC_NONE = 0,
+ MT2063_DNC_1,
+ MT2063_DNC_2,
+ MT2063_DNC_BOTH
+};
+
+/*
+ * Two-wire serial bus subaddresses of the tuner registers.
+ * Also known as the tuner's register addresses.
+ */
+enum MT2063_Register_Offsets {
+ MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
+ MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
+ MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
+ MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
+ MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
+ MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
+ MT2063_REG_RSVD_06, /* 0x06: Reserved */
+ MT2063_REG_LO_STATUS, /* 0x07: LO Status */
+ MT2063_REG_FIFFC, /* 0x08: FIFF Center */
+ MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
+ MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
+ MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
+ MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
+ MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
+ MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
+ MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
+ MT2063_REG_RSVD_10, /* 0x10: Reserved */
+ MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
+ MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
+ MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
+ MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
+ MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
+ MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
+ MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
+ MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
+ MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
+ MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
+ MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
+ MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
+ MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
+ MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
+ MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
+ MT2063_REG_RSVD_20, /* 0x20: Reserved */
+ MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
+ MT2063_REG_RSVD_22, /* 0x22: Reserved */
+ MT2063_REG_RSVD_23, /* 0x23: Reserved */
+ MT2063_REG_RSVD_24, /* 0x24: Reserved */
+ MT2063_REG_RSVD_25, /* 0x25: Reserved */
+ MT2063_REG_RSVD_26, /* 0x26: Reserved */
+ MT2063_REG_RSVD_27, /* 0x27: Reserved */
+ MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
+ MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
+ MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
+ MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
+ MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
+ MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
+ MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
+ MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
+ MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
+ MT2063_REG_RSVD_31, /* 0x31: Reserved */
+ MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
+ MT2063_REG_RSVD_33, /* 0x33: Reserved */
+ MT2063_REG_RSVD_34, /* 0x34: Reserved */
+ MT2063_REG_RSVD_35, /* 0x35: Reserved */
+ MT2063_REG_RSVD_36, /* 0x36: Reserved */
+ MT2063_REG_RSVD_37, /* 0x37: Reserved */
+ MT2063_REG_RSVD_38, /* 0x38: Reserved */
+ MT2063_REG_RSVD_39, /* 0x39: Reserved */
+ MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
+ MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
+ MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
+ MT2063_REG_END_REGS
+};
+
+struct mt2063_state {
+ struct i2c_adapter *i2c;
+
+ bool init;
+
+ const struct mt2063_config *config;
+ struct dvb_tuner_ops ops;
+ struct dvb_frontend *frontend;
+ struct tuner_state status;
+
+ u32 frequency;
+ u32 srate;
+ u32 bandwidth;
+ u32 reference;
+
+ u32 tuner_id;
+ struct MT2063_AvoidSpursData_t AS_Data;
+ u32 f_IF1_actual;
+ u32 rcvr_mode;
+ u32 ctfilt_sw;
+ u32 CTFiltMax[31];
+ u32 num_regs;
+ u8 reg[MT2063_REG_END_REGS];
+};
+
+/*
+ * mt2063_write - Write data into the I2C bus
+ */
+static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
+{
+ struct dvb_frontend *fe = state->frontend;
+ int ret;
+ u8 buf[60];
+ struct i2c_msg msg = {
+ .addr = state->config->tuner_address,
+ .flags = 0,
+ .buf = buf,
+ .len = len + 1
+ };
+
+ dprintk(2, "\n");
+
+ msg.buf[0] = reg;
+ memcpy(msg.buf + 1, data, len);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ if (ret < 0)
+ printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
+
+ return ret;
+}
+
+/*
+ * mt2063_write - Write register data into the I2C bus, caching the value
+ */
+static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
+{
+ u32 status;
+
+ dprintk(2, "\n");
+
+ if (reg >= MT2063_REG_END_REGS)
+ return -ERANGE;
+
+ status = mt2063_write(state, reg, &val, 1);
+ if (status < 0)
+ return status;
+
+ state->reg[reg] = val;
+
+ return 0;
+}
+
+/*
+ * mt2063_read - Read data from the I2C bus
+ */
+static u32 mt2063_read(struct mt2063_state *state,
+ u8 subAddress, u8 *pData, u32 cnt)
+{
+ u32 status = 0; /* Status to be returned */
+ struct dvb_frontend *fe = state->frontend;
+ u32 i = 0;
+
+ dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ for (i = 0; i < cnt; i++) {
+ u8 b0[] = { subAddress + i };
+ struct i2c_msg msg[] = {
+ {
+ .addr = state->config->tuner_address,
+ .flags = 0,
+ .buf = b0,
+ .len = 1
+ }, {
+ .addr = state->config->tuner_address,
+ .flags = I2C_M_RD,
+ .buf = pData + i,
+ .len = 1
+ }
+ };
+
+ status = i2c_transfer(state->i2c, msg, 2);
+ dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
+ subAddress + i, status, *(pData + i));
+ if (status < 0)
+ break;
+ }
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ if (status < 0)
+ printk(KERN_ERR "Can't read from address 0x%02x,\n",
+ subAddress + i);
+
+ return status;
+}
+
+/*
+ * FIXME: Is this really needed?
+ */
+static int MT2063_Sleep(struct dvb_frontend *fe)
+{
+ /*
+ * ToDo: Add code here to implement a OS blocking
+ */
+ msleep(10);
+
+ return 0;
+}
+
+/*
+ * Microtune spur avoidance
+ */
+
+/* Implement ceiling, floor functions. */
+#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
+#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
+
+struct MT2063_FIFZone_t {
+ s32 min_;
+ s32 max_;
+};
+
+static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
+ *pAS_Info,
+ struct MT2063_ExclZone_t *pPrevNode)
+{
+ struct MT2063_ExclZone_t *pNode;
+
+ dprintk(2, "\n");
+
+ /* Check for a node in the free list */
+ if (pAS_Info->freeZones != NULL) {
+ /* Use one from the free list */
+ pNode = pAS_Info->freeZones;
+ pAS_Info->freeZones = pNode->next_;
+ } else {
+ /* Grab a node from the array */
+ pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
+ }
+
+ if (pPrevNode != NULL) {
+ pNode->next_ = pPrevNode->next_;
+ pPrevNode->next_ = pNode;
+ } else { /* insert at the beginning of the list */
+
+ pNode->next_ = pAS_Info->usedZones;
+ pAS_Info->usedZones = pNode;
+ }
+
+ pAS_Info->nZones++;
+ return pNode;
+}
+
+static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
+ *pAS_Info,
+ struct MT2063_ExclZone_t *pPrevNode,
+ struct MT2063_ExclZone_t
+ *pNodeToRemove)
+{
+ struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
+
+ dprintk(2, "\n");
+
+ /* Make previous node point to the subsequent node */
+ if (pPrevNode != NULL)
+ pPrevNode->next_ = pNext;
+
+ /* Add pNodeToRemove to the beginning of the freeZones */
+ pNodeToRemove->next_ = pAS_Info->freeZones;
+ pAS_Info->freeZones = pNodeToRemove;
+
+ /* Decrement node count */
+ pAS_Info->nZones--;
+
+ return pNext;
+}
+
+/*
+ * MT_AddExclZone()
+ *
+ * Add (and merge) an exclusion zone into the list.
+ * If the range (f_min, f_max) is totally outside the
+ * 1st IF BW, ignore the entry.
+ * If the range (f_min, f_max) is negative, ignore the entry.
+ */
+static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
+ u32 f_min, u32 f_max)
+{
+ struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
+ struct MT2063_ExclZone_t *pPrev = NULL;
+ struct MT2063_ExclZone_t *pNext = NULL;
+
+ dprintk(2, "\n");
+
+ /* Check to see if this overlaps the 1st IF filter */
+ if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
+ && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
+ && (f_min < f_max)) {
+ /*
+ * 1 2 3 4 5 6
+ *
+ * New entry: |---| |--| |--| |-| |---| |--|
+ * or or or or or
+ * Existing: |--| |--| |--| |---| |-| |--|
+ */
+
+ /* Check for our place in the list */
+ while ((pNode != NULL) && (pNode->max_ < f_min)) {
+ pPrev = pNode;
+ pNode = pNode->next_;
+ }
+
+ if ((pNode != NULL) && (pNode->min_ < f_max)) {
+ /* Combine me with pNode */
+ if (f_min < pNode->min_)
+ pNode->min_ = f_min;
+ if (f_max > pNode->max_)
+ pNode->max_ = f_max;
+ } else {
+ pNode = InsertNode(pAS_Info, pPrev);
+ pNode->min_ = f_min;
+ pNode->max_ = f_max;
+ }
+
+ /* Look for merging possibilities */
+ pNext = pNode->next_;
+ while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
+ if (pNext->max_ > pNode->max_)
+ pNode->max_ = pNext->max_;
+ /* Remove pNext, return ptr to pNext->next */
+ pNext = RemoveNode(pAS_Info, pNode, pNext);
+ }
+ }
+}
+
+/*
+ * Reset all exclusion zones.
+ * Add zones to protect the PLL FracN regions near zero
+ */
+static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+ u32 center;
+
+ dprintk(2, "\n");
+
+ pAS_Info->nZones = 0; /* this clears the used list */
+ pAS_Info->usedZones = NULL; /* reset ptr */
+ pAS_Info->freeZones = NULL; /* reset ptr */
+
+ center =
+ pAS_Info->f_ref *
+ ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
+ pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
+ while (center <
+ pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
+ pAS_Info->f_LO1_FracN_Avoid) {
+ /* Exclude LO1 FracN */
+ MT2063_AddExclZone(pAS_Info,
+ center - pAS_Info->f_LO1_FracN_Avoid,
+ center - 1);
+ MT2063_AddExclZone(pAS_Info, center + 1,
+ center + pAS_Info->f_LO1_FracN_Avoid);
+ center += pAS_Info->f_ref;
+ }
+
+ center =
+ pAS_Info->f_ref *
+ ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
+ pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
+ while (center <
+ pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
+ pAS_Info->f_LO2_FracN_Avoid) {
+ /* Exclude LO2 FracN */
+ MT2063_AddExclZone(pAS_Info,
+ center - pAS_Info->f_LO2_FracN_Avoid,
+ center - 1);
+ MT2063_AddExclZone(pAS_Info, center + 1,
+ center + pAS_Info->f_LO2_FracN_Avoid);
+ center += pAS_Info->f_ref;
+ }
+
+ if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
+ /* Exclude LO1 values that conflict with DECT channels */
+ MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
+ MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
+ MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
+ MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
+ MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
+ }
+
+ if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
+ MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
+ MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
+ MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
+ MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
+ MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
+ MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
+ MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
+ MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
+ MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
+ MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
+ }
+}
+
+/*
+ * MT_ChooseFirstIF - Choose the best available 1st IF
+ * If f_Desired is not excluded, choose that first.
+ * Otherwise, return the value closest to f_Center that is
+ * not excluded
+ */
+static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+ /*
+ * Update "f_Desired" to be the nearest "combinational-multiple" of
+ * "f_LO1_Step".
+ * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
+ * And F_LO1 is the arithmetic sum of f_in + f_Center.
+ * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
+ * However, the sum must be.
+ */
+ const u32 f_Desired =
+ pAS_Info->f_LO1_Step *
+ ((pAS_Info->f_if1_Request + pAS_Info->f_in +
+ pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
+ pAS_Info->f_in;
+ const u32 f_Step =
+ (pAS_Info->f_LO1_Step >
+ pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
+ f_LO2_Step;
+ u32 f_Center;
+ s32 i;
+ s32 j = 0;
+ u32 bDesiredExcluded = 0;
+ u32 bZeroExcluded = 0;
+ s32 tmpMin, tmpMax;
+ s32 bestDiff;
+ struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
+ struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
+
+ dprintk(2, "\n");
+
+ if (pAS_Info->nZones == 0)
+ return f_Desired;
+
+ /*
+ * f_Center needs to be an integer multiple of f_Step away
+ * from f_Desired
+ */
+ if (pAS_Info->f_if1_Center > f_Desired)
+ f_Center =
+ f_Desired +
+ f_Step *
+ ((pAS_Info->f_if1_Center - f_Desired +
+ f_Step / 2) / f_Step);
+ else
+ f_Center =
+ f_Desired -
+ f_Step *
+ ((f_Desired - pAS_Info->f_if1_Center +
+ f_Step / 2) / f_Step);
+
+ /*
+ * Take MT_ExclZones, center around f_Center and change the
+ * resolution to f_Step
+ */
+ while (pNode != NULL) {
+ /* floor function */
+ tmpMin =
+ floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
+
+ /* ceil function */
+ tmpMax =
+ ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
+
+ if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
+ bDesiredExcluded = 1;
+
+ if ((tmpMin < 0) && (tmpMax > 0))
+ bZeroExcluded = 1;
+
+ /* See if this zone overlaps the previous */
+ if ((j > 0) && (tmpMin < zones[j - 1].max_))
+ zones[j - 1].max_ = tmpMax;
+ else {
+ /* Add new zone */
+ zones[j].min_ = tmpMin;
+ zones[j].max_ = tmpMax;
+ j++;
+ }
+ pNode = pNode->next_;
+ }
+
+ /*
+ * If the desired is okay, return with it
+ */
+ if (bDesiredExcluded == 0)
+ return f_Desired;
+
+ /*
+ * If the desired is excluded and the center is okay, return with it
+ */
+ if (bZeroExcluded == 0)
+ return f_Center;
+
+ /* Find the value closest to 0 (f_Center) */
+ bestDiff = zones[0].min_;
+ for (i = 0; i < j; i++) {
+ if (abs(zones[i].min_) < abs(bestDiff))
+ bestDiff = zones[i].min_;
+ if (abs(zones[i].max_) < abs(bestDiff))
+ bestDiff = zones[i].max_;
+ }
+
+ if (bestDiff < 0)
+ return f_Center - ((u32) (-bestDiff) * f_Step);
+
+ return f_Center + (bestDiff * f_Step);
+}
+
+/**
+ * gcd() - Uses Euclid's algorithm
+ *
+ * @u, @v: Unsigned values whose GCD is desired.
+ *
+ * Returns THE greatest common divisor of u and v, if either value is 0,
+ * the other value is returned as the result.
+ */
+static u32 MT2063_gcd(u32 u, u32 v)
+{
+ u32 r;
+
+ while (v != 0) {
+ r = u % v;
+ u = v;
+ v = r;
+ }
+
+ return u;
+}
+
+/**
+ * IsSpurInBand() - Checks to see if a spur will be present within the IF's
+ * bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
+ *
+ * ma mb mc md
+ * <--+-+-+-------------------+-------------------+-+-+-->
+ * | ^ 0 ^ |
+ * ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
+ * a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
+ *
+ * Note that some equations are doubled to prevent round-off
+ * problems when calculating fIFBW/2
+ *
+ * @pAS_Info: Avoid Spurs information block
+ * @fm: If spur, amount f_IF1 has to move negative
+ * @fp: If spur, amount f_IF1 has to move positive
+ *
+ * Returns 1 if an LO spur would be present, otherwise 0.
+ */
+static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
+ u32 *fm, u32 * fp)
+{
+ /*
+ ** Calculate LO frequency settings.
+ */
+ u32 n, n0;
+ const u32 f_LO1 = pAS_Info->f_LO1;
+ const u32 f_LO2 = pAS_Info->f_LO2;
+ const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
+ const u32 c = d - pAS_Info->f_out_bw;
+ const u32 f = pAS_Info->f_zif_bw / 2;
+ const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
+ s32 f_nsLO1, f_nsLO2;
+ s32 f_Spur;
+ u32 ma, mb, mc, md, me, mf;
+ u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
+
+ dprintk(2, "\n");
+
+ *fm = 0;
+
+ /*
+ ** For each edge (d, c & f), calculate a scale, based on the gcd
+ ** of f_LO1, f_LO2 and the edge value. Use the larger of this
+ ** gcd-based scale factor or f_Scale.
+ */
+ lo_gcd = MT2063_gcd(f_LO1, f_LO2);
+ gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
+ hgds = gd_Scale / 2;
+ gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
+ hgcs = gc_Scale / 2;
+ gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
+ hgfs = gf_Scale / 2;
+
+ n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
+
+ /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
+ for (n = n0; n <= pAS_Info->maxH1; ++n) {
+ md = (n * ((f_LO1 + hgds) / gd_Scale) -
+ ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
+
+ /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
+ if (md >= pAS_Info->maxH1)
+ break;
+
+ ma = (n * ((f_LO1 + hgds) / gd_Scale) +
+ ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
+
+ /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
+ if (md == ma)
+ continue;
+
+ mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
+ ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
+ if (mc != md) {
+ f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
+ f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
+ f_Spur =
+ (gc_Scale * (f_nsLO1 - f_nsLO2)) +
+ n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
+
+ *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
+ *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
+ return 1;
+ }
+
+ /* Location of Zero-IF-spur to be checked */
+ me = (n * ((f_LO1 + hgfs) / gf_Scale) +
+ ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
+ mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
+ ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
+ if (me != mf) {
+ f_nsLO1 = n * (f_LO1 / gf_Scale);
+ f_nsLO2 = me * (f_LO2 / gf_Scale);
+ f_Spur =
+ (gf_Scale * (f_nsLO1 - f_nsLO2)) +
+ n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
+
+ *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
+ *fm = (((s32) f - f_Spur) / (me - n)) + 1;
+ return 1;
+ }
+
+ mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
+ ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
+ if (ma != mb) {
+ f_nsLO1 = n * (f_LO1 / gc_Scale);
+ f_nsLO2 = ma * (f_LO2 / gc_Scale);
+ f_Spur =
+ (gc_Scale * (f_nsLO1 - f_nsLO2)) +
+ n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
+
+ *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
+ *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
+ return 1;
+ }
+ }
+
+ /* No spurs found */
+ return 0;
+}
+
+/*
+ * MT_AvoidSpurs() - Main entry point to avoid spurs.
+ * Checks for existing spurs in present LO1, LO2 freqs
+ * and if present, chooses spur-free LO1, LO2 combination
+ * that tunes the same input/output frequencies.
+ */
+static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
+{
+ u32 status = 0;
+ u32 fm, fp; /* restricted range on LO's */
+ pAS_Info->bSpurAvoided = 0;
+ pAS_Info->nSpursFound = 0;
+
+ dprintk(2, "\n");
+
+ if (pAS_Info->maxH1 == 0)
+ return 0;
+
+ /*
+ * Avoid LO Generated Spurs
+ *
+ * Make sure that have no LO-related spurs within the IF output
+ * bandwidth.
+ *
+ * If there is an LO spur in this band, start at the current IF1 frequency
+ * and work out until we find a spur-free frequency or run up against the
+ * 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
+ * will be unchanged if a spur-free setting is not found.
+ */
+ pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
+ if (pAS_Info->bSpurPresent) {
+ u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
+ u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
+ u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
+ u32 delta_IF1;
+ u32 new_IF1;
+
+ /*
+ ** Spur was found, attempt to find a spur-free 1st IF
+ */
+ do {
+ pAS_Info->nSpursFound++;
+
+ /* Raise f_IF1_upper, if needed */
+ MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
+
+ /* Choose next IF1 that is closest to f_IF1_CENTER */
+ new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
+
+ if (new_IF1 > zfIF1) {
+ pAS_Info->f_LO1 += (new_IF1 - zfIF1);
+ pAS_Info->f_LO2 += (new_IF1 - zfIF1);
+ } else {
+ pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
+ pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
+ }
+ zfIF1 = new_IF1;
+
+ if (zfIF1 > pAS_Info->f_if1_Center)
+ delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
+ else
+ delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
+
+ pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
+ /*
+ * Continue while the new 1st IF is still within the 1st IF bandwidth
+ * and there is a spur in the band (again)
+ */
+ } while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
+
+ /*
+ * Use the LO-spur free values found. If the search went all
+ * the way to the 1st IF band edge and always found spurs, just
+ * leave the original choice. It's as "good" as any other.
+ */
+ if (pAS_Info->bSpurPresent == 1) {
+ status |= MT2063_SPUR_PRESENT_ERR;
+ pAS_Info->f_LO1 = zfLO1;
+ pAS_Info->f_LO2 = zfLO2;
+ } else
+ pAS_Info->bSpurAvoided = 1;
+ }
+
+ status |=
+ ((pAS_Info->
+ nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
+
+ return status;
+}
+
+/*
+ * Constants used by the tuning algorithm
+ */
+#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
+#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
+#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
+#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
+#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
+#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
+#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
+#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
+#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
+#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
+#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
+#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
+#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
+#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
+#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
+#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
+#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
+#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
+
+/*
+ * Define the supported Part/Rev codes for the MT2063
+ */
+#define MT2063_B0 (0x9B)
+#define MT2063_B1 (0x9C)
+#define MT2063_B2 (0x9D)
+#define MT2063_B3 (0x9E)
+
+/**
+ * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
+ *
+ * @state: struct mt2063_state pointer
+ *
+ * This function returns 0, if no lock, 1 if locked and a value < 1 if error
+ */
+static unsigned int mt2063_lockStatus(struct mt2063_state *state)
+{
+ const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
+ const u32 nPollRate = 2; /* poll status bits every 2 ms */
+ const u32 nMaxLoops = nMaxWait / nPollRate;
+ const u8 LO1LK = 0x80;
+ u8 LO2LK = 0x08;
+ u32 status;
+ u32 nDelays = 0;
+
+ dprintk(2, "\n");
+
+ /* LO2 Lock bit was in a different place for B0 version */
+ if (state->tuner_id == MT2063_B0)
+ LO2LK = 0x40;
+
+ do {
+ status = mt2063_read(state, MT2063_REG_LO_STATUS,
+ &state->reg[MT2063_REG_LO_STATUS], 1);
+
+ if (status < 0)
+ return status;
+
+ if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
+ (LO1LK | LO2LK)) {
+ return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
+ }
+ msleep(nPollRate); /* Wait between retries */
+ } while (++nDelays < nMaxLoops);
+
+ /*
+ * Got no lock or partial lock
+ */
+ return 0;
+}
+
+/*
+ * Constants for setting receiver modes.
+ * (6 modes defined at this time, enumerated by mt2063_delivery_sys)
+ * (DNC1GC & DNC2GC are the values, which are used, when the specific
+ * DNC Output is selected, the other is always off)
+ *
+ * enum mt2063_delivery_sys
+ * -------------+----------------------------------------------
+ * Mode 0 : | MT2063_CABLE_QAM
+ * Mode 1 : | MT2063_CABLE_ANALOG
+ * Mode 2 : | MT2063_OFFAIR_COFDM
+ * Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
+ * Mode 4 : | MT2063_OFFAIR_ANALOG
+ * Mode 5 : | MT2063_OFFAIR_8VSB
+ * --------------+----------------------------------------------
+ *
+ * |<---------- Mode -------------->|
+ * Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
+ * ------------+-----+-----+-----+-----+-----+-----+
+ * RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
+ * LNARin | 0 | 0 | 3 | 3 | 3 | 3
+ * FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
+ * FIFFq | 0 | 0 | 0 | 0 | 0 | 0
+ * DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
+ * DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
+ * GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
+ * LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
+ * LNA Target | 44 | 43 | 43 | 43 | 43 | 43
+ * ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
+ * RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
+ * PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
+ * ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
+ * FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
+ * PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
+ */
+
+enum mt2063_delivery_sys {
+ MT2063_CABLE_QAM = 0,
+ MT2063_CABLE_ANALOG,
+ MT2063_OFFAIR_COFDM,
+ MT2063_OFFAIR_COFDM_SAWLESS,
+ MT2063_OFFAIR_ANALOG,
+ MT2063_OFFAIR_8VSB,
+ MT2063_NUM_RCVR_MODES
+};
+
+static const char *mt2063_mode_name[] = {
+ [MT2063_CABLE_QAM] = "digital cable",
+ [MT2063_CABLE_ANALOG] = "analog cable",
+ [MT2063_OFFAIR_COFDM] = "digital offair",
+ [MT2063_OFFAIR_COFDM_SAWLESS] = "digital offair without SAW",
+ [MT2063_OFFAIR_ANALOG] = "analog offair",
+ [MT2063_OFFAIR_8VSB] = "analog offair 8vsb",
+};
+
+static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
+static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
+static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
+static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
+static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
+static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
+static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
+static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
+static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
+
+/*
+ * mt2063_set_dnc_output_enable()
+ */
+static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
+ enum MT2063_DNC_Output_Enable *pValue)
+{
+ dprintk(2, "\n");
+
+ if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
+ if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
+ *pValue = MT2063_DNC_NONE;
+ else
+ *pValue = MT2063_DNC_2;
+ } else { /* DNC1 is on */
+ if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
+ *pValue = MT2063_DNC_1;
+ else
+ *pValue = MT2063_DNC_BOTH;
+ }
+ return 0;
+}
+
+/*
+ * mt2063_set_dnc_output_enable()
+ */
+static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
+ enum MT2063_DNC_Output_Enable nValue)
+{
+ u32 status = 0; /* Status to be returned */
+ u8 val = 0;
+
+ dprintk(2, "\n");
+
+ /* selects, which DNC output is used */
+ switch (nValue) {
+ case MT2063_DNC_NONE:
+ val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
+ if (state->reg[MT2063_REG_DNC_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_DNC_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
+ if (state->reg[MT2063_REG_VGA_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_VGA_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
+ if (state->reg[MT2063_REG_RSVD_20] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_RSVD_20,
+ val);
+
+ break;
+ case MT2063_DNC_1:
+ val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
+ if (state->reg[MT2063_REG_DNC_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_DNC_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
+ if (state->reg[MT2063_REG_VGA_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_VGA_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
+ if (state->reg[MT2063_REG_RSVD_20] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_RSVD_20,
+ val);
+
+ break;
+ case MT2063_DNC_2:
+ val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
+ if (state->reg[MT2063_REG_DNC_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_DNC_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
+ if (state->reg[MT2063_REG_VGA_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_VGA_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
+ if (state->reg[MT2063_REG_RSVD_20] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_RSVD_20,
+ val);
+
+ break;
+ case MT2063_DNC_BOTH:
+ val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
+ if (state->reg[MT2063_REG_DNC_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_DNC_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
+ if (state->reg[MT2063_REG_VGA_GAIN] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_VGA_GAIN,
+ val);
+
+ val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
+ if (state->reg[MT2063_REG_RSVD_20] !=
+ val)
+ status |=
+ mt2063_setreg(state,
+ MT2063_REG_RSVD_20,
+ val);
+
+ break;
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/*
+ * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
+ * the selected enum mt2063_delivery_sys type.
+ *
+ * (DNC1GC & DNC2GC are the values, which are used, when the specific
+ * DNC Output is selected, the other is always off)
+ *
+ * @state: ptr to mt2063_state structure
+ * @Mode: desired reciever delivery system
+ *
+ * Note: Register cache must be valid for it to work
+ */
+
+static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
+ enum mt2063_delivery_sys Mode)
+{
+ u32 status = 0; /* Status to be returned */
+ u8 val;
+ u32 longval;
+
+ dprintk(2, "\n");
+
+ if (Mode >= MT2063_NUM_RCVR_MODES)
+ status = -ERANGE;
+
+ /* RFAGCen */
+ if (status >= 0) {
+ val =
+ (state->
+ reg[MT2063_REG_PD1_TGT] & (u8) ~0x40) | (RFAGCEN[Mode]
+ ? 0x40 :
+ 0x00);
+ if (state->reg[MT2063_REG_PD1_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+ }
+
+ /* LNARin */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_CTRL_2C] & (u8) ~0x03) |
+ (LNARIN[Mode] & 0x03);
+ if (state->reg[MT2063_REG_CTRL_2C] != val)
+ status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
+ }
+
+ /* FIFFQEN and FIFFQ */
+ if (status >= 0) {
+ val =
+ (state->
+ reg[MT2063_REG_FIFF_CTRL2] & (u8) ~0xF0) |
+ (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
+ if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
+ status |=
+ mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
+ /* trigger FIFF calibration, needed after changing FIFFQ */
+ val =
+ (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
+ status |=
+ mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
+ val =
+ (state->
+ reg[MT2063_REG_FIFF_CTRL] & (u8) ~0x01);
+ status |=
+ mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
+ }
+ }
+
+ /* DNC1GC & DNC2GC */
+ status |= mt2063_get_dnc_output_enable(state, &longval);
+ status |= mt2063_set_dnc_output_enable(state, longval);
+
+ /* acLNAmax */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_LNA_OV] & (u8) ~0x1F) |
+ (ACLNAMAX[Mode] & 0x1F);
+ if (state->reg[MT2063_REG_LNA_OV] != val)
+ status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
+ }
+
+ /* LNATGT */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x3F) |
+ (LNATGT[Mode] & 0x3F);
+ if (state->reg[MT2063_REG_LNA_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
+ }
+
+ /* ACRF */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_RF_OV] & (u8) ~0x1F) |
+ (ACRFMAX[Mode] & 0x1F);
+ if (state->reg[MT2063_REG_RF_OV] != val)
+ status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
+ }
+
+ /* PD1TGT */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x3F) |
+ (PD1TGT[Mode] & 0x3F);
+ if (state->reg[MT2063_REG_PD1_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+ }
+
+ /* FIFATN */
+ if (status >= 0) {
+ u8 val = ACFIFMAX[Mode];
+ if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
+ val = 5;
+ val = (state->reg[MT2063_REG_FIF_OV] & (u8) ~0x1F) |
+ (val & 0x1F);
+ if (state->reg[MT2063_REG_FIF_OV] != val)
+ status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
+ }
+
+ /* PD2TGT */
+ if (status >= 0) {
+ u8 val = (state->reg[MT2063_REG_PD2_TGT] & (u8) ~0x3F) |
+ (PD2TGT[Mode] & 0x3F);
+ if (state->reg[MT2063_REG_PD2_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
+ }
+
+ /* Ignore ATN Overload */
+ if (status >= 0) {
+ val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x80) |
+ (RFOVDIS[Mode] ? 0x80 : 0x00);
+ if (state->reg[MT2063_REG_LNA_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
+ }
+
+ /* Ignore FIF Overload */
+ if (status >= 0) {
+ val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x80) |
+ (FIFOVDIS[Mode] ? 0x80 : 0x00);
+ if (state->reg[MT2063_REG_PD1_TGT] != val)
+ status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
+ }
+
+ if (status >= 0) {
+ state->rcvr_mode = Mode;
+ dprintk(1, "mt2063 mode changed to %s\n",
+ mt2063_mode_name[state->rcvr_mode]);
+ }
+
+ return status;
+}
+
+/*
+ * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
+ * sections of the MT2063
+ *
+ * @Bits: Mask bits to be cleared.
+ *
+ * See definition of MT2063_Mask_Bits type for description
+ * of each of the power bits.
+ */
+static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
+ enum MT2063_Mask_Bits Bits)
+{
+ u32 status = 0;
+
+ dprintk(2, "\n");
+ Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
+ if ((Bits & 0xFF00) != 0) {
+ state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
+ status |=
+ mt2063_write(state,
+ MT2063_REG_PWR_2,
+ &state->reg[MT2063_REG_PWR_2], 1);
+ }
+ if ((Bits & 0xFF) != 0) {
+ state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
+ status |=
+ mt2063_write(state,
+ MT2063_REG_PWR_1,
+ &state->reg[MT2063_REG_PWR_1], 1);
+ }
+
+ return status;
+}
+
+/*
+ * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
+ * When Shutdown is 1, any section whose power
+ * mask is set will be shutdown.
+ */
+static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
+{
+ u32 status;
+
+ dprintk(2, "\n");
+ if (Shutdown == 1)
+ state->reg[MT2063_REG_PWR_1] |= 0x04;
+ else
+ state->reg[MT2063_REG_PWR_1] &= ~0x04;
+
+ status = mt2063_write(state,
+ MT2063_REG_PWR_1,
+ &state->reg[MT2063_REG_PWR_1], 1);
+
+ if (Shutdown != 1) {
+ state->reg[MT2063_REG_BYP_CTRL] =
+ (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
+ status |=
+ mt2063_write(state,
+ MT2063_REG_BYP_CTRL,
+ &state->reg[MT2063_REG_BYP_CTRL],
+ 1);
+ state->reg[MT2063_REG_BYP_CTRL] =
+ (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
+ status |=
+ mt2063_write(state,
+ MT2063_REG_BYP_CTRL,
+ &state->reg[MT2063_REG_BYP_CTRL],
+ 1);
+ }
+
+ return status;
+}
+
+static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
+{
+ return f_ref * (f_LO / f_ref)
+ + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
+}
+
+/**
+ * fLO_FractionalTerm() - Calculates the portion contributed by FracN / denom.
+ * This function preserves maximum precision without
+ * risk of overflow. It accurately calculates
+ * f_ref * num / denom to within 1 HZ with fixed math.
+ *
+ * @num : Fractional portion of the multiplier
+ * @denom: denominator portion of the ratio
+ * @f_Ref: SRO frequency.
+ *
+ * This calculation handles f_ref as two separate 14-bit fields.
+ * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
+ * This is the genesis of the magic number "14" and the magic mask value of
+ * 0x03FFF.
+ *
+ * This routine successfully handles denom values up to and including 2^18.
+ * Returns: f_ref * num / denom
+ */
+static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
+{
+ u32 t1 = (f_ref >> 14) * num;
+ u32 term1 = t1 / denom;
+ u32 loss = t1 % denom;
+ u32 term2 =
+ (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
+ return (term1 << 14) + term2;
+}
+
+/*
+ * CalcLO1Mult()- Calculates Integer divider value and the numerator
+ * value for a FracN PLL.
+ *
+ * This function assumes that the f_LO and f_Ref are
+ * evenly divisible by f_LO_Step.
+ *
+ * @Div: OUTPUT: Whole number portion of the multiplier
+ * @FracN: OUTPUT: Fractional portion of the multiplier
+ * @f_LO: desired LO frequency.
+ * @f_LO_Step: Minimum step size for the LO (in Hz).
+ * @f_Ref: SRO frequency.
+ * @f_Avoid: Range of PLL frequencies to avoid near integer multiples
+ * of f_Ref (in Hz).
+ *
+ * Returns: Recalculated LO frequency.
+ */
+static u32 MT2063_CalcLO1Mult(u32 *Div,
+ u32 *FracN,
+ u32 f_LO,
+ u32 f_LO_Step, u32 f_Ref)
+{
+ /* Calculate the whole number portion of the divider */
+ *Div = f_LO / f_Ref;
+
+ /* Calculate the numerator value (round to nearest f_LO_Step) */
+ *FracN =
+ (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
+ (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
+
+ return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
+}
+
+/**
+ * CalcLO2Mult() - Calculates Integer divider value and the numerator
+ * value for a FracN PLL.
+ *
+ * This function assumes that the f_LO and f_Ref are
+ * evenly divisible by f_LO_Step.
+ *
+ * @Div: OUTPUT: Whole number portion of the multiplier
+ * @FracN: OUTPUT: Fractional portion of the multiplier
+ * @f_LO: desired LO frequency.
+ * @f_LO_Step: Minimum step size for the LO (in Hz).
+ * @f_Ref: SRO frequency.
+ * @f_Avoid: Range of PLL frequencies to avoid near
+ * integer multiples of f_Ref (in Hz).
+ *
+ * Returns: Recalculated LO frequency.
+ */
+static u32 MT2063_CalcLO2Mult(u32 *Div,
+ u32 *FracN,
+ u32 f_LO,
+ u32 f_LO_Step, u32 f_Ref)
+{
+ /* Calculate the whole number portion of the divider */
+ *Div = f_LO / f_Ref;
+
+ /* Calculate the numerator value (round to nearest f_LO_Step) */
+ *FracN =
+ (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
+ (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
+
+ return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
+ 8191);
+}
+
+/*
+ * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
+ * used for a given input frequency.
+ *
+ * @state: ptr to tuner data structure
+ * @f_in: RF input center frequency (in Hz).
+ *
+ * Returns: ClearTune filter number (0-31)
+ */
+static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
+{
+ u32 RFBand;
+ u32 idx; /* index loop */
+
+ /*
+ ** Find RF Band setting
+ */
+ RFBand = 31; /* def when f_in > all */
+ for (idx = 0; idx < 31; ++idx) {
+ if (state->CTFiltMax[idx] >= f_in) {
+ RFBand = idx;
+ break;
+ }
+ }
+ return RFBand;
+}
+
+/*
+ * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
+ */
+static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
+{ /* RF input center frequency */
+
+ u32 status = 0;
+ u32 LO1; /* 1st LO register value */
+ u32 Num1; /* Numerator for LO1 reg. value */
+ u32 f_IF1; /* 1st IF requested */
+ u32 LO2; /* 2nd LO register value */
+ u32 Num2; /* Numerator for LO2 reg. value */
+ u32 ofLO1, ofLO2; /* last time's LO frequencies */
+ u8 fiffc = 0x80; /* FIFF center freq from tuner */
+ u32 fiffof; /* Offset from FIFF center freq */
+ const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
+ u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
+ u8 val;
+ u32 RFBand;
+
+ dprintk(2, "\n");
+ /* Check the input and output frequency ranges */
+ if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
+ return -EINVAL;
+
+ if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
+ || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
+ return -EINVAL;
+
+ /*
+ * Save original LO1 and LO2 register values
+ */
+ ofLO1 = state->AS_Data.f_LO1;
+ ofLO2 = state->AS_Data.f_LO2;
+
+ /*
+ * Find and set RF Band setting
+ */
+ if (state->ctfilt_sw == 1) {
+ val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
+ if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
+ status |=
+ mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
+ }
+ val = state->reg[MT2063_REG_CTUNE_OV];
+ RFBand = FindClearTuneFilter(state, f_in);
+ state->reg[MT2063_REG_CTUNE_OV] =
+ (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
+ | RFBand);
+ if (state->reg[MT2063_REG_CTUNE_OV] != val) {
+ status |=
+ mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
+ }
+ }
+
+ /*
+ * Read the FIFF Center Frequency from the tuner
+ */
+ if (status >= 0) {
+ status |=
+ mt2063_read(state,
+ MT2063_REG_FIFFC,
+ &state->reg[MT2063_REG_FIFFC], 1);
+ fiffc = state->reg[MT2063_REG_FIFFC];
+ }
+ /*
+ * Assign in the requested values
+ */
+ state->AS_Data.f_in = f_in;
+ /* Request a 1st IF such that LO1 is on a step size */
+ state->AS_Data.f_if1_Request =
+ MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
+ state->AS_Data.f_LO1_Step,
+ state->AS_Data.f_ref) - f_in;
+
+ /*
+ * Calculate frequency settings. f_IF1_FREQ + f_in is the
+ * desired LO1 frequency
+ */
+ MT2063_ResetExclZones(&state->AS_Data);
+
+ f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
+
+ state->AS_Data.f_LO1 =
+ MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
+ state->AS_Data.f_ref);
+
+ state->AS_Data.f_LO2 =
+ MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
+ state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+
+ /*
+ * Check for any LO spurs in the output bandwidth and adjust
+ * the LO settings to avoid them if needed
+ */
+ status |= MT2063_AvoidSpurs(&state->AS_Data);
+ /*
+ * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
+ * Recalculate the LO frequencies and the values to be placed
+ * in the tuning registers.
+ */
+ state->AS_Data.f_LO1 =
+ MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
+ state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
+ state->AS_Data.f_LO2 =
+ MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
+ state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+ state->AS_Data.f_LO2 =
+ MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
+ state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
+
+ /*
+ * Check the upconverter and downconverter frequency ranges
+ */
+ if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
+ || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
+ status |= MT2063_UPC_RANGE;
+ if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
+ || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
+ status |= MT2063_DNC_RANGE;
+ /* LO2 Lock bit was in a different place for B0 version */
+ if (state->tuner_id == MT2063_B0)
+ LO2LK = 0x40;
+
+ /*
+ * If we have the same LO frequencies and we're already locked,
+ * then skip re-programming the LO registers.
+ */
+ if ((ofLO1 != state->AS_Data.f_LO1)
+ || (ofLO2 != state->AS_Data.f_LO2)
+ || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
+ (LO1LK | LO2LK))) {
+ /*
+ * Calculate the FIFFOF register value
+ *
+ * IF1_Actual
+ * FIFFOF = ------------ - 8 * FIFFC - 4992
+ * f_ref/64
+ */
+ fiffof =
+ (state->AS_Data.f_LO1 -
+ f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
+ 4992;
+ if (fiffof > 0xFF)
+ fiffof = 0xFF;
+
+ /*
+ * Place all of the calculated values into the local tuner
+ * register fields.
+ */
+ if (status >= 0) {
+ state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
+ state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
+ state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
+ |(Num2 >> 12)); /* NUM2q (hi) */
+ state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
+ state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
+
+ /*
+ * Now write out the computed register values
+ * IMPORTANT: There is a required order for writing
+ * (0x05 must follow all the others).
+ */
+ status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
+ if (state->tuner_id == MT2063_B0) {
+ /* Re-write the one-shot bits to trigger the tune operation */
+ status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
+ }
+ /* Write out the FIFF offset only if it's changing */
+ if (state->reg[MT2063_REG_FIFF_OFFSET] !=
+ (u8) fiffof) {
+ state->reg[MT2063_REG_FIFF_OFFSET] =
+ (u8) fiffof;
+ status |=
+ mt2063_write(state,
+ MT2063_REG_FIFF_OFFSET,
+ &state->
+ reg[MT2063_REG_FIFF_OFFSET],
+ 1);
+ }
+ }
+
+ /*
+ * Check for LO's locking
+ */
+
+ if (status < 0)
+ return status;
+
+ status = mt2063_lockStatus(state);
+ if (status < 0)
+ return status;
+ if (!status)
+ return -EINVAL; /* Couldn't lock */
+
+ /*
+ * If we locked OK, assign calculated data to mt2063_state structure
+ */
+ state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
+ }
+
+ return status;
+}
+
+static const u8 MT2063B0_defaults[] = {
+ /* Reg, Value */
+ 0x19, 0x05,
+ 0x1B, 0x1D,
+ 0x1C, 0x1F,
+ 0x1D, 0x0F,
+ 0x1E, 0x3F,
+ 0x1F, 0x0F,
+ 0x20, 0x3F,
+ 0x22, 0x21,
+ 0x23, 0x3F,
+ 0x24, 0x20,
+ 0x25, 0x3F,
+ 0x27, 0xEE,
+ 0x2C, 0x27, /* bit at 0x20 is cleared below */
+ 0x30, 0x03,
+ 0x2C, 0x07, /* bit at 0x20 is cleared here */
+ 0x2D, 0x87,
+ 0x2E, 0xAA,
+ 0x28, 0xE1, /* Set the FIFCrst bit here */
+ 0x28, 0xE0, /* Clear the FIFCrst bit here */
+ 0x00
+};
+
+/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
+static const u8 MT2063B1_defaults[] = {
+ /* Reg, Value */
+ 0x05, 0xF0,
+ 0x11, 0x10, /* New Enable AFCsd */
+ 0x19, 0x05,
+ 0x1A, 0x6C,
+ 0x1B, 0x24,
+ 0x1C, 0x28,
+ 0x1D, 0x8F,
+ 0x1E, 0x14,
+ 0x1F, 0x8F,
+ 0x20, 0x57,
+ 0x22, 0x21, /* New - ver 1.03 */
+ 0x23, 0x3C, /* New - ver 1.10 */
+ 0x24, 0x20, /* New - ver 1.03 */
+ 0x2C, 0x24, /* bit at 0x20 is cleared below */
+ 0x2D, 0x87, /* FIFFQ=0 */
+ 0x2F, 0xF3,
+ 0x30, 0x0C, /* New - ver 1.11 */
+ 0x31, 0x1B, /* New - ver 1.11 */
+ 0x2C, 0x04, /* bit at 0x20 is cleared here */
+ 0x28, 0xE1, /* Set the FIFCrst bit here */
+ 0x28, 0xE0, /* Clear the FIFCrst bit here */
+ 0x00
+};
+
+/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
+static const u8 MT2063B3_defaults[] = {
+ /* Reg, Value */
+ 0x05, 0xF0,
+ 0x19, 0x3D,
+ 0x2C, 0x24, /* bit at 0x20 is cleared below */
+ 0x2C, 0x04, /* bit at 0x20 is cleared here */
+ 0x28, 0xE1, /* Set the FIFCrst bit here */
+ 0x28, 0xE0, /* Clear the FIFCrst bit here */
+ 0x00
+};
+
+static int mt2063_init(struct dvb_frontend *fe)
+{
+ u32 status;
+ struct mt2063_state *state = fe->tuner_priv;
+ u8 all_resets = 0xF0; /* reset/load bits */
+ const u8 *def = NULL;
+ char *step;
+ u32 FCRUN;
+ s32 maxReads;
+ u32 fcu_osc;
+ u32 i;
+
+ dprintk(2, "\n");
+
+ state->rcvr_mode = MT2063_CABLE_QAM;
+
+ /* Read the Part/Rev code from the tuner */
+ status = mt2063_read(state, MT2063_REG_PART_REV,
+ &state->reg[MT2063_REG_PART_REV], 1);
+ if (status < 0) {
+ printk(KERN_ERR "Can't read mt2063 part ID\n");
+ return status;
+ }
+
+ /* Check the part/rev code */
+ switch (state->reg[MT2063_REG_PART_REV]) {
+ case MT2063_B0:
+ step = "B0";
+ break;
+ case MT2063_B1:
+ step = "B1";
+ break;
+ case MT2063_B2:
+ step = "B2";
+ break;
+ case MT2063_B3:
+ step = "B3";
+ break;
+ default:
+ printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
+ state->reg[MT2063_REG_PART_REV]);
+ return -ENODEV; /* Wrong tuner Part/Rev code */
+ }
+
+ /* Check the 2nd byte of the Part/Rev code from the tuner */
+ status = mt2063_read(state, MT2063_REG_RSVD_3B,
+ &state->reg[MT2063_REG_RSVD_3B], 1);
+
+ /* b7 != 0 ==> NOT MT2063 */
+ if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
+ printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
+ state->reg[MT2063_REG_PART_REV],
+ state->reg[MT2063_REG_RSVD_3B]);
+ return -ENODEV; /* Wrong tuner Part/Rev code */
+ }
+
+ printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
+
+ /* Reset the tuner */
+ status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
+ if (status < 0)
+ return status;
+
+ /* change all of the default values that vary from the HW reset values */
+ /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
+ switch (state->reg[MT2063_REG_PART_REV]) {
+ case MT2063_B3:
+ def = MT2063B3_defaults;
+ break;
+
+ case MT2063_B1:
+ def = MT2063B1_defaults;
+ break;
+
+ case MT2063_B0:
+ def = MT2063B0_defaults;
+ break;
+
+ default:
+ return -ENODEV;
+ break;
+ }
+
+ while (status >= 0 && *def) {
+ u8 reg = *def++;
+ u8 val = *def++;
+ status = mt2063_write(state, reg, &val, 1);
+ }
+ if (status < 0)
+ return status;
+
+ /* Wait for FIFF location to complete. */
+ FCRUN = 1;
+ maxReads = 10;
+ while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
+ msleep(2);
+ status = mt2063_read(state,
+ MT2063_REG_XO_STATUS,
+ &state->
+ reg[MT2063_REG_XO_STATUS], 1);
+ FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
+ }
+
+ if (FCRUN != 0 || status < 0)
+ return -ENODEV;
+
+ status = mt2063_read(state,
+ MT2063_REG_FIFFC,
+ &state->reg[MT2063_REG_FIFFC], 1);
+ if (status < 0)
+ return status;
+
+ /* Read back all the registers from the tuner */
+ status = mt2063_read(state,
+ MT2063_REG_PART_REV,
+ state->reg, MT2063_REG_END_REGS);
+ if (status < 0)
+ return status;
+
+ /* Initialize the tuner state. */
+ state->tuner_id = state->reg[MT2063_REG_PART_REV];
+ state->AS_Data.f_ref = MT2063_REF_FREQ;
+ state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
+ ((u32) state->reg[MT2063_REG_FIFFC] + 640);
+ state->AS_Data.f_if1_bw = MT2063_IF1_BW;
+ state->AS_Data.f_out = 43750000UL;
+ state->AS_Data.f_out_bw = 6750000UL;
+ state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
+ state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
+ state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
+ state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
+ state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
+ state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
+ state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
+ state->AS_Data.f_LO1 = 2181000000UL;
+ state->AS_Data.f_LO2 = 1486249786UL;
+ state->f_IF1_actual = state->AS_Data.f_if1_Center;
+ state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
+ state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
+ state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
+ state->num_regs = MT2063_REG_END_REGS;
+ state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
+ state->ctfilt_sw = 0;
+
+ state->CTFiltMax[0] = 69230000;
+ state->CTFiltMax[1] = 105770000;
+ state->CTFiltMax[2] = 140350000;
+ state->CTFiltMax[3] = 177110000;
+ state->CTFiltMax[4] = 212860000;
+ state->CTFiltMax[5] = 241130000;
+ state->CTFiltMax[6] = 274370000;
+ state->CTFiltMax[7] = 309820000;
+ state->CTFiltMax[8] = 342450000;
+ state->CTFiltMax[9] = 378870000;
+ state->CTFiltMax[10] = 416210000;
+ state->CTFiltMax[11] = 456500000;
+ state->CTFiltMax[12] = 495790000;
+ state->CTFiltMax[13] = 534530000;
+ state->CTFiltMax[14] = 572610000;
+ state->CTFiltMax[15] = 598970000;
+ state->CTFiltMax[16] = 635910000;
+ state->CTFiltMax[17] = 672130000;
+ state->CTFiltMax[18] = 714840000;
+ state->CTFiltMax[19] = 739660000;
+ state->CTFiltMax[20] = 770410000;
+ state->CTFiltMax[21] = 814660000;
+ state->CTFiltMax[22] = 846950000;
+ state->CTFiltMax[23] = 867820000;
+ state->CTFiltMax[24] = 915980000;
+ state->CTFiltMax[25] = 947450000;
+ state->CTFiltMax[26] = 983110000;
+ state->CTFiltMax[27] = 1021630000;
+ state->CTFiltMax[28] = 1061870000;
+ state->CTFiltMax[29] = 1098330000;
+ state->CTFiltMax[30] = 1138990000;
+
+ /*
+ ** Fetch the FCU osc value and use it and the fRef value to
+ ** scale all of the Band Max values
+ */
+
+ state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
+ status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
+ &state->reg[MT2063_REG_CTUNE_CTRL], 1);
+ if (status < 0)
+ return status;
+
+ /* Read the ClearTune filter calibration value */
+ status = mt2063_read(state, MT2063_REG_FIFFC,
+ &state->reg[MT2063_REG_FIFFC], 1);
+ if (status < 0)
+ return status;
+
+ fcu_osc = state->reg[MT2063_REG_FIFFC];
+
+ state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
+ status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
+ &state->reg[MT2063_REG_CTUNE_CTRL], 1);
+ if (status < 0)
+ return status;
+
+ /* Adjust each of the values in the ClearTune filter cross-over table */
+ for (i = 0; i < 31; i++)
+ state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
+
+ status = MT2063_SoftwareShutdown(state, 1);
+ if (status < 0)
+ return status;
+ status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
+ if (status < 0)
+ return status;
+
+ state->init = true;
+
+ return 0;
+}
+
+static int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+ int status;
+
+ dprintk(2, "\n");
+
+ if (!state->init)
+ return -ENODEV;
+
+ *tuner_status = 0;
+ status = mt2063_lockStatus(state);
+ if (status < 0)
+ return status;
+ if (status)
+ *tuner_status = TUNER_STATUS_LOCKED;
+
+ dprintk(1, "Tuner status: %d", *tuner_status);
+
+ return 0;
+}
+
+static int mt2063_release(struct dvb_frontend *fe)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+
+ dprintk(2, "\n");
+
+ fe->tuner_priv = NULL;
+ kfree(state);
+
+ return 0;
+}
+
+static int mt2063_set_analog_params(struct dvb_frontend *fe,
+ struct analog_parameters *params)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+ s32 pict_car;
+ s32 pict2chanb_vsb;
+ s32 ch_bw;
+ s32 if_mid;
+ s32 rcvr_mode;
+ int status;
+
+ dprintk(2, "\n");
+
+ if (!state->init) {
+ status = mt2063_init(fe);
+ if (status < 0)
+ return status;
+ }
+
+ switch (params->mode) {
+ case V4L2_TUNER_RADIO:
+ pict_car = 38900000;
+ ch_bw = 8000000;
+ pict2chanb_vsb = -(ch_bw / 2);
+ rcvr_mode = MT2063_OFFAIR_ANALOG;
+ break;
+ case V4L2_TUNER_ANALOG_TV:
+ rcvr_mode = MT2063_CABLE_ANALOG;
+ if (params->std & ~V4L2_STD_MN) {
+ pict_car = 38900000;
+ ch_bw = 6000000;
+ pict2chanb_vsb = -1250000;
+ } else if (params->std & V4L2_STD_PAL_G) {
+ pict_car = 38900000;
+ ch_bw = 7000000;
+ pict2chanb_vsb = -1250000;
+ } else { /* PAL/SECAM standards */
+ pict_car = 38900000;
+ ch_bw = 8000000;
+ pict2chanb_vsb = -1250000;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
+
+ state->AS_Data.f_LO2_Step = 125000; /* FIXME: probably 5000 for FM */
+ state->AS_Data.f_out = if_mid;
+ state->AS_Data.f_out_bw = ch_bw + 750000;
+ status = MT2063_SetReceiverMode(state, rcvr_mode);
+ if (status < 0)
+ return status;
+
+ dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
+ params->frequency, ch_bw, pict2chanb_vsb);
+
+ status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
+ if (status < 0)
+ return status;
+
+ state->frequency = params->frequency;
+ return 0;
+}
+
+/*
+ * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
+ * So, the amount of the needed bandwith is given by:
+ * Bw = Symbol_rate * (1 + 0.15)
+ * As such, the maximum symbol rate supported by 6 MHz is given by:
+ * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
+ */
+#define MAX_SYMBOL_RATE_6MHz 5217391
+
+static int mt2063_set_params(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct mt2063_state *state = fe->tuner_priv;
+ int status;
+ s32 pict_car;
+ s32 pict2chanb_vsb;
+ s32 ch_bw;
+ s32 if_mid;
+ s32 rcvr_mode;
+
+ if (!state->init) {
+ status = mt2063_init(fe);
+ if (status < 0)
+ return status;
+ }
+
+ dprintk(2, "\n");
+
+ if (c->bandwidth_hz == 0)
+ return -EINVAL;
+ if (c->bandwidth_hz <= 6000000)
+ ch_bw = 6000000;
+ else if (c->bandwidth_hz <= 7000000)
+ ch_bw = 7000000;
+ else
+ ch_bw = 8000000;
+
+ switch (c->delivery_system) {
+ case SYS_DVBT:
+ rcvr_mode = MT2063_OFFAIR_COFDM;
+ pict_car = 36125000;
+ pict2chanb_vsb = -(ch_bw / 2);
+ break;
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ rcvr_mode = MT2063_CABLE_QAM;
+ pict_car = 36125000;
+ pict2chanb_vsb = -(ch_bw / 2);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
+
+ state->AS_Data.f_LO2_Step = 125000; /* FIXME: probably 5000 for FM */
+ state->AS_Data.f_out = if_mid;
+ state->AS_Data.f_out_bw = ch_bw + 750000;
+ status = MT2063_SetReceiverMode(state, rcvr_mode);
+ if (status < 0)
+ return status;
+
+ dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
+ c->frequency, ch_bw, pict2chanb_vsb);
+
+ status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
+
+ if (status < 0)
+ return status;
+
+ state->frequency = c->frequency;
+ return 0;
+}
+
+static int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+
+ dprintk(2, "\n");
+
+ if (!state->init)
+ return -ENODEV;
+
+ *freq = state->AS_Data.f_out;
+
+ dprintk(1, "IF frequency: %d\n", *freq);
+
+ return 0;
+}
+
+static int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+
+ dprintk(2, "\n");
+
+ if (!state->init)
+ return -ENODEV;
+
+ *bw = state->AS_Data.f_out_bw - 750000;
+
+ dprintk(1, "bandwidth: %d\n", *bw);
+
+ return 0;
+}
+
+static struct dvb_tuner_ops mt2063_ops = {
+ .info = {
+ .name = "MT2063 Silicon Tuner",
+ .frequency_min = 45000000,
+ .frequency_max = 850000000,
+ .frequency_step = 0,
+ },
+
+ .init = mt2063_init,
+ .sleep = MT2063_Sleep,
+ .get_status = mt2063_get_status,
+ .set_analog_params = mt2063_set_analog_params,
+ .set_params = mt2063_set_params,
+ .get_if_frequency = mt2063_get_if_frequency,
+ .get_bandwidth = mt2063_get_bandwidth,
+ .release = mt2063_release,
+};
+
+struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+ struct mt2063_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct mt2063_state *state = NULL;
+
+ dprintk(2, "\n");
+
+ state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ state->config = config;
+ state->i2c = i2c;
+ state->frontend = fe;
+ state->reference = config->refclock / 1000; /* kHz */
+ fe->tuner_priv = state;
+ fe->ops.tuner_ops = mt2063_ops;
+
+ printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
+ return fe;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(mt2063_attach);
+
+/*
+ * Ancillary routines visible outside mt2063
+ * FIXME: Remove them in favor of using standard tuner callbacks
+ */
+unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+ int err = 0;
+
+ dprintk(2, "\n");
+
+ err = MT2063_SoftwareShutdown(state, 1);
+ if (err < 0)
+ printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
+
+unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
+{
+ struct mt2063_state *state = fe->tuner_priv;
+ int err = 0;
+
+ dprintk(2, "\n");
+
+ err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
+ if (err < 0)
+ printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
+
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_DESCRIPTION("MT2063 Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mt2063.h b/drivers/media/common/tuners/mt2063.h
new file mode 100644
index 0000000..62d0e8e
--- /dev/null
+++ b/drivers/media/common/tuners/mt2063.h
@@ -0,0 +1,36 @@
+#ifndef __MT2063_H__
+#define __MT2063_H__
+
+#include "dvb_frontend.h"
+
+struct mt2063_config {
+ u8 tuner_address;
+ u32 refclock;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_MT2063) || (defined(CONFIG_MEDIA_TUNER_MT2063_MODULE) && defined(MODULE))
+struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+ struct mt2063_config *config,
+ struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
+ struct mt2063_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+
+int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
+ u32 bw_in,
+ enum MTTune_atv_standard tv_type);
+
+/* FIXME: Should use the standard DVB attachment interfaces */
+unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
+unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
+
+#endif /* CONFIG_DVB_MT2063 */
+
+#endif /* __MT2063_H__ */
diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/common/tuners/mt2131.c
index a4f830b..f83b0c1 100644
--- a/drivers/media/common/tuners/mt2131.c
+++ b/drivers/media/common/tuners/mt2131.c
@@ -92,9 +92,9 @@ static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
return 0;
}
-static int mt2131_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int mt2131_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct mt2131_priv *priv;
int ret=0, i;
u32 freq;
@@ -105,12 +105,8 @@ static int mt2131_set_params(struct dvb_frontend *fe,
u8 lockval = 0;
priv = fe->tuner_priv;
- if (fe->ops.info.type == FE_OFDM)
- priv->bandwidth = params->u.ofdm.bandwidth;
- else
- priv->bandwidth = 0;
- freq = params->frequency / 1000; // Hz -> kHz
+ freq = c->frequency / 1000; /* Hz -> kHz */
dprintk(1, "%s() freq=%d\n", __func__, freq);
f_lo1 = freq + MT2131_IF1 * 1000;
@@ -193,14 +189,6 @@ static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
- struct mt2131_priv *priv = fe->tuner_priv;
- dprintk(1, "%s()\n", __func__);
- *bandwidth = priv->bandwidth;
- return 0;
-}
-
static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
{
struct mt2131_priv *priv = fe->tuner_priv;
@@ -263,7 +251,6 @@ static const struct dvb_tuner_ops mt2131_tuner_ops = {
.set_params = mt2131_set_params,
.get_frequency = mt2131_get_frequency,
- .get_bandwidth = mt2131_get_bandwidth,
.get_status = mt2131_get_status
};
@@ -281,7 +268,6 @@ struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
return NULL;
priv->cfg = cfg;
- priv->bandwidth = 6000000; /* 6MHz */
priv->i2c = i2c;
if (mt2131_readreg(priv, 0, &id) != 0) {
diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/common/tuners/mt2131_priv.h
index 4e05a67..62aeedf 100644
--- a/drivers/media/common/tuners/mt2131_priv.h
+++ b/drivers/media/common/tuners/mt2131_priv.h
@@ -38,7 +38,6 @@ struct mt2131_priv {
struct i2c_adapter *i2c;
u32 frequency;
- u32 bandwidth;
};
#endif /* __MT2131_PRIV_H__ */
diff --git a/drivers/media/common/tuners/mt2266.c b/drivers/media/common/tuners/mt2266.c
index 25a8ea3..bca4d75 100644
--- a/drivers/media/common/tuners/mt2266.c
+++ b/drivers/media/common/tuners/mt2266.c
@@ -122,8 +122,9 @@ static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
#define FREF 30000 // Quartz oscillator 30 MHz
-static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int mt2266_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct mt2266_priv *priv;
int ret=0;
u32 freq;
@@ -135,32 +136,32 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
priv = fe->tuner_priv;
- freq = params->frequency / 1000; // Hz -> kHz
+ freq = priv->frequency / 1000; /* Hz -> kHz */
if (freq < 470000 && freq > 230000)
return -EINVAL; /* Gap between VHF and UHF bands */
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
- priv->frequency = freq * 1000;
+ priv->frequency = c->frequency;
tune = 2 * freq * (8192/16) / (FREF/16);
band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
if (band == MT2266_VHF)
tune *= 2;
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
mt2266_writeregs(priv, mt2266_init_6mhz,
sizeof(mt2266_init_6mhz));
break;
- case BANDWIDTH_7_MHZ:
- mt2266_writeregs(priv, mt2266_init_7mhz,
- sizeof(mt2266_init_7mhz));
- break;
- case BANDWIDTH_8_MHZ:
- default:
+ case 8000000:
mt2266_writeregs(priv, mt2266_init_8mhz,
sizeof(mt2266_init_8mhz));
break;
+ case 7000000:
+ default:
+ mt2266_writeregs(priv, mt2266_init_7mhz,
+ sizeof(mt2266_init_7mhz));
+ break;
}
+ priv->bandwidth = c->bandwidth_hz;
if (band == MT2266_VHF && priv->band == MT2266_UHF) {
dprintk("Switch from UHF to VHF");
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 54be9e6..6133315 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -3979,54 +3979,47 @@ static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
return 0;
}
-static int mxl5005s_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int mxl5005s_set_params(struct dvb_frontend *fe)
{
struct mxl5005s_state *state = fe->tuner_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
u32 req_mode, req_bw = 0;
int ret;
dprintk(1, "%s()\n", __func__);
- if (fe->ops.info.type == FE_ATSC) {
- switch (params->u.vsb.modulation) {
- case VSB_8:
- req_mode = MXL_ATSC; break;
- default:
- case QAM_64:
- case QAM_256:
- case QAM_AUTO:
- req_mode = MXL_QAM; break;
- }
- } else
+ switch (delsys) {
+ case SYS_ATSC:
+ req_mode = MXL_ATSC;
+ req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ break;
+ case SYS_DVBC_ANNEX_B:
+ req_mode = MXL_QAM;
+ req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ break;
+ default: /* Assume DVB-T */
req_mode = MXL_DVBT;
-
- /* Change tuner for new modulation type if reqd */
- if (req_mode != state->current_mode) {
- switch (req_mode) {
- case MXL_ATSC:
- case MXL_QAM:
- req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ switch (bw) {
+ case 6000000:
+ req_bw = MXL5005S_BANDWIDTH_6MHZ;
+ break;
+ case 7000000:
+ req_bw = MXL5005S_BANDWIDTH_7MHZ;
+ break;
+ case 8000000:
+ case 0:
+ req_bw = MXL5005S_BANDWIDTH_8MHZ;
break;
- case MXL_DVBT:
default:
- /* Assume DVB-T */
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- req_bw = MXL5005S_BANDWIDTH_6MHZ;
- break;
- case BANDWIDTH_7_MHZ:
- req_bw = MXL5005S_BANDWIDTH_7MHZ;
- break;
- case BANDWIDTH_AUTO:
- case BANDWIDTH_8_MHZ:
- req_bw = MXL5005S_BANDWIDTH_8MHZ;
- break;
- default:
- return -EINVAL;
- }
+ return -EINVAL;
}
+ }
+ /* Change tuner for new modulation type if reqd */
+ if (req_mode != state->current_mode ||
+ req_bw != state->Chan_Bandwidth) {
state->current_mode = req_mode;
ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
@@ -4034,8 +4027,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
ret = 0;
if (ret == 0) {
- dprintk(1, "%s() freq=%d\n", __func__, params->frequency);
- ret = mxl5005s_SetRfFreqHz(fe, params->frequency);
+ dprintk(1, "%s() freq=%d\n", __func__, c->frequency);
+ ret = mxl5005s_SetRfFreqHz(fe, c->frequency);
}
return ret;
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index 5d02221..69e453e 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -165,6 +165,8 @@ struct mxl5007t_state {
struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
+ enum mxl5007t_if_freq if_freq;
+
u32 frequency;
u32 bandwidth;
};
@@ -286,6 +288,8 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
/* set inverted IF or normal IF */
set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
+ state->if_freq = if_freq;
+
return;
}
@@ -612,47 +616,43 @@ fail:
/* ------------------------------------------------------------------------- */
-static int mxl5007t_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int mxl5007t_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
struct mxl5007t_state *state = fe->tuner_priv;
enum mxl5007t_bw_mhz bw;
enum mxl5007t_mode mode;
int ret;
- u32 freq = params->frequency;
+ u32 freq = c->frequency;
- if (fe->ops.info.type == FE_ATSC) {
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- mode = MxL_MODE_ATSC;
- break;
- case QAM_64:
- case QAM_256:
- mode = MxL_MODE_CABLE;
- break;
- default:
- mxl_err("modulation not set!");
- return -EINVAL;
- }
+ switch (delsys) {
+ case SYS_ATSC:
+ mode = MxL_MODE_ATSC;
+ bw = MxL_BW_6MHz;
+ break;
+ case SYS_DVBC_ANNEX_B:
+ mode = MxL_MODE_CABLE;
bw = MxL_BW_6MHz;
- } else if (fe->ops.info.type == FE_OFDM) {
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ break;
+ case SYS_DVBT:
+ case SYS_DVBT2:
+ mode = MxL_MODE_DVBT;
+ switch (c->bandwidth_hz) {
+ case 6000000:
bw = MxL_BW_6MHz;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
bw = MxL_BW_7MHz;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
bw = MxL_BW_8MHz;
break;
default:
- mxl_err("bandwidth not set!");
return -EINVAL;
}
- mode = MxL_MODE_DVBT;
- } else {
+ break;
+ default:
mxl_err("modulation type not supported!");
return -EINVAL;
}
@@ -671,8 +671,7 @@ static int mxl5007t_set_params(struct dvb_frontend *fe,
goto fail;
state->frequency = freq;
- state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
+ state->bandwidth = c->bandwidth_hz;
fail:
mutex_unlock(&state->lock);
@@ -738,6 +737,50 @@ static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
return 0;
}
+static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mxl5007t_state *state = fe->tuner_priv;
+
+ *frequency = 0;
+
+ switch (state->if_freq) {
+ case MxL_IF_4_MHZ:
+ *frequency = 4000000;
+ break;
+ case MxL_IF_4_5_MHZ:
+ *frequency = 4500000;
+ break;
+ case MxL_IF_4_57_MHZ:
+ *frequency = 4570000;
+ break;
+ case MxL_IF_5_MHZ:
+ *frequency = 5000000;
+ break;
+ case MxL_IF_5_38_MHZ:
+ *frequency = 5380000;
+ break;
+ case MxL_IF_6_MHZ:
+ *frequency = 6000000;
+ break;
+ case MxL_IF_6_28_MHZ:
+ *frequency = 6280000;
+ break;
+ case MxL_IF_9_1915_MHZ:
+ *frequency = 9191500;
+ break;
+ case MxL_IF_35_25_MHZ:
+ *frequency = 35250000;
+ break;
+ case MxL_IF_36_15_MHZ:
+ *frequency = 36150000;
+ break;
+ case MxL_IF_44_MHZ:
+ *frequency = 44000000;
+ break;
+ }
+ return 0;
+}
+
static int mxl5007t_release(struct dvb_frontend *fe)
{
struct mxl5007t_state *state = fe->tuner_priv;
@@ -767,6 +810,7 @@ static struct dvb_tuner_ops mxl5007t_tuner_ops = {
.get_frequency = mxl5007t_get_frequency,
.get_bandwidth = mxl5007t_get_bandwidth,
.release = mxl5007t_release,
+ .get_if_frequency = mxl5007t_get_if_frequency,
};
static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
diff --git a/drivers/media/common/tuners/qt1010.c b/drivers/media/common/tuners/qt1010.c
index 9f5dba2..2d79b1f 100644
--- a/drivers/media/common/tuners/qt1010.c
+++ b/drivers/media/common/tuners/qt1010.c
@@ -82,9 +82,9 @@ static void qt1010_dump_regs(struct qt1010_priv *priv)
printk(KERN_CONT "\n");
}
-static int qt1010_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int qt1010_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct qt1010_priv *priv;
int err;
u32 freq, div, mod1, mod2;
@@ -144,13 +144,11 @@ static int qt1010_set_params(struct dvb_frontend *fe,
#define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */
priv = fe->tuner_priv;
- freq = params->frequency;
+ freq = c->frequency;
div = (freq + QT1010_OFFSET) / QT1010_STEP;
freq = (div * QT1010_STEP) - QT1010_OFFSET;
mod1 = (freq + QT1010_OFFSET) % FREQ1;
mod2 = (freq + QT1010_OFFSET) % FREQ2;
- priv->bandwidth =
- (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
priv->frequency = freq;
if (fe->ops.i2c_gate_ctrl)
@@ -320,7 +318,7 @@ static u8 qt1010_init_meas2(struct qt1010_priv *priv,
static int qt1010_init(struct dvb_frontend *fe)
{
struct qt1010_priv *priv = fe->tuner_priv;
- struct dvb_frontend_parameters params;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int err = 0;
u8 i, tmpval, *valptr = NULL;
@@ -397,9 +395,9 @@ static int qt1010_init(struct dvb_frontend *fe)
if ((err = qt1010_init_meas2(priv, i, &tmpval)))
return err;
- params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+ c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
/* MSI Megasky 580 GL861 533000000 */
- return qt1010_set_params(fe, &params);
+ return qt1010_set_params(fe);
}
static int qt1010_release(struct dvb_frontend *fe)
@@ -416,10 +414,9 @@ static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
return 0;
}
-static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct qt1010_priv *priv = fe->tuner_priv;
- *bandwidth = priv->bandwidth;
+ *frequency = 36125000;
return 0;
}
@@ -437,7 +434,7 @@ static const struct dvb_tuner_ops qt1010_tuner_ops = {
.set_params = qt1010_set_params,
.get_frequency = qt1010_get_frequency,
- .get_bandwidth = qt1010_get_bandwidth
+ .get_if_frequency = qt1010_get_if_frequency,
};
struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/common/tuners/qt1010_priv.h b/drivers/media/common/tuners/qt1010_priv.h
index 090cf47..2c42d3f 100644
--- a/drivers/media/common/tuners/qt1010_priv.h
+++ b/drivers/media/common/tuners/qt1010_priv.h
@@ -99,7 +99,6 @@ struct qt1010_priv {
u8 reg25_init_val;
u32 frequency;
- u32 bandwidth;
};
#endif
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c
index e29cc2bc1..602c2e3 100644
--- a/drivers/media/common/tuners/tda18212.c
+++ b/drivers/media/common/tuners/tda18212.c
@@ -25,6 +25,8 @@
struct tda18212_priv {
struct tda18212_config *cfg;
struct i2c_adapter *i2c;
+
+ u32 if_frequency;
};
#define dbg(fmt, arg...) \
@@ -128,20 +130,31 @@ static void tda18212_dump_regs(struct tda18212_priv *priv)
}
#endif
-static int tda18212_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int tda18212_set_params(struct dvb_frontend *fe)
{
struct tda18212_priv *priv = fe->tuner_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
u32 if_khz;
u8 buf[9];
+ #define DVBT_6 0
+ #define DVBT_7 1
+ #define DVBT_8 2
+ #define DVBT2_6 3
+ #define DVBT2_7 4
+ #define DVBT2_8 5
+ #define DVBC_6 6
+ #define DVBC_8 7
static const u8 bw_params[][3] = {
- /* 0f 13 23 */
- { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */
- { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */
- { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */
- { 0x92, 0x53, 0x03 }, /* DVB-C */
+ /* reg: 0f 13 23 */
+ [DVBT_6] = { 0xb3, 0x20, 0x03 },
+ [DVBT_7] = { 0xb3, 0x31, 0x01 },
+ [DVBT_8] = { 0xb3, 0x22, 0x01 },
+ [DVBT2_6] = { 0xbc, 0x20, 0x03 },
+ [DVBT2_7] = { 0xbc, 0x72, 0x03 },
+ [DVBT2_8] = { 0xbc, 0x22, 0x01 },
+ [DVBC_6] = { 0x92, 0x50, 0x03 },
+ [DVBC_8] = { 0x92, 0x53, 0x03 },
};
dbg("delsys=%d RF=%d BW=%d\n",
@@ -155,24 +168,44 @@ static int tda18212_set_params(struct dvb_frontend *fe,
switch (c->bandwidth_hz) {
case 6000000:
if_khz = priv->cfg->if_dvbt_6;
- i = 0;
+ i = DVBT_6;
break;
case 7000000:
if_khz = priv->cfg->if_dvbt_7;
- i = 1;
+ i = DVBT_7;
break;
case 8000000:
if_khz = priv->cfg->if_dvbt_8;
- i = 2;
+ i = DVBT_8;
break;
default:
ret = -EINVAL;
goto error;
}
break;
- case SYS_DVBC_ANNEX_AC:
+ case SYS_DVBT2:
+ switch (c->bandwidth_hz) {
+ case 6000000:
+ if_khz = priv->cfg->if_dvbt2_6;
+ i = DVBT2_6;
+ break;
+ case 7000000:
+ if_khz = priv->cfg->if_dvbt2_7;
+ i = DVBT2_7;
+ break;
+ case 8000000:
+ if_khz = priv->cfg->if_dvbt2_8;
+ i = DVBT2_8;
+ break;
+ default:
+ ret = -EINVAL;
+ goto error;
+ }
+ break;
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
if_khz = priv->cfg->if_dvbc;
- i = 3;
+ i = DVBC_8;
break;
default:
ret = -EINVAL;
@@ -194,7 +227,7 @@ static int tda18212_set_params(struct dvb_frontend *fe,
buf[0] = 0x02;
buf[1] = bw_params[i][1];
buf[2] = 0x03; /* default value */
- buf[3] = if_khz / 50;
+ buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
buf[5] = ((c->frequency / 1000) >> 8) & 0xff;
buf[6] = ((c->frequency / 1000) >> 0) & 0xff;
@@ -204,6 +237,9 @@ static int tda18212_set_params(struct dvb_frontend *fe,
if (ret)
goto error;
+ /* actual IF rounded as it is on register */
+ priv->if_frequency = buf[3] * 50 * 1000;
+
exit:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
@@ -215,6 +251,15 @@ error:
goto exit;
}
+static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tda18212_priv *priv = fe->tuner_priv;
+
+ *frequency = priv->if_frequency;
+
+ return 0;
+}
+
static int tda18212_release(struct dvb_frontend *fe)
{
kfree(fe->tuner_priv);
@@ -234,6 +279,7 @@ static const struct dvb_tuner_ops tda18212_tuner_ops = {
.release = tda18212_release,
.set_params = tda18212_set_params,
+ .get_if_frequency = tda18212_get_if_frequency,
};
struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h
index 83b497f..9bd5da4 100644
--- a/drivers/media/common/tuners/tda18212.h
+++ b/drivers/media/common/tuners/tda18212.h
@@ -29,6 +29,10 @@ struct tda18212_config {
u16 if_dvbt_6;
u16 if_dvbt_7;
u16 if_dvbt_8;
+ u16 if_dvbt2_5;
+ u16 if_dvbt2_6;
+ u16 if_dvbt2_7;
+ u16 if_dvbt2_8;
u16 if_dvbc;
};
diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c
index 4fc2973..dfb3a83 100644
--- a/drivers/media/common/tuners/tda18218.c
+++ b/drivers/media/common/tuners/tda18218.c
@@ -109,10 +109,11 @@ static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
return tda18218_rd_regs(priv, reg, val, 1);
}
-static int tda18218_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tda18218_set_params(struct dvb_frontend *fe)
{
struct tda18218_priv *priv = fe->tuner_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 bw = c->bandwidth_hz;
int ret;
u8 buf[3], i, BP_Filter, LP_Fc;
u32 LO_Frac;
@@ -138,22 +139,19 @@ static int tda18218_set_params(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
/* low-pass filter cut-off frequency */
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ if (bw <= 6000000) {
LP_Fc = 0;
- LO_Frac = params->frequency + 3000000;
- break;
- case BANDWIDTH_7_MHZ:
+ priv->if_frequency = 3000000;
+ } else if (bw <= 7000000) {
LP_Fc = 1;
- LO_Frac = params->frequency + 3500000;
- break;
- case BANDWIDTH_8_MHZ:
- default:
+ priv->if_frequency = 3500000;
+ } else {
LP_Fc = 2;
- LO_Frac = params->frequency + 4000000;
- break;
+ priv->if_frequency = 4000000;
}
+ LO_Frac = c->frequency + priv->if_frequency;
+
/* band-pass filter */
if (LO_Frac < 188000000)
BP_Filter = 3;
@@ -206,6 +204,14 @@ error:
return ret;
}
+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);
+ return 0;
+}
+
static int tda18218_sleep(struct dvb_frontend *fe)
{
struct tda18218_priv *priv = fe->tuner_priv;
@@ -268,6 +274,8 @@ static const struct dvb_tuner_ops tda18218_tuner_ops = {
.sleep = tda18218_sleep,
.set_params = tda18218_set_params,
+
+ .get_if_frequency = tda18218_get_if_frequency,
};
struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/common/tuners/tda18218_priv.h
index 904e536..dc52b72 100644
--- a/drivers/media/common/tuners/tda18218_priv.h
+++ b/drivers/media/common/tuners/tda18218_priv.h
@@ -100,6 +100,8 @@ struct tda18218_priv {
struct tda18218_config *cfg;
struct i2c_adapter *i2c;
+ u32 if_frequency;
+
u8 regs[TDA18218_NUM_REGS];
};
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 63cc400..2e67f44 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -928,59 +928,49 @@ fail:
/* ------------------------------------------------------------------ */
-static int tda18271_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tda18271_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
+ u32 freq = c->frequency;
struct tda18271_priv *priv = fe->tuner_priv;
struct tda18271_std_map *std_map = &priv->std;
struct tda18271_std_map_item *map;
int ret;
- u32 bw, freq = params->frequency;
priv->mode = TDA18271_DIGITAL;
- if (fe->ops.info.type == FE_ATSC) {
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- map = &std_map->atsc_6;
- break;
- case QAM_64:
- case QAM_256:
- map = &std_map->qam_6;
- break;
- default:
- tda_warn("modulation not set!\n");
- return -EINVAL;
- }
-#if 0
- /* userspace request is already center adjusted */
- freq += 1750000; /* Adjust to center (+1.75MHZ) */
-#endif
+ switch (delsys) {
+ case SYS_ATSC:
+ map = &std_map->atsc_6;
bw = 6000000;
- } else if (fe->ops.info.type == FE_OFDM) {
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- bw = 6000000;
+ break;
+ case SYS_ISDBT:
+ case SYS_DVBT:
+ case SYS_DVBT2:
+ if (bw <= 6000000) {
map = &std_map->dvbt_6;
- break;
- case BANDWIDTH_7_MHZ:
- bw = 7000000;
+ } else if (bw <= 7000000) {
map = &std_map->dvbt_7;
- break;
- case BANDWIDTH_8_MHZ:
- bw = 8000000;
+ } else {
map = &std_map->dvbt_8;
- break;
- default:
- tda_warn("bandwidth not set!\n");
- return -EINVAL;
}
- } else if (fe->ops.info.type == FE_QAM) {
- /* DVB-C */
- map = &std_map->qam_8;
- bw = 8000000;
- } else {
+ break;
+ case SYS_DVBC_ANNEX_B:
+ bw = 6000000;
+ /* falltrough */
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ if (bw <= 6000000) {
+ map = &std_map->qam_6;
+ } else if (bw <= 7000000) {
+ map = &std_map->qam_7;
+ } else {
+ map = &std_map->qam_8;
+ }
+ break;
+ default:
tda_warn("modulation type not supported!\n");
return -EINVAL;
}
@@ -994,9 +984,9 @@ static int tda18271_set_params(struct dvb_frontend *fe,
if (tda_fail(ret))
goto fail;
+ priv->if_freq = map->if_freq;
priv->frequency = freq;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
+ priv->bandwidth = bw;
fail:
return ret;
}
@@ -1050,6 +1040,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe,
if (tda_fail(ret))
goto fail;
+ priv->if_freq = map->if_freq;
priv->frequency = freq;
priv->bandwidth = 0;
fail:
@@ -1086,6 +1077,13 @@ static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
return 0;
}
+static int tda18271_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct tda18271_priv *priv = fe->tuner_priv;
+ *frequency = (u32)priv->if_freq * 1000;
+ return 0;
+}
+
/* ------------------------------------------------------------------ */
#define tda18271_update_std(std_cfg, name) do { \
@@ -1245,6 +1243,7 @@ static const struct dvb_tuner_ops tda18271_tuner_ops = {
.set_config = tda18271_set_config,
.get_frequency = tda18271_get_frequency,
.get_bandwidth = tda18271_get_bandwidth,
+ .get_if_frequency = tda18271_get_if_frequency,
};
struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c
index 3d5b6ab..fb881c6 100644
--- a/drivers/media/common/tuners/tda18271-maps.c
+++ b/drivers/media/common/tuners/tda18271-maps.c
@@ -1213,6 +1213,8 @@ static struct tda18271_std_map tda18271c1_std_map = {
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
.qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+ .qam_7 = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
.qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
};
@@ -1244,6 +1246,8 @@ static struct tda18271_std_map tda18271c2_std_map = {
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
.qam_6 = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
+ .qam_7 = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
+ .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
.qam_8 = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
.if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
};
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
index 94340f4..454c152 100644
--- a/drivers/media/common/tuners/tda18271-priv.h
+++ b/drivers/media/common/tuners/tda18271-priv.h
@@ -122,6 +122,8 @@ struct tda18271_priv {
struct mutex lock;
+ u16 if_freq;
+
u32 frequency;
u32 bandwidth;
};
diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h
index 50cfa8c..640bae4 100644
--- a/drivers/media/common/tuners/tda18271.h
+++ b/drivers/media/common/tuners/tda18271.h
@@ -53,6 +53,7 @@ struct tda18271_std_map {
struct tda18271_std_map_item dvbt_7;
struct tda18271_std_map_item dvbt_8;
struct tda18271_std_map_item qam_6;
+ struct tda18271_std_map_item qam_7;
struct tda18271_std_map_item qam_8;
};
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index e0d5b43..a0d1762 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -152,9 +152,9 @@ static int tuner_transfer(struct dvb_frontend *fe,
return rc;
}
-static int tda827xo_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tda827xo_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct tda827x_priv *priv = fe->tuner_priv;
u8 buf[14];
int rc;
@@ -165,18 +165,16 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
u32 N;
dprintk("%s:\n", __func__);
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ if (c->bandwidth_hz == 0) {
+ if_freq = 5000000;
+ } else if (c->bandwidth_hz <= 6000000) {
if_freq = 4000000;
- break;
- case BANDWIDTH_7_MHZ:
+ } else if (c->bandwidth_hz <= 7000000) {
if_freq = 4500000;
- break;
- default: /* 8 MHz or Auto */
+ } else { /* 8 MHz */
if_freq = 5000000;
- break;
}
- tuner_freq = params->frequency;
+ tuner_freq = c->frequency;
i = 0;
while (tda827x_table[i].lomax < tuner_freq) {
@@ -220,8 +218,8 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
if (rc < 0)
goto err;
- priv->frequency = params->frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+ priv->frequency = c->frequency;
+ priv->bandwidth = c->bandwidth_hz;
return 0;
@@ -513,9 +511,9 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
}
}
-static int tda827xa_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tda827xa_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct tda827x_priv *priv = fe->tuner_priv;
struct tda827xa_data *frequency_map = tda827xa_dvbt;
u8 buf[11];
@@ -531,22 +529,25 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
tda827xa_lna_gain(fe, 1, NULL);
msleep(20);
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ if (c->bandwidth_hz == 0) {
+ if_freq = 5000000;
+ } else if (c->bandwidth_hz <= 6000000) {
if_freq = 4000000;
- break;
- case BANDWIDTH_7_MHZ:
+ } else if (c->bandwidth_hz <= 7000000) {
if_freq = 4500000;
- break;
- default: /* 8 MHz or Auto */
+ } else { /* 8 MHz */
if_freq = 5000000;
- break;
}
- tuner_freq = params->frequency;
+ tuner_freq = c->frequency;
- if (fe->ops.info.type == FE_QAM) {
+ switch (c->delivery_system) {
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
dprintk("%s select tda827xa_dvbc\n", __func__);
frequency_map = tda827xa_dvbc;
+ break;
+ default:
+ break;
}
i = 0;
@@ -645,9 +646,8 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
if (rc < 0)
goto err;
- priv->frequency = params->frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
-
+ priv->frequency = c->frequency;
+ priv->bandwidth = c->bandwidth_hz;
return 0;
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index f8ee29e..39e7e58 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -751,6 +751,17 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
if (4 != rc)
tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+ /* Write AUX byte */
+ switch (priv->type) {
+ case TUNER_PHILIPS_FM1216ME_MK3:
+ buffer[2] = 0x98;
+ buffer[3] = 0x20; /* set TOP AGC */
+ rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
+ if (4 != rc)
+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
+ break;
+ }
+
return 0;
}
@@ -780,24 +791,26 @@ static int simple_set_params(struct dvb_frontend *fe,
}
static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+ const u32 delsys,
+ const u32 frequency,
+ const u32 bandwidth)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
switch (priv->type) {
case TUNER_PHILIPS_FMD1216ME_MK3:
case TUNER_PHILIPS_FMD1216MEX_MK3:
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
- params->frequency >= 158870000)
+ if (bandwidth == 8000000 &&
+ frequency >= 158870000)
buf[3] |= 0x08;
break;
case TUNER_PHILIPS_TD1316:
/* determine band */
- buf[3] |= (params->frequency < 161000000) ? 1 :
- (params->frequency < 444000000) ? 2 : 4;
+ buf[3] |= (frequency < 161000000) ? 1 :
+ (frequency < 444000000) ? 2 : 4;
/* setup PLL filter */
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ if (bandwidth == 8000000)
buf[3] |= 1 << 3;
break;
case TUNER_PHILIPS_TUV1236D:
@@ -808,12 +821,11 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
if (dtv_input[priv->nr])
new_rf = dtv_input[priv->nr];
else
- switch (params->u.vsb.modulation) {
- case QAM_64:
- case QAM_256:
+ switch (delsys) {
+ case SYS_DVBC_ANNEX_B:
new_rf = 1;
break;
- case VSB_8:
+ case SYS_ATSC:
default:
new_rf = 0;
break;
@@ -827,7 +839,9 @@ static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
}
static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+ const u32 delsys,
+ const u32 freq,
+ const u32 bw)
{
/* This function returns the tuned frequency on success, 0 on error */
struct tuner_simple_priv *priv = fe->tuner_priv;
@@ -836,7 +850,7 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
u8 config, cb;
u32 div;
int ret;
- unsigned frequency = params->frequency / 62500;
+ u32 frequency = freq / 62500;
if (!tun->stepsize) {
/* tuner-core was loaded before the digital tuner was
@@ -860,7 +874,7 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
buf[2] = config;
buf[3] = cb;
- simple_set_dvb(fe, buf, params);
+ simple_set_dvb(fe, buf, delsys, freq, bw);
tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
tun->name, div, buf[0], buf[1], buf[2], buf[3]);
@@ -870,32 +884,37 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
}
static int simple_dvb_calc_regs(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
u8 *buf, int buf_len)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
struct tuner_simple_priv *priv = fe->tuner_priv;
u32 frequency;
if (buf_len < 5)
return -EINVAL;
- frequency = simple_dvb_configure(fe, buf+1, params);
+ frequency = simple_dvb_configure(fe, buf+1, delsys, c->frequency, bw);
if (frequency == 0)
return -EINVAL;
buf[0] = priv->i2c_props.addr;
priv->frequency = frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
+ priv->bandwidth = c->bandwidth_hz;
return 5;
}
-static int simple_dvb_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int simple_dvb_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
+ u32 freq = c->frequency;
struct tuner_simple_priv *priv = fe->tuner_priv;
+ u32 frequency;
u32 prev_freq, prev_bw;
int ret;
u8 buf[5];
@@ -906,9 +925,14 @@ static int simple_dvb_set_params(struct dvb_frontend *fe,
prev_freq = priv->frequency;
prev_bw = priv->bandwidth;
- ret = simple_dvb_calc_regs(fe, params, buf, 5);
- if (ret != 5)
- goto fail;
+ frequency = simple_dvb_configure(fe, buf+1, delsys, freq, bw);
+ if (frequency == 0)
+ return -EINVAL;
+
+ buf[0] = priv->i2c_props.addr;
+
+ priv->frequency = frequency;
+ priv->bandwidth = bw;
/* put analog demod in standby when tuning digital */
if (fe->ops.analog_ops.standby)
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 3acbaa0..2755599 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -311,7 +311,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
n_array, fname, name,
priv->firm_version >> 8, priv->firm_version & 0xff);
- priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+ priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
if (priv->firm == NULL) {
tuner_err("Not enough memory to load firmware file.\n");
rc = -ENOMEM;
@@ -891,7 +891,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
/* Frequency is locked */
if (frq_lock == 1)
- signal = 32768;
+ signal = 1 << 11;
/* Get SNR of the video signal */
rc = xc2028_get_reg(priv, 0x0040, &signal);
@@ -962,14 +962,24 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
* For DTV 7/8, the firmware uses BW = 8000, so it needs a
* further adjustment to get the frequency center on VHF
*/
+
+ /*
+ * The firmware DTV78 used to work fine in UHF band (8 MHz
+ * bandwidth) but not at all in VHF band (7 MHz bandwidth).
+ * The real problem was connected to the formula used to
+ * calculate the center frequency offset in VHF band.
+ * In fact, removing the 500KHz adjustment fixed the problem.
+ * This is coherent to what was implemented for the DTV7
+ * firmware.
+ * In the end, now the center frequency is the same for all 3
+ * firmwares (DTV7, DTV8, DTV78) and doesn't depend on channel
+ * bandwidth.
+ */
+
if (priv->cur_fw.type & DTV6)
offset = 1750000;
- else if (priv->cur_fw.type & DTV7)
- offset = 2250000;
- else /* DTV8 or DTV78 */
+ else /* DTV7 or DTV8 or DTV78 */
offset = 2750000;
- if ((priv->cur_fw.type & DTV78) && freq < 470000000)
- offset -= 500000;
/*
* xc3028 additional "magic"
@@ -979,17 +989,13 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
* newer firmwares
*/
-#if 1
/*
* The proper adjustment would be to do it at s-code table.
* However, this didn't work, as reported by
* Robert Lowery <rglowery@exemail.com.au>
*/
- if (priv->cur_fw.type & DTV7)
- offset += 500000;
-
-#else
+#if 0
/*
* Still need tests for XC3028L (firmware 3.2 or upper)
* So, for now, let's just comment the per-firmware
@@ -1084,68 +1090,28 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
V4L2_TUNER_ANALOG_TV, type, p->std, 0);
}
-static int xc2028_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int xc2028_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
struct xc2028_data *priv = fe->tuner_priv;
unsigned int type=0;
- fe_bandwidth_t bw = BANDWIDTH_8_MHZ;
u16 demod = 0;
tuner_dbg("%s called\n", __func__);
- switch(fe->ops.info.type) {
- case FE_OFDM:
- bw = p->u.ofdm.bandwidth;
+ switch (delsys) {
+ case SYS_DVBT:
+ case SYS_DVBT2:
/*
* The only countries with 6MHz seem to be Taiwan/Uruguay.
* Both seem to require QAM firmware for OFDM decoding
* Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
*/
- if (bw == BANDWIDTH_6_MHZ)
+ if (bw <= 6000000)
type |= QAM;
- break;
- case FE_ATSC:
- bw = BANDWIDTH_6_MHZ;
- /* The only ATSC firmware (at least on v2.7) is D2633 */
- type |= ATSC | D2633;
- break;
- /* DVB-S and pure QAM (FE_QAM) are not supported */
- default:
- return -EINVAL;
- }
-
- switch (bw) {
- case BANDWIDTH_8_MHZ:
- if (p->frequency < 470000000)
- priv->ctrl.vhfbw7 = 0;
- else
- priv->ctrl.uhfbw8 = 1;
- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
- type |= F8MHZ;
- break;
- case BANDWIDTH_7_MHZ:
- if (p->frequency < 470000000)
- priv->ctrl.vhfbw7 = 1;
- else
- priv->ctrl.uhfbw8 = 0;
- type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
- type |= F8MHZ;
- break;
- case BANDWIDTH_6_MHZ:
- type |= DTV6;
- priv->ctrl.vhfbw7 = 0;
- priv->ctrl.uhfbw8 = 0;
- break;
- default:
- tuner_err("error: bandwidth not supported.\n");
- };
- /*
- Selects between D2633 or D2620 firmware.
- It doesn't make sense for ATSC, since it should be D2633 on all cases
- */
- if (fe->ops.info.type != FE_ATSC) {
switch (priv->ctrl.type) {
case XC2028_D2633:
type |= D2633;
@@ -1161,6 +1127,34 @@ static int xc2028_set_params(struct dvb_frontend *fe,
else
type |= D2620;
}
+ break;
+ case SYS_ATSC:
+ /* The only ATSC firmware (at least on v2.7) is D2633 */
+ type |= ATSC | D2633;
+ break;
+ /* DVB-S and pure QAM (FE_QAM) are not supported */
+ default:
+ return -EINVAL;
+ }
+
+ if (bw <= 6000000) {
+ type |= DTV6;
+ priv->ctrl.vhfbw7 = 0;
+ priv->ctrl.uhfbw8 = 0;
+ } else if (bw <= 7000000) {
+ if (c->frequency < 470000000)
+ priv->ctrl.vhfbw7 = 1;
+ else
+ priv->ctrl.uhfbw8 = 0;
+ type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
+ type |= F8MHZ;
+ } else {
+ if (c->frequency < 470000000)
+ priv->ctrl.vhfbw7 = 0;
+ else
+ priv->ctrl.uhfbw8 = 1;
+ type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
+ type |= F8MHZ;
}
/* All S-code tables need a 200kHz shift */
@@ -1185,7 +1179,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
*/
}
- return generic_set_freq(fe, p->frequency,
+ return generic_set_freq(fe, c->frequency,
V4L2_TUNER_DIGITAL_TV, type, 0, demod);
}
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
index 634f4d9..d218c1d 100644
--- a/drivers/media/common/tuners/xc4000.c
+++ b/drivers/media/common/tuners/xc4000.c
@@ -758,7 +758,7 @@ static int xc4000_fwupload(struct dvb_frontend *fe)
n_array, fname, name,
priv->firm_version >> 8, priv->firm_version & 0xff);
- priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+ priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
if (priv->firm == NULL) {
printk(KERN_ERR "Not enough memory to load firmware file.\n");
rc = -ENOMEM;
@@ -1121,83 +1121,62 @@ static void xc_debug_dump(struct xc4000_priv *priv)
dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
}
-static int xc4000_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int xc4000_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ u32 bw = c->bandwidth_hz;
struct xc4000_priv *priv = fe->tuner_priv;
unsigned int type;
int ret = -EREMOTEIO;
- dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+ dprintk(1, "%s() frequency=%d (Hz)\n", __func__, c->frequency);
mutex_lock(&priv->lock);
- if (fe->ops.info.type == FE_ATSC) {
- dprintk(1, "%s() ATSC\n", __func__);
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- dprintk(1, "%s() VSB modulation\n", __func__);
- priv->rf_mode = XC_RF_MODE_AIR;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = XC4000_DTV6;
- type = DTV6;
- break;
- case QAM_64:
- case QAM_256:
- case QAM_AUTO:
- dprintk(1, "%s() QAM modulation\n", __func__);
- priv->rf_mode = XC_RF_MODE_CABLE;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = XC4000_DTV6;
- type = DTV6;
- break;
- default:
- ret = -EINVAL;
- goto fail;
- }
- } else if (fe->ops.info.type == FE_OFDM) {
+ switch (delsys) {
+ case SYS_ATSC:
+ dprintk(1, "%s() VSB modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_AIR;
+ priv->freq_hz = c->frequency - 1750000;
+ priv->video_standard = XC4000_DTV6;
+ type = DTV6;
+ break;
+ case SYS_DVBC_ANNEX_B:
+ dprintk(1, "%s() QAM modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_CABLE;
+ priv->freq_hz = c->frequency - 1750000;
+ priv->video_standard = XC4000_DTV6;
+ type = DTV6;
+ break;
+ case SYS_DVBT:
+ case SYS_DVBT2:
dprintk(1, "%s() OFDM\n", __func__);
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- priv->bandwidth = BANDWIDTH_6_MHZ;
+ if (bw == 0) {
+ if (c->frequency < 400000000) {
+ priv->freq_hz = c->frequency - 2250000;
+ } else {
+ priv->freq_hz = c->frequency - 2750000;
+ }
+ priv->video_standard = XC4000_DTV7_8;
+ type = DTV78;
+ } else if (bw <= 6000000) {
priv->video_standard = XC4000_DTV6;
- priv->freq_hz = params->frequency - 1750000;
+ priv->freq_hz = c->frequency - 1750000;
type = DTV6;
- break;
- case BANDWIDTH_7_MHZ:
- priv->bandwidth = BANDWIDTH_7_MHZ;
+ } else if (bw <= 7000000) {
priv->video_standard = XC4000_DTV7;
- priv->freq_hz = params->frequency - 2250000;
+ priv->freq_hz = c->frequency - 2250000;
type = DTV7;
- break;
- case BANDWIDTH_8_MHZ:
- priv->bandwidth = BANDWIDTH_8_MHZ;
+ } else {
priv->video_standard = XC4000_DTV8;
- priv->freq_hz = params->frequency - 2750000;
+ priv->freq_hz = c->frequency - 2750000;
type = DTV8;
- break;
- case BANDWIDTH_AUTO:
- if (params->frequency < 400000000) {
- priv->bandwidth = BANDWIDTH_7_MHZ;
- priv->freq_hz = params->frequency - 2250000;
- } else {
- priv->bandwidth = BANDWIDTH_8_MHZ;
- priv->freq_hz = params->frequency - 2750000;
- }
- priv->video_standard = XC4000_DTV7_8;
- type = DTV78;
- break;
- default:
- printk(KERN_ERR "xc4000 bandwidth not set!\n");
- ret = -EINVAL;
- goto fail;
}
priv->rf_mode = XC_RF_MODE_AIR;
- } else {
- printk(KERN_ERR "xc4000 modulation type not supported!\n");
+ break;
+ default:
+ printk(KERN_ERR "xc4000 delivery system not supported!\n");
ret = -EINVAL;
goto fail;
}
@@ -1209,6 +1188,8 @@ static int xc4000_set_params(struct dvb_frontend *fe,
if (check_firmware(fe, type, 0, priv->if_khz) != 0)
goto fail;
+ priv->bandwidth = c->bandwidth_hz;
+
ret = xc_set_signal_source(priv, priv->rf_mode);
if (ret != 0) {
printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
@@ -1605,7 +1586,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
break;
case 1:
/* new tuner instance */
- priv->bandwidth = BANDWIDTH_6_MHZ;
+ priv->bandwidth = 6000000;
/* set default configuration */
priv->if_khz = 4560;
priv->default_pm = 0;
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index aa1b2e8..296df05 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -628,20 +628,13 @@ static void xc_debug_dump(struct xc5000_priv *priv)
dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
}
-/*
- * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
- * Bw = Symbol_rate * (1 + 0.15)
- * As such, the maximum symbol rate supported by 6 MHz is given by:
- * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
- */
-#define MAX_SYMBOL_RATE_6MHz 5217391
-
-static int xc5000_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int xc5000_set_params(struct dvb_frontend *fe)
{
+ int ret, b;
struct xc5000_priv *priv = fe->tuner_priv;
- int ret;
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ 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) {
@@ -650,88 +643,69 @@ static int xc5000_set_params(struct dvb_frontend *fe,
}
}
- dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
-
- if (fe->ops.info.type == FE_ATSC) {
- dprintk(1, "%s() ATSC\n", __func__);
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- dprintk(1, "%s() VSB modulation\n", __func__);
- priv->rf_mode = XC_RF_MODE_AIR;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = DTV6;
- break;
- case QAM_64:
- case QAM_256:
- case QAM_AUTO:
- dprintk(1, "%s() QAM modulation\n", __func__);
- priv->rf_mode = XC_RF_MODE_CABLE;
- priv->freq_hz = params->frequency - 1750000;
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = DTV6;
- break;
- default:
- return -EINVAL;
- }
- } else if (fe->ops.info.type == FE_OFDM) {
+ dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
+
+ switch (delsys) {
+ case SYS_ATSC:
+ dprintk(1, "%s() VSB modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_AIR;
+ priv->freq_hz = freq - 1750000;
+ priv->video_standard = DTV6;
+ break;
+ case SYS_DVBC_ANNEX_B:
+ dprintk(1, "%s() QAM modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_CABLE;
+ priv->freq_hz = freq - 1750000;
+ priv->video_standard = DTV6;
+ break;
+ case SYS_DVBT:
+ case SYS_DVBT2:
dprintk(1, "%s() OFDM\n", __func__);
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- priv->bandwidth = BANDWIDTH_6_MHZ;
+ switch (bw) {
+ case 6000000:
priv->video_standard = DTV6;
- priv->freq_hz = params->frequency - 1750000;
+ priv->freq_hz = freq - 1750000;
break;
- case BANDWIDTH_7_MHZ:
- printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n");
- return -EINVAL;
- case BANDWIDTH_8_MHZ:
- priv->bandwidth = BANDWIDTH_8_MHZ;
+ case 7000000:
+ priv->video_standard = DTV7;
+ priv->freq_hz = freq - 2250000;
+ break;
+ case 8000000:
priv->video_standard = DTV8;
- priv->freq_hz = params->frequency - 2750000;
+ priv->freq_hz = freq - 2750000;
break;
default:
printk(KERN_ERR "xc5000 bandwidth not set!\n");
return -EINVAL;
}
priv->rf_mode = XC_RF_MODE_AIR;
- } else if (fe->ops.info.type == FE_QAM) {
- switch (params->u.qam.modulation) {
- case QAM_256:
- case QAM_AUTO:
- case QAM_16:
- case QAM_32:
- case QAM_64:
- case QAM_128:
- dprintk(1, "%s() QAM modulation\n", __func__);
- priv->rf_mode = XC_RF_MODE_CABLE;
- /*
- * Using a 8MHz bandwidth sometimes fail
- * with 6MHz-spaced channels, due to inter-carrier
- * interference. So, use DTV6 firmware
- */
- if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) {
- priv->bandwidth = BANDWIDTH_6_MHZ;
- priv->video_standard = DTV6;
- priv->freq_hz = params->frequency - 1750000;
- } else {
- priv->bandwidth = BANDWIDTH_8_MHZ;
- priv->video_standard = DTV7_8;
- priv->freq_hz = params->frequency - 2750000;
- }
- break;
- default:
- dprintk(1, "%s() Unsupported QAM type\n", __func__);
- return -EINVAL;
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ dprintk(1, "%s() QAM modulation\n", __func__);
+ priv->rf_mode = XC_RF_MODE_CABLE;
+ if (bw <= 6000000) {
+ priv->video_standard = DTV6;
+ priv->freq_hz = freq - 1750000;
+ b = 6;
+ } else if (bw <= 7000000) {
+ priv->video_standard = DTV7;
+ priv->freq_hz = freq - 2250000;
+ b = 7;
+ } else {
+ priv->video_standard = DTV7_8;
+ priv->freq_hz = freq - 2750000;
+ b = 8;
}
- } else {
- printk(KERN_ERR "xc5000 modulation type not supported!\n");
+ dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
+ b, bw);
+ break;
+ default:
+ printk(KERN_ERR "xc5000: delivery system is not supported!\n");
return -EINVAL;
}
- dprintk(1, "%s() frequency=%d (compensated)\n",
- __func__, priv->freq_hz);
+ dprintk(1, "%s() frequency=%d (compensated to %d)\n",
+ __func__, freq, priv->freq_hz);
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
@@ -763,6 +737,8 @@ static int xc5000_set_params(struct dvb_frontend *fe,
if (debug)
xc_debug_dump(priv);
+ priv->bandwidth = bw;
+
return 0;
}
@@ -968,6 +944,14 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
return 0;
}
+static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+ struct xc5000_priv *priv = fe->tuner_priv;
+ dprintk(1, "%s()\n", __func__);
+ *freq = priv->if_khz * 1000;
+ return 0;
+}
+
static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
{
struct xc5000_priv *priv = fe->tuner_priv;
@@ -1108,6 +1092,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
.set_params = xc5000_set_params,
.set_analog_params = xc5000_set_analog_params,
.get_frequency = xc5000_get_frequency,
+ .get_if_frequency = xc5000_get_if_frequency,
.get_bandwidth = xc5000_get_bandwidth,
.get_status = xc5000_get_status
};
@@ -1135,7 +1120,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
break;
case 1:
/* new tuner instance */
- priv->bandwidth = BANDWIDTH_6_MHZ;
+ priv->bandwidth = 6000000;
fe->tuner_priv = priv;
break;
default:
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 2df1b02..b1e8c99 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -86,7 +86,8 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
fc->demux.stop_feed = flexcop_dvb_stop_feed;
fc->demux.write_to_decoder = NULL;
- if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
+ ret = dvb_dmx_init(&fc->demux);
+ if (ret < 0) {
err("dvb_dmx failed: error %d", ret);
goto err_dmx;
}
@@ -96,32 +97,42 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
fc->dmxdev.filternum = fc->demux.feednum;
fc->dmxdev.demux = &fc->demux.dmx;
fc->dmxdev.capabilities = 0;
- if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
+ ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter);
+ if (ret < 0) {
err("dvb_dmxdev_init failed: error %d", ret);
goto err_dmx_dev;
}
- if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+ ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend);
+ if (ret < 0) {
err("adding hw_frontend to dmx failed: error %d", ret);
goto err_dmx_add_hw_frontend;
}
fc->mem_frontend.source = DMX_MEMORY_FE;
- if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) {
+ ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend);
+ if (ret < 0) {
err("adding mem_frontend to dmx failed: error %d", ret);
goto err_dmx_add_mem_frontend;
}
- if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+ ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend);
+ if (ret < 0) {
err("connect frontend failed: error %d", ret);
goto err_connect_frontend;
}
- dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+ ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+ if (ret < 0) {
+ err("dvb_net_init failed: error %d", ret);
+ goto err_net;
+ }
fc->init_state |= FC_STATE_DVB_INIT;
return 0;
+err_net:
+ fc->demux.dmx.disconnect_frontend(&fc->demux.dmx);
err_connect_frontend:
fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend);
err_dmx_add_mem_frontend:
@@ -254,7 +265,8 @@ int flexcop_device_initialize(struct flexcop_device *fc)
flexcop_hw_filter_init(fc);
flexcop_smc_ctrl(fc, 0);
- if ((ret = flexcop_dvb_init(fc)))
+ ret = flexcop_dvb_init(fc);
+ if (ret)
goto error;
/* i2c has to be done before doing EEProm stuff -
@@ -272,7 +284,8 @@ int flexcop_device_initialize(struct flexcop_device *fc)
} else
warn("reading of MAC address failed.\n");
- if ((ret = flexcop_frontend_init(fc)))
+ ret = flexcop_frontend_init(fc);
+ if (ret)
goto error;
flexcop_device_name(fc,"initialization of","complete");
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index caa4e18..430b3eb 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -386,7 +386,7 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
return 0;
}
-static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
+static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
{
state->bandwidth = bandwidth;
@@ -394,7 +394,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
return -EOPNOTSUPP;
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
if (state->dst_hw_cap & DST_TYPE_HAS_CA)
state->tx_tuna[7] = 0x06;
else {
@@ -402,7 +402,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
state->tx_tuna[7] = 0x00;
}
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
if (state->dst_hw_cap & DST_TYPE_HAS_CA)
state->tx_tuna[7] = 0x07;
else {
@@ -410,7 +410,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
state->tx_tuna[7] = 0x00;
}
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
if (state->dst_hw_cap & DST_TYPE_HAS_CA)
state->tx_tuna[7] = 0x08;
else {
@@ -1561,7 +1561,7 @@ static int dst_init(struct dvb_frontend *fe)
state->tone = SEC_TONE_OFF;
state->diseq_flags = 0;
state->k22 = 0x02;
- state->bandwidth = BANDWIDTH_7_MHZ;
+ state->bandwidth = 7000000;
state->cur_jiff = jiffies;
if (state->dst_type == DST_TYPE_IS_SAT)
memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
@@ -1609,8 +1609,9 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
return retval;
}
-static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int retval = -EINVAL;
struct dst_state *state = fe->demodulator_priv;
@@ -1623,17 +1624,17 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
- dst_set_fec(state, p->u.qpsk.fec_inner);
- dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ dst_set_fec(state, p->fec_inner);
+ dst_set_symbolrate(state, p->symbol_rate);
dst_set_polarization(state);
- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
} else if (state->dst_type == DST_TYPE_IS_TERR)
- dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+ dst_set_bandwidth(state, p->bandwidth_hz);
else if (state->dst_type == DST_TYPE_IS_CABLE) {
- dst_set_fec(state, p->u.qam.fec_inner);
- dst_set_symbolrate(state, p->u.qam.symbol_rate);
- dst_set_modulation(state, p->u.qam.modulation);
+ dst_set_fec(state, p->fec_inner);
+ dst_set_symbolrate(state, p->symbol_rate);
+ dst_set_modulation(state, p->modulation);
}
retval = dst_write_tuna(fe);
}
@@ -1642,31 +1643,32 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
}
static int dst_tune_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* p,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
- if (p != NULL) {
+ if (re_tune) {
dst_set_freq(state, p->frequency);
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
- dst_set_fec(state, p->u.qpsk.fec_inner);
- dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ dst_set_fec(state, p->fec_inner);
+ dst_set_symbolrate(state, p->symbol_rate);
dst_set_polarization(state);
- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
} else if (state->dst_type == DST_TYPE_IS_TERR)
- dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+ dst_set_bandwidth(state, p->bandwidth_hz);
else if (state->dst_type == DST_TYPE_IS_CABLE) {
- dst_set_fec(state, p->u.qam.fec_inner);
- dst_set_symbolrate(state, p->u.qam.symbol_rate);
- dst_set_modulation(state, p->u.qam.modulation);
+ dst_set_fec(state, p->fec_inner);
+ dst_set_symbolrate(state, p->symbol_rate);
+ dst_set_modulation(state, p->modulation);
}
dst_write_tuna(fe);
}
@@ -1683,22 +1685,23 @@ static int dst_get_tuning_algo(struct dvb_frontend *fe)
return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
}
-static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dst_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct dst_state *state = fe->demodulator_priv;
p->frequency = state->decode_freq;
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
p->inversion = state->inversion;
- p->u.qpsk.symbol_rate = state->symbol_rate;
- p->u.qpsk.fec_inner = dst_get_fec(state);
+ p->symbol_rate = state->symbol_rate;
+ p->fec_inner = dst_get_fec(state);
} else if (state->dst_type == DST_TYPE_IS_TERR) {
- p->u.ofdm.bandwidth = state->bandwidth;
+ p->bandwidth_hz = state->bandwidth;
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
- p->u.qam.symbol_rate = state->symbol_rate;
- p->u.qam.fec_inner = dst_get_fec(state);
- p->u.qam.modulation = dst_get_modulation(state);
+ p->symbol_rate = state->symbol_rate;
+ p->fec_inner = dst_get_fec(state);
+ p->modulation = dst_get_modulation(state);
}
return 0;
@@ -1756,10 +1759,9 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
EXPORT_SYMBOL(dst_attach);
static struct dvb_frontend_ops dst_dvbt_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "DST DVB-T",
- .type = FE_OFDM,
.frequency_min = 137000000,
.frequency_max = 858000000,
.frequency_stepsize = 166667,
@@ -1786,10 +1788,9 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
};
static struct dvb_frontend_ops dst_dvbs_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "DST DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1000, /* kHz for QPSK frontends */
@@ -1816,10 +1817,9 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
};
static struct dvb_frontend_ops dst_dvbc_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "DST DVB-C",
- .type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 51000000,
.frequency_max = 858000000,
@@ -1846,9 +1846,9 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
};
static struct dvb_frontend_ops dst_atsc_ops = {
+ .delsys = { SYS_ATSC },
.info = {
.name = "DST ATSC",
- .type = FE_ATSC,
.frequency_stepsize = 62500,
.frequency_min = 510000000,
.frequency_max = 858000000,
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index d88cf2a..d70d98f 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -124,7 +124,7 @@ struct dst_state {
u16 decode_snr;
unsigned long cur_jiff;
u8 k22;
- fe_bandwidth_t bandwidth;
+ u32 bandwidth;
u32 dst_hw_cap;
u8 dst_fw_version;
fe_sec_mini_cmd_t minicmd;
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 521d691..81fab9a 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -19,6 +19,8 @@
*
*/
+#define pr_fmt(fmt) "dvb_bt8xx: " fmt
+
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -148,8 +150,9 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend *fe, u8* pllbuf, int buf_len)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
@@ -157,18 +160,18 @@ static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_f
if (buf_len < 5)
return -EINVAL;
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+ div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 542000000)
+ if (c->frequency < 542000000)
cp = 0xb4;
- else if (params->frequency < 771000000)
+ else if (c->frequency < 771000000)
cp = 0xbc;
else
cp = 0xf4;
- if (params->frequency == 0)
+ if (c->frequency == 0)
bs = 0x03;
- else if (params->frequency < 443250000)
+ else if (c->frequency < 443250000)
bs = 0x02;
else
bs = 0x08;
@@ -191,13 +194,12 @@ static struct zl10353_config thomson_dtt7579_zl10353_config = {
.demod_address = 0x0f,
};
-static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int cx24108_tuner_set_params(struct dvb_frontend *fe)
{
- u32 freq = params->frequency;
-
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 freq = c->frequency;
int i, a, n, pump;
u32 band, pll;
-
u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
1576000,1718000,1856000,2036000,2150000};
u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
@@ -205,7 +207,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
0x00120000,0x00140000};
#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
- printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
+ dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq);
/* This is really the bit driving the tuner chip cx24108 */
@@ -216,7 +218,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
/* decide which VCO to use for the input frequency */
for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++);
- printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
+ dprintk("cx24108 debug: select vco #%d (f=%d)\n", i, freq);
band=bandsel[i];
/* the gain values must be set by SetSymbolrate */
/* compute the pll divider needed, from Conexant data sheet,
@@ -232,7 +234,7 @@ static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend
((a&0x1f)<<11);
/* everything is shifted left 11 bits to left-align the bits in the
32bit word. Output to the tuner goes MSB-aligned, after all */
- printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
+ dprintk("cx24108 debug: pump=%d, n=%d, a=%d\n", pump, n, a);
cx24110_pll_write(fe,band);
/* set vga and vca to their widest-band settings, as a precaution.
SetSymbolrate might not be called to set this up */
@@ -267,31 +269,32 @@ static struct cx24110_config pctvsat_config = {
.demod_address = 0x55,
};
-static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 cfg, cpump, band_select;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (36000000 + params->frequency + 83333) / 166666;
+ div = (36000000 + c->frequency + 83333) / 166666;
cfg = 0x88;
- if (params->frequency < 175000000)
+ if (c->frequency < 175000000)
cpump = 2;
- else if (params->frequency < 390000000)
+ else if (c->frequency < 390000000)
cpump = 1;
- else if (params->frequency < 470000000)
+ else if (c->frequency < 470000000)
cpump = 2;
- else if (params->frequency < 750000000)
+ else if (c->frequency < 750000000)
cpump = 2;
else
cpump = 3;
- if (params->frequency < 175000000)
+ if (c->frequency < 175000000)
band_select = 0x0e;
- else if (params->frequency < 470000000)
+ else if (c->frequency < 470000000)
band_select = 0x05;
else
band_select = 0x03;
@@ -342,50 +345,51 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend *fe, u8 *pllbuf, int buf_len)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
if (buf_len < 5) return -EINVAL;
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+ div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- if (params->frequency < 150000000)
+ if (c->frequency < 150000000)
cp = 0xB4;
- else if (params->frequency < 173000000)
+ else if (c->frequency < 173000000)
cp = 0xBC;
- else if (params->frequency < 250000000)
+ else if (c->frequency < 250000000)
cp = 0xB4;
- else if (params->frequency < 400000000)
+ else if (c->frequency < 400000000)
cp = 0xBC;
- else if (params->frequency < 420000000)
+ else if (c->frequency < 420000000)
cp = 0xF4;
- else if (params->frequency < 470000000)
+ else if (c->frequency < 470000000)
cp = 0xFC;
- else if (params->frequency < 600000000)
+ else if (c->frequency < 600000000)
cp = 0xBC;
- else if (params->frequency < 730000000)
+ else if (c->frequency < 730000000)
cp = 0xF4;
else
cp = 0xFC;
- if (params->frequency < 150000000)
+ if (c->frequency < 150000000)
bs = 0x01;
- else if (params->frequency < 173000000)
+ else if (c->frequency < 173000000)
bs = 0x01;
- else if (params->frequency < 250000000)
+ else if (c->frequency < 250000000)
bs = 0x02;
- else if (params->frequency < 400000000)
+ else if (c->frequency < 400000000)
bs = 0x02;
- else if (params->frequency < 420000000)
+ else if (c->frequency < 420000000)
bs = 0x02;
- else if (params->frequency < 470000000)
+ else if (c->frequency < 470000000)
bs = 0x02;
- else if (params->frequency < 600000000)
+ else if (c->frequency < 600000000)
bs = 0x08;
- else if (params->frequency < 730000000)
+ else if (c->frequency < 730000000)
bs = 0x08;
else
bs = 0x08;
@@ -461,25 +465,26 @@ static struct or51211_config or51211_config = {
.sleep = or51211_sleep,
};
-static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
- div = (params->frequency + 36166667) / 166667;
+ div = (c->frequency + 36166667) / 166667;
buf[0] = (div >> 8) & 0x7F;
buf[1] = div & 0xFF;
buf[2] = 0x85;
- if ((params->frequency >= 47000000) && (params->frequency < 153000000))
+ if ((c->frequency >= 47000000) && (c->frequency < 153000000))
buf[3] = 0x01;
- else if ((params->frequency >= 153000000) && (params->frequency < 430000000))
+ else if ((c->frequency >= 153000000) && (c->frequency < 430000000))
buf[3] = 0x02;
- else if ((params->frequency >= 430000000) && (params->frequency < 824000000))
+ else if ((c->frequency >= 430000000) && (c->frequency < 824000000))
buf[3] = 0x0C;
- else if ((params->frequency >= 824000000) && (params->frequency < 863000000))
+ else if ((c->frequency >= 824000000) && (c->frequency < 863000000))
buf[3] = 0x8C;
else
return -EINVAL;
@@ -513,31 +518,31 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend *fe, u8 *pllbuf, int buf_len)
{
u32 div;
- struct dvb_ofdm_parameters *op = &params->u.ofdm;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
if (buf_len < 5)
return -EINVAL;
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+ div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
pllbuf[0] = 0x61;
pllbuf[1] = (div >> 8) & 0x7F;
pllbuf[2] = div & 0xFF;
pllbuf[3] = 0x85;
- dprintk("frequency %u, div %u\n", params->frequency, div);
+ dprintk("frequency %u, div %u\n", c->frequency, div);
- if (params->frequency < 470000000)
+ if (c->frequency < 470000000)
pllbuf[4] = 0x02;
- else if (params->frequency > 823000000)
+ else if (c->frequency > 823000000)
pllbuf[4] = 0x88;
else
pllbuf[4] = 0x08;
- if (op->bandwidth == 8)
+ if (c->bandwidth_hz == 8000000)
pllbuf[4] |= 0x04;
return 5;
@@ -663,7 +668,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
/* DST is not a frontend driver !!! */
state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
if (!state) {
- printk("dvb_bt8xx: No memory\n");
+ pr_err("No memory\n");
break;
}
/* Setup the Card */
@@ -673,7 +678,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
state->dst_ca = NULL;
/* DST is not a frontend, attaching the ASIC */
if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
- printk("%s: Could not find a Twinhan DST.\n", __func__);
+ pr_err("%s: Could not find a Twinhan DST\n", __func__);
break;
}
/* Attach other DST peripherals if any */
@@ -702,14 +707,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
}
if (card->fe == NULL)
- printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
card->bt->dev->vendor,
card->bt->dev->device,
card->bt->dev->subsystem_vendor,
card->bt->dev->subsystem_device);
else
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
- printk("dvb-bt8xx: Frontend registration failed!\n");
+ pr_err("Frontend registration failed!\n");
dvb_frontend_detach(card->fe);
card->fe = NULL;
}
@@ -723,7 +728,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
THIS_MODULE, &card->bt->dev->dev,
adapter_nr);
if (result < 0) {
- printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
+ pr_err("dvb_register_adapter failed (errno = %d)\n", result);
return result;
}
card->dvb_adapter.priv = card;
@@ -741,66 +746,69 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->demux.stop_feed = dvb_bt8xx_stop_feed;
card->demux.write_to_decoder = NULL;
- if ((result = dvb_dmx_init(&card->demux)) < 0) {
- printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
- dvb_unregister_adapter(&card->dvb_adapter);
- return result;
+ result = dvb_dmx_init(&card->demux);
+ if (result < 0) {
+ pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+ goto err_unregister_adaptor;
}
card->dmxdev.filternum = 256;
card->dmxdev.demux = &card->demux.dmx;
card->dmxdev.capabilities = 0;
- if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) {
- printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
-
- dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(&card->dvb_adapter);
- return result;
+ result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter);
+ if (result < 0) {
+ pr_err("dvb_dmxdev_init failed (errno = %d)\n", result);
+ goto err_dmx_release;
}
card->fe_hw.source = DMX_FRONTEND_0;
- if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
- printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
- dvb_dmxdev_release(&card->dmxdev);
- dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(&card->dvb_adapter);
- return result;
+ result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw);
+ if (result < 0) {
+ pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+ goto err_dmxdev_release;
}
card->fe_mem.source = DMX_MEMORY_FE;
- if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {
- printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
- card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
- dvb_dmxdev_release(&card->dmxdev);
- dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(&card->dvb_adapter);
- return result;
+ result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem);
+ if (result < 0) {
+ pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+ goto err_remove_hw_frontend;
}
- if ((result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
- printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
-
- card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
- card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
- dvb_dmxdev_release(&card->dmxdev);
- dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(&card->dvb_adapter);
- return result;
+ result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw);
+ if (result < 0) {
+ pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+ goto err_remove_mem_frontend;
}
- dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+ result = dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+ if (result < 0) {
+ pr_err("dvb_net_init failed (errno = %d)\n", result);
+ goto err_disconnect_frontend;
+ }
tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
frontend_init(card, type);
return 0;
+
+err_disconnect_frontend:
+ card->demux.dmx.disconnect_frontend(&card->demux.dmx);
+err_remove_mem_frontend:
+ card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+err_remove_hw_frontend:
+ card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+err_dmxdev_release:
+ dvb_dmxdev_release(&card->dmxdev);
+err_dmx_release:
+ dvb_dmx_release(&card->demux);
+err_unregister_adaptor:
+ dvb_unregister_adapter(&card->dvb_adapter);
+ return result;
}
static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
@@ -881,8 +889,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
break;
default:
- printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n",
- sub->core->type);
+ pr_err("Unknown bttv card type: %d\n", sub->core->type);
kfree(card);
return -ENODEV;
}
@@ -890,16 +897,14 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
- printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
+ pr_err("no pci device for card %d\n", card->bttv_nr);
kfree(card);
return -ENODEV;
}
if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
- printk("dvb_bt8xx: unable to determine DMA core of card %d,\n",
- card->bttv_nr);
- printk("dvb_bt8xx: if you have the ALSA bt87x audio driver "
- "installed, try removing it.\n");
+ pr_err("unable to determine DMA core of card %d,\n", card->bttv_nr);
+ pr_err("if you have the ALSA bt87x audio driver installed, try removing it.\n");
kfree(card);
return -ENODEV;
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c
index d1e91bc..ce4f858 100644
--- a/drivers/media/dvb/ddbridge/ddbridge-core.c
+++ b/drivers/media/dvb/ddbridge/ddbridge-core.c
@@ -580,7 +580,7 @@ static int demod_attach_drxk(struct ddb_input *input)
memset(&config, 0, sizeof(config));
config.adr = 0x29 + (input->nr & 1);
- fe = input->fe = dvb_attach(drxk_attach, &config, i2c, &input->fe2);
+ fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
if (!input->fe) {
printk(KERN_ERR "No DRXK found!\n");
return -ENODEV;
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 55e6533..a609b3a 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -1115,11 +1115,14 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
if (ret < 0)
goto err_remove_mem_frontend;
- ret = frontend_init(dev);
+ ret = dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
if (ret < 0)
goto err_disconnect_frontend;
- dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
+ ret = frontend_init(dev);
+ if (ret < 0)
+ goto err_dvb_net;
+
dm1105_ir_init(dev);
INIT_WORK(&dev->work, dm1105_dmx_buffer);
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 7ea517b..9be65a3 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1306,6 +1306,10 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
/* fragment the packets & store in the buffer */
while (fragpos < count) {
fraglen = ca->slot_info[slot].link_buf_size - 2;
+ if (fraglen < 0)
+ break;
+ if (fraglen > HOST_LINK_BUF_SIZE - 2)
+ fraglen = HOST_LINK_BUF_SIZE - 2;
if ((count - fragpos) < fraglen)
fraglen = count - fragpos;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 2c0acdb..b15db4f 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -25,6 +25,9 @@
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
+/* Enables DVBv3 compatibility bits at the headers */
+#define __DVB_CORE__
+
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -105,7 +108,6 @@ struct dvb_frontend_private {
/* thread/frontend values */
struct dvb_device *dvbdev;
- struct dvb_frontend_parameters parameters_in;
struct dvb_frontend_parameters parameters_out;
struct dvb_fe_events events;
struct semaphore sem;
@@ -139,6 +141,62 @@ struct dvb_frontend_private {
};
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
+static int dtv_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p_out);
+
+static bool has_get_frontend(struct dvb_frontend *fe)
+{
+ return fe->ops.get_frontend;
+}
+
+/*
+ * Due to DVBv3 API calls, a delivery system should be mapped into one of
+ * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
+ * otherwise, a DVBv3 call will fail.
+ */
+enum dvbv3_emulation_type {
+ DVBV3_UNKNOWN,
+ DVBV3_QPSK,
+ DVBV3_QAM,
+ DVBV3_OFDM,
+ DVBV3_ATSC,
+};
+
+static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
+{
+ switch (delivery_system) {
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ return DVBV3_QAM;
+ case SYS_DVBS:
+ case SYS_DVBS2:
+ case SYS_TURBO:
+ case SYS_ISDBS:
+ case SYS_DSS:
+ return DVBV3_QPSK;
+ case SYS_DVBT:
+ case SYS_DVBT2:
+ case SYS_ISDBT:
+ case SYS_DMBTH:
+ return DVBV3_OFDM;
+ case SYS_ATSC:
+ case SYS_DVBC_ANNEX_B:
+ return DVBV3_ATSC;
+ case SYS_UNDEFINED:
+ case SYS_ISDBC:
+ case SYS_DVBH:
+ case SYS_DAB:
+ case SYS_ATSCMH:
+ default:
+ /*
+ * Doesn't know how to emulate those types and/or
+ * there's no frontend driver from this type yet
+ * with some emulation code, so, we're not sure yet how
+ * to handle them, or they're not compatible with a DVBv3 call.
+ */
+ return DVBV3_UNKNOWN;
+ }
+}
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
{
@@ -149,8 +207,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
dprintk ("%s\n", __func__);
- if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
- fe->ops.get_frontend(fe, &fepriv->parameters_out);
+ if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
+ dtv_get_frontend(fe, &fepriv->parameters_out);
mutex_lock(&events->mtx);
@@ -277,12 +335,13 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
int ready = 0;
int fe_set_err = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- int original_inversion = fepriv->parameters_in.inversion;
- u32 original_frequency = fepriv->parameters_in.frequency;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
+ int original_inversion = c->inversion;
+ u32 original_frequency = c->frequency;
/* are we using autoinversion? */
autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters_in.inversion == INVERSION_AUTO));
+ (c->inversion == INVERSION_AUTO));
/* setup parameters correctly */
while(!ready) {
@@ -348,19 +407,20 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
/* set the frontend itself */
- fepriv->parameters_in.frequency += fepriv->lnb_drift;
+ c->frequency += fepriv->lnb_drift;
if (autoinversion)
- fepriv->parameters_in.inversion = fepriv->inversion;
+ c->inversion = fepriv->inversion;
+ tmp = *c;
if (fe->ops.set_frontend)
- fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in);
- fepriv->parameters_out = fepriv->parameters_in;
+ fe_set_err = fe->ops.set_frontend(fe);
+ *c = tmp;
if (fe_set_err < 0) {
fepriv->state = FESTATE_ERROR;
return fe_set_err;
}
- fepriv->parameters_in.frequency = original_frequency;
- fepriv->parameters_in.inversion = original_inversion;
+ c->frequency = original_frequency;
+ c->inversion = original_inversion;
fepriv->auto_sub_step++;
return 0;
@@ -371,6 +431,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
fe_status_t s = 0;
int retval = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
@@ -382,10 +443,10 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* in SCAN mode, we just set the frontend when asked and leave it alone */
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) {
+ tmp = *c;
if (fe->ops.set_frontend)
- retval = fe->ops.set_frontend(fe,
- &fepriv->parameters_in);
- fepriv->parameters_out = fepriv->parameters_in;
+ retval = fe->ops.set_frontend(fe);
+ *c = tmp;
if (retval < 0)
fepriv->state = FESTATE_ERROR;
else
@@ -415,8 +476,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* if we're tuned, then we have determined the correct inversion */
if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters_in.inversion == INVERSION_AUTO)) {
- fepriv->parameters_in.inversion = fepriv->inversion;
+ (c->inversion == INVERSION_AUTO)) {
+ c->inversion = fepriv->inversion;
}
return;
}
@@ -507,7 +568,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
return 1;
if (fepriv->dvbdev->writers == 1)
- if (time_after(jiffies, fepriv->release_jiffies +
+ if (time_after_eq(jiffies, fepriv->release_jiffies +
dvb_shutdown_timeout * HZ))
return 1;
@@ -540,7 +601,7 @@ static int dvb_frontend_thread(void *data)
fe_status_t s;
enum dvbfe_algo algo;
- struct dvb_frontend_parameters *params;
+ bool re_tune = false;
dprintk("%s\n", __func__);
@@ -589,18 +650,15 @@ restart:
switch (algo) {
case DVBFE_ALGO_HW:
dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
- params = NULL; /* have we been asked to RETUNE ? */
if (fepriv->state & FESTATE_RETUNE) {
dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
- params = &fepriv->parameters_in;
+ re_tune = true;
fepriv->state = FESTATE_TUNED;
}
if (fe->ops.tune)
- fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
- if (params)
- fepriv->parameters_out = *params;
+ 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__);
@@ -624,7 +682,7 @@ restart:
*/
if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
if (fe->ops.search) {
- fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in);
+ fepriv->algo_status = fe->ops.search(fe);
/* We did do a search as was requested, the flags are
* now unset as well and has the flags wrt to search.
*/
@@ -633,14 +691,10 @@ restart:
}
}
/* Track the carrier if the search was successful */
- if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
- if (fe->ops.track)
- fe->ops.track(fe, &fepriv->parameters_in);
- } else {
+ if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) {
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
fepriv->delay = HZ / 2;
}
- fepriv->parameters_out = fepriv->parameters_in;
fe->ops.read_status(fe, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s); /* update event list */
@@ -807,52 +861,40 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
fe->dvb->num,fe->id);
}
-static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *parms)
+static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 freq_min;
u32 freq_max;
/* range check: frequency */
dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
- if ((freq_min && parms->frequency < freq_min) ||
- (freq_max && parms->frequency > 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, parms->frequency, freq_min, freq_max);
+ fe->dvb->num, fe->id, c->frequency, freq_min, freq_max);
return -EINVAL;
}
/* range check: symbol rate */
- if (fe->ops.info.type == FE_QPSK) {
- if ((fe->ops.info.symbol_rate_min &&
- parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
- (fe->ops.info.symbol_rate_max &&
- parms->u.qpsk.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, parms->u.qpsk.symbol_rate,
- fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
- return -EINVAL;
- }
-
- } else if (fe->ops.info.type == FE_QAM) {
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ case SYS_DVBS2:
+ case SYS_TURBO:
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
if ((fe->ops.info.symbol_rate_min &&
- parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
+ c->symbol_rate < fe->ops.info.symbol_rate_min) ||
(fe->ops.info.symbol_rate_max &&
- parms->u.qam.symbol_rate > 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, parms->u.qam.symbol_rate,
- fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
+ fe->dvb->num, fe->id, c->symbol_rate,
+ fe->ops.info.symbol_rate_min,
+ fe->ops.info.symbol_rate_max);
return -EINVAL;
}
- }
-
- /* check for supported modulation */
- if (fe->ops.info.type == FE_QAM &&
- (parms->u.qam.modulation > QAM_AUTO ||
- !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) {
- printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n",
- fe->dvb->num, fe->id, parms->u.qam.modulation);
- return -EINVAL;
+ default:
+ break;
}
return 0;
@@ -866,28 +908,52 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
memset(c, 0, sizeof(struct dtv_frontend_properties));
c->state = DTV_CLEAR;
- c->delivery_system = SYS_UNDEFINED;
- c->inversion = INVERSION_AUTO;
- c->fec_inner = FEC_AUTO;
+
+ dprintk("%s() Clearing cache for delivery system %d\n", __func__,
+ c->delivery_system);
+
c->transmission_mode = TRANSMISSION_MODE_AUTO;
- c->bandwidth_hz = BANDWIDTH_AUTO;
+ c->bandwidth_hz = 0; /* AUTO */
c->guard_interval = GUARD_INTERVAL_AUTO;
c->hierarchy = HIERARCHY_AUTO;
- c->symbol_rate = QAM_AUTO;
+ c->symbol_rate = 0;
c->code_rate_HP = FEC_AUTO;
c->code_rate_LP = FEC_AUTO;
-
- c->isdbt_partial_reception = -1;
- c->isdbt_sb_mode = -1;
- c->isdbt_sb_subchannel = -1;
- c->isdbt_sb_segment_idx = -1;
- c->isdbt_sb_segment_count = -1;
- c->isdbt_layer_enabled = 0x7;
+ c->fec_inner = FEC_AUTO;
+ c->rolloff = ROLLOFF_AUTO;
+ c->voltage = SEC_VOLTAGE_OFF;
+ c->sectone = SEC_TONE_OFF;
+ c->pilot = PILOT_AUTO;
+
+ c->isdbt_partial_reception = 0;
+ c->isdbt_sb_mode = 0;
+ c->isdbt_sb_subchannel = 0;
+ c->isdbt_sb_segment_idx = 0;
+ c->isdbt_sb_segment_count = 0;
+ c->isdbt_layer_enabled = 0;
for (i = 0; i < 3; i++) {
c->layer[i].fec = FEC_AUTO;
c->layer[i].modulation = QAM_AUTO;
- c->layer[i].interleaving = -1;
- c->layer[i].segment_count = -1;
+ c->layer[i].interleaving = 0;
+ c->layer[i].segment_count = 0;
+ }
+
+ c->isdbs_ts_id = 0;
+ c->dvbt2_plp_id = 0;
+
+ switch (c->delivery_system) {
+ case SYS_DVBS:
+ case SYS_DVBS2:
+ case SYS_TURBO:
+ c->modulation = QPSK; /* implied for DVB-S in legacy API */
+ c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+ break;
+ case SYS_ATSC:
+ c->modulation = VSB_8;
+ break;
+ default:
+ c->modulation = QAM_AUTO;
+ break;
}
return 0;
@@ -973,6 +1039,8 @@ 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_ENUM_DELSYS, 0, 0),
};
static void dtv_property_dump(struct dtv_property *tvp)
@@ -1006,70 +1074,54 @@ static void dtv_property_dump(struct dtv_property *tvp)
dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
}
-static int is_legacy_delivery_system(fe_delivery_system_t s)
-{
- if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
- (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
- (s == SYS_ATSC))
- return 1;
-
- return 0;
-}
-
-/* Initialize the cache with some default values derived from the
- * legacy frontend_info structure.
- */
-static void dtv_property_cache_init(struct dvb_frontend *fe,
- struct dtv_frontend_properties *c)
-{
- switch (fe->ops.info.type) {
- case FE_QPSK:
- c->modulation = QPSK; /* implied for DVB-S in legacy API */
- c->rolloff = ROLLOFF_35;/* implied for DVB-S */
- c->delivery_system = SYS_DVBS;
- break;
- case FE_QAM:
- c->delivery_system = SYS_DVBC_ANNEX_AC;
- break;
- case FE_OFDM:
- c->delivery_system = SYS_DVBT;
- break;
- case FE_ATSC:
- break;
- }
-}
-
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
*/
-static void dtv_property_cache_sync(struct dvb_frontend *fe,
- struct dtv_frontend_properties *c,
- const struct dvb_frontend_parameters *p)
+static int dtv_property_cache_sync(struct dvb_frontend *fe,
+ struct dtv_frontend_properties *c,
+ const struct dvb_frontend_parameters *p)
{
c->frequency = p->frequency;
c->inversion = p->inversion;
- switch (fe->ops.info.type) {
- case FE_QPSK:
+ switch (dvbv3_type(c->delivery_system)) {
+ case DVBV3_QPSK:
+ dprintk("%s() Preparing QPSK req\n", __func__);
c->symbol_rate = p->u.qpsk.symbol_rate;
c->fec_inner = p->u.qpsk.fec_inner;
break;
- case FE_QAM:
+ case DVBV3_QAM:
+ dprintk("%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 FE_OFDM:
- if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
- c->bandwidth_hz = 6000000;
- else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
- c->bandwidth_hz = 7000000;
- else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ case DVBV3_OFDM:
+ dprintk("%s() Preparing OFDM req\n", __func__);
+ switch (p->u.ofdm.bandwidth) {
+ case BANDWIDTH_10_MHZ:
+ c->bandwidth_hz = 10000000;
+ break;
+ case BANDWIDTH_8_MHZ:
c->bandwidth_hz = 8000000;
- else
- /* Including BANDWIDTH_AUTO */
+ break;
+ case BANDWIDTH_7_MHZ:
+ c->bandwidth_hz = 7000000;
+ break;
+ case BANDWIDTH_6_MHZ:
+ c->bandwidth_hz = 6000000;
+ break;
+ case BANDWIDTH_5_MHZ:
+ c->bandwidth_hz = 5000000;
+ break;
+ case BANDWIDTH_1_712_MHZ:
+ c->bandwidth_hz = 1712000;
+ break;
+ case BANDWIDTH_AUTO:
c->bandwidth_hz = 0;
+ }
+
c->code_rate_HP = p->u.ofdm.code_rate_HP;
c->code_rate_LP = p->u.ofdm.code_rate_LP;
c->modulation = p->u.ofdm.constellation;
@@ -1077,50 +1129,78 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
c->guard_interval = p->u.ofdm.guard_interval;
c->hierarchy = p->u.ofdm.hierarchy_information;
break;
- case FE_ATSC:
+ case DVBV3_ATSC:
+ dprintk("%s() Preparing ATSC req\n", __func__);
c->modulation = p->u.vsb.modulation;
if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
c->delivery_system = SYS_ATSC;
else
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);
+ return -EINVAL;
}
+
+ return 0;
}
/* Ensure the cached values are set correctly in the frontend
* legacy tuning structures, for the advanced tuning API.
*/
-static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct dvb_frontend_private *fepriv = fe->frontend_priv;
- struct dvb_frontend_parameters *p = &fepriv->parameters_in;
p->frequency = c->frequency;
p->inversion = c->inversion;
- switch (fe->ops.info.type) {
- case FE_QPSK:
+ 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);
+ return -EINVAL;
+ case DVBV3_QPSK:
dprintk("%s() Preparing QPSK req\n", __func__);
p->u.qpsk.symbol_rate = c->symbol_rate;
p->u.qpsk.fec_inner = c->fec_inner;
break;
- case FE_QAM:
+ case DVBV3_QAM:
dprintk("%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 FE_OFDM:
+ case DVBV3_OFDM:
dprintk("%s() Preparing OFDM req\n", __func__);
- if (c->bandwidth_hz == 6000000)
- p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
- else if (c->bandwidth_hz == 7000000)
- p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
- else if (c->bandwidth_hz == 8000000)
+
+ switch (c->bandwidth_hz) {
+ case 10000000:
+ p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ;
+ break;
+ case 8000000:
p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
- else
+ break;
+ case 7000000:
+ p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ break;
+ case 6000000:
+ p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ break;
+ case 5000000:
+ p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ;
+ break;
+ case 1712000:
+ p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ;
+ break;
+ case 0:
+ default:
p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+ }
p->u.ofdm.code_rate_HP = c->code_rate_HP;
p->u.ofdm.code_rate_LP = c->code_rate_LP;
p->u.ofdm.constellation = c->modulation;
@@ -1128,78 +1208,40 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
p->u.ofdm.guard_interval = c->guard_interval;
p->u.ofdm.hierarchy_information = c->hierarchy;
break;
- case FE_ATSC:
+ case DVBV3_ATSC:
dprintk("%s() Preparing VSB req\n", __func__);
p->u.vsb.modulation = c->modulation;
break;
}
+ return 0;
}
-/* Ensure the cached values are set correctly in the frontend
- * legacy tuning structures, for the legacy tuning API.
+/**
+ * dtv_get_frontend - calls a callback for retrieving DTV parameters
+ * @fe: struct dvb_frontend pointer
+ * @c: struct dtv_frontend_properties pointer (DVBv5 cache)
+ * @p_out struct dvb_frontend_parameters pointer (DVBv3 FE struct)
+ *
+ * This routine calls either the DVBv3 or DVBv5 get_frontend call.
+ * If c is not null, it will update the DVBv5 cache struct pointed by it.
+ * If p_out is not null, it will update the DVBv3 params pointed by it.
*/
-static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
+static int dtv_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p_out)
{
- const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct dvb_frontend_private *fepriv = fe->frontend_priv;
- struct dvb_frontend_parameters *p = &fepriv->parameters_in;
-
- p->frequency = c->frequency;
- p->inversion = c->inversion;
-
- if (c->delivery_system == SYS_DSS ||
- c->delivery_system == SYS_DVBS ||
- c->delivery_system == SYS_DVBS2 ||
- c->delivery_system == SYS_ISDBS ||
- c->delivery_system == SYS_TURBO) {
- p->u.qpsk.symbol_rate = c->symbol_rate;
- p->u.qpsk.fec_inner = c->fec_inner;
- }
+ int r;
- /* Fake out a generic DVB-T request so we pass validation in the ioctl */
- if ((c->delivery_system == SYS_ISDBT) ||
- (c->delivery_system == SYS_DVBT2)) {
- p->u.ofdm.constellation = QAM_AUTO;
- p->u.ofdm.code_rate_HP = FEC_AUTO;
- p->u.ofdm.code_rate_LP = FEC_AUTO;
- p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
- p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
- p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
- if (c->bandwidth_hz == 8000000)
- p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
- else if (c->bandwidth_hz == 7000000)
- p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
- else if (c->bandwidth_hz == 6000000)
- p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
- else
- p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+ if (fe->ops.get_frontend) {
+ r = fe->ops.get_frontend(fe);
+ if (unlikely(r < 0))
+ return r;
+ if (p_out)
+ dtv_property_legacy_params_sync(fe, p_out);
+ return 0;
}
-}
-
-static void dtv_property_cache_submit(struct dvb_frontend *fe)
-{
- const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- /* For legacy delivery systems we don't need the delivery_system to
- * be specified, but we populate the older structures from the cache
- * so we can call set_frontend on older drivers.
- */
- if(is_legacy_delivery_system(c->delivery_system)) {
-
- dprintk("%s() legacy, modulation = %d\n", __func__, c->modulation);
- dtv_property_legacy_params_sync(fe);
-
- } else {
- dprintk("%s() adv, modulation = %d\n", __func__, c->modulation);
-
- /* For advanced delivery systems / modulation types ...
- * we seed the lecacy dvb_frontend_parameters structure
- * so that the sanity checking code later in the IOCTL processing
- * can validate our basic frequency ranges, symbolrates, modulation
- * etc.
- */
- dtv_property_adv_params_sync(fe);
- }
+ /* As everything is in cache, get_frontend fops are always supported */
+ return 0;
}
static int dvb_frontend_ioctl_legacy(struct file *file,
@@ -1208,25 +1250,21 @@ static int dvb_frontend_ioctl_properties(struct file *file,
unsigned int cmd, void *parg);
static int dtv_property_process_get(struct dvb_frontend *fe,
+ const struct dtv_frontend_properties *c,
struct dtv_property *tvp,
struct file *file)
{
- const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct dvb_frontend_private *fepriv = fe->frontend_priv;
- struct dtv_frontend_properties cdetected;
- int r;
-
- /*
- * If the driver implements a get_frontend function, then convert
- * detected parameters to S2API properties.
- */
- if (fe->ops.get_frontend) {
- cdetected = *c;
- dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out);
- c = &cdetected;
- }
+ int r, ncaps;
switch(tvp->cmd) {
+ case DTV_ENUM_DELSYS:
+ ncaps = 0;
+ while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+ tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
+ ncaps++;
+ }
+ tvp->u.buffer.len = ncaps;
+ break;
case DTV_FREQUENCY:
tvp->u.data = c->frequency;
break;
@@ -1356,14 +1394,159 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
return 0;
}
+static int dtv_set_frontend(struct dvb_frontend *fe);
+
+static bool is_dvbv3_delsys(u32 delsys)
+{
+ bool status;
+
+ status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
+ (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
+
+ return status;
+}
+
+static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
+{
+ int ncaps, i;
+ u32 delsys = SYS_UNDEFINED;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ enum dvbv3_emulation_type type;
+
+ if (desired_system == SYS_UNDEFINED) {
+ /*
+ * A DVBv3 call doesn't know what's the desired system.
+ * Also, DVBv3 applications don't know that ops.info->type
+ * could be changed, and they simply dies when it doesn't
+ * match.
+ * So, don't change the current delivery system, as it
+ * may be trying to do the wrong thing, like setting an
+ * ISDB-T frontend as DVB-T. Instead, find the closest
+ * 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);
+ return 0;
+ }
+ type = dvbv3_type(c->delivery_system);
+ switch (type) {
+ case DVBV3_QPSK:
+ desired_system = SYS_DVBS;
+ break;
+ case DVBV3_QAM:
+ desired_system = SYS_DVBC_ANNEX_A;
+ break;
+ case DVBV3_ATSC:
+ desired_system = SYS_ATSC;
+ break;
+ case DVBV3_OFDM:
+ desired_system = SYS_DVBT;
+ break;
+ default:
+ dprintk("%s(): This frontend doesn't support DVBv3 calls\n",
+ __func__);
+ return -EINVAL;
+ }
+ } else {
+ /*
+ * This is a DVBv5 call. So, it likely knows the supported
+ * delivery systems.
+ */
+
+ /* Check if the desired delivery system is supported */
+ ncaps = 0;
+ 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);
+ return 0;
+ }
+ ncaps++;
+ }
+ type = dvbv3_type(desired_system);
+
+ /*
+ * The delivery system is not supported. See if it can be
+ * emulated.
+ * The emulation only works if the desired system is one of the
+ * 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__);
+ return -EINVAL;
+ }
+
+ /*
+ * Get the last non-DVBv3 delivery system that has the same type
+ * of the desired system
+ */
+ ncaps = 0;
+ while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+ if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
+ !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
+ delsys = fe->ops.delsys[ncaps];
+ ncaps++;
+ }
+ /* 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__);
+ return -EINVAL;
+ }
+ c->delivery_system = delsys;
+ }
+
+ /*
+ * The DVBv3 or DVBv5 call is requesting a different system. So,
+ * emulation is needed.
+ *
+ * Emulate newer delivery systems like ISDBT, DVBT and DMBTH
+ * 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);
+
+ /*
+ * For now, handles ISDB-T calls. More code may be needed here for the
+ * other emulated stuff
+ */
+ if (type == DVBV3_OFDM) {
+ if (c->delivery_system == SYS_ISDBT) {
+ dprintk("%s() Using defaults for SYS_ISDBT\n",
+ __func__);
+ if (!c->bandwidth_hz)
+ c->bandwidth_hz = 6000000;
+
+ c->isdbt_partial_reception = 0;
+ c->isdbt_sb_mode = 0;
+ c->isdbt_sb_subchannel = 0;
+ c->isdbt_sb_segment_idx = 0;
+ c->isdbt_sb_segment_count = 0;
+ c->isdbt_layer_enabled = 0;
+ for (i = 0; i < 3; i++) {
+ c->layer[i].fec = FEC_AUTO;
+ c->layer[i].modulation = QAM_AUTO;
+ c->layer[i].interleaving = 0;
+ c->layer[i].segment_count = 0;
+ }
+ }
+ }
+ dprintk("change delivery system on cache to %d\n", c->delivery_system);
+
+ return 0;
+}
+
static int dtv_property_process_set(struct dvb_frontend *fe,
struct dtv_property *tvp,
struct file *file)
{
int r = 0;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct dvb_frontend_private *fepriv = fe->frontend_priv;
- dtv_property_dump(tvp);
/* Allow the frontend to validate incoming properties */
if (fe->ops.set_property) {
@@ -1374,11 +1557,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
switch(tvp->cmd) {
case DTV_CLEAR:
- /* Reset a cache of data specific to the frontend here. This does
+ /*
+ * Reset a cache of data specific to the frontend here. This does
* not effect hardware.
*/
dvb_frontend_clear_cache(fe);
- dprintk("%s() Flushing property cache\n", __func__);
break;
case DTV_TUNE:
/* interpret the cache of data, build either a traditional frontend
@@ -1387,10 +1570,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
*/
c->state = tvp->cmd;
dprintk("%s() Finalised property cache\n", __func__);
- dtv_property_cache_submit(fe);
- r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND,
- &fepriv->parameters_in);
+ r = dtv_set_frontend(fe);
break;
case DTV_FREQUENCY:
c->frequency = tvp->u.data;
@@ -1417,7 +1598,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
c->rolloff = tvp->u.data;
break;
case DTV_DELIVERY_SYSTEM:
- c->delivery_system = tvp->u.data;
+ r = set_delivery_system(fe, tvp->u.data);
break;
case DTV_VOLTAGE:
c->voltage = tvp->u.data;
@@ -1594,7 +1775,6 @@ static int dvb_frontend_ioctl_properties(struct file *file,
} else
if(cmd == FE_GET_PROPERTY) {
-
tvps = (struct dtv_properties __user *)parg;
dprintk("%s() properties.num = %d\n", __func__, tvps->num);
@@ -1616,8 +1796,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
goto out;
}
+ /*
+ * Fills the cache out struct with the cache contents, plus
+ * the data retrieved from get_frontend.
+ */
+ dtv_get_frontend(fe, NULL);
for (i = 0; i < tvps->num; i++) {
- err = dtv_property_process_get(fe, tvp + i, file);
+ err = dtv_property_process_get(fe, c, tvp + i, file);
if (err < 0)
goto out;
(tvp + i)->result = err;
@@ -1636,12 +1821,121 @@ out:
return err;
}
+static int dtv_set_frontend(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct dvb_frontend_tune_settings fetunesettings;
+ u32 rolloff = 0;
+
+ if (dvb_frontend_check_parameters(fe) < 0)
+ return -EINVAL;
+
+ /*
+ * Be sure that the bandwidth will be filled for all
+ * non-satellite systems, as tuners need to know what
+ * low pass/Nyquist half filter should be applied, in
+ * order to avoid inter-channel noise.
+ *
+ * ISDB-T and DVB-T/T2 already sets bandwidth.
+ * ATSC and DVB-C don't set, so, the core should fill it.
+ *
+ * On DVB-C Annex A and C, the bandwidth is a function of
+ * the roll-off and symbol rate. Annex B defines different
+ * roll-off factors depending on the modulation. Fortunately,
+ * Annex B is only used with 6MHz, so there's no need to
+ * calculate it.
+ *
+ * While not officially supported, a side effect of handling it at
+ * the cache level is that a program could retrieve the bandwidth
+ * via DTV_BANDWIDTH_HZ, which may be useful for test programs.
+ */
+ switch (c->delivery_system) {
+ case SYS_ATSC:
+ case SYS_DVBC_ANNEX_B:
+ c->bandwidth_hz = 6000000;
+ break;
+ case SYS_DVBC_ANNEX_A:
+ rolloff = 115;
+ break;
+ case SYS_DVBC_ANNEX_C:
+ rolloff = 113;
+ break;
+ default:
+ break;
+ }
+ if (rolloff)
+ c->bandwidth_hz = (c->symbol_rate * rolloff) / 100;
+
+ /* force auto frequency inversion if requested */
+ if (dvb_force_auto_inversion)
+ c->inversion = INVERSION_AUTO;
+
+ /*
+ * without hierarchical coding code_rate_LP is irrelevant,
+ * so we tolerate the otherwise invalid FEC_NONE setting
+ */
+ if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
+ c->code_rate_LP = FEC_AUTO;
+
+ /* get frontend-specific tuning settings */
+ memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+ if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+ fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+ fepriv->max_drift = fetunesettings.max_drift;
+ fepriv->step_size = fetunesettings.step_size;
+ } else {
+ /* default values */
+ switch (c->delivery_system) {
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = c->symbol_rate / 16000;
+ fepriv->max_drift = c->symbol_rate / 2000;
+ break;
+ case SYS_DVBT:
+ case SYS_DVBT2:
+ case SYS_ISDBT:
+ case SYS_DMBTH:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+ fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+ break;
+ default:
+ /*
+ * FIXME: This sounds wrong! if freqency_stepsize is
+ * defined by the frontend, why not use it???
+ */
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = 0; /* no zigzag */
+ fepriv->max_drift = 0;
+ break;
+ }
+ }
+ if (dvb_override_tune_delay > 0)
+ fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+ fepriv->state = FESTATE_RETUNE;
+
+ /* Request the search algorithm to search */
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+ dvb_frontend_clear_events(fe);
+ dvb_frontend_add_event(fe, 0);
+ dvb_frontend_wakeup(fe);
+ fepriv->status = 0;
+
+ return 0;
+}
+
+
static int dvb_frontend_ioctl_legacy(struct file *file,
unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev = file->private_data;
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) {
@@ -1658,9 +1952,43 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
switch (cmd) {
case FE_GET_INFO: {
struct dvb_frontend_info* info = parg;
+
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
+ /*
+ * Associate the 4 delivery systems supported by DVBv3
+ * API with their DVBv5 counterpart. For the other standards,
+ * use the closest type, assuming that it would hopefully
+ * work with a DVBv3 application.
+ * It should be noticed that, on multi-frontend devices with
+ * different types (terrestrial and cable, for example),
+ * a pure DVBv3 application won't be able to use all delivery
+ * systems. Yet, changing the DVBv5 cache to the other delivery
+ * system should be enough for making it work.
+ */
+ switch (dvbv3_type(c->delivery_system)) {
+ case DVBV3_QPSK:
+ info->type = FE_QPSK;
+ break;
+ case DVBV3_ATSC:
+ info->type = FE_ATSC;
+ break;
+ case DVBV3_QAM:
+ info->type = FE_QAM;
+ break;
+ case DVBV3_OFDM:
+ 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);
+ fe->ops.info.type = FE_OFDM;
+ }
+ dprintk("current delivery system on cache: %d, V3 type: %d\n",
+ 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. */
info->caps |= FE_CAN_INVERSION_AUTO;
@@ -1819,108 +2147,22 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
break;
- case FE_SET_FRONTEND: {
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- struct dvb_frontend_tune_settings fetunesettings;
-
- if (c->state == DTV_TUNE) {
- if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) {
- err = -EINVAL;
- break;
- }
- } else {
- if (dvb_frontend_check_parameters(fe, parg) < 0) {
- err = -EINVAL;
- break;
- }
-
- memcpy (&fepriv->parameters_in, parg,
- sizeof (struct dvb_frontend_parameters));
- dtv_property_cache_init(fe, c);
- dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
- }
-
- /*
- * Initialize output parameters to match the values given by
- * the user. FE_SET_FRONTEND triggers an initial frontend event
- * with status = 0, which copies output parameters to userspace.
- */
- fepriv->parameters_out = fepriv->parameters_in;
-
- memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
- memcpy(&fetunesettings.parameters, parg,
- sizeof (struct dvb_frontend_parameters));
-
- /* force auto frequency inversion if requested */
- if (dvb_force_auto_inversion) {
- fepriv->parameters_in.inversion = INVERSION_AUTO;
- fetunesettings.parameters.inversion = INVERSION_AUTO;
- }
- if (fe->ops.info.type == FE_OFDM) {
- /* without hierarchical coding code_rate_LP is irrelevant,
- * so we tolerate the otherwise invalid FEC_NONE setting */
- if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
- fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE)
- fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO;
- }
-
- /* get frontend-specific tuning settings */
- if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
- fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
- fepriv->max_drift = fetunesettings.max_drift;
- fepriv->step_size = fetunesettings.step_size;
- } else {
- /* default values */
- switch(fe->ops.info.type) {
- case FE_QPSK:
- fepriv->min_delay = HZ/20;
- fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000;
- fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000;
- break;
-
- case FE_QAM:
- fepriv->min_delay = HZ/20;
- fepriv->step_size = 0; /* no zigzag */
- fepriv->max_drift = 0;
- break;
-
- case FE_OFDM:
- fepriv->min_delay = HZ/20;
- fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
- fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
- break;
- case FE_ATSC:
- fepriv->min_delay = HZ/20;
- fepriv->step_size = 0;
- fepriv->max_drift = 0;
- break;
- }
- }
- if (dvb_override_tune_delay > 0)
- fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
-
- fepriv->state = FESTATE_RETUNE;
-
- /* Request the search algorithm to search */
- fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+ case FE_SET_FRONTEND:
+ err = set_delivery_system(fe, SYS_UNDEFINED);
+ if (err)
+ break;
- dvb_frontend_clear_events(fe);
- dvb_frontend_add_event(fe, 0);
- dvb_frontend_wakeup(fe);
- fepriv->status = 0;
- err = 0;
+ err = dtv_property_cache_sync(fe, c, parg);
+ if (err)
+ break;
+ err = dtv_set_frontend(fe);
break;
- }
-
case FE_GET_EVENT:
err = dvb_frontend_get_event (fe, parg, file->f_flags);
break;
case FE_GET_FRONTEND:
- if (fe->ops.get_frontend) {
- err = fe->ops.get_frontend(fe, &fepriv->parameters_out);
- memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters));
- }
+ err = dtv_get_frontend(fe, parg);
break;
case FE_SET_FRONTEND_TUNE_MODE:
@@ -2061,12 +2303,15 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
dprintk ("%s\n", __func__);
- if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
fepriv->release_jiffies = jiffies;
+ mb();
+ }
ret = dvb_generic_release (inode, file);
if (dvbdev->users == -1) {
+ wake_up(&fepriv->wait_queue);
if (fepriv->exit != DVB_FE_NO_EXIT) {
fops_put(file->f_op);
file->f_op = NULL;
@@ -2127,6 +2372,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND);
+ /*
+ * Initialize the cache to the proper values according with the
+ * first supported delivery system (ops->delsys[0])
+ */
+
+ fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
+ dvb_frontend_clear_cache(fe);
+
mutex_unlock(&frontend_mutex);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 67bbfa7..d63a821 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -42,11 +42,16 @@
#include "dvbdev.h"
+/*
+ * Maximum number of Delivery systems per frontend. It
+ * should be smaller or equal to 32
+ */
+#define MAX_DELSYS 8
+
struct dvb_frontend_tune_settings {
int min_delay_ms;
int step_size;
int max_drift;
- struct dvb_frontend_parameters parameters;
};
struct dvb_frontend;
@@ -198,11 +203,11 @@ struct dvb_tuner_ops {
int (*sleep)(struct dvb_frontend *fe);
/** This is for simple PLLs - set all parameters in one go. */
- int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+ int (*set_params)(struct dvb_frontend *fe);
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
- int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+ int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
/** This is to allow setting tuner-specific configs */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
@@ -250,10 +255,14 @@ struct analog_demod_ops {
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
};
+struct dtv_frontend_properties;
+
struct dvb_frontend_ops {
struct dvb_frontend_info info;
+ u8 delsys[MAX_DELSYS];
+
void (*release)(struct dvb_frontend* fe);
void (*release_sec)(struct dvb_frontend* fe);
@@ -264,7 +273,7 @@ struct dvb_frontend_ops {
/* if this is set, it overrides the default swzigzag */
int (*tune)(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status);
@@ -272,10 +281,10 @@ struct dvb_frontend_ops {
enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */
- int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ int (*set_frontend)(struct dvb_frontend *fe);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
- int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ int (*get_frontend)(struct dvb_frontend *fe);
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
@@ -297,8 +306,7 @@ struct dvb_frontend_ops {
/* These callbacks are for devices that implement their own
* tuning algorithms, rather than a simple swzigzag
*/
- enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
- int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+ enum dvbfe_search (*search)(struct dvb_frontend *fe);
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
@@ -307,6 +315,7 @@ struct dvb_frontend_ops {
int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
};
+#ifdef __DVB_CORE__
#define MAX_EVENT 8
struct dvb_fe_events {
@@ -317,6 +326,7 @@ struct dvb_fe_events {
wait_queue_head_t wait_queue;
struct mutex mtx;
};
+#endif
struct dtv_frontend_properties {
@@ -374,6 +384,7 @@ struct dvb_frontend {
void *analog_demod_priv;
struct dtv_frontend_properties dtv_property_cache;
#define DVB_FRONTEND_COMPONENT_TUNER 0
+#define DVB_FRONTEND_COMPONENT_DEMOD 1
int (*callback)(void *adapter_priv, int component, int cmd, int arg);
int id;
};
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 93d9869..8766ce8 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1510,9 +1510,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
for (i=0; i<DVB_NET_DEVICES_MAX; i++)
dvbnet->state[i] = 0;
- dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net,
+ return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
dvbnet, DVB_DEVICE_NET);
-
- return 0;
}
EXPORT_SYMBOL(dvb_net_init);
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 5825716..9f203c6 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -311,6 +311,7 @@ config DVB_USB_ANYSEE
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.
@@ -340,7 +341,7 @@ config DVB_USB_AF9015
config DVB_USB_CE6230
tristate "Intel CE6230 DVB-T USB2.0 support"
- depends on DVB_USB && EXPERIMENTAL
+ depends on DVB_USB
select DVB_ZL10353
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
help
@@ -354,7 +355,7 @@ config DVB_USB_FRIIO
config DVB_USB_EC168
tristate "E3C EC168 DVB-T USB2.0 support"
- depends on DVB_USB && EXPERIMENTAL
+ depends on DVB_USB
select DVB_EC100
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
help
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
index 3263e97..740f3f4 100644
--- a/drivers/media/dvb/dvb-usb/af9005-fe.c
+++ b/drivers/media/dvb/dvb-usb/af9005-fe.c
@@ -303,7 +303,7 @@ static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
return -EINVAL;
}
- /* read constellation mode */
+ /* read modulation mode */
ret =
af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
reg_tpsd_const_pos, reg_tpsd_const_len,
@@ -321,7 +321,7 @@ static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
bits = 6;
break;
default:
- err("invalid constellation mode");
+ err("invalid modulation mode");
return -EINVAL;
}
*pre_bit_count = super_frame_count * 68 * 4 * x * bits;
@@ -533,13 +533,13 @@ static int af9005_fe_read_signal_strength(struct dvb_frontend *fe,
static int af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr)
{
- /* the snr can be derived from the ber and the constellation
+ /* the snr can be derived from the ber and the modulation
but I don't think this kind of complex calculations belong
in the driver. I may be wrong.... */
return -ENOSYS;
}
-static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
+static int af9005_fe_program_cfoe(struct dvb_usb_device *d, u32 bw)
{
u8 temp0, temp1, temp2, temp3, buf[4];
int ret;
@@ -551,7 +551,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
u32 NS_coeff2_8k;
switch (bw) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
NS_coeff1_2048Nu = 0x2ADB6DC;
NS_coeff1_8191Nu = 0xAB7313;
NS_coeff1_8192Nu = 0xAB6DB7;
@@ -560,7 +560,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
NS_coeff2_8k = 0x55B6DC;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
NS_coeff1_2048Nu = 0x3200001;
NS_coeff1_8191Nu = 0xC80640;
NS_coeff1_8192Nu = 0xC80000;
@@ -569,7 +569,7 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
NS_coeff2_8k = 0x640000;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
NS_coeff1_2048Nu = 0x3924926;
NS_coeff1_8191Nu = 0xE4996E;
NS_coeff1_8192Nu = 0xE49249;
@@ -773,17 +773,17 @@ static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw)
}
-static int af9005_fe_select_bw(struct dvb_usb_device *d, fe_bandwidth_t bw)
+static int af9005_fe_select_bw(struct dvb_usb_device *d, u32 bw)
{
u8 temp;
switch (bw) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
temp = 0;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
temp = 1;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
temp = 2;
break;
default:
@@ -930,10 +930,11 @@ static int af9005_fe_init(struct dvb_frontend *fe)
/* init other parameters: program cfoe and select bandwidth */
deb_info("program cfoe\n");
- if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ)))
+ ret = af9005_fe_program_cfoe(state->d, 6000000);
+ if (ret)
return ret;
- /* set read-update bit for constellation */
- deb_info("set read-update bit for constellation\n");
+ /* set read-update bit for modulation */
+ deb_info("set read-update bit for modulation\n");
if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_feq_read_update,
reg_feq_read_update_pos,
@@ -943,8 +944,8 @@ static int af9005_fe_init(struct dvb_frontend *fe)
/* sample code has a set MPEG TS code here
but sniffing reveals that it doesn't do it */
- /* set read-update bit to 1 for DCA constellation */
- deb_info("set read-update bit 1 for DCA constellation\n");
+ /* set read-update bit to 1 for DCA modulation */
+ deb_info("set read-update bit 1 for DCA modulation\n");
if ((ret =
af9005_write_register_bits(state->d, xd_p_reg_dca_read_update,
reg_dca_read_update_pos,
@@ -1099,15 +1100,15 @@ static int af9005_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
return 0;
}
-static int af9005_fe_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int af9005_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct af9005_fe_state *state = fe->demodulator_priv;
int ret;
u8 temp, temp0, temp1, temp2;
deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency,
- fep->u.ofdm.bandwidth);
+ fep->bandwidth_hz);
if (fe->ops.tuner_ops.release == NULL) {
err("Tuner not attached");
return -ENODEV;
@@ -1167,10 +1168,10 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
/* select bandwidth */
deb_info("select bandwidth");
- ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth);
+ ret = af9005_fe_select_bw(state->d, fep->bandwidth_hz);
if (ret)
return ret;
- ret = af9005_fe_program_cfoe(state->d, fep->u.ofdm.bandwidth);
+ ret = af9005_fe_program_cfoe(state->d, fep->bandwidth_hz);
if (ret)
return ret;
@@ -1189,7 +1190,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
return ret;
/* set tuner */
deb_info("set tuner\n");
- ret = fe->ops.tuner_ops.set_params(fe, fep);
+ ret = fe->ops.tuner_ops.set_params(fe);
if (ret)
return ret;
@@ -1225,9 +1226,9 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int af9005_fe_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int af9005_fe_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct af9005_fe_state *state = fe->demodulator_priv;
int ret;
u8 temp;
@@ -1239,19 +1240,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
&temp);
if (ret)
return ret;
- deb_info("===== fe_get_frontend ==============\n");
+ deb_info("===== fe_get_frontend_legacy = =============\n");
deb_info("CONSTELLATION ");
switch (temp) {
case 0:
- fep->u.ofdm.constellation = QPSK;
+ fep->modulation = QPSK;
deb_info("QPSK\n");
break;
case 1:
- fep->u.ofdm.constellation = QAM_16;
+ fep->modulation = QAM_16;
deb_info("QAM_16\n");
break;
case 2:
- fep->u.ofdm.constellation = QAM_64;
+ fep->modulation = QAM_64;
deb_info("QAM_64\n");
break;
}
@@ -1266,19 +1267,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("HIERARCHY ");
switch (temp) {
case 0:
- fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fep->hierarchy = HIERARCHY_NONE;
deb_info("NONE\n");
break;
case 1:
- fep->u.ofdm.hierarchy_information = HIERARCHY_1;
+ fep->hierarchy = HIERARCHY_1;
deb_info("1\n");
break;
case 2:
- fep->u.ofdm.hierarchy_information = HIERARCHY_2;
+ fep->hierarchy = HIERARCHY_2;
deb_info("2\n");
break;
case 3:
- fep->u.ofdm.hierarchy_information = HIERARCHY_4;
+ fep->hierarchy = HIERARCHY_4;
deb_info("4\n");
break;
}
@@ -1302,23 +1303,23 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("CODERATE HP ");
switch (temp) {
case 0:
- fep->u.ofdm.code_rate_HP = FEC_1_2;
+ fep->code_rate_HP = FEC_1_2;
deb_info("FEC_1_2\n");
break;
case 1:
- fep->u.ofdm.code_rate_HP = FEC_2_3;
+ fep->code_rate_HP = FEC_2_3;
deb_info("FEC_2_3\n");
break;
case 2:
- fep->u.ofdm.code_rate_HP = FEC_3_4;
+ fep->code_rate_HP = FEC_3_4;
deb_info("FEC_3_4\n");
break;
case 3:
- fep->u.ofdm.code_rate_HP = FEC_5_6;
+ fep->code_rate_HP = FEC_5_6;
deb_info("FEC_5_6\n");
break;
case 4:
- fep->u.ofdm.code_rate_HP = FEC_7_8;
+ fep->code_rate_HP = FEC_7_8;
deb_info("FEC_7_8\n");
break;
}
@@ -1333,23 +1334,23 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("CODERATE LP ");
switch (temp) {
case 0:
- fep->u.ofdm.code_rate_LP = FEC_1_2;
+ fep->code_rate_LP = FEC_1_2;
deb_info("FEC_1_2\n");
break;
case 1:
- fep->u.ofdm.code_rate_LP = FEC_2_3;
+ fep->code_rate_LP = FEC_2_3;
deb_info("FEC_2_3\n");
break;
case 2:
- fep->u.ofdm.code_rate_LP = FEC_3_4;
+ fep->code_rate_LP = FEC_3_4;
deb_info("FEC_3_4\n");
break;
case 3:
- fep->u.ofdm.code_rate_LP = FEC_5_6;
+ fep->code_rate_LP = FEC_5_6;
deb_info("FEC_5_6\n");
break;
case 4:
- fep->u.ofdm.code_rate_LP = FEC_7_8;
+ fep->code_rate_LP = FEC_7_8;
deb_info("FEC_7_8\n");
break;
}
@@ -1363,19 +1364,19 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("GUARD INTERVAL ");
switch (temp) {
case 0:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ fep->guard_interval = GUARD_INTERVAL_1_32;
deb_info("1_32\n");
break;
case 1:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ fep->guard_interval = GUARD_INTERVAL_1_16;
deb_info("1_16\n");
break;
case 2:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ fep->guard_interval = GUARD_INTERVAL_1_8;
deb_info("1_8\n");
break;
case 3:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ fep->guard_interval = GUARD_INTERVAL_1_4;
deb_info("1_4\n");
break;
}
@@ -1390,11 +1391,11 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("TRANSMISSION MODE ");
switch (temp) {
case 0:
- fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ fep->transmission_mode = TRANSMISSION_MODE_2K;
deb_info("2K\n");
break;
case 1:
- fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ fep->transmission_mode = TRANSMISSION_MODE_8K;
deb_info("8K\n");
break;
}
@@ -1406,15 +1407,15 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe,
deb_info("BANDWIDTH ");
switch (temp) {
case 0:
- fep->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ fep->bandwidth_hz = 6000000;
deb_info("6\n");
break;
case 1:
- fep->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ fep->bandwidth_hz = 7000000;
deb_info("7\n");
break;
case 2:
- fep->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ fep->bandwidth_hz = 8000000;
deb_info("8\n");
break;
}
@@ -1454,9 +1455,9 @@ struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d)
}
static struct dvb_frontend_ops af9005_fe_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "AF9005 USB DVB-T",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 250000,
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
index bd51a76..af176b6 100644
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ b/drivers/media/dvb/dvb-usb/af9005.c
@@ -30,7 +30,7 @@ MODULE_PARM_DESC(debug,
"set debugging level (1=info,xfer=2,rc=4,reg=8,i2c=16,fw=32 (or-able))."
DVB_USB_DEBUG_STATUS);
/* enable obnoxious led */
-int dvb_usb_af9005_led = 1;
+bool dvb_usb_af9005_led = 1;
module_param_named(led, dvb_usb_af9005_led, bool, 0644);
MODULE_PARM_DESC(led, "enable led (default: 1).");
@@ -977,11 +977,20 @@ static int af9005_usb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr);
}
+enum af9005_usb_table_entry {
+ AFATECH_AF9005,
+ TERRATEC_AF9005,
+ ANSONIC_AF9005,
+};
+
static struct usb_device_id af9005_usb_table[] = {
- {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},
- {USB_DEVICE(USB_VID_ANSONIC, USB_PID_ANSONIC_DVBT_USB)},
- {0},
+ [AFATECH_AF9005] = {USB_DEVICE(USB_VID_AFATECH,
+ USB_PID_AFATECH_AF9005)},
+ [TERRATEC_AF9005] = {USB_DEVICE(USB_VID_TERRATEC,
+ USB_PID_TERRATEC_CINERGY_T_USB_XE)},
+ [ANSONIC_AF9005] = {USB_DEVICE(USB_VID_ANSONIC,
+ USB_PID_ANSONIC_DVBT_USB)},
+ { }
};
MODULE_DEVICE_TABLE(usb, af9005_usb_table);
@@ -1041,15 +1050,15 @@ static struct dvb_usb_device_properties af9005_properties = {
.num_device_descs = 3,
.devices = {
{.name = "Afatech DVB-T USB1.1 stick",
- .cold_ids = {&af9005_usb_table[0], NULL},
+ .cold_ids = {&af9005_usb_table[AFATECH_AF9005], NULL},
.warm_ids = {NULL},
},
{.name = "TerraTec Cinergy T USB XE",
- .cold_ids = {&af9005_usb_table[1], NULL},
+ .cold_ids = {&af9005_usb_table[TERRATEC_AF9005], NULL},
.warm_ids = {NULL},
},
{.name = "Ansonic DVB-T USB1.1 stick",
- .cold_ids = {&af9005_usb_table[2], NULL},
+ .cold_ids = {&af9005_usb_table[ANSONIC_AF9005], NULL},
.warm_ids = {NULL},
},
{NULL},
diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h
index c71c77b..6a2bf3d 100644
--- a/drivers/media/dvb/dvb-usb/af9005.h
+++ b/drivers/media/dvb/dvb-usb/af9005.h
@@ -35,7 +35,7 @@ extern int dvb_usb_af9005_debug;
#define deb_i2c(args...) dprintk(dvb_usb_af9005_debug,0x10,args)
#define deb_fw(args...) dprintk(dvb_usb_af9005_debug,0x20,args)
-extern int dvb_usb_af9005_led;
+extern bool dvb_usb_af9005_led;
/* firmware */
#define FW_BULKOUT_SIZE 250
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 56cbd36..282a43d 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -50,14 +50,14 @@ static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
static struct af9013_config af9015_af9013_config[] = {
{
- .demod_address = AF9015_I2C_DEMOD,
- .output_mode = AF9013_OUTPUT_MODE_USB,
+ .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,
}, {
- .output_mode = AF9013_OUTPUT_MODE_SERIAL,
+ .ts_mode = AF9013_TS_SERIAL,
.api_version = { 0, 1, 9, 0 },
.gpio[0] = AF9013_GPIO_TUNER_ON,
.gpio[1] = AF9013_GPIO_LO,
@@ -216,8 +216,8 @@ static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
{
struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
- if (addr == af9015_af9013_config[0].demod_address ||
- addr == af9015_af9013_config[1].demod_address)
+ 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);
@@ -228,8 +228,8 @@ static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
{
struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
- if (addr == af9015_af9013_config[0].demod_address ||
- addr == af9015_af9013_config[1].demod_address)
+ 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);
@@ -271,8 +271,8 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
return -EAGAIN;
while (i < num) {
- if (msg[i].addr == af9015_af9013_config[0].demod_address ||
- msg[i].addr == af9015_af9013_config[1].demod_address) {
+ 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];
@@ -288,8 +288,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
ret = -EOPNOTSUPP;
goto error;
}
- if (msg[i].addr ==
- af9015_af9013_config[0].demod_address)
+ if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
req.cmd = READ_MEMORY;
else
req.cmd = READ_I2C;
@@ -307,7 +306,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
goto error;
}
if (msg[i].addr ==
- af9015_af9013_config[0].demod_address) {
+ af9015_af9013_config[0].i2c_addr) {
ret = -EINVAL;
goto error;
}
@@ -325,8 +324,7 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
ret = -EOPNOTSUPP;
goto error;
}
- if (msg[i].addr ==
- af9015_af9013_config[0].demod_address)
+ if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
req.cmd = WRITE_MEMORY;
else
req.cmd = WRITE_I2C;
@@ -508,7 +506,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
msleep(100);
ret = af9015_read_reg_i2c(d,
- af9015_af9013_config[1].demod_address, 0x98be, &val);
+ af9015_af9013_config[1].i2c_addr, 0x98be, &val);
if (ret)
goto error;
else
@@ -536,7 +534,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
goto error;
/* request boot firmware */
- ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address,
+ 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)
@@ -547,7 +545,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
/* check firmware status */
ret = af9015_read_reg_i2c(d,
- af9015_af9013_config[1].demod_address, 0x98be, &val);
+ 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)
@@ -840,7 +838,7 @@ static int af9015_read_config(struct usb_device *udev)
if (ret)
goto error;
- deb_info("%s: IR mode:%d\n", __func__, val);
+ 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;
@@ -854,7 +852,7 @@ static int af9015_read_config(struct usb_device *udev)
if (ret)
goto error;
af9015_config.dual_mode = val;
- deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
+ 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 */
@@ -878,7 +876,7 @@ static int af9015_read_config(struct usb_device *udev)
ret = af9015_rw_udev(udev, &req);
if (ret)
goto error;
- af9015_af9013_config[1].demod_address = val;
+ af9015_af9013_config[1].i2c_addr = val;
/* enable 2nd adapter */
for (i = 0; i < af9015_properties_count; i++)
@@ -900,34 +898,38 @@ static int af9015_read_config(struct usb_device *udev)
goto error;
switch (val) {
case 0:
- af9015_af9013_config[i].adc_clock = 28800;
+ af9015_af9013_config[i].clock = 28800000;
break;
case 1:
- af9015_af9013_config[i].adc_clock = 20480;
+ af9015_af9013_config[i].clock = 20480000;
break;
case 2:
- af9015_af9013_config[i].adc_clock = 28000;
+ af9015_af9013_config[i].clock = 28000000;
break;
case 3:
- af9015_af9013_config[i].adc_clock = 25000;
+ af9015_af9013_config[i].clock = 25000000;
break;
};
- deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i,
- val, af9015_af9013_config[i].adc_clock);
+ deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i,
+ val, af9015_af9013_config[i].clock);
- /* tuner IF */
+ /* IF frequency */
req.addr = AF9015_EEPROM_IF1H + offset;
ret = af9015_rw_udev(udev, &req);
if (ret)
goto error;
- af9015_af9013_config[i].tuner_if = val << 8;
+
+ 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].tuner_if += val;
- deb_info("%s: [%d] IF1:%d\n", __func__, i,
- af9015_af9013_config[0].tuner_if);
+
+ 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;
@@ -940,7 +942,7 @@ static int af9015_read_config(struct usb_device *udev)
if (ret)
goto error;
af9015_config.mt2060_if1[i] += val;
- deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i,
+ deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i,
af9015_config.mt2060_if1[i]);
/* tuner */
@@ -957,30 +959,30 @@ static int af9015_read_config(struct usb_device *udev)
case AF9013_TUNER_TDA18271:
case AF9013_TUNER_QT1010A:
case AF9013_TUNER_TDA18218:
- af9015_af9013_config[i].rf_spec_inv = 1;
+ 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].rf_spec_inv = 0;
+ 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].rf_spec_inv = 1;
+ af9015_af9013_config[i].spec_inv = 1;
break;
default:
- warn("tuner id:%d not supported, please report!", val);
+ 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);
+ deb_info("%s: [%d] tuner id=%d\n", __func__, i, val);
}
error:
if (ret)
- err("eeprom read failed:%d", 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
@@ -998,7 +1000,7 @@ error:
af9015_properties[i].num_adapters = 1;
/* set correct IF */
- af9015_af9013_config[0].tuner_if = 4570;
+ af9015_af9013_config[0].if_frequency = 4570000;
}
return ret;
@@ -1093,9 +1095,79 @@ error:
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;
+}
+
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 */
@@ -1116,6 +1188,32 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
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;
}
@@ -1245,49 +1343,112 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
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[] = {
-/* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
- {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
- {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
- {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
-/* 5 */{USB_DEVICE(USB_VID_VISIONPLUS,
- USB_PID_TINYTWIN)},
- {USB_DEVICE(USB_VID_VISIONPLUS,
- USB_PID_AZUREWAVE_AD_TU700)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
-/* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
- {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
- {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
-/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
- {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
-/* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
- {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
-/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
- {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
-/* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
- {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
- {USB_DEVICE(USB_VID_TERRATEC,
- USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
-/* 35 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
- {USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
- {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
- {0},
+ [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);
@@ -1362,68 +1523,104 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.devices = {
{
.name = "Afatech AF9015 DVB-T USB2.0 stick",
- .cold_ids = {&af9015_usb_table[0],
- &af9015_usb_table[1], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AFATECH_9015],
+ &af9015_usb_table[AFATECH_9016],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Leadtek WinFast DTV Dongle Gold",
- .cold_ids = {&af9015_usb_table[2], NULL},
+ .cold_ids = {
+ &af9015_usb_table[WINFAST_DTV_GOLD],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Pinnacle PCTV 71e",
- .cold_ids = {&af9015_usb_table[3], NULL},
+ .cold_ids = {
+ &af9015_usb_table[PINNACLE_PCTV_71E],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld PlusTV Dual DVB-T Stick " \
"(DVB-T 399U)",
- .cold_ids = {&af9015_usb_table[4],
- &af9015_usb_table[25], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_PLUSTV_399U],
+ &af9015_usb_table[KWORLD_399U_2],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "DigitalNow TinyTwin DVB-T Receiver",
- .cold_ids = {&af9015_usb_table[5],
- &af9015_usb_table[28],
- &af9015_usb_table[36], NULL},
+ .cold_ids = {
+ &af9015_usb_table[TINYTWIN],
+ &af9015_usb_table[TINYTWIN_2],
+ &af9015_usb_table[TINYTWIN_3],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "TwinHan AzureWave AD-TU700(704J)",
- .cold_ids = {&af9015_usb_table[6], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AZUREWAVE_TU700],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "TerraTec Cinergy T USB XE",
- .cold_ids = {&af9015_usb_table[7], NULL},
+ .cold_ids = {
+ &af9015_usb_table[TERRATEC_AF9015],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld PlusTV Dual DVB-T PCI " \
"(DVB-T PC160-2T)",
- .cold_ids = {&af9015_usb_table[8], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_PLUSTV_PC160],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "AVerMedia AVerTV DVB-T Volar X",
- .cold_ids = {&af9015_usb_table[9], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERTV_VOLAR_X],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "TerraTec Cinergy T Stick RC",
- .cold_ids = {&af9015_usb_table[33], NULL},
+ .cold_ids = {
+ &af9015_usb_table[CINERGY_T_STICK_RC],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "TerraTec Cinergy T Stick Dual RC",
- .cold_ids = {&af9015_usb_table[34], NULL},
+ .cold_ids = {
+ &af9015_usb_table[CINERGY_T_DUAL_RC],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "AverMedia AVerTV Red HD+ (A850T)",
- .cold_ids = {&af9015_usb_table[35], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERTV_A850T],
+ NULL
+ },
.warm_ids = {NULL},
},
}
@@ -1496,57 +1693,87 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.devices = {
{
.name = "Xtensions XD-380",
- .cold_ids = {&af9015_usb_table[10], NULL},
+ .cold_ids = {
+ &af9015_usb_table[XTENSIONS_380U],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "MSI DIGIVOX Duo",
- .cold_ids = {&af9015_usb_table[11], NULL},
+ .cold_ids = {
+ &af9015_usb_table[MSI_DIGIVOX_DUO],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
- .cold_ids = {&af9015_usb_table[12], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERTV_VOLAR_X_REV2],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Telestar Starstick 2",
- .cold_ids = {&af9015_usb_table[13], NULL},
+ .cold_ids = {
+ &af9015_usb_table[TELESTAR_STARSTICK_2],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "AVerMedia A309",
- .cold_ids = {&af9015_usb_table[14], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERMEDIA_A309_USB],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "MSI Digi VOX mini III",
- .cold_ids = {&af9015_usb_table[15], NULL},
+ .cold_ids = {
+ &af9015_usb_table[MSI_DIGIVOX_MINI_III],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld USB DVB-T TV Stick II " \
"(VS-DVB-T 395U)",
- .cold_ids = {&af9015_usb_table[16],
- &af9015_usb_table[17],
- &af9015_usb_table[18],
- &af9015_usb_table[31], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_E396],
+ &af9015_usb_table[KWORLD_E39B],
+ &af9015_usb_table[KWORLD_E395],
+ &af9015_usb_table[KWORLD_E39A],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "TrekStor DVB-T USB Stick",
- .cold_ids = {&af9015_usb_table[19], NULL},
+ .cold_ids = {
+ &af9015_usb_table[TREKSTOR_DVBT],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "AverMedia AVerTV Volar Black HD " \
"(A850)",
- .cold_ids = {&af9015_usb_table[20], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERTV_A850],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
- .cold_ids = {&af9015_usb_table[37], NULL},
+ .cold_ids = {
+ &af9015_usb_table[SVEON_STV22],
+ NULL
+ },
.warm_ids = {NULL},
},
}
@@ -1619,50 +1846,77 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.devices = {
{
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
- .cold_ids = {&af9015_usb_table[21], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERTV_A805],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
"V3.0",
- .cold_ids = {&af9015_usb_table[22], NULL},
+ .cold_ids = {
+ &af9015_usb_table[CONCEPTRONIC_CTVDIGRCU],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld Digial MC-810",
- .cold_ids = {&af9015_usb_table[23], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_MC810],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Genius TVGo DVB-T03",
- .cold_ids = {&af9015_usb_table[24], NULL},
+ .cold_ids = {
+ &af9015_usb_table[GENIUS_TVGO_DVB_T03],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld PlusTV DVB-T PCI Pro Card " \
"(DVB-T PC160-T)",
- .cold_ids = {&af9015_usb_table[26], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_PC160_T],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Sveon STV20 Tuner USB DVB-T HDTV",
- .cold_ids = {&af9015_usb_table[27], NULL},
+ .cold_ids = {
+ &af9015_usb_table[SVEON_STV20],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "Leadtek WinFast DTV2000DS",
- .cold_ids = {&af9015_usb_table[29], NULL},
+ .cold_ids = {
+ &af9015_usb_table[WINFAST_DTV2000DS],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "KWorld USB DVB-T Stick Mobile " \
"(UB383-T)",
- .cold_ids = {&af9015_usb_table[30], NULL},
+ .cold_ids = {
+ &af9015_usb_table[KWORLD_UB383_T],
+ NULL
+ },
.warm_ids = {NULL},
},
{
.name = "AverMedia AVerTV Volar M (A815Mac)",
- .cold_ids = {&af9015_usb_table[32], NULL},
+ .cold_ids = {
+ &af9015_usb_table[AVERMEDIA_A815M],
+ NULL
+ },
.warm_ids = {NULL},
},
}
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index 6252ea6..f619063 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -102,6 +102,12 @@ struct af9015_state {
u8 rc_repeat;
u32 rc_keycode;
u8 rc_last[4];
+
+ /* for demod callback override */
+ int (*set_frontend[2]) (struct dvb_frontend *fe);
+ int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status);
+ int (*init[2]) (struct dvb_frontend *fe);
+ int (*sleep[2]) (struct dvb_frontend *fe);
};
struct af9015_config {
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index b39f14f..d661929 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -41,6 +41,7 @@
#include "stv0900.h"
#include "stv6110.h"
#include "isl6423.h"
+#include "cxd2820r.h"
/* debug */
static int dvb_usb_anysee_debug;
@@ -66,10 +67,12 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
return -EAGAIN;
+ deb_xfer(">>> ");
+ debug_dump(buf, slen, deb_xfer);
+
/* 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);
-
if (!ret) {
/* receive 2nd answer */
ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
@@ -79,7 +82,10 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
err("%s: recv bulk message failed: %d", __func__, ret);
else {
deb_xfer("<<< ");
- debug_dump(buf, act_len, deb_xfer);
+ debug_dump(buf, rlen, deb_xfer);
+
+ if (buf[63] != 0x4f)
+ deb_info("%s: cmd failed\n", __func__);
}
}
@@ -129,6 +135,29 @@ static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
return anysee_write_reg(d, reg, val);
}
+/* read single register with mask */
+static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val,
+ u8 mask)
+{
+ int ret, i;
+ u8 tmp;
+
+ ret = anysee_read_reg(d, reg, &tmp);
+ if (ret)
+ return ret;
+
+ tmp &= mask;
+
+ /* find position of the first bit */
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 0x01)
+ break;
+ }
+ *val = tmp >> i;
+
+ return 0;
+}
+
static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
{
u8 buf[] = {CMD_GET_HW_INFO};
@@ -156,22 +185,6 @@ static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
}
-static int anysee_init(struct dvb_usb_device *d)
-{
- int ret;
- /* LED light */
- ret = anysee_led_ctrl(d, 0x01, 0x03);
- if (ret)
- return ret;
-
- /* enable IR */
- ret = anysee_ir_ctrl(d, 1);
- if (ret)
- return ret;
-
- return 0;
-}
-
/* I2C */
static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
int num)
@@ -297,7 +310,7 @@ static struct tda10023_config anysee_tda10023_tda18212_config = {
.pll_m = 12,
.pll_p = 3,
.pll_n = 1,
- .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+ .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B,
.deltaf = 0xba02,
};
@@ -309,6 +322,17 @@ static struct tda18212_config anysee_tda18212_config = {
.if_dvbc = 5000,
};
+static struct tda18212_config anysee_tda18212_config2 = {
+ .i2c_address = 0x60 /* (0xc0 >> 1) */,
+ .if_dvbt_6 = 3550,
+ .if_dvbt_7 = 3700,
+ .if_dvbt_8 = 4150,
+ .if_dvbt2_6 = 3250,
+ .if_dvbt2_7 = 4000,
+ .if_dvbt2_8 = 4000,
+ .if_dvbc = 5000,
+};
+
static struct cx24116_config anysee_cx24116_config = {
.demod_address = (0xaa >> 1),
.mpg_clk_pos_pol = 0x00,
@@ -339,6 +363,11 @@ static struct isl6423_config anysee_isl6423_config = {
.addr = (0x10 >> 1),
};
+static struct cxd2820r_config anysee_cxd2820r_config = {
+ .i2c_address = 0x6d, /* (0xda >> 1) */
+ .ts_mode = 0x38,
+};
+
/*
* New USB device strings: Mfr=1, Product=2, SerialNumber=0
* Manufacturer: AMT.CO.KR
@@ -421,6 +450,14 @@ static struct isl6423_config anysee_isl6423_config = {
* IOA[7] TS 1=enabled
* IOE[5] STV0903 1=enabled
*
+ * E7 T2C VID=1c73 PID=861f HW=20 FW=0.1 AMTCI=0.5 "anysee-E7T2C(LP)"
+ * PCB: 508T2C (rev0.3)
+ * parts: DNOQ44QCH106A(CXD2820R, TDA18212), TDA8024
+ * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
+ * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
+ * IOA[7] TS 1=enabled
+ * IOE[5] CXD2820R 1=enabled
+ *
* E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)"
* PCB: 508PTC (rev0.5)
* parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
@@ -437,7 +474,7 @@ static struct isl6423_config anysee_isl6423_config = {
* IOD[6] ZL10353 1=enabled
* IOE[0] IF 0=enabled
*
- * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
+ * E7 PS2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
* PCB: 508PS2 (rev0.4)
* parts: DNBU10512IST(STV0903, STV6110), ISL6423
* OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
@@ -446,6 +483,16 @@ static struct isl6423_config anysee_isl6423_config = {
* IOE[5] STV0903 1=enabled
*/
+
+/* 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);
+}
+
static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
@@ -577,7 +624,8 @@ 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 bug).
+ * 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)
@@ -606,14 +654,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
break;
/* attach demod */
- adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(mt352_attach,
+ &anysee_mt352_config, &adap->dev->i2c_adap);
if (adap->fe_adap[0].fe)
break;
/* attach demod */
- adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
+ &anysee_zl10353_config, &adap->dev->i2c_adap);
break;
case ANYSEE_HW_507CD: /* 6 */
@@ -665,8 +713,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
- &adap->dev->i2c_adap);
+ adap->fe_adap[0].fe = dvb_attach(cx24116_attach,
+ &anysee_cx24116_config, &adap->dev->i2c_adap);
break;
case ANYSEE_HW_507FA: /* 15 */
@@ -747,17 +795,19 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
}
}
+ /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+ 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;
+ }
+
break;
case ANYSEE_HW_508TC: /* 18 */
case ANYSEE_HW_508PTC: /* 21 */
/* E7 TC */
/* E7 PTC */
- /* enable transport stream on IOA[7] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
- if (ret)
- goto error;
-
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),
@@ -772,7 +822,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
+ adap->fe_adap[state->fe_id].fe =
+ dvb_attach(tda10023_attach,
&anysee_tda10023_tda18212_config,
&adap->dev->i2c_adap, 0x48);
} else {
@@ -789,11 +840,19 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
goto error;
/* attach demod */
- adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
+ adap->fe_adap[state->fe_id].fe =
+ dvb_attach(zl10353_attach,
&anysee_zl10353_tda18212_config,
&adap->dev->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;
+
+ state->has_ci = true;
+
break;
case ANYSEE_HW_508S2: /* 19 */
case ANYSEE_HW_508PS2: /* 22 */
@@ -803,19 +862,41 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
if (state->fe_id)
break;
- /* enable transport stream on IOA[7] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
+ /* enable DVB-S/S2 demod on IOE[5] */
+ ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
if (ret)
goto error;
- /* enable DVB-S/S2 demod on IOE[5] */
+ /* attach demod */
+ adap->fe_adap[0].fe = dvb_attach(stv0900_attach,
+ &anysee_stv0900_config, &adap->dev->i2c_adap, 0);
+
+ state->has_ci = true;
+
+ break;
+ case ANYSEE_HW_508T2C: /* 20 */
+ /* E7 T2C */
+
+ /* enable DVB-T/T2/C demod on IOE[5] */
ret = anysee_wr_reg_mask(adap->dev, 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);
+ if (state->fe_id == 0) {
+ /* DVB-T/T2 */
+ adap->fe_adap[state->fe_id].fe =
+ dvb_attach(cxd2820r_attach,
+ &anysee_cxd2820r_config,
+ &adap->dev->i2c_adap, NULL);
+ } else {
+ /* DVB-C */
+ adap->fe_adap[state->fe_id].fe =
+ dvb_attach(cxd2820r_attach,
+ &anysee_cxd2820r_config,
+ &adap->dev->i2c_adap, adap->fe_adap[0].fe);
+ }
+
+ state->has_ci = true;
break;
}
@@ -842,24 +923,26 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* 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_adap[0].fe,
+ (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_adap[0].fe,
+ (0xc2 >> 1), &adap->dev->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_adap[0].fe,
+ (0xc0 >> 1), &adap->dev->i2c_adap,
+ DVB_PLL_SAMSUNG_DTOS403IH102A);
break;
case ANYSEE_HW_507SI: /* 11 */
@@ -877,22 +960,12 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* Try first attach TDA18212 silicon tuner on IOE[4], if that
* fails attach old simple PLL. */
- /* enable tuner on IOE[4] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
- if (ret)
- goto error;
-
/* attach tuner */
fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
&adap->dev->i2c_adap, &anysee_tda18212_config);
if (fe)
break;
- /* disable tuner on IOE[4] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
- if (ret)
- goto error;
-
/* attach tuner */
fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
(0xc0 >> 1), &adap->dev->i2c_adap,
@@ -904,11 +977,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
/* E7 TC */
/* E7 PTC */
- /* enable tuner on IOE[4] */
- ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
- if (ret)
- goto error;
-
/* attach tuner */
fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
&adap->dev->i2c_adap, &anysee_tda18212_config);
@@ -930,6 +998,15 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
}
break;
+
+ case ANYSEE_HW_508T2C: /* 20 */
+ /* E7 T2C */
+
+ /* attach tuner */
+ fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
+ &adap->dev->i2c_adap, &anysee_tda18212_config2);
+
+ break;
default:
fe = NULL;
}
@@ -939,7 +1016,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
else
ret = -ENODEV;
-error:
return ret;
}
@@ -969,6 +1045,201 @@ static int anysee_rc_query(struct dvb_usb_device *d)
return 0;
}
+static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
+ int addr)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+ u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1};
+ u8 val;
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
+ if (ret)
+ return ret;
+
+ return val;
+}
+
+static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
+ int addr, u8 val)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+ u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val};
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot,
+ u8 addr)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+ u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1};
+ u8 val;
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
+ if (ret)
+ return ret;
+
+ return val;
+}
+
+static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot,
+ u8 addr, u8 val)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+ u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val};
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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;
+
+ state->ci_cam_ready = jiffies + msecs_to_jiffies(1000);
+
+ ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
+ if (ret)
+ return ret;
+
+ msleep(300);
+
+ ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+
+ ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
+ if (ret)
+ return ret;
+
+ msleep(30);
+
+ ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
+{
+ struct dvb_usb_device *d = ci->data;
+ int ret;
+
+ ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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;
+ int ret;
+ u8 tmp;
+
+ ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40);
+ if (ret)
+ return ret;
+
+ if (tmp == 0) {
+ ret = DVB_CA_EN50221_POLL_CAM_PRESENT;
+ if (time_after(jiffies, state->ci_cam_ready))
+ ret |= DVB_CA_EN50221_POLL_CAM_READY;
+ }
+
+ return ret;
+}
+
+static int anysee_ci_init(struct dvb_usb_device *d)
+{
+ struct anysee_state *state = d->priv;
+ int ret;
+
+ state->ci.owner = THIS_MODULE;
+ state->ci.read_attribute_mem = anysee_ci_read_attribute_mem;
+ state->ci.write_attribute_mem = anysee_ci_write_attribute_mem;
+ state->ci.read_cam_control = anysee_ci_read_cam_control;
+ state->ci.write_cam_control = anysee_ci_write_cam_control;
+ state->ci.slot_reset = anysee_ci_slot_reset;
+ state->ci.slot_shutdown = anysee_ci_slot_shutdown;
+ state->ci.slot_ts_enable = anysee_ci_slot_ts_enable;
+ state->ci.poll_slot_status = anysee_ci_poll_slot_status;
+ state->ci.data = d;
+
+ ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
+ if (ret)
+ return ret;
+
+ ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void anysee_ci_release(struct dvb_usb_device *d)
+{
+ struct anysee_state *state = d->priv;
+
+ /* detach CI */
+ if (state->has_ci)
+ dvb_ca_en50221_release(&state->ci);
+
+ return;
+}
+
+static int anysee_init(struct dvb_usb_device *d)
+{
+ struct anysee_state *state = d->priv;
+ int ret;
+
+ /* LED light */
+ ret = anysee_led_ctrl(d, 0x01, 0x03);
+ if (ret)
+ return ret;
+
+ /* enable IR */
+ ret = anysee_ir_ctrl(d, 1);
+ if (ret)
+ return ret;
+
+ /* attach CI */
+ if (state->has_ci) {
+ ret = anysee_ci_init(d);
+ if (ret) {
+ state->has_ci = false;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties anysee_properties;
@@ -1010,6 +1281,16 @@ static int anysee_probe(struct usb_interface *intf,
return anysee_init(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) },
@@ -1029,7 +1310,7 @@ static struct dvb_usb_device_properties anysee_properties = {
{
.num_frontends = 2,
.frontend_ctrl = anysee_frontend_ctrl,
- .fe = {{
+ .fe = { {
.streaming_ctrl = anysee_streaming_ctrl,
.frontend_attach = anysee_frontend_attach,
.tuner_attach = anysee_tuner_attach,
@@ -1057,7 +1338,7 @@ static struct dvb_usb_device_properties anysee_properties = {
}
}
},
- }},
+ } },
}
},
@@ -1087,7 +1368,7 @@ static struct dvb_usb_device_properties anysee_properties = {
static struct usb_driver anysee_driver = {
.name = "dvb_usb_anysee",
.probe = anysee_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = anysee_disconnect,
.id_table = anysee_table,
};
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
index 57ee500..8ac8794 100644
--- a/drivers/media/dvb/dvb-usb/anysee.h
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -36,6 +36,7 @@
#define DVB_USB_LOG_PREFIX "anysee"
#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)
@@ -54,12 +55,16 @@ enum cmd {
CMD_GET_IR_CODE = 0x41,
CMD_GET_HW_INFO = 0x19,
CMD_SMARTCARD = 0x34,
+ CMD_CI = 0x37,
};
struct anysee_state {
u8 hw; /* PCB ID */
u8 seq;
u8 fe_id:1; /* frondend ID */
+ u8 has_ci:1;
+ struct dvb_ca_en50221 ci;
+ unsigned long ci_cam_ready; /* jiffies */
};
#define ANYSEE_HW_507T 2 /* E30 */
@@ -69,6 +74,7 @@ struct anysee_state {
#define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */
#define ANYSEE_HW_508TC 18 /* E7 TC */
#define ANYSEE_HW_508S2 19 /* E7 S2 */
+#define ANYSEE_HW_508T2C 20 /* E7 T2C */
#define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */
#define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
index 9cd51ac..8a57ed8 100644
--- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
@@ -40,9 +40,8 @@
* We replace errornous fields by default TPS fields (the ones with value 0).
*/
-static uint16_t compute_tps(struct dvb_frontend_parameters *p)
+static uint16_t compute_tps(struct dtv_frontend_properties *op)
{
- struct dvb_ofdm_parameters *op = &p->u.ofdm;
uint16_t tps = 0;
switch (op->code_rate_HP) {
@@ -83,7 +82,7 @@ static uint16_t compute_tps(struct dvb_frontend_parameters *p)
/* tps |= (0 << 4) */;
}
- switch (op->constellation) {
+ switch (op->modulation) {
case QAM_16:
tps |= (1 << 13);
break;
@@ -119,7 +118,7 @@ static uint16_t compute_tps(struct dvb_frontend_parameters *p)
/* tps |= (0 << 2) */;
}
- switch (op->hierarchy_information) {
+ switch (op->hierarchy) {
case HIERARCHY_1:
tps |= (1 << 10);
break;
@@ -263,9 +262,9 @@ static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_set_parameters_msg param;
char result[2];
@@ -274,9 +273,20 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
param.tps = cpu_to_le16(compute_tps(fep));
param.freq = cpu_to_le32(fep->frequency / 1000);
- param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
param.flags = 0;
+ switch (fep->bandwidth_hz) {
+ case 8000000:
+ param.bandwidth = 0;
+ break;
+ case 7000000:
+ param.bandwidth = 1;
+ break;
+ case 6000000:
+ param.bandwidth = 2;
+ break;
+ }
+
err = dvb_usb_generic_rw(state->d,
(char *)&param, sizeof(param),
result, sizeof(result), 0);
@@ -286,12 +296,6 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
return (err < 0) ? err : 0;
}
-static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
-{
- return 0;
-}
-
static void cinergyt2_fe_release(struct dvb_frontend *fe)
{
struct cinergyt2_fe_state *state = fe->demodulator_priv;
@@ -316,9 +320,9 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
static struct dvb_frontend_ops cinergyt2_fe_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = DRIVER_NAME,
- .type = FE_OFDM,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 166667,
@@ -341,7 +345,6 @@ static struct dvb_frontend_ops cinergyt2_fe_ops = {
.sleep = cinergyt2_fe_sleep,
.set_frontend = cinergyt2_fe_set_frontend,
- .get_frontend = cinergyt2_fe_get_frontend,
.get_tune_settings = cinergyt2_fe_get_tune_settings,
.read_status = cinergyt2_fe_read_status,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 949ea1b..3940bb0 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -1067,18 +1067,17 @@ static struct dib0070_config dib7070p_dib0070_config = {
};
struct dib0700_adapter_state {
- int (*set_param_save) (struct dvb_frontend *,
- struct dvb_frontend_parameters *);
+ int (*set_param_save) (struct dvb_frontend *);
};
-static int dib7070_set_param_override(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int dib7070_set_param_override(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
u16 offset;
- u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF: offset = 950; break;
default:
@@ -1087,7 +1086,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe,
dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
- return state->set_param_save(fe, fep);
+ return state->set_param_save(fe);
}
static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index f313182..81ef4b4 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -30,7 +30,7 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif
"if applicable for the device (default: 0=automatic/off).");
struct dib0700_adapter_state {
- int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
+ int (*set_param_save) (struct dvb_frontend *);
const struct firmware *frontend_firmware;
};
@@ -804,13 +804,14 @@ static struct dib0070_config dib7770p_dib0070_config = {
.charge_pump = 2,
};
-static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7070_set_param_override(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
u16 offset;
- u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF: offset = 950; break;
case BAND_UHF:
@@ -818,17 +819,17 @@ static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_fronte
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
- return state->set_param_save(fe, fep);
+ return state->set_param_save(fe);
}
-static int dib7770_set_param_override(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int dib7770_set_param_override(struct dvb_frontend *fe)
{
- struct dvb_usb_adapter *adap = fe->dvb->priv;
- struct dib0700_adapter_state *state = adap->priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
u16 offset;
- u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF:
dib7000p_set_gpio(fe, 0, 0, 1);
@@ -842,7 +843,7 @@ static int dib7770_set_param_override(struct dvb_frontend *fe,
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
- return state->set_param_save(fe, fep);
+ return state->set_param_save(fe);
}
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
@@ -1205,14 +1206,14 @@ static struct dib0070_config dib807x_dib0070_config[2] = {
}
};
-static int dib807x_set_param_override(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int dib807x_set_param_override(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
u16 offset = dib0070_wbd_offset(fe);
- u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF:
offset += 750;
@@ -1224,7 +1225,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe,
deb_info("WBD for DiB8000: %d\n", offset);
dib8000_set_wbd_ref(fe, offset);
- return state->set_param_save(fe, fep);
+ return state->set_param_save(fe);
}
static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
@@ -1279,7 +1280,7 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
- 0x80);
+ 0x80, 0);
adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
@@ -1308,7 +1309,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
+ dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
@@ -1319,7 +1320,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
{
/* initialize IC 1 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
+ dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
@@ -1328,7 +1329,7 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
}
/* STK8096GP */
-struct dibx000_agc_config dib8090_agc_config[2] = {
+static struct dibx000_agc_config dib8090_agc_config[2] = {
{
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
@@ -1503,22 +1504,22 @@ static struct dib0090_config dib809x_dib0090_config = {
.fref_clock_ratio = 6,
};
-static int dib8096_set_param_override(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int dib8096_set_param_override(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
- u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
u16 target;
int ret = 0;
enum frontend_tune_state tune_state = CT_SHUTDOWN;
u16 ltgain, rf_gain_limit;
- ret = state->set_param_save(fe, fep);
+ ret = state->set_param_save(fe);
if (ret < 0)
return ret;
- target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
+ target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
dib8000_set_wbd_ref(fe, target);
@@ -1578,7 +1579,7 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
+ dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
@@ -1629,7 +1630,7 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
+ dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
if (adap->fe_adap[0].fe == NULL)
@@ -1641,6 +1642,261 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
return fe_slave == NULL ? -ENODEV : 0;
}
+/* TFE8096P */
+static struct dibx000_agc_config dib8096p_agc_config[2] = {
+ {
+ .band_caps = BAND_UHF,
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
+ P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
+ P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+ P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
+ P_agc_write=0 */
+ .setup = (0 << 15) | (0 << 14) | (5 << 11)
+ | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
+ | (0 << 4) | (5 << 1) | (0 << 0),
+
+ .inv_gain = 684,
+ .time_stabiliz = 10,
+
+ .alpha_level = 0,
+ .thlock = 118,
+
+ .wbd_inv = 0,
+ .wbd_ref = 1200,
+ .wbd_sel = 3,
+ .wbd_alpha = 5,
+
+ .agc1_max = 65535,
+ .agc1_min = 0,
+
+ .agc2_max = 32767,
+ .agc2_min = 0,
+
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 0,
+ .agc1_pt3 = 105,
+ .agc1_slope1 = 0,
+ .agc1_slope2 = 156,
+ .agc2_pt1 = 105,
+ .agc2_pt2 = 255,
+ .agc2_slope1 = 54,
+ .agc2_slope2 = 0,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
+ } , {
+ .band_caps = BAND_FM | BAND_VHF | BAND_CBAND,
+ /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
+ P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
+ P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+ P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
+ P_agc_write=0 */
+ .setup = (0 << 15) | (0 << 14) | (5 << 11)
+ | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
+ | (0 << 4) | (5 << 1) | (0 << 0),
+
+ .inv_gain = 732,
+ .time_stabiliz = 10,
+
+ .alpha_level = 0,
+ .thlock = 118,
+
+ .wbd_inv = 0,
+ .wbd_ref = 1200,
+ .wbd_sel = 3,
+ .wbd_alpha = 5,
+
+ .agc1_max = 65535,
+ .agc1_min = 0,
+
+ .agc2_max = 32767,
+ .agc2_min = 0,
+
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 0,
+ .agc1_pt3 = 98,
+ .agc1_slope1 = 0,
+ .agc1_slope2 = 167,
+ .agc2_pt1 = 98,
+ .agc2_pt2 = 255,
+ .agc2_slope1 = 52,
+ .agc2_slope2 = 0,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
+ }
+};
+
+static struct dibx000_bandwidth_config dib8096p_clock_config_12_mhz = {
+ 108000, 13500,
+ 1, 9, 1, 0, 0,
+ 0, 0, 0, 0, 2,
+ (3 << 14) | (1 << 12) | (524 << 0),
+ (0 << 25) | 0,
+ 20199729,
+ 12000000,
+};
+
+static struct dib8000_config tfe8096p_dib8000_config = {
+ .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .update_lna = NULL,
+
+ .agc_config_count = 2,
+ .agc = dib8096p_agc_config,
+ .pll = &dib8096p_clock_config_12_mhz,
+
+ .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
+
+ .agc_control = NULL,
+ .diversity_delay = 48,
+ .output_mode = OUTMODE_MPEG2_FIFO,
+ .enMpegOutput = 1,
+};
+
+static struct dib0090_wbd_slope dib8096p_wbd_table[] = {
+ { 380, 81, 850, 64, 540, 4},
+ { 860, 51, 866, 21, 375, 4},
+ {1700, 0, 250, 0, 100, 6},
+ {2600, 0, 250, 0, 100, 6},
+ { 0xFFFF, 0, 0, 0, 0, 0},
+};
+
+static const struct dib0090_config tfe8096p_dib0090_config = {
+ .io.clock_khz = 12000,
+ .io.pll_bypass = 0,
+ .io.pll_range = 0,
+ .io.pll_prediv = 3,
+ .io.pll_loopdiv = 6,
+ .io.adc_clock_ratio = 0,
+ .io.pll_int_loop_filt = 0,
+ .reset = dib8096p_tuner_sleep,
+ .sleep = dib8096p_tuner_sleep,
+
+ .freq_offset_khz_uhf = -143,
+ .freq_offset_khz_vhf = -143,
+
+ .get_adc_power = dib8090_get_adc_power,
+
+ .clkouttobamse = 1,
+ .analog_output = 0,
+
+ .wbd_vhf_offset = 0,
+ .wbd_cband_offset = 0,
+ .use_pwm_agc = 1,
+ .clkoutdrive = 0,
+
+ .fref_clock_ratio = 1,
+
+ .wbd = dib8096p_wbd_table,
+
+ .ls_cfg_pad_drv = 0,
+ .data_tx_drv = 0,
+ .low_if = NULL,
+ .in_soc = 1,
+ .force_cband_input = 0,
+};
+
+struct dibx090p_adc {
+ u32 freq; /* RF freq MHz */
+ u32 timf; /* New Timf */
+ u32 pll_loopdiv; /* New prediv */
+ u32 pll_prediv; /* New loopdiv */
+};
+
+struct dibx090p_adc dib8090p_adc_tab[] = {
+ { 50000, 17043521, 16, 3}, /* 64 MHz */
+ {878000, 20199729, 9, 1}, /* 60 MHz */
+ {0xffffffff, 0, 0, 0}, /* 60 MHz */
+};
+
+static int dib8096p_agc_startup(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+ struct dibx000_bandwidth_config pll;
+ u16 target;
+ int better_sampling_freq = 0, ret;
+ struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0];
+
+ ret = state->set_param_save(fe);
+ if (ret < 0)
+ return ret;
+ memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
+
+ dib0090_pwm_gain_reset(fe);
+ /* dib0090_get_wbd_target is returning any possible
+ temperature compensated wbd-target */
+ target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
+ dib8000_set_wbd_ref(fe, target);
+
+
+ while (p->frequency / 1000 > adc_table->freq) {
+ better_sampling_freq = 1;
+ adc_table++;
+ }
+
+ if ((adc_table->freq != 0xffffffff) && better_sampling_freq) {
+ pll.pll_ratio = adc_table->pll_loopdiv;
+ pll.pll_prediv = adc_table->pll_prediv;
+ dib8000_update_pll(fe, &pll);
+ dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc_table->timf);
+ }
+ return 0;
+}
+
+static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
+
+ adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
+ &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
+
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
+}
+
+static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
+
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+ &tfe8096p_dib0090_config) == NULL)
+ return -ENODEV;
+
+ dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
+ return 0;
+}
+
/* STK9090M */
static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
@@ -1883,7 +2139,7 @@ static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
return -ENODEV;
- dib0700_set_i2c_speed(adap->dev, 2000);
+ dib0700_set_i2c_speed(adap->dev, 1500);
if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
release_firmware(state->frontend_firmware);
@@ -1962,7 +2218,8 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
return -ENODEV;
- dib0700_set_i2c_speed(adap->dev, 2000);
+
+ dib0700_set_i2c_speed(adap->dev, 1500);
if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
return -ENODEV;
@@ -1975,7 +2232,7 @@ static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
return -ENODEV;
fe_slave->dvb = adap->fe_adap[0].fe->dvb;
- dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 2000);
+ dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 1500);
if (dib9000_firmware_post_pll_init(fe_slave) < 0)
return -ENODEV;
}
@@ -2064,7 +2321,7 @@ static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_
return 0;
}
-static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7090_agc_startup(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
@@ -2073,13 +2330,13 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para
struct dib7090p_best_adc adc;
int ret;
- ret = state->set_param_save(fe, fep);
+ ret = state->set_param_save(fe);
if (ret < 0)
return ret;
memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
dib0090_pwm_gain_reset(fe);
- target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2;
+ target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
dib7000p_set_wbd_ref(fe, target);
if (dib7090p_get_best_sampling(fe, &adc) == 0) {
@@ -2092,6 +2349,49 @@ static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_para
return 0;
}
+static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
+{
+ deb_info("AGC restart callback: %d", restart);
+ if (restart == 0) /* before AGC startup */
+ dib0090_set_dc_servo(fe, 1);
+ return 0;
+}
+
+static int dib7090e_update_lna(struct dvb_frontend *fe, u16 agc_global)
+{
+ u16 agc1 = 0, agc2, wbd = 0, wbd_target, wbd_offset, threshold_agc1;
+ s16 wbd_delta;
+
+ if ((fe->dtv_property_cache.frequency) < 400000000)
+ threshold_agc1 = 25000;
+ else
+ threshold_agc1 = 30000;
+
+ wbd_target = (dib0090_get_wbd_target(fe)*8+1)/2;
+ wbd_offset = dib0090_get_wbd_offset(fe);
+ dib7000p_get_agc_values(fe, NULL, &agc1, &agc2, &wbd);
+ wbd_delta = (s16)wbd - (((s16)wbd_offset+10)*4) ;
+
+ deb_info("update lna, agc_global=%d agc1=%d agc2=%d",
+ agc_global, agc1, agc2);
+ deb_info("update lna, wbd=%d wbd target=%d wbd offset=%d wbd delta=%d",
+ wbd, wbd_target, wbd_offset, wbd_delta);
+
+ if ((agc1 < threshold_agc1) && (wbd_delta > 0)) {
+ dib0090_set_switch(fe, 1, 1, 1);
+ dib0090_set_vga(fe, 0);
+ dib0090_update_rframp_7090(fe, 0);
+ dib0090_update_tuning_table_7090(fe, 0);
+ } else {
+ dib0090_set_vga(fe, 1);
+ dib0090_update_rframp_7090(fe, 1);
+ dib0090_update_tuning_table_7090(fe, 1);
+ dib0090_set_switch(fe, 0, 0, 0);
+ }
+
+ return 0;
+}
+
static struct dib0090_wbd_slope dib7090_wbd_table[] = {
{ 380, 81, 850, 64, 540, 4},
{ 860, 51, 866, 21, 375, 4},
@@ -2100,7 +2400,16 @@ static struct dib0090_wbd_slope dib7090_wbd_table[] = {
{ 0xFFFF, 0, 0, 0, 0, 0},
};
-struct dibx000_agc_config dib7090_agc_config[2] = {
+static struct dib0090_wbd_slope dib7090e_wbd_table[] = {
+ { 380, 81, 850, 64, 540, 4},
+ { 700, 51, 866, 21, 320, 4},
+ { 860, 48, 666, 18, 330, 6},
+ {1700, 0, 250, 0, 100, 6},
+ {2600, 0, 250, 0, 100, 6},
+ { 0xFFFF, 0, 0, 0, 0, 0},
+};
+
+static struct dibx000_agc_config dib7090_agc_config[2] = {
{
.band_caps = BAND_UHF,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
@@ -2278,6 +2587,34 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
}
};
+static struct dib7000p_config tfe7090e_dib7000p_config = {
+ .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .tuner_is_baseband = 1,
+ .update_lna = dib7090e_update_lna,
+
+ .agc_config_count = 2,
+ .agc = dib7090_agc_config,
+
+ .bw = &dib7090_clock_config_12_mhz,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .pwm_freq_div = 0,
+
+ .agc_control = dib7090_agc_restart,
+
+ .spur_protect = 0,
+ .disable_sample_and_hold = 0,
+ .enable_current_mirror = 0,
+ .diversity_delay = 0,
+
+ .output_mode = OUTMODE_MPEG2_FIFO,
+ .enMpegOutput = 1,
+};
+
static const struct dib0090_config nim7090_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
@@ -2312,6 +2649,107 @@ static const struct dib0090_config nim7090_dib0090_config = {
.in_soc = 1,
};
+static const struct dib0090_config tfe7090e_dib0090_config = {
+ .io.clock_khz = 12000,
+ .io.pll_bypass = 0,
+ .io.pll_range = 0,
+ .io.pll_prediv = 3,
+ .io.pll_loopdiv = 6,
+ .io.adc_clock_ratio = 0,
+ .io.pll_int_loop_filt = 0,
+ .reset = dib7090_tuner_sleep,
+ .sleep = dib7090_tuner_sleep,
+
+ .freq_offset_khz_uhf = 0,
+ .freq_offset_khz_vhf = 0,
+
+ .get_adc_power = dib7090_get_adc_power,
+
+ .clkouttobamse = 1,
+ .analog_output = 0,
+
+ .wbd_vhf_offset = 0,
+ .wbd_cband_offset = 0,
+ .use_pwm_agc = 1,
+ .clkoutdrive = 0,
+
+ .fref_clock_ratio = 0,
+
+ .wbd = dib7090e_wbd_table,
+
+ .ls_cfg_pad_drv = 0,
+ .data_tx_drv = 0,
+ .low_if = NULL,
+ .in_soc = 1,
+ .force_cband_input = 1,
+ .is_dib7090e = 1,
+};
+
+static struct dib7000p_config tfe7790e_dib7000p_config = {
+ .output_mpeg2_in_188_bytes = 1,
+ .hostbus_diversity = 1,
+ .tuner_is_baseband = 1,
+ .update_lna = dib7090e_update_lna,
+
+ .agc_config_count = 2,
+ .agc = dib7090_agc_config,
+
+ .bw = &dib7090_clock_config_12_mhz,
+
+ .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+ .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+ .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+ .pwm_freq_div = 0,
+
+ .agc_control = dib7090_agc_restart,
+
+ .spur_protect = 0,
+ .disable_sample_and_hold = 0,
+ .enable_current_mirror = 0,
+ .diversity_delay = 0,
+
+ .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
+ .enMpegOutput = 1,
+};
+
+static const struct dib0090_config tfe7790e_dib0090_config = {
+ .io.clock_khz = 12000,
+ .io.pll_bypass = 0,
+ .io.pll_range = 0,
+ .io.pll_prediv = 3,
+ .io.pll_loopdiv = 6,
+ .io.adc_clock_ratio = 0,
+ .io.pll_int_loop_filt = 0,
+ .reset = dib7090_tuner_sleep,
+ .sleep = dib7090_tuner_sleep,
+
+ .freq_offset_khz_uhf = 0,
+ .freq_offset_khz_vhf = 0,
+
+ .get_adc_power = dib7090_get_adc_power,
+
+ .clkouttobamse = 1,
+ .analog_output = 0,
+
+ .wbd_vhf_offset = 0,
+ .wbd_cband_offset = 0,
+ .use_pwm_agc = 1,
+ .clkoutdrive = 0,
+
+ .fref_clock_ratio = 0,
+
+ .wbd = dib7090e_wbd_table,
+
+ .ls_cfg_pad_drv = 0,
+ .data_tx_drv = 0,
+ .low_if = NULL,
+ .in_soc = 1,
+ .force_cband_input = 1,
+ .is_dib7090e = 1,
+ .force_crystal_mode = 1,
+};
+
static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
{
.io.clock_khz = 12000,
@@ -2504,6 +2942,97 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int tfe7090e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+ 1, 0x10, &tfe7090e_dib7000p_config) != 0) {
+ err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ __func__);
+ return -ENODEV;
+ }
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80, &tfe7090e_dib7000p_config);
+
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
+}
+
+static int tfe7790e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_state *st = adap->dev->priv;
+
+ /* The TFE7790E requires the dib0700 to not be in master mode */
+ st->disable_streaming_master_mode = 1;
+
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+ msleep(20);
+ dib0700_ctrl_clock(adap->dev, 72, 1);
+ dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+ if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+ 1, 0x10, &tfe7790e_dib7000p_config) != 0) {
+ err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ __func__);
+ return -ENODEV;
+ }
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ 0x80, &tfe7790e_dib7000p_config);
+
+ return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
+}
+
+static int tfe7790e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c =
+ dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+ &tfe7790e_dib0090_config) == NULL)
+ return -ENODEV;
+
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ return 0;
+}
+
+static int tfe7090e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c =
+ dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+
+ if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
+ &tfe7090e_dib0090_config) == NULL)
+ return -ENODEV;
+
+ dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+ return 0;
+}
+
/* STK7070PD */
static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
{
@@ -2960,6 +3489,9 @@ struct usb_device_id dib0700_usb_id_table[] = {
/* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) },
+ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090E) },
+ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7790E) },
+/* 80 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE8096P) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -4025,6 +4557,127 @@ struct dvb_usb_device_properties dib0700_devices[] = {
RC_TYPE_NEC,
.change_protocol = dib0700_change_protocol,
},
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .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 = stk70x0p_pid_filter,
+ .pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+ .frontend_attach = tfe7090e_frontend_attach,
+ .tuner_attach = tfe7090e_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ } },
+
+ .size_of_priv =
+ sizeof(struct dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DiBcom TFE7090E reference design",
+ { &dib0700_usb_id_table[78], NULL },
+ { NULL },
+ },
+ },
+
+ .rc.core = {
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
+ .module_name = "dib0700",
+ .rc_query = dib0700_rc_query_old_firmware,
+ .allowed_protos = RC_TYPE_RC5 |
+ RC_TYPE_RC6 |
+ RC_TYPE_NEC,
+ .change_protocol = dib0700_change_protocol,
+ },
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .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 = stk70x0p_pid_filter,
+ .pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+ .frontend_attach = tfe7790e_frontend_attach,
+ .tuner_attach = tfe7790e_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ } },
+
+ .size_of_priv =
+ sizeof(struct dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DiBcom TFE7790E reference design",
+ { &dib0700_usb_id_table[79], NULL },
+ { NULL },
+ },
+ },
+
+ .rc.core = {
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
+ .module_name = "dib0700",
+ .rc_query = dib0700_rc_query_old_firmware,
+ .allowed_protos = RC_TYPE_RC5 |
+ RC_TYPE_RC6 |
+ RC_TYPE_NEC,
+ .change_protocol = dib0700_change_protocol,
+ },
+ }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+ .num_adapters = 1,
+ .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 = stk80xx_pid_filter,
+ .pid_filter_ctrl = stk80xx_pid_filter_ctrl,
+ .frontend_attach = tfe8096p_frontend_attach,
+ .tuner_attach = tfe8096p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+ } },
+
+ .size_of_priv =
+ sizeof(struct dib0700_adapter_state),
+ },
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DiBcom TFE8096P reference design",
+ { &dib0700_usb_id_table[80], NULL },
+ { NULL },
+ },
+ },
+
+ .rc.core = {
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_codes = RC_MAP_DIB0700_RC5_TABLE,
+ .module_name = "dib0700",
+ .rc_query = dib0700_rc_query_old_firmware,
+ .allowed_protos = RC_TYPE_RC5 |
+ RC_TYPE_RC6 |
+ RC_TYPE_NEC,
+ .change_protocol = dib0700_change_protocol,
+ },
},
};
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 0a9a798..ff34419 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -118,12 +118,12 @@ static struct mt352_config digitv_mt352_config = {
.demod_init = digitv_mt352_demod_init,
};
-static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
u8 b[5];
- fe->ops.tuner_ops.calc_regs(fe, fep, b, sizeof(b));
+ fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index 17413ad..3d81daa 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -16,7 +16,7 @@ struct dtt200u_fe_state {
fe_status_t stat;
- struct dvb_frontend_parameters fep;
+ struct dtv_frontend_properties fep;
struct dvb_frontend frontend;
};
@@ -100,22 +100,27 @@ static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
-static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dtt200u_fe_state *state = fe->demodulator_priv;
int i;
fe_status_t st;
u16 freq = fep->frequency / 250000;
u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
- switch (fep->u.ofdm.bandwidth) {
- case BANDWIDTH_8_MHZ: bwbuf[1] = 8; break;
- case BANDWIDTH_7_MHZ: bwbuf[1] = 7; break;
- case BANDWIDTH_6_MHZ: bwbuf[1] = 6; break;
- case BANDWIDTH_AUTO: return -EOPNOTSUPP;
- default:
- return -EINVAL;
+ switch (fep->bandwidth_hz) {
+ case 8000000:
+ bwbuf[1] = 8;
+ break;
+ case 7000000:
+ bwbuf[1] = 7;
+ break;
+ case 6000000:
+ bwbuf[1] = 6;
+ break;
+ default:
+ return -EINVAL;
}
dvb_usb_generic_write(state->d,bwbuf,2);
@@ -134,11 +139,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
return 0;
}
-static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dtt200u_fe_get_frontend(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dtt200u_fe_state *state = fe->demodulator_priv;
- memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
+ memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
return 0;
}
@@ -172,9 +177,9 @@ error:
}
static struct dvb_frontend_ops dtt200u_fe_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "WideView USB DVB-T",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 250000,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index ba4a751..ddf282f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -141,11 +141,17 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
goto err_dmx_dev;
}
- dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+ if ((ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net,
+ &adap->demux.dmx)) < 0) {
+ err("dvb_net_init failed: error %d",ret);
+ goto err_net_init;
+ }
adap->state |= DVB_USB_ADAP_STATE_DVB;
return 0;
+err_net_init:
+ dvb_dmxdev_release(&adap->dmxdev);
err_dmx_dev:
dvb_dmx_release(&adap->demux);
err_dmx:
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 2d08c9b..d390dda 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -109,10 +109,13 @@
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_NIM8096MD 0x1fa8
+#define USB_PID_DIBCOM_TFE8096P 0x1f9C
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DIBCOM_NIM7090 0x1bb2
#define USB_PID_DIBCOM_TFE7090PVR 0x1bb4
+#define USB_PID_DIBCOM_TFE7090E 0x1bb7
+#define USB_PID_DIBCOM_TFE7790E 0x1e6e
#define USB_PID_DIBCOM_NIM9090M 0x2383
#define USB_PID_DIBCOM_NIM9090MD 0x2384
#define USB_PID_DPOSH_M9206_COLD 0x9206
@@ -128,6 +131,8 @@
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500
#define USB_PID_ITETECH_IT9135 0x9135
+#define USB_PID_ITETECH_IT9135_9005 0x9005
+#define USB_PID_ITETECH_IT9135_9006 0x9006
#define USB_PID_KWORLD_399U 0xe399
#define USB_PID_KWORLD_399U_2 0xe400
#define USB_PID_KWORLD_395U 0xe396
@@ -322,6 +327,7 @@
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
#define USB_PID_SVEON_STV22 0xe401
+#define USB_PID_SVEON_STV22_IT9137 0xe411
#define USB_PID_AZUREWAVE_AZ6027 0x3275
#define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4
#define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index ff941d2..451c5a7 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1435,22 +1435,40 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
+enum dw2102_table_entry {
+ CYPRESS_DW2102,
+ CYPRESS_DW2101,
+ CYPRESS_DW2104,
+ TEVII_S650,
+ TERRATEC_CINERGY_S,
+ CYPRESS_DW3101,
+ TEVII_S630,
+ PROF_1100,
+ TEVII_S660,
+ PROF_7500,
+ GENIATECH_SU3000,
+ TERRATEC_CINERGY_S2,
+ TEVII_S480_1,
+ TEVII_S480_2,
+ X3M_SPC1400HD,
+};
+
static struct usb_device_id dw2102_table[] = {
- {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
- {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
- {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
- {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
- {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
- {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
- {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
- {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
- {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
- {USB_DEVICE(0x3034, 0x7500)},
- {USB_DEVICE(0x1f4d, 0x3000)},
- {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
- {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
- {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
- {USB_DEVICE(0x1f4d, 0x3100)},
+ [CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
+ [CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+ [CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
+ [TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
+ [TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
+ [CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
+ [TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
+ [PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
+ [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
+ [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
+ [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
+ [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
+ [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
+ [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
+ [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
{ }
};
@@ -1610,15 +1628,15 @@ static struct dvb_usb_device_properties dw2102_properties = {
.num_device_descs = 3,
.devices = {
{"DVBWorld DVB-S 2102 USB2.0",
- {&dw2102_table[0], NULL},
+ {&dw2102_table[CYPRESS_DW2102], NULL},
{NULL},
},
{"DVBWorld DVB-S 2101 USB2.0",
- {&dw2102_table[1], NULL},
+ {&dw2102_table[CYPRESS_DW2101], NULL},
{NULL},
},
{"TerraTec Cinergy S USB",
- {&dw2102_table[4], NULL},
+ {&dw2102_table[TERRATEC_CINERGY_S], NULL},
{NULL},
},
}
@@ -1664,11 +1682,11 @@ static struct dvb_usb_device_properties dw2104_properties = {
.num_device_descs = 2,
.devices = {
{ "DVBWorld DW2104 USB2.0",
- {&dw2102_table[2], NULL},
+ {&dw2102_table[CYPRESS_DW2104], NULL},
{NULL},
},
{ "TeVii S650 USB2.0",
- {&dw2102_table[3], NULL},
+ {&dw2102_table[TEVII_S650], NULL},
{NULL},
},
}
@@ -1715,7 +1733,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
.num_device_descs = 1,
.devices = {
{ "DVBWorld DVB-C 3101 USB2.0",
- {&dw2102_table[5], NULL},
+ {&dw2102_table[CYPRESS_DW3101], NULL},
{NULL},
},
}
@@ -1761,7 +1779,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
.num_device_descs = 1,
.devices = {
{"TeVii S630 USB",
- {&dw2102_table[6], NULL},
+ {&dw2102_table[TEVII_S630], NULL},
{NULL},
},
}
@@ -1770,33 +1788,33 @@ static struct dvb_usb_device_properties s6x0_properties = {
struct dvb_usb_device_properties *p1100;
static struct dvb_usb_device_description d1100 = {
"Prof 1100 USB ",
- {&dw2102_table[7], NULL},
+ {&dw2102_table[PROF_1100], NULL},
{NULL},
};
struct dvb_usb_device_properties *s660;
static struct dvb_usb_device_description d660 = {
"TeVii S660 USB",
- {&dw2102_table[8], NULL},
+ {&dw2102_table[TEVII_S660], NULL},
{NULL},
};
static struct dvb_usb_device_description d480_1 = {
"TeVii S480.1 USB",
- {&dw2102_table[12], NULL},
+ {&dw2102_table[TEVII_S480_1], NULL},
{NULL},
};
static struct dvb_usb_device_description d480_2 = {
"TeVii S480.2 USB",
- {&dw2102_table[13], NULL},
+ {&dw2102_table[TEVII_S480_2], NULL},
{NULL},
};
struct dvb_usb_device_properties *p7500;
static struct dvb_usb_device_description d7500 = {
"Prof 7500 USB DVB-S2",
- {&dw2102_table[9], NULL},
+ {&dw2102_table[PROF_7500], NULL},
{NULL},
};
@@ -1842,15 +1860,15 @@ static struct dvb_usb_device_properties su3000_properties = {
.num_device_descs = 3,
.devices = {
{ "SU3000HD DVB-S USB2.0",
- { &dw2102_table[10], NULL },
+ { &dw2102_table[GENIATECH_SU3000], NULL },
{ NULL },
},
{ "Terratec Cinergy S2 USB HD",
- { &dw2102_table[11], NULL },
+ { &dw2102_table[TERRATEC_CINERGY_S2], NULL },
{ NULL },
},
{ "X3M TV SPC1400HD PCI",
- { &dw2102_table[14], NULL },
+ { &dw2102_table[X3M_SPC1400HD], NULL },
{ NULL },
},
}
@@ -1859,12 +1877,11 @@ static struct dvb_usb_device_properties su3000_properties = {
static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
- p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+ p1100 = kmemdup(&s6x0_properties,
+ sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!p1100)
return -ENOMEM;
/* copy default structure */
- memcpy(p1100, &s6x0_properties,
- sizeof(struct dvb_usb_device_properties));
/* fill only different fields */
p1100->firmware = "dvb-usb-p1100.fw";
p1100->devices[0] = d1100;
@@ -1872,13 +1889,12 @@ static int dw2102_probe(struct usb_interface *intf,
p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
- s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+ s660 = kmemdup(&s6x0_properties,
+ sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!s660) {
kfree(p1100);
return -ENOMEM;
}
- memcpy(s660, &s6x0_properties,
- sizeof(struct dvb_usb_device_properties));
s660->firmware = "dvb-usb-s660.fw";
s660->num_device_descs = 3;
s660->devices[0] = d660;
@@ -1886,14 +1902,13 @@ static int dw2102_probe(struct usb_interface *intf,
s660->devices[2] = d480_2;
s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
- p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+ p7500 = kmemdup(&s6x0_properties,
+ sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
if (!p7500) {
kfree(p1100);
kfree(s660);
return -ENOMEM;
}
- memcpy(p7500, &s6x0_properties,
- sizeof(struct dvb_usb_device_properties));
p7500->firmware = "dvb-usb-p7500.fw";
p7500->devices[0] = d7500;
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c
index 015b4e8..90a70c6 100644
--- a/drivers/media/dvb/dvb-usb/friio-fe.c
+++ b/drivers/media/dvb/dvb-usb/friio-fe.c
@@ -282,23 +282,24 @@ static int jdvbt90502_set_property(struct dvb_frontend *fe,
return r;
}
-static int jdvbt90502_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int jdvbt90502_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
p->inversion = INVERSION_AUTO;
- p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
- p->u.ofdm.code_rate_HP = FEC_AUTO;
- p->u.ofdm.code_rate_LP = FEC_AUTO;
- p->u.ofdm.constellation = QAM_64;
- p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
- p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
- p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
+ p->bandwidth_hz = 6000000;
+ p->code_rate_HP = FEC_AUTO;
+ p->code_rate_LP = FEC_AUTO;
+ p->modulation = QAM_64;
+ p->transmission_mode = TRANSMISSION_MODE_AUTO;
+ p->guard_interval = GUARD_INTERVAL_AUTO;
+ p->hierarchy = HIERARCHY_AUTO;
return 0;
}
-static int jdvbt90502_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int jdvbt90502_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
/**
* NOTE: ignore all the parameters except frequency.
* others should be fixed to the proper value for ISDB-T,
@@ -438,14 +439,12 @@ error:
}
static struct dvb_frontend_ops jdvbt90502_ops = {
-
+ .delsys = { SYS_ISDBT },
.info = {
.name = "Comtech JDVBT90502 ISDB-T",
- .type = FE_OFDM,
.frequency_min = 473000000, /* UHF 13ch, center */
.frequency_max = 767142857, /* UHF 62ch, center */
- .frequency_stepsize = JDVBT90502_PLL_CLK /
- JDVBT90502_PLL_DIVIDER,
+ .frequency_stepsize = JDVBT90502_PLL_CLK / JDVBT90502_PLL_DIVIDER,
.frequency_tolerance = 0,
/* NOTE: this driver ignores all parameters but frequency. */
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index 5426267..67957dd 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -113,28 +113,12 @@ static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
return 0;
}
-static int gp8psk_fe_set_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- deb_fe("%s(..)\n", __func__);
- return 0;
-}
-
-static int gp8psk_fe_get_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- deb_fe("%s(..)\n", __func__);
- return 0;
-}
-
-
-static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
{
struct gp8psk_fe_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u8 cmd[10];
- u32 freq = fep->frequency * 1000;
+ u32 freq = c->frequency * 1000;
int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
deb_fe("%s()\n", __func__);
@@ -342,9 +326,9 @@ success:
static struct dvb_frontend_ops gp8psk_fe_ops = {
+ .delsys = { SYS_DVBS },
.info = {
.name = "Genpix DVB-S",
- .type = FE_QPSK,
.frequency_min = 800000,
.frequency_max = 2250000,
.frequency_stepsize = 100,
@@ -366,8 +350,6 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
.init = NULL,
.sleep = NULL,
- .set_property = gp8psk_fe_set_property,
- .get_property = gp8psk_fe_get_property,
.set_frontend = gp8psk_fe_set_frontend,
.get_tune_settings = gp8psk_fe_get_tune_settings,
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
index 67094b8..9f01cd7 100644
--- a/drivers/media/dvb/dvb-usb/it913x.c
+++ b/drivers/media/dvb/dvb-usb/it913x.c
@@ -52,42 +52,59 @@ 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 {
- u8 chip_ver;
- u16 chip_type;
- u32 firmware;
- u8 tuner_id_0;
- u8 tuner_id_1;
- u8 dual_mode;
+ struct ite_config it913x_config;
};
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;
+ 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 == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+ break;
+ }
+
+ if (len != actual_l && ret == 0)
+ ret = -EAGAIN;
- ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
- snd, len , &actual_l, 100);
return ret;
}
static int it913x_bulk_read(struct usb_device *dev,
u8 *rev, int len, u8 pipe)
{
- int ret, actual_l;
+ 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 == 0 || ret != -EBUSY || ret != -ETIMEDOUT)
+ break;
+ }
+
+ if (len != actual_l && ret == 0)
+ ret = -EAGAIN;
- ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
- rev, len , &actual_l, 200);
return ret;
}
@@ -100,7 +117,7 @@ static u16 check_sum(u8 *p, u8 len)
return ~sum;
}
-static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
+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;
@@ -159,22 +176,41 @@ static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
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) ?
+ 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];
+ ret = buff[2];
else
memcpy(data, &buff[3], rlen);
cmd_counter++;
- kfree(buff);
+error: kfree(buff);
- return (ret < 0) ? -ENODEV : 0;
+ 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)
@@ -223,15 +259,15 @@ static u32 it913x_query(struct usb_device *udev, u8 pro)
static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
- int ret = 0;
+ struct usb_device *udev = adap->dev->udev;
+ int ret;
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
return -EAGAIN;
deb_info(1, "PID_C (%02x)", onoff);
- if (!onoff)
- ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
+ ret = it913x_wr_reg(udev, pro, PID_EN, onoff);
mutex_unlock(&adap->dev->i2c_mutex);
return ret;
@@ -241,27 +277,20 @@ static int it913x_pid_filter(struct dvb_usb_adapter *adap,
int index, u16 pid, int onoff)
{
struct usb_device *udev = adap->dev->udev;
- int ret = 0;
+ int ret;
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
- if (pid_filter > 0)
- return 0;
-
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
return -EAGAIN;
deb_info(1, "PID_F (%02x)", onoff);
- if (onoff) {
- ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
-
- 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_LSB, (u8)(pid & 0xff));
- ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
+ ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
- ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
+ ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
- }
+ ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
mutex_unlock(&adap->dev->i2c_mutex);
return 0;
@@ -337,15 +366,73 @@ static int it913x_rc_query(struct dvb_usb_device *d)
if ((ibuf[2] + ibuf[3]) == 0xff) {
key = ibuf[2];
- key += ibuf[0] << 8;
- deb_info(1, "INT Key =%08x", key);
+ 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.idProduct) ==
+ USB_PID_ITETECH_IT9135)
+ sw = IT9135_V1_FW;
+ else if (le16_to_cpu(udev->descriptor.idProduct) ==
+ USB_PID_ITETECH_IT9135_9005)
+ sw = IT9135_V1_FW;
+ else if (le16_to_cpu(udev->descriptor.idProduct) ==
+ USB_PID_ITETECH_IT9135_9006) {
+ sw = IT9135_V2_FW;
+ if (it913x_config.tuner_id_0 == 0)
+ it913x_config.tuner_id_0 = IT9135_60;
+ } else
+ sw = IT9137_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;
+ props->firmware = fw_it9135_v1;
+ break;
+ case IT9135_V2_FW:
+ it913x_config.firmware_ver = 1;
+ it913x_config.adc_x2 = 1;
+ props->firmware = fw_it9135_v2;
+ break;
+ case IT9137_FW:
+ default:
+ it913x_config.firmware_ver = 0;
+ it913x_config.adc_x2 = 0;
+ props->firmware = fw_it9137;
+ }
+
+ return 0;
+}
+
+#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_identify_state(struct usb_device *udev,
struct dvb_usb_device_properties *props,
struct dvb_usb_device_description **desc,
@@ -359,6 +446,19 @@ static int it913x_identify_state(struct usb_device *udev,
/* checnk for dual mode */
it913x_config.dual_mode = it913x_read_reg(udev, 0x49c5);
+ 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;
+
/* TODO different remotes */
remote = it913x_read_reg(udev, 0x49ac); /* Remote */
if (remote == 0)
@@ -370,6 +470,28 @@ static int it913x_identify_state(struct usb_device *udev,
info("Dual mode=%x Remote=%x Tuner Type=%x", it913x_config.dual_mode
, remote, it913x_config.tuner_id_0);
+ /* 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;
+
+ ret = ite_firmware_select(udev, props);
+
if (firm_no > 0) {
*cold = 0;
return 0;
@@ -391,18 +513,22 @@ static int it913x_identify_state(struct usb_device *udev,
ret = it913x_wr_reg(udev, DEV_0,
GPIOH1_O, 0x0);
}
- props->num_adapters = 2;
- } else
- props->num_adapters = 1;
+ }
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);
- ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 0x1);
+ 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);
- ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 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;
@@ -428,35 +554,45 @@ static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return ret;
}
-
static int it913x_download_firmware(struct usb_device *udev,
const struct firmware *fw)
{
- int ret = 0, i;
- u8 packet_size, dlen;
+ int ret = 0, i = 0, pos = 0;
+ u8 packet_size, min_pkt;
u8 *fw_data;
- packet_size = 0x29;
-
ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_100);
info("FRM Starting Firmware Download");
- /* This uses scatter write firmware headers follow */
- /* 03 XX 00 XX = chip number? */
-
- for (i = 0; i < fw->size; i += packet_size) {
- if (i > 0)
- packet_size = 0x39;
- fw_data = (u8 *)(fw->data + i);
- dlen = ((i + packet_size) > fw->size)
- ? (fw->size - i) : packet_size;
- ret |= it913x_io(udev, WRITE_DATA, DEV_0,
- CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
- udelay(1000);
+
+ /* 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);
+ udelay(1000);
+ }
+ }
+ i++;
}
- ret |= it913x_io(udev, WRITE_CMD, DEV_0,
- CMD_BOOT, 0, 0, NULL, 0);
+ ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
msleep(100);
@@ -474,12 +610,17 @@ static int it913x_download_firmware(struct usb_device *udev,
/* Tuner function */
if (it913x_config.dual_mode)
ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
-
- 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);
+ 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;
@@ -500,32 +641,23 @@ static int it913x_name(struct dvb_usb_adapter *adap)
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 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
- u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
- u8 tuner_id, tuner_type;
+ 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)
- tuner_id = it913x_config.tuner_id_0;
- else
- tuner_id = it913x_config.tuner_id_1;
-
- /* TODO we always use IT9137 possible references here*/
- /* Documentation suggests don't care */
- switch (tuner_id) {
- case 0x51:
- case 0x52:
- case 0x60:
- case 0x61:
- case 0x62:
- default:
- case 0x38:
- tuner_type = IT9137;
- }
+ 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, adf, tuner_type);
+ &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);
@@ -536,13 +668,13 @@ static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
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, 0x80);
+ 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, 0x80);
+ 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);
@@ -582,6 +714,9 @@ static int it913x_probe(struct usb_interface *intf,
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 */
};
@@ -614,8 +749,8 @@ static struct dvb_usb_device_properties it913x_properties = {
.endpoint = 0x04,
.u = {/* Keep Low if PID filter on */
.bulk = {
- .buffersize = 3584,
-
+ .buffersize =
+ TS_BUFFER_SIZE_PID,
}
}
}
@@ -639,8 +774,8 @@ static struct dvb_usb_device_properties it913x_properties = {
.endpoint = 0x05,
.u = {
.bulk = {
- .buffersize = 3584,
-
+ .buffersize =
+ TS_BUFFER_SIZE_PID,
}
}
}
@@ -654,10 +789,10 @@ static struct dvb_usb_device_properties it913x_properties = {
.rc_query = it913x_rc_query,
.rc_interval = IT913X_POLL,
.allowed_protos = RC_TYPE_NEC,
- .rc_codes = RC_MAP_KWORLD_315U,
+ .rc_codes = RC_MAP_MSI_DIGIVOX_III,
},
.i2c_algo = &it913x_i2c_algo,
- .num_device_descs = 2,
+ .num_device_descs = 5,
.devices = {
{ "Kworld UB499-2T T09(IT9137)",
{ &it913x_table[0], NULL },
@@ -665,6 +800,15 @@ static struct dvb_usb_device_properties it913x_properties = {
{ "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 },
+ },
}
};
@@ -679,5 +823,5 @@ module_usb_driver(it913x_driver);
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.07");
+MODULE_VERSION("1.22");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
index 1a876a6..b3fe05b 100644
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ b/drivers/media/dvb/dvb-usb/lmedm04.c
@@ -388,8 +388,7 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
pid, index, onoff);
- if (onoff)
- if (!pid_filter) {
+ if (onoff) {
ret = mutex_lock_interruptible(&adap->dev->i2c_mutex);
if (ret < 0)
return -EAGAIN;
@@ -654,6 +653,9 @@ static int lme2510_identify_state(struct usb_device *udev,
struct dvb_usb_device_description **desc,
int *cold)
{
+ if (pid_filter > 0)
+ props->adapter[0].fe[0].caps &=
+ ~DVB_USB_ADAP_NEED_PID_FILTERING;
*cold = 0;
return 0;
}
@@ -1293,5 +1295,5 @@ module_usb_driver(lme2510_driver);
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.90");
+MODULE_VERSION("1.91");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c b/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
index d1f5837..d83df4b 100644
--- a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
@@ -102,8 +102,8 @@ fail:
}
static
-int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
- fe_modulation_t *constellation)
+int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
+ fe_modulation_t *modulation)
{
u8 val;
int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
@@ -113,13 +113,13 @@ int mxl1x1sf_demod_get_tps_constellation(struct mxl111sf_demod_state *state,
switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
case 0:
- *constellation = QPSK;
+ *modulation = QPSK;
break;
case 1:
- *constellation = QAM_16;
+ *modulation = QAM_16;
break;
case 2:
- *constellation = QAM_64;
+ *modulation = QAM_64;
break;
}
fail:
@@ -284,8 +284,7 @@ static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
/* ------------------------------------------------------------------------ */
-static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
{
struct mxl111sf_demod_state *state = fe->demodulator_priv;
int ret = 0;
@@ -303,7 +302,7 @@ static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe,
mxl_dbg("()");
if (fe->ops.tuner_ops.set_params) {
- ret = fe->ops.tuner_ops.set_params(fe, param);
+ ret = fe->ops.tuner_ops.set_params(fe);
if (mxl_fail(ret))
goto fail;
msleep(50);
@@ -481,13 +480,13 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
struct mxl111sf_demod_state *state = fe->demodulator_priv;
- fe_modulation_t constellation;
+ fe_modulation_t modulation;
u16 snr;
mxl111sf_demod_calc_snr(state, &snr);
- mxl1x1sf_demod_get_tps_constellation(state, &constellation);
+ mxl1x1sf_demod_get_tps_modulation(state, &modulation);
- switch (constellation) {
+ switch (modulation) {
case QPSK:
*signal_strength = (snr >= 1300) ?
min(65535, snr * 44) : snr * 38;
@@ -508,9 +507,9 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
return 0;
}
-static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mxl111sf_demod_state *state = fe->demodulator_priv;
mxl_dbg("()");
@@ -518,18 +517,18 @@ static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe,
p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
#endif
if (fe->ops.tuner_ops.get_bandwidth)
- fe->ops.tuner_ops.get_bandwidth(fe, &p->u.ofdm.bandwidth);
+ fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
if (fe->ops.tuner_ops.get_frequency)
fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
- mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_HP);
- mxl1x1sf_demod_get_tps_code_rate(state, &p->u.ofdm.code_rate_LP);
- mxl1x1sf_demod_get_tps_constellation(state, &p->u.ofdm.constellation);
+ mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
+ mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
+ mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
mxl1x1sf_demod_get_tps_guard_fft_mode(state,
- &p->u.ofdm.transmission_mode);
+ &p->transmission_mode);
mxl1x1sf_demod_get_tps_guard_interval(state,
- &p->u.ofdm.guard_interval);
+ &p->guard_interval);
mxl1x1sf_demod_get_tps_hierarchy(state,
- &p->u.ofdm.hierarchy_information);
+ &p->hierarchy);
return 0;
}
@@ -551,10 +550,9 @@ static void mxl111sf_demod_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops mxl111sf_demod_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "MaxLinear MxL111SF DVB-T demodulator",
- .type = FE_OFDM,
.frequency_min = 177000000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
index a634105..72db6ee 100644
--- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
+++ b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
@@ -38,6 +38,8 @@ struct mxl111sf_tuner_state {
struct mxl111sf_tuner_config *cfg;
+ enum mxl_if_freq if_freq;
+
u32 frequency;
u32 bandwidth;
};
@@ -186,7 +188,10 @@ static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
ctrl = iffcw & 0x00ff;
#endif
ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
- mxl_fail(ret);
+ if (mxl_fail(ret))
+ goto fail;
+
+ state->if_freq = state->cfg->if_freq;
fail:
return ret;
}
@@ -267,55 +272,49 @@ static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
/* ------------------------------------------------------------------------ */
-static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
struct mxl111sf_tuner_state *state = fe->tuner_priv;
int ret;
u8 bw;
mxl_dbg("()");
- if (fe->ops.info.type == FE_ATSC) {
- switch (params->u.vsb.modulation) {
- case VSB_8:
- case VSB_16:
- bw = 0; /* ATSC */
- break;
- case QAM_64:
- case QAM_256:
- bw = 1; /* US CABLE */
- break;
- default:
- err("%s: modulation not set!", __func__);
- return -EINVAL;
- }
- } else if (fe->ops.info.type == FE_OFDM) {
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (delsys) {
+ case SYS_ATSC:
+ bw = 0; /* ATSC */
+ break;
+ case SYS_DVBC_ANNEX_B:
+ bw = 1; /* US CABLE */
+ break;
+ case SYS_DVBT:
+ switch (c->bandwidth_hz) {
+ case 6000000:
bw = 6;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
bw = 7;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
bw = 8;
break;
default:
err("%s: bandwidth not set!", __func__);
return -EINVAL;
}
- } else {
+ break;
+ default:
err("%s: modulation type not supported!", __func__);
return -EINVAL;
}
- ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
+ ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
if (mxl_fail(ret))
goto fail;
- state->frequency = params->frequency;
- state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
- params->u.ofdm.bandwidth : 0;
+ state->frequency = c->frequency;
+ state->bandwidth = c->bandwidth_hz;
fail:
return ret;
}
@@ -407,6 +406,54 @@ static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
return 0;
}
+static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
+ u32 *frequency)
+{
+ struct mxl111sf_tuner_state *state = fe->tuner_priv;
+
+ *frequency = 0;
+
+ switch (state->if_freq) {
+ case MXL_IF_4_0: /* 4.0 MHz */
+ *frequency = 4000000;
+ break;
+ case MXL_IF_4_5: /* 4.5 MHz */
+ *frequency = 4500000;
+ break;
+ case MXL_IF_4_57: /* 4.57 MHz */
+ *frequency = 4570000;
+ break;
+ case MXL_IF_5_0: /* 5.0 MHz */
+ *frequency = 5000000;
+ break;
+ case MXL_IF_5_38: /* 5.38 MHz */
+ *frequency = 5380000;
+ break;
+ case MXL_IF_6_0: /* 6.0 MHz */
+ *frequency = 6000000;
+ break;
+ case MXL_IF_6_28: /* 6.28 MHz */
+ *frequency = 6280000;
+ break;
+ case MXL_IF_7_2: /* 7.2 MHz */
+ *frequency = 7200000;
+ break;
+ case MXL_IF_35_25: /* 35.25 MHz */
+ *frequency = 35250000;
+ break;
+ case MXL_IF_36: /* 36 MHz */
+ *frequency = 36000000;
+ break;
+ case MXL_IF_36_15: /* 36.15 MHz */
+ *frequency = 36150000;
+ break;
+ case MXL_IF_44: /* 44 MHz */
+ *frequency = 44000000;
+ break;
+ }
+ return 0;
+}
+
static int mxl111sf_tuner_release(struct dvb_frontend *fe)
{
struct mxl111sf_tuner_state *state = fe->tuner_priv;
@@ -436,6 +483,7 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
.get_rf_strength = mxl111sf_get_rf_strength,
.get_frequency = mxl111sf_tuner_get_frequency,
.get_bandwidth = mxl111sf_tuner_get_bandwidth,
+ .get_if_frequency = mxl111sf_tuner_get_if_frequency,
.release = mxl111sf_tuner_release,
};
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c
index 825a8b2..38ef025 100644
--- a/drivers/media/dvb/dvb-usb/mxl111sf.c
+++ b/drivers/media/dvb/dvb-usb/mxl111sf.c
@@ -758,6 +758,7 @@ 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, \
@@ -772,6 +773,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
/* 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, \
@@ -788,6 +790,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
}
#define MXL111SF_EP6_BULK_STREAMING_CONFIG \
+ .size_of_priv = sizeof(struct mxl111sf_adap_state), \
.streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
.stream = { \
.type = USB_BULK, \
@@ -802,6 +805,7 @@ MODULE_DEVICE_TABLE(usb, mxl111sf_table);
/* 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, \
@@ -839,8 +843,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
.num_frontends = 1,
.fe = {{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_attach_demod,
.tuner_attach = mxl111sf_attach_tuner,
@@ -883,8 +885,6 @@ static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
.num_frontends = 1,
.fe = {{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_attach_demod,
.tuner_attach = mxl111sf_attach_tuner,
@@ -927,16 +927,12 @@ static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
.num_frontends = 2,
.fe = {{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
.tuner_attach = mxl111sf_attach_tuner,
MXL111SF_EP6_BULK_STREAMING_CONFIG,
},
{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_attach_demod,
.tuner_attach = mxl111sf_attach_tuner,
@@ -992,16 +988,12 @@ static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
.num_frontends = 2,
.fe = {{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
.tuner_attach = mxl111sf_attach_tuner,
MXL111SF_EP6_ISOC_STREAMING_CONFIG,
},
{
- .size_of_priv = sizeof(struct mxl111sf_adap_state),
-
.frontend_attach = mxl111sf_attach_demod,
.tuner_attach = mxl111sf_attach_tuner,
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 56acf8e..e53a106 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -75,10 +75,18 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
struct ttusb2_state *st = d->priv;
- u8 s[wlen+4],r[64] = { 0 };
+ u8 *s, *r = NULL;
int ret = 0;
- memset(s,0,wlen+4);
+ s = kzalloc(wlen+4, GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ r = kzalloc(64, GFP_KERNEL);
+ if (!r) {
+ kfree(s);
+ return -ENOMEM;
+ }
s[0] = 0xaa;
s[1] = ++st->id;
@@ -94,12 +102,17 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
r[2] != cmd ||
(rlen > 0 && r[3] != rlen)) {
warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
+ kfree(s);
+ kfree(r);
return -EIO;
}
if (rlen > 0)
memcpy(rbuf, &r[4], rlen);
+ kfree(s);
+ kfree(r);
+
return 0;
}
@@ -384,7 +397,7 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
memcpy(&obuf[3], msg[i].buf, msg[i].len);
- if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
+ if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
err("i2c transfer failed.");
break;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 2bb8d4c..5eab468 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -135,9 +135,9 @@ static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
return 0;
}
-static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int vp702x_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct vp702x_fe_state *st = fe->demodulator_priv;
struct vp702x_device_state *dst = st->d->priv;
u32 freq = fep->frequency/1000;
@@ -155,14 +155,14 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
cmd[1] = freq & 0xff;
cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
- sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
+ sr = (u64) (fep->symbol_rate/1000) << 20;
do_div(sr,88000);
cmd[3] = (sr >> 12) & 0xff;
cmd[4] = (sr >> 4) & 0xff;
cmd[5] = (sr << 4) & 0xf0;
deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
- fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
+ fep->frequency, freq, freq, fep->symbol_rate,
(unsigned long) sr, (unsigned long) sr);
/* if (fep->inversion == INVERSION_ON)
@@ -171,7 +171,7 @@ static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
if (st->voltage == SEC_VOLTAGE_18)
cmd[6] |= 0x40;
-/* if (fep->u.qpsk.symbol_rate > 8000000)
+/* if (fep->symbol_rate > 8000000)
cmd[6] |= 0x20;
if (fep->frequency < 1531000)
@@ -211,13 +211,6 @@ static int vp702x_fe_sleep(struct dvb_frontend *fe)
return 0;
}
-static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
-{
- deb_fe("%s\n",__func__);
- return 0;
-}
-
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *m)
{
@@ -350,9 +343,9 @@ error:
static struct dvb_frontend_ops vp702x_fe_ops = {
+ .delsys = { SYS_DVBS },
.info = {
.name = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1000, /* kHz for QPSK frontends */
@@ -371,7 +364,6 @@ static struct dvb_frontend_ops vp702x_fe_ops = {
.sleep = vp702x_fe_sleep,
.set_frontend = vp702x_fe_set_frontend,
- .get_frontend = vp702x_fe_get_frontend,
.get_tune_settings = vp702x_fe_get_tune_settings,
.read_status = vp702x_fe_read_status,
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 8452eef..b8825b1 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -103,9 +103,9 @@ static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
return 0;
}
-static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int vp7045_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct vp7045_fe_state *state = fe->demodulator_priv;
u8 buf[5];
u32 freq = fep->frequency / 1000;
@@ -115,25 +115,24 @@ static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
buf[2] = freq & 0xff;
buf[3] = 0;
- switch (fep->u.ofdm.bandwidth) {
- case BANDWIDTH_8_MHZ: buf[4] = 8; break;
- case BANDWIDTH_7_MHZ: buf[4] = 7; break;
- case BANDWIDTH_6_MHZ: buf[4] = 6; break;
- case BANDWIDTH_AUTO: return -EOPNOTSUPP;
- default:
- return -EINVAL;
+ switch (fep->bandwidth_hz) {
+ case 8000000:
+ buf[4] = 8;
+ break;
+ case 7000000:
+ buf[4] = 7;
+ break;
+ case 6000000:
+ buf[4] = 6;
+ break;
+ default:
+ return -EINVAL;
}
vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
return 0;
}
-static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
-{
- return 0;
-}
-
static void vp7045_fe_release(struct dvb_frontend* fe)
{
struct vp7045_fe_state *state = fe->demodulator_priv;
@@ -159,9 +158,9 @@ error:
static struct dvb_frontend_ops vp7045_fe_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "Twinhan VP7045/46 USB DVB-T",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 1000,
@@ -181,7 +180,6 @@ static struct dvb_frontend_ops vp7045_fe_ops = {
.sleep = vp7045_fe_sleep,
.set_frontend = vp7045_fe_set_frontend,
- .get_frontend = vp7045_fe_get_frontend,
.get_tune_settings = vp7045_fe_get_tune_settings,
.read_status = vp7045_fe_read_status,
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 489ae82..d1a1a13 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -335,7 +335,7 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
* (not supported by the AVC standard)
*/
static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params)
+ struct dtv_frontend_properties *p)
{
struct avc_command_frame *c = (void *)fdtv->avc_data;
@@ -349,15 +349,15 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
else
c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
- c->operand[4] = (params->frequency >> 24) & 0xff;
- c->operand[5] = (params->frequency >> 16) & 0xff;
- c->operand[6] = (params->frequency >> 8) & 0xff;
- c->operand[7] = params->frequency & 0xff;
+ c->operand[4] = (p->frequency >> 24) & 0xff;
+ c->operand[5] = (p->frequency >> 16) & 0xff;
+ c->operand[6] = (p->frequency >> 8) & 0xff;
+ c->operand[7] = p->frequency & 0xff;
- c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
- c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
+ c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
+ c->operand[9] = (p->symbol_rate / 1000) & 0xff;
- switch (params->u.qpsk.fec_inner) {
+ switch (p->fec_inner) {
case FEC_1_2: c->operand[10] = 0x1; break;
case FEC_2_3: c->operand[10] = 0x2; break;
case FEC_3_4: c->operand[10] = 0x3; break;
@@ -392,10 +392,11 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
default: c->operand[13] = 0x2; break;
}
switch (fdtv->fe.dtv_property_cache.rolloff) {
- case ROLLOFF_AUTO: c->operand[14] = 0x2; break;
case ROLLOFF_35: c->operand[14] = 0x2; break;
case ROLLOFF_20: c->operand[14] = 0x0; break;
case ROLLOFF_25: c->operand[14] = 0x1; break;
+ case ROLLOFF_AUTO:
+ default: c->operand[14] = 0x2; break;
/* case ROLLOFF_NONE: c->operand[14] = 0xff; break; */
}
switch (fdtv->fe.dtv_property_cache.pilot) {
@@ -415,7 +416,7 @@ static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
}
static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params)
+ struct dtv_frontend_properties *p)
{
struct avc_command_frame *c = (void *)fdtv->avc_data;
@@ -434,8 +435,8 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
| 1 << 4 /* Frequency */
| 1 << 3 /* Symbol_Rate */
| 0 << 2 /* FEC_outer */
- | (params->u.qam.fec_inner != FEC_AUTO ? 1 << 1 : 0)
- | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
+ | (p->fec_inner != FEC_AUTO ? 1 << 1 : 0)
+ | (p->modulation != QAM_AUTO ? 1 << 0 : 0);
/* multiplex_valid_flags, low byte */
c->operand[6] = 0 << 7 /* NetworkID */
@@ -446,15 +447,15 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
c->operand[9] = 0x00;
c->operand[10] = 0x00;
- c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
- c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
- c->operand[13] = (params->frequency / 4000) & 0xff;
- c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
- c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
- c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
+ c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+ c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
+ c->operand[13] = (p->frequency / 4000) & 0xff;
+ c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
+ c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
+ c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
c->operand[17] = 0x00;
- switch (params->u.qpsk.fec_inner) {
+ switch (p->fec_inner) {
case FEC_1_2: c->operand[18] = 0x1; break;
case FEC_2_3: c->operand[18] = 0x2; break;
case FEC_3_4: c->operand[18] = 0x3; break;
@@ -466,7 +467,7 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
default: c->operand[18] = 0x0;
}
- switch (params->u.qam.modulation) {
+ switch (p->modulation) {
case QAM_16: c->operand[19] = 0x08; break;
case QAM_32: c->operand[19] = 0x10; break;
case QAM_64: c->operand[19] = 0x18; break;
@@ -483,9 +484,8 @@ static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
}
static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params)
+ struct dtv_frontend_properties *p)
{
- struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
struct avc_command_frame *c = (void *)fdtv->avc_data;
c->opcode = AVC_OPCODE_DSD;
@@ -500,42 +500,42 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
c->operand[5] =
0 << 7 /* reserved */
| 1 << 6 /* CenterFrequency */
- | (ofdm->bandwidth != BANDWIDTH_AUTO ? 1 << 5 : 0)
- | (ofdm->constellation != QAM_AUTO ? 1 << 4 : 0)
- | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
- | (ofdm->code_rate_HP != FEC_AUTO ? 1 << 2 : 0)
- | (ofdm->code_rate_LP != FEC_AUTO ? 1 << 1 : 0)
- | (ofdm->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0);
+ | (p->bandwidth_hz != 0 ? 1 << 5 : 0)
+ | (p->modulation != QAM_AUTO ? 1 << 4 : 0)
+ | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
+ | (p->code_rate_HP != FEC_AUTO ? 1 << 2 : 0)
+ | (p->code_rate_LP != FEC_AUTO ? 1 << 1 : 0)
+ | (p->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0);
/* multiplex_valid_flags, low byte */
c->operand[6] =
0 << 7 /* NetworkID */
- | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+ | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
| 0 << 5 /* OtherFrequencyFlag */
| 0 << 0 /* reserved */ ;
c->operand[7] = 0x0;
- c->operand[8] = (params->frequency / 10) >> 24;
- c->operand[9] = ((params->frequency / 10) >> 16) & 0xff;
- c->operand[10] = ((params->frequency / 10) >> 8) & 0xff;
- c->operand[11] = (params->frequency / 10) & 0xff;
-
- switch (ofdm->bandwidth) {
- case BANDWIDTH_7_MHZ: c->operand[12] = 0x20; break;
- case BANDWIDTH_8_MHZ:
- case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
- case BANDWIDTH_AUTO:
+ c->operand[8] = (p->frequency / 10) >> 24;
+ c->operand[9] = ((p->frequency / 10) >> 16) & 0xff;
+ c->operand[10] = ((p->frequency / 10) >> 8) & 0xff;
+ c->operand[11] = (p->frequency / 10) & 0xff;
+
+ switch (p->bandwidth_hz) {
+ case 7000000: c->operand[12] = 0x20; break;
+ case 8000000:
+ case 6000000: /* not defined by AVC spec */
+ case 0:
default: c->operand[12] = 0x00;
}
- switch (ofdm->constellation) {
+ switch (p->modulation) {
case QAM_16: c->operand[13] = 1 << 6; break;
case QAM_64: c->operand[13] = 2 << 6; break;
case QPSK:
default: c->operand[13] = 0x00;
}
- switch (ofdm->hierarchy_information) {
+ switch (p->hierarchy) {
case HIERARCHY_1: c->operand[13] |= 1 << 3; break;
case HIERARCHY_2: c->operand[13] |= 2 << 3; break;
case HIERARCHY_4: c->operand[13] |= 3 << 3; break;
@@ -544,7 +544,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
default: break;
}
- switch (ofdm->code_rate_HP) {
+ switch (p->code_rate_HP) {
case FEC_2_3: c->operand[13] |= 1; break;
case FEC_3_4: c->operand[13] |= 2; break;
case FEC_5_6: c->operand[13] |= 3; break;
@@ -553,7 +553,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
default: break;
}
- switch (ofdm->code_rate_LP) {
+ switch (p->code_rate_LP) {
case FEC_2_3: c->operand[14] = 1 << 5; break;
case FEC_3_4: c->operand[14] = 2 << 5; break;
case FEC_5_6: c->operand[14] = 3 << 5; break;
@@ -562,7 +562,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
default: c->operand[14] = 0x00; break;
}
- switch (ofdm->guard_interval) {
+ switch (p->guard_interval) {
case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break;
case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break;
case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break;
@@ -571,7 +571,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
default: break;
}
- switch (ofdm->transmission_mode) {
+ switch (p->transmission_mode) {
case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break;
case TRANSMISSION_MODE_2K:
case TRANSMISSION_MODE_AUTO:
@@ -585,7 +585,7 @@ static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
}
int avc_tuner_dsd(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params)
+ struct dtv_frontend_properties *p)
{
struct avc_command_frame *c = (void *)fdtv->avc_data;
int pos, ret;
@@ -597,9 +597,9 @@ int avc_tuner_dsd(struct firedtv *fdtv,
switch (fdtv->type) {
case FIREDTV_DVB_S:
- case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
- case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
- case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
+ case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
+ case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
+ case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
default:
BUG();
}
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
index fd8bbbf..eb7496e 100644
--- a/drivers/media/dvb/firewire/firedtv-dvb.c
+++ b/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -203,7 +203,9 @@ int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
if (err)
goto fail_rem_frontend;
- dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+ err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+ if (err)
+ goto fail_disconnect_frontend;
fdtv_frontend_init(fdtv, name);
err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
@@ -218,6 +220,7 @@ int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
fail_net_release:
dvb_net_release(&fdtv->dvbnet);
+fail_disconnect_frontend:
fdtv->demux.dmx.close(&fdtv->demux.dmx);
fail_rem_frontend:
fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c
index 8748a61..6fe9793 100644
--- a/drivers/media/dvb/firewire/firedtv-fe.c
+++ b/drivers/media/dvb/firewire/firedtv-fe.c
@@ -141,28 +141,12 @@ static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
return -EOPNOTSUPP;
}
-static int fdtv_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int fdtv_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct firedtv *fdtv = fe->sec_priv;
- return avc_tuner_dsd(fdtv, params);
-}
-
-static int fdtv_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- return -EOPNOTSUPP;
-}
-
-static int fdtv_get_property(struct dvb_frontend *fe, struct dtv_property *tvp)
-{
- return 0;
-}
-
-static int fdtv_set_property(struct dvb_frontend *fe, struct dtv_property *tvp)
-{
- return 0;
+ return avc_tuner_dsd(fdtv, p);
}
void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
@@ -174,10 +158,6 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
ops->sleep = fdtv_sleep;
ops->set_frontend = fdtv_set_frontend;
- ops->get_frontend = fdtv_get_frontend;
-
- ops->get_property = fdtv_get_property;
- ops->set_property = fdtv_set_property;
ops->read_status = fdtv_read_status;
ops->read_ber = fdtv_read_ber;
@@ -192,7 +172,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
switch (fdtv->type) {
case FIREDTV_DVB_S:
- fi->type = FE_QPSK;
+ ops->delsys[0] = SYS_DVBS;
fi->frequency_min = 950000;
fi->frequency_max = 2150000;
@@ -211,7 +191,8 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
break;
case FIREDTV_DVB_S2:
- fi->type = FE_QPSK;
+ ops->delsys[0] = SYS_DVBS;
+ ops->delsys[1] = SYS_DVBS2;
fi->frequency_min = 950000;
fi->frequency_max = 2150000;
@@ -231,7 +212,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
break;
case FIREDTV_DVB_C:
- fi->type = FE_QAM;
+ ops->delsys[0] = SYS_DVBC_ANNEX_A;
fi->frequency_min = 47000000;
fi->frequency_max = 866000000;
@@ -249,7 +230,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
break;
case FIREDTV_DVB_T:
- fi->type = FE_OFDM;
+ ops->delsys[0] = SYS_DVBT;
fi->frequency_min = 49000000;
fi->frequency_max = 861000000;
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
index bd00b04..4fdcd8c 100644
--- a/drivers/media/dvb/firewire/firedtv.h
+++ b/drivers/media/dvb/firewire/firedtv.h
@@ -112,8 +112,8 @@ struct firedtv {
/* firedtv-avc.c */
int avc_recv(struct firedtv *fdtv, void *data, size_t length);
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
-struct dvb_frontend_parameters;
-int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
+struct dtv_frontend_properties;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dtv_frontend_properties *params);
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
int avc_tuner_get_ts(struct firedtv *fdtv);
int avc_identify_subunit(struct firedtv *fdtv);
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 4a2d2e6..ebb5ed7 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -404,6 +404,13 @@ config DVB_EC100
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
+ help
+ Say Y when you want to support this frontend.
+
config DVB_STV0367
tristate "ST STV0367 based"
depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index f639f67..00a2063 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_DVB_STV090x) += stv090x.o
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
obj-$(CONFIG_DVB_ISL6423) += isl6423.o
obj-$(CONFIG_DVB_EC100) += ec100.o
+obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
obj-$(CONFIG_DVB_DS3000) += ds3000.o
obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
index 345311c..6bcbcf5 100644
--- a/drivers/media/dvb/frontends/af9013.c
+++ b/drivers/media/dvb/frontends/af9013.c
@@ -2,6 +2,7 @@
* Afatech AF9013 demodulator driver
*
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
*
* Thanks to Afatech who kindly provided information.
*
@@ -21,25 +22,15 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
#include "af9013_priv.h"
-#include "af9013.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 frontend;
-
+ struct dvb_frontend fe;
struct af9013_config config;
/* tuner/demod RF and IF AGC limits used for signal strength calc */
@@ -48,107 +39,178 @@ struct af9013_state {
u32 ber;
u32 ucblocks;
u16 snr;
- u32 frequency;
- unsigned long next_statistics_check;
+ u32 bandwidth_hz;
+ fe_status_t fe_status;
+ unsigned long set_frontend_jiffies;
+ unsigned long read_status_jiffies;
+ bool first_tune;
+ bool i2c_gate_state;
+ unsigned int statistics_step:3;
+ struct delayed_work statistics_work;
};
-static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
-
-static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg,
- u8 *val, u8 len)
+/* write multiple registers */
+static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+ const u8 *val, int len)
{
+ int ret;
u8 buf[3+len];
- struct i2c_msg msg = {
- .addr = state->config.demod_address,
- .flags = 0,
- .len = sizeof(buf),
- .buf = buf };
-
- buf[0] = reg >> 8;
- buf[1] = reg & 0xff;
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->config.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ buf[0] = (reg >> 8) & 0xff;
+ buf[1] = (reg >> 0) & 0xff;
buf[2] = mbox;
memcpy(&buf[3], val, len);
- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
- warn("I2C write failed reg:%04x len:%d", reg, len);
- return -EREMOTEIO;
+ ret = i2c_transfer(priv->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
}
- return 0;
+ return ret;
}
-static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val,
- u8 len)
+/* read multiple registers */
+static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+ u8 *val, int len)
{
- u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7);
- return af9013_write_regs(state, mbox, reg, val, len);
+ int ret;
+ u8 buf[3];
+ struct i2c_msg msg[2] = {
+ {
+ .addr = priv->config.i2c_addr,
+ .flags = 0,
+ .len = 3,
+ .buf = buf,
+ }, {
+ .addr = priv->config.i2c_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = val,
+ }
+ };
+
+ buf[0] = (reg >> 8) & 0xff;
+ buf[1] = (reg >> 0) & 0xff;
+ buf[2] = mbox;
+
+ ret = i2c_transfer(priv->i2c, msg, 2);
+ if (ret == 2) {
+ ret = 0;
+ } else {
+ warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+ return ret;
}
-static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
- u8 len)
+/* write multiple registers */
+static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const u8 *val,
+ int len)
+{
+ int ret, i;
+ u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
+
+ if ((priv->config.ts_mode == AF9013_TS_USB) &&
+ ((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+ mbox |= ((len - 1) << 2);
+ ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
+ } else {
+ for (i = 0; i < len; i++) {
+ ret = af9013_wr_regs_i2c(priv, mbox, reg+i, val+i, 1);
+ if (ret)
+ goto err;
+ }
+ }
+
+err:
+ return 0;
+}
+
+/* read multiple registers */
+static int af9013_rd_regs(struct af9013_state *priv, u16 reg, u8 *val, int len)
{
- u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7);
- return af9013_write_regs(state, mbox, reg, val, len);
+ int ret, i;
+ u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
+
+ if ((priv->config.ts_mode == AF9013_TS_USB) &&
+ ((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+ mbox |= ((len - 1) << 2);
+ ret = af9013_rd_regs_i2c(priv, mbox, reg, val, len);
+ } else {
+ for (i = 0; i < len; i++) {
+ ret = af9013_rd_regs_i2c(priv, mbox, reg+i, val+i, 1);
+ if (ret)
+ goto err;
+ }
+ }
+
+err:
+ return 0;
}
/* write single register */
-static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val)
+static int af9013_wr_reg(struct af9013_state *priv, u16 reg, u8 val)
{
- return af9013_write_ofdm_regs(state, reg, &val, 1);
+ return af9013_wr_regs(priv, reg, &val, 1);
}
/* read single register */
-static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val)
+static int af9013_rd_reg(struct af9013_state *priv, u16 reg, u8 *val)
{
- u8 obuf[3] = { reg >> 8, reg & 0xff, 0 };
- u8 ibuf[1];
- struct i2c_msg msg[2] = {
- {
- .addr = state->config.demod_address,
- .flags = 0,
- .len = sizeof(obuf),
- .buf = obuf
- }, {
- .addr = state->config.demod_address,
- .flags = I2C_M_RD,
- .len = sizeof(ibuf),
- .buf = ibuf
- }
- };
+ return af9013_rd_regs(priv, reg, val, 1);
+}
- if (i2c_transfer(state->i2c, msg, 2) != 2) {
- warn("I2C read failed reg:%04x", reg);
- return -EREMOTEIO;
- }
- *val = ibuf[0];
- return 0;
+static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
+ u8 len)
+{
+ u8 mbox = (1 << 7)|(1 << 6)|((len - 1) << 2)|(1 << 1)|(1 << 0);
+ return af9013_wr_regs_i2c(state, mbox, reg, val, len);
}
-static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
- u8 len, u8 val)
+static int af9013_wr_reg_bits(struct af9013_state *state, u16 reg, int pos,
+ int len, u8 val)
{
int ret;
u8 tmp, mask;
- ret = af9013_read_reg(state, reg, &tmp);
- if (ret)
- return ret;
+ /* no need for read if whole reg is written */
+ if (len != 8) {
+ ret = af9013_rd_reg(state, reg, &tmp);
+ if (ret)
+ return ret;
- mask = regmask[len - 1] << pos;
- tmp = (tmp & ~mask) | ((val << pos) & mask);
+ mask = (0xff >> (8 - len)) << pos;
+ val <<= pos;
+ tmp &= ~mask;
+ val |= tmp;
+ }
- return af9013_write_reg(state, reg, tmp);
+ return af9013_wr_reg(state, reg, val);
}
-static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
- u8 len, u8 *val)
+static int af9013_rd_reg_bits(struct af9013_state *state, u16 reg, int pos,
+ int len, u8 *val)
{
int ret;
u8 tmp;
- ret = af9013_read_reg(state, reg, &tmp);
+ ret = af9013_rd_reg(state, reg, &tmp);
if (ret)
return ret;
- *val = (tmp >> pos) & regmask[len - 1];
+
+ *val = (tmp >> pos);
+ *val &= (0xff >> (8 - len));
+
return 0;
}
@@ -157,10 +219,13 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
int ret;
u8 pos;
u16 addr;
- deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval);
-/* GPIO0 & GPIO1 0xd735
- GPIO2 & GPIO3 0xd736 */
+ dbg("%s: gpio=%d gpioval=%02x", __func__, gpio, gpioval);
+
+ /*
+ * GPIO0 & GPIO1 0xd735
+ * GPIO2 & GPIO3 0xd736
+ */
switch (gpio) {
case 0:
@@ -175,7 +240,7 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
default:
err("invalid gpio:%d\n", gpio);
ret = -EINVAL;
- goto error;
+ goto err;
};
switch (gpio) {
@@ -190,16 +255,21 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
break;
};
- ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval);
+ ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
+ if (ret)
+ goto err;
-error:
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
static u32 af913_div(u32 a, u32 b, u32 x)
{
u32 r = 0, c = 0, i;
- deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x);
+
+ dbg("%s: a=%d b=%d x=%d", __func__, a, b, x);
if (a > b) {
c = a / b;
@@ -216,205 +286,407 @@ static u32 af913_div(u32 a, u32 b, u32 x)
}
r = (c << (u32)x) + r;
- deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r);
+ dbg("%s: a=%d b=%d x=%d r=%x", __func__, a, b, x, r);
return r;
}
-static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw)
+static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
{
- int ret, i, j, found;
- deb_info("%s: adc_clock:%d bw:%d\n", __func__,
- state->config.adc_clock, bw);
-
- /* lookup coeff from table */
- for (i = 0, found = 0; i < ARRAY_SIZE(coeff_table); i++) {
- if (coeff_table[i].adc_clock == state->config.adc_clock &&
- coeff_table[i].bw == bw) {
- found = 1;
- break;
- }
- }
+ int ret, i;
+ u8 tmp;
- if (!found) {
- err("invalid bw or clock");
- ret = -EINVAL;
- goto error;
+ dbg("%s: onoff=%d", __func__, onoff);
+
+ /* enable reset */
+ ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1);
+ if (ret)
+ goto err;
+
+ /* start reset mechanism */
+ ret = af9013_wr_reg(state, 0xaeff, 1);
+ if (ret)
+ goto err;
+
+ /* wait reset performs */
+ for (i = 0; i < 150; i++) {
+ ret = af9013_rd_reg_bits(state, 0xd417, 1, 1, &tmp);
+ if (ret)
+ goto err;
+
+ if (tmp)
+ break; /* reset done */
+
+ usleep_range(5000, 25000);
}
- deb_info("%s: coeff: ", __func__);
- debug_dump(coeff_table[i].val, sizeof(coeff_table[i].val), deb_info);
+ if (!tmp)
+ return -ETIMEDOUT;
- /* program */
- for (j = 0; j < sizeof(coeff_table[i].val); j++) {
- ret = af9013_write_reg(state, 0xae00 + j,
- coeff_table[i].val[j]);
+ if (onoff) {
+ /* clear reset */
+ ret = af9013_wr_reg_bits(state, 0xd417, 1, 1, 0);
if (ret)
- break;
+ goto err;
+
+ /* disable reset */
+ ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 0);
+
+ /* power on */
+ ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 0);
+ } else {
+ /* power off */
+ ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 1);
}
-error:
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+
+ dbg("%s", __func__);
+
+ /* reset and start BER counter */
+ ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1);
+ if (ret)
+ goto err;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
-static int af9013_set_adc_ctrl(struct af9013_state *state)
+static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
{
+ struct af9013_state *state = fe->demodulator_priv;
int ret;
- u8 buf[3], tmp, i;
- u32 adc_cw;
+ u8 buf[5];
- deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock);
+ dbg("%s", __func__);
- /* adc frequency type */
- switch (state->config.adc_clock) {
- case 28800: /* 28.800 MHz */
- tmp = 0;
- break;
- case 20480: /* 20.480 MHz */
- tmp = 1;
+ /* check if error bit count is ready */
+ ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]);
+ if (ret)
+ goto err;
+
+ if (!buf[0]) {
+ dbg("%s: not ready", __func__);
+ return 0;
+ }
+
+ ret = af9013_rd_regs(state, 0xd387, buf, 5);
+ if (ret)
+ goto err;
+
+ state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+ state->ucblocks += (buf[4] << 8) | buf[3];
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int af9013_statistics_snr_start(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+
+ dbg("%s", __func__);
+
+ /* start SNR meas */
+ ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1);
+ if (ret)
+ goto err;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int af9013_statistics_snr_result(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret, i, len;
+ u8 buf[3], tmp;
+ u32 snr_val;
+ const struct af9013_snr *uninitialized_var(snr_lut);
+
+ dbg("%s", __func__);
+
+ /* check if SNR ready */
+ ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp);
+ if (ret)
+ goto err;
+
+ if (!tmp) {
+ dbg("%s: not ready", __func__);
+ return 0;
+ }
+
+ /* read value */
+ ret = af9013_rd_regs(state, 0xd2e3, buf, 3);
+ if (ret)
+ goto err;
+
+ snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ /* read current modulation */
+ ret = af9013_rd_reg(state, 0xd3c1, &tmp);
+ if (ret)
+ goto err;
+
+ switch ((tmp >> 6) & 3) {
+ case 0:
+ len = ARRAY_SIZE(qpsk_snr_lut);
+ snr_lut = qpsk_snr_lut;
break;
- case 28000: /* 28.000 MHz */
- tmp = 2;
+ case 1:
+ len = ARRAY_SIZE(qam16_snr_lut);
+ snr_lut = qam16_snr_lut;
break;
- case 25000: /* 25.000 MHz */
- tmp = 3;
+ case 2:
+ len = ARRAY_SIZE(qam64_snr_lut);
+ snr_lut = qam64_snr_lut;
break;
default:
- err("invalid xtal");
- return -EINVAL;
+ goto err;
+ break;
}
- adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul);
+ for (i = 0; i < len; i++) {
+ tmp = snr_lut[i].snr;
- buf[0] = (u8) ((adc_cw & 0x000000ff));
- buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8);
- buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16);
+ if (snr_val < snr_lut[i].val)
+ break;
+ }
+ state->snr = tmp * 10; /* dB/10 */
- deb_info("%s: adc_cw:", __func__);
- debug_dump(buf, sizeof(buf), deb_info);
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret = 0;
+ u8 buf[2], rf_gain, if_gain;
+ int signal_strength;
+
+ dbg("%s", __func__);
+
+ if (!state->signal_strength_en)
+ return 0;
+
+ ret = af9013_rd_regs(state, 0xd07c, buf, 2);
+ if (ret)
+ goto err;
+
+ rf_gain = buf[0];
+ if_gain = buf[1];
+
+ signal_strength = (0xffff / \
+ (9 * (state->rf_50 + state->if_50) - \
+ 11 * (state->rf_80 + state->if_80))) * \
+ (10 * (rf_gain + if_gain) - \
+ 11 * (state->rf_80 + state->if_80));
+ if (signal_strength < 0)
+ signal_strength = 0;
+ else if (signal_strength > 0xffff)
+ signal_strength = 0xffff;
+
+ state->signal_strength = signal_strength;
- /* program */
- for (i = 0; i < sizeof(buf); i++) {
- ret = af9013_write_reg(state, 0xd180 + i, buf[i]);
- if (ret)
- goto error;
- }
- ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp);
-error:
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
-static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw)
+static void af9013_statistics_work(struct work_struct *work)
{
int ret;
- u16 addr;
- u8 buf[3], i, j;
- u32 adc_freq, freq_cw;
- s8 bfs_spec_inv;
- int if_sample_freq;
-
- for (j = 0; j < 3; j++) {
- if (j == 0) {
- addr = 0xd140; /* fcw normal */
- bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
- } else if (j == 1) {
- addr = 0x9be7; /* fcw dummy ram */
- bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
- } else {
- addr = 0x9bea; /* fcw inverted */
- bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1;
- }
+ struct af9013_state *state = container_of(work,
+ struct af9013_state, statistics_work.work);
+ unsigned int next_msec;
+
+ /* update only signal strength when demod is not locked */
+ if (!(state->fe_status & FE_HAS_LOCK)) {
+ state->statistics_step = 0;
+ state->ber = 0;
+ state->snr = 0;
+ }
+
+ switch (state->statistics_step) {
+ default:
+ state->statistics_step = 0;
+ case 0:
+ ret = af9013_statistics_signal_strength(&state->fe);
+ state->statistics_step++;
+ next_msec = 300;
+ break;
+ case 1:
+ ret = af9013_statistics_snr_start(&state->fe);
+ state->statistics_step++;
+ next_msec = 200;
+ break;
+ case 2:
+ ret = af9013_statistics_ber_unc_start(&state->fe);
+ state->statistics_step++;
+ next_msec = 1000;
+ break;
+ case 3:
+ ret = af9013_statistics_snr_result(&state->fe);
+ state->statistics_step++;
+ next_msec = 400;
+ break;
+ case 4:
+ ret = af9013_statistics_ber_unc_result(&state->fe);
+ state->statistics_step++;
+ next_msec = 100;
+ break;
+ }
- adc_freq = state->config.adc_clock * 1000;
- if_sample_freq = state->config.tuner_if * 1000;
+ schedule_delayed_work(&state->statistics_work,
+ msecs_to_jiffies(next_msec));
- /* TDA18271 uses different sampling freq for every bw */
- if (state->config.tuner == AF9013_TUNER_TDA18271) {
- switch (bw) {
- case BANDWIDTH_6_MHZ:
- if_sample_freq = 3300000; /* 3.3 MHz */
- break;
- case BANDWIDTH_7_MHZ:
- if_sample_freq = 3500000; /* 3.5 MHz */
- break;
- case BANDWIDTH_8_MHZ:
- default:
- if_sample_freq = 4000000; /* 4.0 MHz */
- break;
- }
- } else if (state->config.tuner == AF9013_TUNER_TDA18218) {
- switch (bw) {
- case BANDWIDTH_6_MHZ:
- if_sample_freq = 3000000; /* 3 MHz */
- break;
- case BANDWIDTH_7_MHZ:
- if_sample_freq = 3500000; /* 3.5 MHz */
- break;
- case BANDWIDTH_8_MHZ:
- default:
- if_sample_freq = 4000000; /* 4 MHz */
+ return;
+}
+
+static int af9013_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *fesettings)
+{
+ fesettings->min_delay_ms = 800;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+
+ return 0;
+}
+
+static int af9013_set_frontend(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int ret, i, sampling_freq;
+ bool auto_mode, spec_inv;
+ u8 buf[6];
+ u32 if_frequency, freq_cw;
+
+ dbg("%s: frequency=%d bandwidth_hz=%d", __func__,
+ c->frequency, c->bandwidth_hz);
+
+ /* program tuner */
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+
+ /* program CFOE coefficients */
+ if (c->bandwidth_hz != state->bandwidth_hz) {
+ for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
+ if (coeff_lut[i].clock == state->config.clock &&
+ coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
break;
}
}
- while (if_sample_freq > (adc_freq / 2))
- if_sample_freq = if_sample_freq - adc_freq;
+ ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val,
+ sizeof(coeff_lut[i].val));
+ }
- if (if_sample_freq >= 0)
- bfs_spec_inv = bfs_spec_inv * (-1);
+ /* program frequency control */
+ if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) {
+ /* get used IF frequency */
+ if (fe->ops.tuner_ops.get_if_frequency)
+ fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
else
- if_sample_freq = if_sample_freq * (-1);
+ if_frequency = state->config.if_frequency;
+
+ sampling_freq = if_frequency;
- freq_cw = af913_div(if_sample_freq, adc_freq, 23ul);
+ while (sampling_freq > (state->config.clock / 2))
+ sampling_freq -= state->config.clock;
- if (bfs_spec_inv == -1)
- freq_cw = 0x00800000 - freq_cw;
+ if (sampling_freq < 0) {
+ sampling_freq *= -1;
+ spec_inv = state->config.spec_inv;
+ } else {
+ spec_inv = !state->config.spec_inv;
+ }
- buf[0] = (u8) ((freq_cw & 0x000000ff));
- buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8);
- buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16);
+ freq_cw = af913_div(sampling_freq, state->config.clock, 23);
+ if (spec_inv)
+ freq_cw = 0x800000 - freq_cw;
- deb_info("%s: freq_cw:", __func__);
- debug_dump(buf, sizeof(buf), deb_info);
+ buf[0] = (freq_cw >> 0) & 0xff;
+ buf[1] = (freq_cw >> 8) & 0xff;
+ buf[2] = (freq_cw >> 16) & 0x7f;
- /* program */
- for (i = 0; i < sizeof(buf); i++) {
- ret = af9013_write_reg(state, addr++, buf[i]);
- if (ret)
- goto error;
- }
+ freq_cw = 0x800000 - freq_cw;
+
+ buf[3] = (freq_cw >> 0) & 0xff;
+ buf[4] = (freq_cw >> 8) & 0xff;
+ buf[5] = (freq_cw >> 16) & 0x7f;
+
+ ret = af9013_wr_regs(state, 0xd140, buf, 3);
+ if (ret)
+ goto err;
+
+ ret = af9013_wr_regs(state, 0x9be7, buf, 6);
+ if (ret)
+ goto err;
}
-error:
- return ret;
-}
-static int af9013_set_ofdm_params(struct af9013_state *state,
- struct dvb_ofdm_parameters *params, u8 *auto_mode)
-{
- int ret;
- u8 i, buf[3] = {0, 0, 0};
- *auto_mode = 0; /* set if parameters are requested to auto set */
+ /* clear TPS lock flag */
+ ret = af9013_wr_reg_bits(state, 0xd330, 3, 1, 1);
+ if (ret)
+ goto err;
+
+ /* clear MPEG2 lock flag */
+ ret = af9013_wr_reg_bits(state, 0xd507, 6, 1, 0);
+ if (ret)
+ goto err;
+
+ /* empty channel function */
+ ret = af9013_wr_reg_bits(state, 0x9bfe, 0, 1, 0);
+ if (ret)
+ goto err;
- /* Try auto-detect transmission parameters in case of AUTO requested or
- garbage parameters given by application for compatibility.
- MPlayer seems to provide garbage parameters currently. */
+ /* empty DVB-T channel function */
+ ret = af9013_wr_reg_bits(state, 0x9bc2, 0, 1, 0);
+ if (ret)
+ goto err;
+
+ /* transmission parameters */
+ auto_mode = false;
+ memset(buf, 0, 3);
- switch (params->transmission_mode) {
+ switch (c->transmission_mode) {
case TRANSMISSION_MODE_AUTO:
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case TRANSMISSION_MODE_2K:
break;
case TRANSMISSION_MODE_8K:
buf[0] |= (1 << 0);
break;
default:
- deb_info("%s: invalid transmission_mode\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid transmission_mode", __func__);
+ auto_mode = 1;
}
- switch (params->guard_interval) {
+ switch (c->guard_interval) {
case GUARD_INTERVAL_AUTO:
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case GUARD_INTERVAL_1_32:
break;
case GUARD_INTERVAL_1_16:
@@ -427,13 +699,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[0] |= (3 << 2);
break;
default:
- deb_info("%s: invalid guard_interval\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid guard_interval", __func__);
+ auto_mode = 1;
}
- switch (params->hierarchy_information) {
+ switch (c->hierarchy) {
case HIERARCHY_AUTO:
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case HIERARCHY_NONE:
break;
case HIERARCHY_1:
@@ -446,13 +719,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[0] |= (3 << 4);
break;
default:
- deb_info("%s: invalid hierarchy_information\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid hierarchy", __func__);
+ auto_mode = 1;
};
- switch (params->constellation) {
+ switch (c->modulation) {
case QAM_AUTO:
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case QPSK:
break;
case QAM_16:
@@ -462,16 +736,17 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[1] |= (2 << 6);
break;
default:
- deb_info("%s: invalid constellation\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid modulation", __func__);
+ auto_mode = 1;
}
/* Use HP. How and which case we can switch to LP? */
buf[1] |= (1 << 4);
- switch (params->code_rate_HP) {
+ switch (c->code_rate_HP) {
case FEC_AUTO:
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case FEC_1_2:
break;
case FEC_2_3:
@@ -487,16 +762,14 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[2] |= (4 << 0);
break;
default:
- deb_info("%s: invalid code_rate_HP\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid code_rate_HP", __func__);
+ auto_mode = 1;
}
- switch (params->code_rate_LP) {
+ switch (c->code_rate_LP) {
case FEC_AUTO:
- /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO
- by dvb_frontend.c for compatibility */
- if (params->hierarchy_information != HIERARCHY_NONE)
- *auto_mode = 1;
+ auto_mode = 1;
+ break;
case FEC_1_2:
break;
case FEC_2_3:
@@ -512,709 +785,373 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
buf[2] |= (4 << 3);
break;
case FEC_NONE:
- if (params->hierarchy_information == HIERARCHY_AUTO)
- break;
+ break;
default:
- deb_info("%s: invalid code_rate_LP\n", __func__);
- *auto_mode = 1;
+ dbg("%s: invalid code_rate_LP", __func__);
+ auto_mode = 1;
}
- switch (params->bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
buf[1] |= (1 << 2);
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
buf[1] |= (2 << 2);
break;
default:
- deb_info("%s: invalid bandwidth\n", __func__);
- buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */
- }
-
- /* program */
- for (i = 0; i < sizeof(buf); i++) {
- ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]);
- if (ret)
- break;
+ dbg("%s: invalid bandwidth_hz", __func__);
+ ret = -EINVAL;
+ goto err;
}
- return ret;
-}
-
-static int af9013_reset(struct af9013_state *state, u8 sleep)
-{
- int ret;
- u8 tmp, i;
- deb_info("%s\n", __func__);
-
- /* enable OFDM reset */
- ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1);
- if (ret)
- goto error;
-
- /* start reset mechanism */
- ret = af9013_write_reg(state, 0xaeff, 1);
+ ret = af9013_wr_regs(state, 0xd3c0, buf, 3);
if (ret)
- goto error;
+ goto err;
- /* reset is done when bit 1 is set */
- for (i = 0; i < 150; i++) {
- ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp);
- if (ret)
- goto error;
- if (tmp)
- break; /* reset done */
- msleep(10);
- }
- if (!tmp)
- return -ETIMEDOUT;
-
- /* don't clear reset when going to sleep */
- if (!sleep) {
- /* clear OFDM reset */
- ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+ if (auto_mode) {
+ /* clear easy mode flag */
+ ret = af9013_wr_reg(state, 0xaefd, 0);
if (ret)
- goto error;
-
- /* disable OFDM reset */
- ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
- }
-error:
- return ret;
-}
-
-static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
-{
- int ret;
- deb_info("%s: onoff:%d\n", __func__, onoff);
+ goto err;
- if (onoff) {
- /* power on */
- ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0);
- if (ret)
- goto error;
- ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
- if (ret)
- goto error;
- ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+ dbg("%s: auto params", __func__);
} else {
- /* power off */
- ret = af9013_reset(state, 1);
+ /* set easy mode flag */
+ ret = af9013_wr_reg(state, 0xaefd, 1);
if (ret)
- goto error;
- ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1);
- }
-error:
- return ret;
-}
-
-static int af9013_lock_led(struct af9013_state *state, u8 onoff)
-{
- deb_info("%s: onoff:%d\n", __func__, onoff);
-
- return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff);
-}
-
-static int af9013_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret;
- u8 auto_mode; /* auto set TPS */
+ goto err;
- deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
- params->u.ofdm.bandwidth);
-
- state->frequency = params->frequency;
-
- /* program tuner */
- if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, params);
-
- /* program CFOE coefficients */
- ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
- if (ret)
- goto error;
-
- /* program frequency control */
- ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth);
- if (ret)
- goto error;
-
- /* clear TPS lock flag (inverted flag) */
- ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1);
- if (ret)
- goto error;
-
- /* clear MPEG2 lock flag */
- ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0);
- if (ret)
- goto error;
-
- /* empty channel function */
- ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0);
- if (ret)
- goto error;
-
- /* empty DVB-T channel function */
- ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0);
- if (ret)
- goto error;
-
- /* program TPS and bandwidth, check if auto mode needed */
- ret = af9013_set_ofdm_params(state, &params->u.ofdm, &auto_mode);
- if (ret)
- goto error;
-
- if (auto_mode) {
- /* clear easy mode flag */
- ret = af9013_write_reg(state, 0xaefd, 0);
- deb_info("%s: auto TPS\n", __func__);
- } else {
- /* set easy mode flag */
- ret = af9013_write_reg(state, 0xaefd, 1);
+ ret = af9013_wr_reg(state, 0xaefe, 0);
if (ret)
- goto error;
- ret = af9013_write_reg(state, 0xaefe, 0);
- deb_info("%s: manual TPS\n", __func__);
+ goto err;
+
+ dbg("%s: manual params", __func__);
}
- if (ret)
- goto error;
- /* everything is set, lets try to receive channel - OFSM GO! */
- ret = af9013_write_reg(state, 0xffff, 0);
+ /* tune */
+ ret = af9013_wr_reg(state, 0xffff, 0);
if (ret)
- goto error;
+ goto err;
+
+ state->bandwidth_hz = c->bandwidth_hz;
+ state->set_frontend_jiffies = jiffies;
+ state->first_tune = false;
-error:
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
-static int af9013_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int af9013_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct af9013_state *state = fe->demodulator_priv;
int ret;
- u8 i, buf[3];
- deb_info("%s\n", __func__);
+ u8 buf[3];
- /* read TPS registers */
- for (i = 0; i < 3; i++) {
- ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]);
- if (ret)
- goto error;
- }
+ dbg("%s", __func__);
+
+ ret = af9013_rd_regs(state, 0xd3c0, buf, 3);
+ if (ret)
+ goto err;
switch ((buf[1] >> 6) & 3) {
case 0:
- p->u.ofdm.constellation = QPSK;
+ c->modulation = QPSK;
break;
case 1:
- p->u.ofdm.constellation = QAM_16;
+ c->modulation = QAM_16;
break;
case 2:
- p->u.ofdm.constellation = QAM_64;
+ c->modulation = QAM_64;
break;
}
switch ((buf[0] >> 0) & 3) {
case 0:
- p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ c->transmission_mode = TRANSMISSION_MODE_2K;
break;
case 1:
- p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ c->transmission_mode = TRANSMISSION_MODE_8K;
}
switch ((buf[0] >> 2) & 3) {
case 0:
- p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ c->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
- p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ c->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
- p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ c->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ c->guard_interval = GUARD_INTERVAL_1_4;
break;
}
switch ((buf[0] >> 4) & 7) {
case 0:
- p->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ c->hierarchy = HIERARCHY_NONE;
break;
case 1:
- p->u.ofdm.hierarchy_information = HIERARCHY_1;
+ c->hierarchy = HIERARCHY_1;
break;
case 2:
- p->u.ofdm.hierarchy_information = HIERARCHY_2;
+ c->hierarchy = HIERARCHY_2;
break;
case 3:
- p->u.ofdm.hierarchy_information = HIERARCHY_4;
+ c->hierarchy = HIERARCHY_4;
break;
}
switch ((buf[2] >> 0) & 7) {
case 0:
- p->u.ofdm.code_rate_HP = FEC_1_2;
+ c->code_rate_HP = FEC_1_2;
break;
case 1:
- p->u.ofdm.code_rate_HP = FEC_2_3;
+ c->code_rate_HP = FEC_2_3;
break;
case 2:
- p->u.ofdm.code_rate_HP = FEC_3_4;
+ c->code_rate_HP = FEC_3_4;
break;
case 3:
- p->u.ofdm.code_rate_HP = FEC_5_6;
+ c->code_rate_HP = FEC_5_6;
break;
case 4:
- p->u.ofdm.code_rate_HP = FEC_7_8;
+ c->code_rate_HP = FEC_7_8;
break;
}
switch ((buf[2] >> 3) & 7) {
case 0:
- p->u.ofdm.code_rate_LP = FEC_1_2;
+ c->code_rate_LP = FEC_1_2;
break;
case 1:
- p->u.ofdm.code_rate_LP = FEC_2_3;
+ c->code_rate_LP = FEC_2_3;
break;
case 2:
- p->u.ofdm.code_rate_LP = FEC_3_4;
+ c->code_rate_LP = FEC_3_4;
break;
case 3:
- p->u.ofdm.code_rate_LP = FEC_5_6;
+ c->code_rate_LP = FEC_5_6;
break;
case 4:
- p->u.ofdm.code_rate_LP = FEC_7_8;
+ c->code_rate_LP = FEC_7_8;
break;
}
switch ((buf[1] >> 2) & 3) {
case 0:
- p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ c->bandwidth_hz = 6000000;
break;
case 1:
- p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ c->bandwidth_hz = 7000000;
break;
case 2:
- p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ c->bandwidth_hz = 8000000;
break;
}
- p->inversion = INVERSION_AUTO;
- p->frequency = state->frequency;
-
-error:
return ret;
-}
-
-static int af9013_update_ber_unc(struct dvb_frontend *fe)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret;
- u8 buf[3], i;
- u32 error_bit_count = 0;
- u32 total_bit_count = 0;
- u32 abort_packet_count = 0;
-
- state->ber = 0;
-
- /* check if error bit count is ready */
- ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]);
- if (ret)
- goto error;
- if (!buf[0])
- goto exit;
-
- /* get RSD packet abort count */
- for (i = 0; i < 2; i++) {
- ret = af9013_read_reg(state, 0xd38a + i, &buf[i]);
- if (ret)
- goto error;
- }
- abort_packet_count = (buf[1] << 8) + buf[0];
-
- /* get error bit count */
- for (i = 0; i < 3; i++) {
- ret = af9013_read_reg(state, 0xd387 + i, &buf[i]);
- if (ret)
- goto error;
- }
- error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0];
- error_bit_count = error_bit_count - abort_packet_count * 8 * 8;
-
- /* get used RSD counting period (10000 RSD packets used) */
- for (i = 0; i < 2; i++) {
- ret = af9013_read_reg(state, 0xd385 + i, &buf[i]);
- if (ret)
- goto error;
- }
- total_bit_count = (buf[1] << 8) + buf[0];
- total_bit_count = total_bit_count - abort_packet_count;
- total_bit_count = total_bit_count * 204 * 8;
-
- if (total_bit_count)
- state->ber = error_bit_count * 1000000000 / total_bit_count;
-
- state->ucblocks += abort_packet_count;
-
- deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__,
- error_bit_count, total_bit_count, abort_packet_count);
-
- /* set BER counting range */
- ret = af9013_write_reg(state, 0xd385, 10000 & 0xff);
- if (ret)
- goto error;
- ret = af9013_write_reg(state, 0xd386, 10000 >> 8);
- if (ret)
- goto error;
- /* reset and start BER counter */
- ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1);
- if (ret)
- goto error;
-
-exit:
-error:
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
-static int af9013_update_snr(struct dvb_frontend *fe)
+static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct af9013_state *state = fe->demodulator_priv;
int ret;
- u8 buf[3], i, len;
- u32 quant = 0;
- struct snr_table *uninitialized_var(snr_table);
-
- /* check if quantizer ready (for snr) */
- ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]);
- if (ret)
- goto error;
- if (buf[0]) {
- /* quantizer ready - read it */
- for (i = 0; i < 3; i++) {
- ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]);
- if (ret)
- goto error;
- }
- quant = (buf[2] << 16) + (buf[1] << 8) + buf[0];
-
- /* read current constellation */
- ret = af9013_read_reg(state, 0xd3c1, &buf[0]);
- if (ret)
- goto error;
-
- switch ((buf[0] >> 6) & 3) {
- case 0:
- len = ARRAY_SIZE(qpsk_snr_table);
- snr_table = qpsk_snr_table;
- break;
- case 1:
- len = ARRAY_SIZE(qam16_snr_table);
- snr_table = qam16_snr_table;
- break;
- case 2:
- len = ARRAY_SIZE(qam64_snr_table);
- snr_table = qam64_snr_table;
- break;
- default:
- len = 0;
- break;
- }
-
- if (len) {
- for (i = 0; i < len; i++) {
- if (quant < snr_table[i].val) {
- state->snr = snr_table[i].snr * 10;
- break;
- }
- }
- }
-
- /* set quantizer super frame count */
- ret = af9013_write_reg(state, 0xd2e2, 1);
- if (ret)
- goto error;
-
- /* check quantizer availability */
- for (i = 0; i < 10; i++) {
- msleep(10);
- ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1,
- &buf[0]);
- if (ret)
- goto error;
- if (!buf[0])
- break;
- }
-
- /* reset quantizer */
- ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1);
- if (ret)
- goto error;
- }
-
-error:
- return ret;
-}
-
-static int af9013_update_signal_strength(struct dvb_frontend *fe)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret = 0;
- u8 rf_gain, if_gain;
- int signal_strength;
-
- deb_info("%s\n", __func__);
+ u8 tmp;
- if (state->signal_strength_en) {
- ret = af9013_read_reg(state, 0xd07c, &rf_gain);
- if (ret)
- goto error;
- ret = af9013_read_reg(state, 0xd07d, &if_gain);
- if (ret)
- goto error;
- signal_strength = (0xffff / \
- (9 * (state->rf_50 + state->if_50) - \
- 11 * (state->rf_80 + state->if_80))) * \
- (10 * (rf_gain + if_gain) - \
- 11 * (state->rf_80 + state->if_80));
- if (signal_strength < 0)
- signal_strength = 0;
- else if (signal_strength > 0xffff)
- signal_strength = 0xffff;
-
- state->signal_strength = signal_strength;
+ /*
+ * Return status from the cache if it is younger than 2000ms with the
+ * exception of last tune is done during 4000ms.
+ */
+ if (time_is_after_jiffies(
+ state->read_status_jiffies + msecs_to_jiffies(2000)) &&
+ time_is_before_jiffies(
+ state->set_frontend_jiffies + msecs_to_jiffies(4000))
+ ) {
+ *status = state->fe_status;
+ return 0;
} else {
- state->signal_strength = 0;
+ *status = 0;
}
-error:
- return ret;
-}
-
-static int af9013_update_statistics(struct dvb_frontend *fe)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret;
-
- if (time_before(jiffies, state->next_statistics_check))
- return 0;
-
- /* set minimum statistic update interval */
- state->next_statistics_check = jiffies + msecs_to_jiffies(1200);
-
- ret = af9013_update_signal_strength(fe);
- if (ret)
- goto error;
- ret = af9013_update_snr(fe);
- if (ret)
- goto error;
- ret = af9013_update_ber_unc(fe);
- if (ret)
- goto error;
-
-error:
- return ret;
-}
-
-static int af9013_get_tune_settings(struct dvb_frontend *fe,
- struct dvb_frontend_tune_settings *fesettings)
-{
- fesettings->min_delay_ms = 800;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
-
- return 0;
-}
-
-static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret = 0;
- u8 tmp;
- *status = 0;
-
/* MPEG2 lock */
- ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
+ ret = af9013_rd_reg_bits(state, 0xd507, 6, 1, &tmp);
if (ret)
- goto error;
+ goto err;
+
if (tmp)
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
FE_HAS_SYNC | FE_HAS_LOCK;
if (!*status) {
/* TPS lock */
- ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
+ ret = af9013_rd_reg_bits(state, 0xd330, 3, 1, &tmp);
if (ret)
- goto error;
+ goto err;
+
if (tmp)
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI;
}
- if (!*status) {
- /* CFO lock */
- ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
- if (ret)
- goto error;
- if (tmp)
- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
- }
-
- if (!*status) {
- /* SFOE lock */
- ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
- if (ret)
- goto error;
- if (tmp)
- *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
- }
+ state->fe_status = *status;
+ state->read_status_jiffies = jiffies;
- if (!*status) {
- /* AGC lock */
- ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
- if (ret)
- goto error;
- if (tmp)
- *status |= FE_HAS_SIGNAL;
- }
-
- ret = af9013_update_statistics(fe);
-
-error:
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
-
-static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
+static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct af9013_state *state = fe->demodulator_priv;
- int ret;
- ret = af9013_update_statistics(fe);
- *ber = state->ber;
- return ret;
+ *snr = state->snr;
+ return 0;
}
static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct af9013_state *state = fe->demodulator_priv;
- int ret;
- ret = af9013_update_statistics(fe);
*strength = state->signal_strength;
- return ret;
+ return 0;
}
-static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
+static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct af9013_state *state = fe->demodulator_priv;
- int ret;
- ret = af9013_update_statistics(fe);
- *snr = state->snr;
- return ret;
+ *ber = state->ber;
+ return 0;
}
static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct af9013_state *state = fe->demodulator_priv;
- int ret;
- ret = af9013_update_statistics(fe);
*ucblocks = state->ucblocks;
- return ret;
-}
-
-static int af9013_sleep(struct dvb_frontend *fe)
-{
- struct af9013_state *state = fe->demodulator_priv;
- int ret;
- deb_info("%s\n", __func__);
-
- ret = af9013_lock_led(state, 0);
- if (ret)
- goto error;
-
- ret = af9013_power_ctrl(state, 0);
-error:
- return ret;
+ return 0;
}
static int af9013_init(struct dvb_frontend *fe)
{
struct af9013_state *state = fe->demodulator_priv;
int ret, i, len;
- u8 tmp0, tmp1;
- struct regdesc *init;
- deb_info("%s\n", __func__);
+ u8 buf[3], tmp;
+ u32 adc_cw;
+ const struct af9013_reg_bit *init;
- /* reset OFDM */
- ret = af9013_reset(state, 0);
- if (ret)
- goto error;
+ dbg("%s", __func__);
/* power on */
ret = af9013_power_ctrl(state, 1);
if (ret)
- goto error;
+ goto err;
/* enable ADC */
- ret = af9013_write_reg(state, 0xd73a, 0xa4);
+ ret = af9013_wr_reg(state, 0xd73a, 0xa4);
if (ret)
- goto error;
+ goto err;
/* write API version to firmware */
- for (i = 0; i < sizeof(state->config.api_version); i++) {
- ret = af9013_write_reg(state, 0x9bf2 + i,
- state->config.api_version[i]);
- if (ret)
- goto error;
- }
+ ret = af9013_wr_regs(state, 0x9bf2, state->config.api_version, 4);
+ if (ret)
+ goto err;
/* program ADC control */
- ret = af9013_set_adc_ctrl(state);
+ switch (state->config.clock) {
+ case 28800000: /* 28.800 MHz */
+ tmp = 0;
+ break;
+ case 20480000: /* 20.480 MHz */
+ tmp = 1;
+ break;
+ case 28000000: /* 28.000 MHz */
+ tmp = 2;
+ break;
+ case 25000000: /* 25.000 MHz */
+ tmp = 3;
+ break;
+ default:
+ err("invalid clock");
+ return -EINVAL;
+ }
+
+ adc_cw = af913_div(state->config.clock, 1000000ul, 19);
+ buf[0] = (adc_cw >> 0) & 0xff;
+ buf[1] = (adc_cw >> 8) & 0xff;
+ buf[2] = (adc_cw >> 16) & 0xff;
+
+ ret = af9013_wr_regs(state, 0xd180, buf, 3);
+ if (ret)
+ goto err;
+
+ ret = af9013_wr_reg_bits(state, 0x9bd2, 0, 4, tmp);
if (ret)
- goto error;
+ goto err;
/* set I2C master clock */
- ret = af9013_write_reg(state, 0xd416, 0x14);
+ ret = af9013_wr_reg(state, 0xd416, 0x14);
if (ret)
- goto error;
+ goto err;
/* set 16 embx */
- ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1);
+ ret = af9013_wr_reg_bits(state, 0xd700, 1, 1, 1);
if (ret)
- goto error;
+ goto err;
/* set no trigger */
- ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0);
+ ret = af9013_wr_reg_bits(state, 0xd700, 2, 1, 0);
if (ret)
- goto error;
+ goto err;
/* set read-update bit for constellation */
- ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1);
+ ret = af9013_wr_reg_bits(state, 0xd371, 1, 1, 1);
if (ret)
- goto error;
+ goto err;
- /* enable FEC monitor */
- ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1);
+ /* settings for mp2if */
+ if (state->config.ts_mode == AF9013_TS_USB) {
+ /* AF9015 split PSB to 1.5k + 0.5k */
+ ret = af9013_wr_reg_bits(state, 0xd50b, 2, 1, 1);
+ if (ret)
+ goto err;
+ } else {
+ /* AF9013 change the output bit to data7 */
+ ret = af9013_wr_reg_bits(state, 0xd500, 3, 1, 1);
+ if (ret)
+ goto err;
+
+ /* AF9013 set mpeg to full speed */
+ ret = af9013_wr_reg_bits(state, 0xd502, 4, 1, 1);
+ if (ret)
+ goto err;
+ }
+
+ ret = af9013_wr_reg_bits(state, 0xd520, 4, 1, 1);
if (ret)
- goto error;
+ goto err;
/* load OFSM settings */
- deb_info("%s: load ofsm settings\n", __func__);
+ dbg("%s: load ofsm settings", __func__);
len = ARRAY_SIZE(ofsm_init);
init = ofsm_init;
for (i = 0; i < len; i++) {
- ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+ ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
init[i].len, init[i].val);
if (ret)
- goto error;
+ goto err;
}
/* load tuner specific settings */
- deb_info("%s: load tuner specific settings\n", __func__);
+ dbg("%s: load tuner specific settings", __func__);
switch (state->config.tuner) {
case AF9013_TUNER_MXL5003D:
len = ARRAY_SIZE(tuner_init_mxl5003d);
@@ -1260,65 +1197,133 @@ static int af9013_init(struct dvb_frontend *fe)
}
for (i = 0; i < len; i++) {
- ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+ ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
init[i].len, init[i].val);
if (ret)
- goto error;
+ goto err;
}
- /* set TS mode */
- deb_info("%s: setting ts mode\n", __func__);
- tmp0 = 0; /* parallel mode */
- tmp1 = 0; /* serial mode */
- switch (state->config.output_mode) {
- case AF9013_OUTPUT_MODE_PARALLEL:
- tmp0 = 1;
- break;
- case AF9013_OUTPUT_MODE_SERIAL:
- tmp1 = 1;
- break;
- case AF9013_OUTPUT_MODE_USB:
- /* usb mode for AF9015 */
- default:
- break;
- }
- ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */
+ /* TS mode */
+ ret = af9013_wr_reg_bits(state, 0xd500, 1, 2, state->config.ts_mode);
if (ret)
- goto error;
- ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */
- if (ret)
- goto error;
+ goto err;
/* enable lock led */
- ret = af9013_lock_led(state, 1);
+ ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 1);
if (ret)
- goto error;
+ goto err;
- /* read values needed for signal strength calculation */
- ret = af9013_read_reg_bits(state, 0x9bee, 0, 1,
- &state->signal_strength_en);
- if (ret)
- goto error;
+ /* check if we support signal strength */
+ if (!state->signal_strength_en) {
+ ret = af9013_rd_reg_bits(state, 0x9bee, 0, 1,
+ &state->signal_strength_en);
+ if (ret)
+ goto err;
+ }
- if (state->signal_strength_en) {
- ret = af9013_read_reg(state, 0x9bbd, &state->rf_50);
+ /* read values needed for signal strength calculation */
+ if (state->signal_strength_en && !state->rf_50) {
+ ret = af9013_rd_reg(state, 0x9bbd, &state->rf_50);
if (ret)
- goto error;
- ret = af9013_read_reg(state, 0x9bd0, &state->rf_80);
+ goto err;
+
+ ret = af9013_rd_reg(state, 0x9bd0, &state->rf_80);
if (ret)
- goto error;
- ret = af9013_read_reg(state, 0x9be2, &state->if_50);
+ goto err;
+
+ ret = af9013_rd_reg(state, 0x9be2, &state->if_50);
if (ret)
- goto error;
- ret = af9013_read_reg(state, 0x9be4, &state->if_80);
+ goto err;
+
+ ret = af9013_rd_reg(state, 0x9be4, &state->if_80);
if (ret)
- goto error;
+ goto err;
}
-error:
+ /* SNR */
+ ret = af9013_wr_reg(state, 0xd2e2, 1);
+ if (ret)
+ goto err;
+
+ /* BER / UCB */
+ buf[0] = (10000 >> 0) & 0xff;
+ buf[1] = (10000 >> 8) & 0xff;
+ ret = af9013_wr_regs(state, 0xd385, buf, 2);
+ if (ret)
+ goto err;
+
+ /* enable FEC monitor */
+ ret = af9013_wr_reg_bits(state, 0xd392, 1, 1, 1);
+ if (ret)
+ goto err;
+
+ state->first_tune = true;
+ schedule_delayed_work(&state->statistics_work, msecs_to_jiffies(400));
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
return ret;
}
+static int af9013_sleep(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ int ret;
+
+ dbg("%s", __func__);
+
+ /* stop statistics polling */
+ cancel_delayed_work_sync(&state->statistics_work);
+
+ /* disable lock led */
+ ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 0);
+ if (ret)
+ goto err;
+
+ /* power off */
+ ret = af9013_power_ctrl(state, 0);
+ if (ret)
+ goto err;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+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);
+
+ /* gate already open or close */
+ if (state->i2c_gate_state == enable)
+ return 0;
+
+ if (state->config.ts_mode == AF9013_TS_USB)
+ ret = af9013_wr_reg_bits(state, 0xd417, 3, 1, enable);
+ else
+ ret = af9013_wr_reg_bits(state, 0xd607, 2, 1, enable);
+ if (ret)
+ goto err;
+
+ state->i2c_gate_state = enable;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static void af9013_release(struct dvb_frontend *fe)
+{
+ struct af9013_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
static struct dvb_frontend_ops af9013_ops;
static int af9013_download_firmware(struct af9013_state *state)
@@ -1332,11 +1337,11 @@ static int af9013_download_firmware(struct af9013_state *state)
msleep(100);
/* check whether firmware is already running */
- ret = af9013_read_reg(state, 0x98be, &val);
+ ret = af9013_rd_reg(state, 0x98be, &val);
if (ret)
- goto error;
+ goto err;
else
- deb_info("%s: firmware status:%02x\n", __func__, val);
+ dbg("%s: firmware status=%02x", __func__, val);
if (val == 0x0c) /* fw is running, no need for download */
goto exit;
@@ -1351,7 +1356,7 @@ static int af9013_download_firmware(struct af9013_state *state)
"Please see linux/Documentation/dvb/ for more details" \
" on firmware-problems. (%d)",
fw_file, ret);
- goto error;
+ goto err;
}
info("downloading firmware from file '%s'", fw_file);
@@ -1369,7 +1374,7 @@ static int af9013_download_firmware(struct af9013_state *state)
ret = af9013_write_ofsm_regs(state, 0x50fc,
fw_params, sizeof(fw_params));
if (ret)
- goto error_release;
+ goto err_release;
#define FW_ADDR 0x5100 /* firmware start address */
#define LEN_MAX 16 /* max packet size */
@@ -1383,24 +1388,24 @@ static int af9013_download_firmware(struct af9013_state *state)
(u8 *) &fw->data[fw->size - remaining], len);
if (ret) {
err("firmware download failed:%d", ret);
- goto error_release;
+ goto err_release;
}
}
/* request boot firmware */
- ret = af9013_write_reg(state, 0xe205, 1);
+ ret = af9013_wr_reg(state, 0xe205, 1);
if (ret)
- goto error_release;
+ goto err_release;
for (i = 0; i < 15; i++) {
msleep(100);
/* check firmware status */
- ret = af9013_read_reg(state, 0x98be, &val);
+ ret = af9013_rd_reg(state, 0x98be, &val);
if (ret)
- goto error_release;
+ goto err_release;
- deb_info("%s: firmware status:%02x\n", __func__, val);
+ dbg("%s: firmware status=%02x", __func__, val);
if (val == 0x0c || val == 0x04) /* success or fail */
break;
@@ -1408,43 +1413,21 @@ static int af9013_download_firmware(struct af9013_state *state)
if (val == 0x04) {
err("firmware did not run");
- ret = -1;
+ ret = -ENODEV;
} else if (val != 0x0c) {
err("firmware boot timeout");
- ret = -1;
+ ret = -ENODEV;
}
-error_release:
+err_release:
release_firmware(fw);
-error:
+err:
exit:
if (!ret)
info("found a '%s' in warm state.", af9013_ops.info.name);
return ret;
}
-static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
- int ret;
- struct af9013_state *state = fe->demodulator_priv;
- deb_info("%s: enable:%d\n", __func__, enable);
-
- if (state->config.output_mode == AF9013_OUTPUT_MODE_USB)
- ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable);
- else
- ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable);
-
- return ret;
-}
-
-static void af9013_release(struct dvb_frontend *fe)
-{
- struct af9013_state *state = fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops af9013_ops;
-
struct dvb_frontend *af9013_attach(const struct af9013_config *config,
struct i2c_adapter *i2c)
{
@@ -1455,91 +1438,65 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
/* allocate memory for the internal state */
state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
if (state == NULL)
- goto error;
+ goto err;
/* setup the state */
state->i2c = i2c;
memcpy(&state->config, config, sizeof(struct af9013_config));
/* download firmware */
- if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
+ if (state->config.ts_mode != AF9013_TS_USB) {
ret = af9013_download_firmware(state);
if (ret)
- goto error;
+ goto err;
}
/* firmware version */
- for (i = 0; i < 4; i++) {
- ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
- if (ret)
- goto error;
- }
- info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
-
- /* chip version */
- ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
+ ret = af9013_rd_regs(state, 0x5103, buf, 4);
if (ret)
- goto error;
+ goto err;
- /* ROM version */
- for (i = 0; i < 2; i++) {
- ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
- if (ret)
- goto error;
- }
- deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
- buf[2], buf[0], buf[1]);
-
- /* settings for mp2if */
- if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
- /* AF9015 split PSB to 1.5k + 0.5k */
- ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1);
- } else {
- /* AF9013 change the output bit to data7 */
- ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1);
- if (ret)
- goto error;
- /* AF9013 set mpeg to full speed */
- ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1);
- }
- if (ret)
- goto error;
- ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1);
- if (ret)
- goto error;
+ info("firmware version %d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
/* set GPIOs */
for (i = 0; i < sizeof(state->config.gpio); i++) {
ret = af9013_set_gpio(state, i, state->config.gpio[i]);
if (ret)
- goto error;
+ goto err;
}
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &af9013_ops,
+ memcpy(&state->fe.ops, &af9013_ops,
sizeof(struct dvb_frontend_ops));
- state->frontend.demodulator_priv = state;
+ state->fe.demodulator_priv = state;
+
+ INIT_DELAYED_WORK(&state->statistics_work, af9013_statistics_work);
- return &state->frontend;
-error:
+ return &state->fe;
+err:
kfree(state);
return NULL;
}
EXPORT_SYMBOL(af9013_attach);
static struct dvb_frontend_ops af9013_ops = {
+ .delsys = { SYS_DVBT },
.info = {
- .name = "Afatech AF9013 DVB-T",
- .type = FE_OFDM,
+ .name = "Afatech AF9013",
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 250000,
.frequency_tolerance = 0,
- .caps =
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK | FE_CAN_QAM_16 |
- FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ .caps = FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO |
@@ -1548,24 +1505,22 @@ static struct dvb_frontend_ops af9013_ops = {
},
.release = af9013_release,
+
.init = af9013_init,
.sleep = af9013_sleep,
- .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+ .get_tune_settings = af9013_get_tune_settings,
.set_frontend = af9013_set_frontend,
.get_frontend = af9013_get_frontend,
- .get_tune_settings = af9013_get_tune_settings,
-
.read_status = af9013_read_status,
- .read_ber = af9013_read_ber,
- .read_signal_strength = af9013_read_signal_strength,
.read_snr = af9013_read_snr,
+ .read_signal_strength = af9013_read_signal_strength,
+ .read_ber = af9013_read_ber,
.read_ucblocks = af9013_read_ucblocks,
-};
-module_param_named(debug, af9013_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+ .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+};
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h
index e53d873..b973fc5 100644
--- a/drivers/media/dvb/frontends/af9013.h
+++ b/drivers/media/dvb/frontends/af9013.h
@@ -2,6 +2,7 @@
* Afatech AF9013 demodulator driver
*
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
*
* Thanks to Afatech who kindly provided information.
*
@@ -21,33 +22,11 @@
*
*/
-#ifndef _AF9013_H_
-#define _AF9013_H_
+#ifndef AF9013_H
+#define AF9013_H
#include <linux/dvb/frontend.h>
-enum af9013_ts_mode {
- AF9013_OUTPUT_MODE_PARALLEL,
- AF9013_OUTPUT_MODE_SERIAL,
- AF9013_OUTPUT_MODE_USB, /* only for AF9015 */
-};
-
-enum af9013_tuner {
- AF9013_TUNER_MXL5003D = 3, /* MaxLinear */
- AF9013_TUNER_MXL5005D = 13, /* MaxLinear */
- AF9013_TUNER_MXL5005R = 30, /* MaxLinear */
- AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */
- AF9013_TUNER_MT2060 = 130, /* Microtune */
- AF9013_TUNER_MC44S803 = 133, /* Freescale */
- AF9013_TUNER_QT1010 = 134, /* Quantek */
- AF9013_TUNER_UNKNOWN = 140, /* for can tuners ? */
- AF9013_TUNER_MT2060_2 = 147, /* Microtune */
- AF9013_TUNER_TDA18271 = 156, /* NXP */
- AF9013_TUNER_QT1010A = 162, /* Quantek */
- AF9013_TUNER_MXL5007T = 177, /* MaxLinear */
- AF9013_TUNER_TDA18218 = 179, /* NXP */
-};
-
/* AF9013/5 GPIOs (mostly guessed)
demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
demod#1-gpio#1 - xtal setting (?)
@@ -55,44 +34,74 @@ enum af9013_tuner {
demod#2-gpio#0 - tuner#2
demod#2-gpio#1 - xtal setting (?)
*/
+
+struct af9013_config {
+ /*
+ * I2C address
+ */
+ u8 i2c_addr;
+
+ /*
+ * clock
+ * 20480000, 25000000, 28000000, 28800000
+ */
+ u32 clock;
+
+ /*
+ * tuner
+ */
+#define AF9013_TUNER_MXL5003D 3 /* MaxLinear */
+#define AF9013_TUNER_MXL5005D 13 /* MaxLinear */
+#define AF9013_TUNER_MXL5005R 30 /* MaxLinear */
+#define AF9013_TUNER_ENV77H11D5 129 /* Panasonic */
+#define AF9013_TUNER_MT2060 130 /* Microtune */
+#define AF9013_TUNER_MC44S803 133 /* Freescale */
+#define AF9013_TUNER_QT1010 134 /* Quantek */
+#define AF9013_TUNER_UNKNOWN 140 /* for can tuners ? */
+#define AF9013_TUNER_MT2060_2 147 /* Microtune */
+#define AF9013_TUNER_TDA18271 156 /* NXP */
+#define AF9013_TUNER_QT1010A 162 /* Quantek */
+#define AF9013_TUNER_MXL5007T 177 /* MaxLinear */
+#define AF9013_TUNER_TDA18218 179 /* NXP */
+ u8 tuner;
+
+ /*
+ * IF frequency
+ */
+ u32 if_frequency;
+
+ /*
+ * TS settings
+ */
+#define AF9013_TS_USB 0
+#define AF9013_TS_PARALLEL 1
+#define AF9013_TS_SERIAL 2
+ u8 ts_mode:2;
+
+ /*
+ * input spectrum inversion
+ */
+ bool spec_inv;
+
+ /*
+ * firmware API version
+ */
+ u8 api_version[4];
+
+ /*
+ * GPIOs
+ */
#define AF9013_GPIO_ON (1 << 0)
#define AF9013_GPIO_EN (1 << 1)
#define AF9013_GPIO_O (1 << 2)
#define AF9013_GPIO_I (1 << 3)
-
#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-
#define AF9013_GPIO_TUNER_ON (AF9013_GPIO_ON|AF9013_GPIO_EN)
#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-
-struct af9013_config {
- /* demodulator's I2C address */
- u8 demod_address;
-
- /* frequencies in kHz */
- u32 adc_clock;
-
- /* tuner ID */
- u8 tuner;
-
- /* tuner IF */
- u16 tuner_if;
-
- /* TS data output mode */
- u8 output_mode:2;
-
- /* RF spectrum inversion */
- u8 rf_spec_inv:1;
-
- /* API version */
- u8 api_version[4];
-
- /* GPIOs */
u8 gpio[4];
};
-
#if defined(CONFIG_DVB_AF9013) || \
(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
@@ -106,4 +115,4 @@ const struct af9013_config *config, struct i2c_adapter *i2c)
}
#endif /* CONFIG_DVB_AF9013 */
-#endif /* _AF9013_H_ */
+#endif /* AF9013_H */
diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h
index e00b2a4..fa848af 100644
--- a/drivers/media/dvb/frontends/af9013_priv.h
+++ b/drivers/media/dvb/frontends/af9013_priv.h
@@ -2,6 +2,7 @@
* Afatech AF9013 demodulator driver
*
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
*
* Thanks to Afatech who kindly provided information.
*
@@ -21,24 +22,19 @@
*
*/
-#ifndef _AF9013_PRIV_
-#define _AF9013_PRIV_
+#ifndef AF9013_PRIV_H
+#define AF9013_PRIV_H
-#define LOG_PREFIX "af9013"
-extern int af9013_debug;
-
-#define dprintk(var, level, args...) \
- do { if ((var & level)) printk(args); } while (0)
+#include "dvb_frontend.h"
+#include "af9013.h"
+#include <linux/firmware.h>
-#define debug_dump(b, l, func) {\
- int loop_; \
- for (loop_ = 0; loop_ < l; loop_++) \
- func("%02x ", b[loop_]); \
- func("\n");\
-}
-
-#define deb_info(args...) dprintk(af9013_debug, 0x01, args)
+#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
@@ -48,70 +44,71 @@ extern int af9013_debug;
#define AF9013_DEFAULT_FIRMWARE "dvb-fe-af9013.fw"
-struct regdesc {
+struct af9013_reg_bit {
u16 addr;
u8 pos:4;
u8 len:4;
u8 val;
};
-struct snr_table {
+struct af9013_snr {
u32 val;
u8 snr;
};
-struct coeff {
- u32 adc_clock;
- fe_bandwidth_t bw;
+struct af9013_coeff {
+ u32 clock;
+ u32 bandwidth_hz;
u8 val[24];
};
/* pre-calculated coeff lookup table */
-static struct coeff coeff_table[] = {
+static const struct af9013_coeff coeff_lut[] = {
/* 28.800 MHz */
- { 28800, BANDWIDTH_8_MHZ, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
+ { 28800000, 8000000, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
0x51, 0x11, 0x00, 0xa2, 0x8f, 0x3d, 0x00, 0xa2, 0x8a,
0x29, 0x00, 0xa2, 0x85, 0x14, 0x01, 0x45, 0x14, 0x14 } },
- { 28800, BANDWIDTH_7_MHZ, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
+ { 28800000, 7000000, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
0xc7, 0x07, 0x00, 0x8e, 0x3d, 0x55, 0x00, 0x8e, 0x38,
0xe4, 0x00, 0x8e, 0x34, 0x72, 0x01, 0x1c, 0x71, 0x32 } },
- { 28800, BANDWIDTH_6_MHZ, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
+ { 28800000, 6000000, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
0x3c, 0x3d, 0x00, 0x79, 0xeb, 0x6e, 0x00, 0x79, 0xe7,
0x9e, 0x00, 0x79, 0xe3, 0xcf, 0x00, 0xf3, 0xcf, 0x0f } },
/* 20.480 MHz */
- { 20480, BANDWIDTH_8_MHZ, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
+ { 20480000, 8000000, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
0x92, 0x13, 0x00, 0xe4, 0x99, 0x6e, 0x00, 0xe4, 0x92,
0x49, 0x00, 0xe4, 0x8b, 0x25, 0x01, 0xc9, 0x24, 0x25 } },
- { 20480, BANDWIDTH_7_MHZ, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
+ { 20480000, 7000000, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
0x00, 0x00, 0x00, 0xc8, 0x06, 0x40, 0x00, 0xc8, 0x00,
0x00, 0x00, 0xc7, 0xf9, 0xc0, 0x01, 0x90, 0x00, 0x00 } },
- { 20480, BANDWIDTH_6_MHZ, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
+ { 20480000, 6000000, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
0x6d, 0x2e, 0x00, 0xab, 0x73, 0x13, 0x00, 0xab, 0x6d,
0xb7, 0x00, 0xab, 0x68, 0x5c, 0x01, 0x56, 0xdb, 0x1c } },
/* 28.000 MHz */
- { 28000, BANDWIDTH_8_MHZ, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
+ { 28000000, 8000000, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
0x78, 0x0a, 0x00, 0xa7, 0x34, 0x3f, 0x00, 0xa7, 0x2f,
0x05, 0x00, 0xa7, 0x29, 0xcc, 0x01, 0x4e, 0x5e, 0x03 } },
- { 28000, BANDWIDTH_7_MHZ, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
+ { 28000000, 7000000, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
0x49, 0x09, 0x00, 0x92, 0x4d, 0xb7, 0x00, 0x92, 0x49,
0x25, 0x00, 0x92, 0x44, 0x92, 0x01, 0x24, 0x92, 0x12 } },
- { 28000, BANDWIDTH_6_MHZ, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
+ { 28000000, 6000000, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
0x1a, 0x08, 0x00, 0x7d, 0x67, 0x2f, 0x00, 0x7d, 0x63,
0x44, 0x00, 0x7d, 0x5f, 0x59, 0x00, 0xfa, 0xc6, 0x22 } },
/* 25.000 MHz */
- { 25000, BANDWIDTH_8_MHZ, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
+ { 25000000, 8000000, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
0xf7, 0x0e, 0x00, 0xbb, 0x44, 0xc1, 0x00, 0xbb, 0x3e,
0xe7, 0x00, 0xbb, 0x39, 0x0d, 0x01, 0x76, 0x7d, 0x34 } },
- { 25000, BANDWIDTH_7_MHZ, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
+ { 25000000, 7000000, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
0xb8, 0x14, 0x00, 0xa3, 0xdc, 0x29, 0x00, 0xa3, 0xd7,
0x0a, 0x00, 0xa3, 0xd1, 0xec, 0x01, 0x47, 0xae, 0x05 } },
- { 25000, BANDWIDTH_6_MHZ, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
+ { 25000000, 6000000, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
0x79, 0x1b, 0x00, 0x8c, 0x73, 0x91, 0x00, 0x8c, 0x6f,
0x2d, 0x00, 0x8c, 0x6a, 0xca, 0x01, 0x18, 0xde, 0x17 } },
};
/* QPSK SNR lookup table */
-static struct snr_table qpsk_snr_table[] = {
+static const struct af9013_snr qpsk_snr_lut[] = {
+ { 0x000000, 0 },
{ 0x0b4771, 0 },
{ 0x0c1aed, 1 },
{ 0x0d0d27, 2 },
@@ -131,7 +128,8 @@ static struct snr_table qpsk_snr_table[] = {
};
/* QAM16 SNR lookup table */
-static struct snr_table qam16_snr_table[] = {
+static const struct af9013_snr qam16_snr_lut[] = {
+ { 0x000000, 0 },
{ 0x05eb62, 5 },
{ 0x05fecf, 6 },
{ 0x060b80, 7 },
@@ -151,7 +149,8 @@ static struct snr_table qam16_snr_table[] = {
};
/* QAM64 SNR lookup table */
-static struct snr_table qam64_snr_table[] = {
+static const struct af9013_snr qam64_snr_lut[] = {
+ { 0x000000, 0 },
{ 0x03109b, 12 },
{ 0x0310d4, 13 },
{ 0x031920, 14 },
@@ -170,7 +169,7 @@ static struct snr_table qam64_snr_table[] = {
{ 0xffffff, 27 },
};
-static struct regdesc ofsm_init[] = {
+static const struct af9013_reg_bit ofsm_init[] = {
{ 0xd73a, 0, 8, 0xa1 },
{ 0xd73b, 0, 8, 0x1f },
{ 0xd73c, 4, 4, 0x0a },
@@ -252,7 +251,7 @@ static struct regdesc ofsm_init[] = {
/* Panasonic ENV77H11D5 tuner init
AF9013_TUNER_ENV77H11D5 = 129 */
-static struct regdesc tuner_init_env77h11d5[] = {
+static const struct af9013_reg_bit tuner_init_env77h11d5[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x03 },
{ 0x9bbe, 0, 8, 0x01 },
@@ -318,7 +317,7 @@ static struct regdesc tuner_init_env77h11d5[] = {
/* Microtune MT2060 tuner init
AF9013_TUNER_MT2060 = 130 */
-static struct regdesc tuner_init_mt2060[] = {
+static const struct af9013_reg_bit tuner_init_mt2060[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x07 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -395,7 +394,7 @@ static struct regdesc tuner_init_mt2060[] = {
/* Microtune MT2060 tuner init
AF9013_TUNER_MT2060_2 = 147 */
-static struct regdesc tuner_init_mt2060_2[] = {
+static const struct af9013_reg_bit tuner_init_mt2060_2[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x06 },
{ 0x9bbe, 0, 8, 0x01 },
@@ -462,7 +461,7 @@ static struct regdesc tuner_init_mt2060_2[] = {
/* MaxLinear MXL5003 tuner init
AF9013_TUNER_MXL5003D = 3 */
-static struct regdesc tuner_init_mxl5003d[] = {
+static const struct af9013_reg_bit tuner_init_mxl5003d[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x09 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -534,7 +533,7 @@ static struct regdesc tuner_init_mxl5003d[] = {
AF9013_TUNER_MXL5005D = 13
AF9013_TUNER_MXL5005R = 30
AF9013_TUNER_MXL5007T = 177 */
-static struct regdesc tuner_init_mxl5005[] = {
+static const struct af9013_reg_bit tuner_init_mxl5005[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x07 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -613,7 +612,7 @@ static struct regdesc tuner_init_mxl5005[] = {
/* Quantek QT1010 tuner init
AF9013_TUNER_QT1010 = 134
AF9013_TUNER_QT1010A = 162 */
-static struct regdesc tuner_init_qt1010[] = {
+static const struct af9013_reg_bit tuner_init_qt1010[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x09 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -690,7 +689,7 @@ static struct regdesc tuner_init_qt1010[] = {
/* Freescale MC44S803 tuner init
AF9013_TUNER_MC44S803 = 133 */
-static struct regdesc tuner_init_mc44s803[] = {
+static const struct af9013_reg_bit tuner_init_mc44s803[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x06 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -772,7 +771,7 @@ static struct regdesc tuner_init_mc44s803[] = {
/* unknown, probably for tin can tuner, tuner init
AF9013_TUNER_UNKNOWN = 140 */
-static struct regdesc tuner_init_unknown[] = {
+static const struct af9013_reg_bit tuner_init_unknown[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x02 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -845,7 +844,7 @@ static struct regdesc tuner_init_unknown[] = {
/* NXP TDA18271 & TDA18218 tuner init
AF9013_TUNER_TDA18271 = 156
AF9013_TUNER_TDA18218 = 179 */
-static struct regdesc tuner_init_tda18271[] = {
+static const struct af9013_reg_bit tuner_init_tda18271[] = {
{ 0x9bd5, 0, 8, 0x01 },
{ 0x9bd6, 0, 8, 0x04 },
{ 0xd1a0, 1, 1, 0x01 },
@@ -920,4 +919,4 @@ static struct regdesc tuner_init_tda18271[] = {
{ 0x9bee, 0, 1, 0x01 },
};
-#endif /* _AF9013_PRIV_ */
+#endif /* AF9013_PRIV_H */
diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c
index 1539ea1..a2261ea 100644
--- a/drivers/media/dvb/frontends/atbm8830.c
+++ b/drivers/media/dvb/frontends/atbm8830.c
@@ -267,8 +267,7 @@ static void atbm8830_release(struct dvb_frontend *fe)
kfree(state);
}
-static int atbm8830_set_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fe_params)
+static int atbm8830_set_fe(struct dvb_frontend *fe)
{
struct atbm_state *priv = fe->demodulator_priv;
int i;
@@ -279,7 +278,7 @@ static int atbm8830_set_fe(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, fe_params);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -298,31 +297,31 @@ static int atbm8830_set_fe(struct dvb_frontend *fe,
return 0;
}
-static int atbm8830_get_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fe_params)
+static int atbm8830_get_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
dprintk("%s\n", __func__);
/* TODO: get real readings from device */
/* inversion status */
- fe_params->inversion = INVERSION_OFF;
+ c->inversion = INVERSION_OFF;
/* bandwidth */
- fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ c->bandwidth_hz = 8000000;
- fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
- fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
+ c->code_rate_HP = FEC_AUTO;
+ c->code_rate_LP = FEC_AUTO;
- fe_params->u.ofdm.constellation = QAM_AUTO;
+ c->modulation = QAM_AUTO;
/* transmission mode */
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+ c->transmission_mode = TRANSMISSION_MODE_AUTO;
/* guard interval */
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+ c->guard_interval = GUARD_INTERVAL_AUTO;
/* hierarchy */
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ c->hierarchy = HIERARCHY_NONE;
return 0;
}
@@ -429,9 +428,9 @@ static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
}
static struct dvb_frontend_ops atbm8830_ops = {
+ .delsys = { SYS_DMBTH },
.info = {
.name = "AltoBeam ATBM8830/8831 DMB-TH",
- .type = FE_OFDM,
.frequency_min = 474000000,
.frequency_max = 858000000,
.frequency_stepsize = 10000,
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
index 1d57294..c688b95d 100644
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -576,19 +576,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int au8522_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int au8522_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct au8522_state *state = fe->demodulator_priv;
int ret = -EINVAL;
- dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+ dprintk("%s(frequency=%d)\n", __func__, c->frequency);
- if ((state->current_frequency == p->frequency) &&
- (state->current_modulation == p->u.vsb.modulation))
+ if ((state->current_frequency == c->frequency) &&
+ (state->current_modulation == c->modulation))
return 0;
- au8522_enable_modulation(fe, p->u.vsb.modulation);
+ au8522_enable_modulation(fe, c->modulation);
/* Allow the demod to settle */
msleep(100);
@@ -596,7 +596,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- ret = fe->ops.tuner_ops.set_params(fe, p);
+ ret = fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -604,7 +604,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
if (ret < 0)
return ret;
- state->current_frequency = p->frequency;
+ state->current_frequency = c->frequency;
return 0;
}
@@ -862,7 +862,36 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
static int au8522_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
- return au8522_read_snr(fe, signal_strength);
+ /* borrowed from lgdt330x.c
+ *
+ * Calculate strength from SNR up to 35dB
+ * Even though the SNR can go higher than 35dB,
+ * there is some comfort factor in having a range of
+ * strong signals that can show at 100%
+ */
+ u16 snr;
+ u32 tmp;
+ int ret = au8522_read_snr(fe, &snr);
+
+ *signal_strength = 0;
+
+ if (0 == ret) {
+ /* The following calculation method was chosen
+ * purely for the sake of code re-use from the
+ * other demod drivers that use this method */
+
+ /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+ tmp = (snr * ((1 << 24) / 10));
+
+ /* Convert from 8.24 fixed-point to
+ * scale the range 0 - 35*2^24 into 0 - 65535*/
+ if (tmp >= 8960 * 0x10000)
+ *signal_strength = 0xffff;
+ else
+ *signal_strength = tmp / 8960;
+ }
+
+ return ret;
}
static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -882,13 +911,13 @@ static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
return au8522_read_ucblocks(fe, ber);
}
-static int au8522_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int au8522_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct au8522_state *state = fe->demodulator_priv;
- p->frequency = state->current_frequency;
- p->u.vsb.modulation = state->current_modulation;
+ c->frequency = state->current_frequency;
+ c->modulation = state->current_modulation;
return 0;
}
@@ -981,10 +1010,9 @@ error:
EXPORT_SYMBOL(au8522_attach);
static struct dvb_frontend_ops au8522_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Auvitek AU8522 QAM/8VSB Frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 8aff586..033cd7a 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -479,16 +479,16 @@ static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
return -EINVAL;
}
-static int bcm3510_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int bcm3510_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct bcm3510_state* st = fe->demodulator_priv;
struct bcm3510_hab_cmd_ext_acquire cmd;
struct bcm3510_hab_cmd_bert_control bert;
int ret;
memset(&cmd,0,sizeof(cmd));
- switch (p->u.vsb.modulation) {
+ switch (c->modulation) {
case QAM_256:
cmd.ACQUIRE0.MODE = 0x1;
cmd.ACQUIRE1.SYM_RATE = 0x1;
@@ -499,7 +499,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
cmd.ACQUIRE1.SYM_RATE = 0x2;
cmd.ACQUIRE1.IF_FREQ = 0x1;
break;
-/* case QAM_256:
+#if 0
+ case QAM_256:
cmd.ACQUIRE0.MODE = 0x3;
break;
case QAM_128:
@@ -513,7 +514,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
break;
case QAM_16:
cmd.ACQUIRE0.MODE = 0x7;
- break;*/
+ break;
+#endif
case VSB_8:
cmd.ACQUIRE0.MODE = 0x8;
cmd.ACQUIRE1.SYM_RATE = 0x0;
@@ -552,7 +554,8 @@ static int bcm3510_set_frontend(struct dvb_frontend* fe,
bcm3510_bert_reset(st);
- if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
+ ret = bcm3510_set_freq(st, c->frequency);
+ if (ret < 0)
return ret;
memset(&st->status1,0,sizeof(st->status1));
@@ -819,10 +822,9 @@ error:
EXPORT_SYMBOL(bcm3510_attach);
static struct dvb_frontend_ops bcm3510_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Broadcom BCM3510 VSB/QAM frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 803000000,
/* stepsize is just a guess */
diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
index 5e431eb..53e4d0d 100644
--- a/drivers/media/dvb/frontends/bsbe1.h
+++ b/drivers/media/dvb/frontends/bsbe1.h
@@ -69,18 +69,19 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int ret;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
struct i2c_adapter *i2c = fe->tuner_priv;
- if ((params->frequency < 950000) || (params->frequency > 2150000))
+ if ((p->frequency < 950000) || (p->frequency > 2150000))
return -EINVAL;
- div = params->frequency / 1000;
+ div = p->frequency / 1000;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
index c480c83..c2a578e 100644
--- a/drivers/media/dvb/frontends/bsru6.h
+++ b/drivers/media/dvb/frontends/bsru6.h
@@ -101,23 +101,24 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
struct i2c_adapter *i2c = fe->tuner_priv;
- if ((params->frequency < 950000) || (params->frequency > 2150000))
+ if ((p->frequency < 950000) || (p->frequency > 2150000))
return -EINVAL;
- div = (params->frequency + (125 - 1)) / 125; // round correctly
+ div = (p->frequency + (125 - 1)) / 125; /* round correctly */
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0xC4;
- if (params->frequency > 1530000)
+ if (p->frequency > 1530000)
buf[3] = 0xc0;
if (fe->ops.i2c_gate_ctrl)
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index 0142214..f2a90f9 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -121,7 +121,8 @@ static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
}
}
-static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_parameters *p)
+static int cx22700_set_tps(struct cx22700_state *state,
+ struct dtv_frontend_properties *p)
{
static const u8 qam_tab [4] = { 0, 1, 0, 2 };
static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
@@ -146,25 +147,25 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
p->transmission_mode != TRANSMISSION_MODE_8K)
return -EINVAL;
- if (p->constellation != QPSK &&
- p->constellation != QAM_16 &&
- p->constellation != QAM_64)
+ if (p->modulation != QPSK &&
+ p->modulation != QAM_16 &&
+ p->modulation != QAM_64)
return -EINVAL;
- if (p->hierarchy_information < HIERARCHY_NONE ||
- p->hierarchy_information > HIERARCHY_4)
+ if (p->hierarchy < HIERARCHY_NONE ||
+ p->hierarchy > HIERARCHY_4)
return -EINVAL;
- if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ)
+ if (p->bandwidth_hz > 8000000 || p->bandwidth_hz < 6000000)
return -EINVAL;
- if (p->bandwidth == BANDWIDTH_7_MHZ)
+ if (p->bandwidth_hz == 7000000)
cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 | 0x10));
else
cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 & ~0x10));
- val = qam_tab[p->constellation - QPSK];
- val |= p->hierarchy_information - HIERARCHY_NONE;
+ val = qam_tab[p->modulation - QPSK];
+ val |= p->hierarchy - HIERARCHY_NONE;
cx22700_writereg (state, 0x04, val);
@@ -184,7 +185,8 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
return 0;
}
-static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_parameters *p)
+static int cx22700_get_tps(struct cx22700_state *state,
+ struct dtv_frontend_properties *p)
{
static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
@@ -199,14 +201,14 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
val = cx22700_readreg (state, 0x01);
if ((val & 0x7) > 4)
- p->hierarchy_information = HIERARCHY_AUTO;
+ p->hierarchy = HIERARCHY_AUTO;
else
- p->hierarchy_information = HIERARCHY_NONE + (val & 0x7);
+ p->hierarchy = HIERARCHY_NONE + (val & 0x7);
if (((val >> 3) & 0x3) > 2)
- p->constellation = QAM_AUTO;
+ p->modulation = QAM_AUTO;
else
- p->constellation = qam_tab[(val >> 3) & 0x3];
+ p->modulation = qam_tab[(val >> 3) & 0x3];
val = cx22700_readreg (state, 0x02);
@@ -318,33 +320,35 @@ static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22700_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx22700_state* state = fe->demodulator_priv;
cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
cx22700_writereg (state, 0x00, 0x00);
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- cx22700_set_inversion (state, p->inversion);
- cx22700_set_tps (state, &p->u.ofdm);
+ cx22700_set_inversion(state, c->inversion);
+ cx22700_set_tps(state, c);
cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */
cx22700_writereg (state, 0x00, 0x01); /* restart acquire */
return 0;
}
-static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx22700_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx22700_state* state = fe->demodulator_priv;
u8 reg09 = cx22700_readreg (state, 0x09);
- p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
- return cx22700_get_tps (state, &p->u.ofdm);
+ c->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
+ return cx22700_get_tps(state, c);
}
static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
@@ -401,10 +405,9 @@ error:
}
static struct dvb_frontend_ops cx22700_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Conexant CX22700 DVB-T",
- .type = FE_OFDM,
.frequency_min = 470000000,
.frequency_max = 860000000,
.frequency_stepsize = 166667,
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 3139558..faba824 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -146,7 +146,7 @@ static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
/* Retrieve the demod settings */
static int cx22702_get_tps(struct cx22702_state *state,
- struct dvb_ofdm_parameters *p)
+ struct dtv_frontend_properties *p)
{
u8 val;
@@ -157,27 +157,27 @@ static int cx22702_get_tps(struct cx22702_state *state,
val = cx22702_readreg(state, 0x01);
switch ((val & 0x18) >> 3) {
case 0:
- p->constellation = QPSK;
+ p->modulation = QPSK;
break;
case 1:
- p->constellation = QAM_16;
+ p->modulation = QAM_16;
break;
case 2:
- p->constellation = QAM_64;
+ p->modulation = QAM_64;
break;
}
switch (val & 0x07) {
case 0:
- p->hierarchy_information = HIERARCHY_NONE;
+ p->hierarchy = HIERARCHY_NONE;
break;
case 1:
- p->hierarchy_information = HIERARCHY_1;
+ p->hierarchy = HIERARCHY_1;
break;
case 2:
- p->hierarchy_information = HIERARCHY_2;
+ p->hierarchy = HIERARCHY_2;
break;
case 3:
- p->hierarchy_information = HIERARCHY_4;
+ p->hierarchy = HIERARCHY_4;
break;
}
@@ -260,14 +260,14 @@ static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx22702_set_tps(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u8 val;
struct cx22702_state *state = fe->demodulator_priv;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -277,14 +277,14 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
/* set bandwidth */
val = cx22702_readreg(state, 0x0C) & 0xcf;
- switch (p->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
val |= 0x20;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
val |= 0x10;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
break;
default:
dprintk("%s: invalid bandwidth\n", __func__);
@@ -292,15 +292,15 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
}
cx22702_writereg(state, 0x0C, val);
- p->u.ofdm.code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
+ p->code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
/* use auto configuration? */
- if ((p->u.ofdm.hierarchy_information == HIERARCHY_AUTO) ||
- (p->u.ofdm.constellation == QAM_AUTO) ||
- (p->u.ofdm.code_rate_HP == FEC_AUTO) ||
- (p->u.ofdm.code_rate_LP == FEC_AUTO) ||
- (p->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO) ||
- (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO)) {
+ if ((p->hierarchy == HIERARCHY_AUTO) ||
+ (p->modulation == QAM_AUTO) ||
+ (p->code_rate_HP == FEC_AUTO) ||
+ (p->code_rate_LP == FEC_AUTO) ||
+ (p->guard_interval == GUARD_INTERVAL_AUTO) ||
+ (p->transmission_mode == TRANSMISSION_MODE_AUTO)) {
/* TPS Source - use hardware driven values */
cx22702_writereg(state, 0x06, 0x10);
@@ -316,7 +316,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
}
/* manually programmed values */
- switch (p->u.ofdm.constellation) { /* mask 0x18 */
+ switch (p->modulation) { /* mask 0x18 */
case QPSK:
val = 0x00;
break;
@@ -327,10 +327,10 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
val = 0x10;
break;
default:
- dprintk("%s: invalid constellation\n", __func__);
+ dprintk("%s: invalid modulation\n", __func__);
return -EINVAL;
}
- switch (p->u.ofdm.hierarchy_information) { /* mask 0x07 */
+ switch (p->hierarchy) { /* mask 0x07 */
case HIERARCHY_NONE:
break;
case HIERARCHY_1:
@@ -348,7 +348,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
}
cx22702_writereg(state, 0x06, val);
- switch (p->u.ofdm.code_rate_HP) { /* mask 0x38 */
+ switch (p->code_rate_HP) { /* mask 0x38 */
case FEC_NONE:
case FEC_1_2:
val = 0x00;
@@ -369,7 +369,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
dprintk("%s: invalid code_rate_HP\n", __func__);
return -EINVAL;
}
- switch (p->u.ofdm.code_rate_LP) { /* mask 0x07 */
+ switch (p->code_rate_LP) { /* mask 0x07 */
case FEC_NONE:
case FEC_1_2:
break;
@@ -391,7 +391,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
}
cx22702_writereg(state, 0x07, val);
- switch (p->u.ofdm.guard_interval) { /* mask 0x0c */
+ switch (p->guard_interval) { /* mask 0x0c */
case GUARD_INTERVAL_1_32:
val = 0x00;
break;
@@ -408,7 +408,7 @@ static int cx22702_set_tps(struct dvb_frontend *fe,
dprintk("%s: invalid guard_interval\n", __func__);
return -EINVAL;
}
- switch (p->u.ofdm.transmission_mode) { /* mask 0x03 */
+ switch (p->transmission_mode) { /* mask 0x03 */
case TRANSMISSION_MODE_2K:
break;
case TRANSMISSION_MODE_8K:
@@ -546,15 +546,15 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-static int cx22702_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx22702_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx22702_state *state = fe->demodulator_priv;
u8 reg0C = cx22702_readreg(state, 0x0C);
- p->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
- return cx22702_get_tps(state, &p->u.ofdm);
+ c->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
+ return cx22702_get_tps(state, c);
}
static int cx22702_get_tune_settings(struct dvb_frontend *fe,
@@ -603,10 +603,9 @@ error:
EXPORT_SYMBOL(cx22702_attach);
static const struct dvb_frontend_ops cx22702_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Conexant CX22702 DVB-T",
- .type = FE_OFDM,
.frequency_min = 177000000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index bf9c999..5101f10 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -531,26 +531,27 @@ static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24110_set_frontend(struct dvb_frontend *fe)
{
struct cx24110_state *state = fe->demodulator_priv;
-
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- cx24110_set_inversion (state, p->inversion);
- cx24110_set_fec (state, p->u.qpsk.fec_inner);
- cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
+ cx24110_set_inversion(state, p->inversion);
+ cx24110_set_fec(state, p->fec_inner);
+ cx24110_set_symbolrate(state, p->symbol_rate);
cx24110_writereg(state,0x04,0x05); /* start acquisition */
return 0;
}
-static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int cx24110_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24110_state *state = fe->demodulator_priv;
s32 afc; unsigned sclk;
@@ -571,7 +572,7 @@ static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
p->frequency += afc;
p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
INVERSION_ON : INVERSION_OFF;
- p->u.qpsk.fec_inner = cx24110_get_fec (state);
+ p->fec_inner = cx24110_get_fec(state);
return 0;
}
@@ -623,10 +624,9 @@ error:
}
static struct dvb_frontend_ops cx24110_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Conexant CX24110 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb/frontends/cx24113.c
index c341d57..3883c3b 100644
--- a/drivers/media/dvb/frontends/cx24113.c
+++ b/drivers/media/dvb/frontends/cx24113.c
@@ -476,21 +476,21 @@ static int cx24113_init(struct dvb_frontend *fe)
return ret;
}
-static int cx24113_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24113_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx24113_state *state = fe->tuner_priv;
/* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */
u32 roll_off = 675;
u32 bw;
- bw = ((p->u.qpsk.symbol_rate/100) * roll_off) / 1000;
+ bw = ((c->symbol_rate/100) * roll_off) / 1000;
bw += (10000000/100) + 5;
bw /= 10;
bw += 1000;
cx24113_set_bandwidth(state, bw);
- cx24113_set_frequency(state, p->frequency);
+ cx24113_set_frequency(state, c->frequency);
msleep(5);
return cx24113_get_status(fe, &bw);
}
@@ -547,11 +547,9 @@ static const struct dvb_tuner_ops cx24113_tuner_ops = {
.release = cx24113_release,
.init = cx24113_init,
- .sleep = NULL,
.set_params = cx24113_set_params,
.get_frequency = cx24113_get_frequency,
- .get_bandwidth = NULL,
.get_status = cx24113_get_status,
};
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index ccd0525..b488791 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -1212,25 +1212,10 @@ static int cx24116_sleep(struct dvb_frontend *fe)
return 0;
}
-static int cx24116_set_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
-static int cx24116_get_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
/* dvb-core told us to tune, the tv property cache will be complete,
* it's safe for is to pull values and use them for tuning purposes.
*/
-static int cx24116_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24116_set_frontend(struct dvb_frontend *fe)
{
struct cx24116_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1455,12 +1440,20 @@ tuned: /* Set/Reset B/W */
return cx24116_cmd_execute(fe, &cmd);
}
-static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
+static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
{
+ /*
+ * It is safe to discard "params" here, as the DVB core will sync
+ * fe->dtv_property_cache with fepriv->parameters_in, where the
+ * DVBv3 params are stored. The only practical usage for it indicate
+ * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
+ * true.
+ */
+
*delay = HZ / 5;
- if (params) {
- int ret = cx24116_set_frontend(fe, params);
+ if (re_tune) {
+ int ret = cx24116_set_frontend(fe);
if (ret)
return ret;
}
@@ -1473,10 +1466,9 @@ static int cx24116_get_algo(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops cx24116_ops = {
-
+ .delsys = { SYS_DVBS, SYS_DVBS2 },
.info = {
.name = "Conexant CX24116/CX24118",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
@@ -1507,8 +1499,6 @@ static struct dvb_frontend_ops cx24116_ops = {
.get_frontend_algo = cx24116_get_algo,
.tune = cx24116_tune,
- .set_property = cx24116_set_property,
- .get_property = cx24116_get_property,
.set_frontend = cx24116_set_frontend,
};
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index b1dd8ac..7e28b4e 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -526,9 +526,9 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
* to be configured and the correct band selected.
* Calculate those values.
*/
-static int cx24123_pll_calculate(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24123_pll_calculate(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24123_state *state = fe->demodulator_priv;
u32 ndiv = 0, adiv = 0, vco_div = 0;
int i = 0;
@@ -548,8 +548,8 @@ static int cx24123_pll_calculate(struct dvb_frontend *fe,
* FILTUNE programming bits */
for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
agcv = &cx24123_AGC_vals[i];
- if ((agcv->symbolrate_low <= p->u.qpsk.symbol_rate) &&
- (agcv->symbolrate_high >= p->u.qpsk.symbol_rate)) {
+ if ((agcv->symbolrate_low <= p->symbol_rate) &&
+ (agcv->symbolrate_high >= p->symbol_rate)) {
state->VCAarg = agcv->VCAprogdata;
state->VGAarg = agcv->VGAprogdata;
state->FILTune = agcv->FILTune;
@@ -601,8 +601,7 @@ static int cx24123_pll_calculate(struct dvb_frontend *fe,
* Tuner cx24109 is written through a dedicated 3wire interface
* on the demod chip.
*/
-static int cx24123_pll_writereg(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p, u32 data)
+static int cx24123_pll_writereg(struct dvb_frontend *fe, u32 data)
{
struct cx24123_state *state = fe->demodulator_priv;
unsigned long timeout;
@@ -659,26 +658,26 @@ static int cx24123_pll_writereg(struct dvb_frontend *fe,
return 0;
}
-static int cx24123_pll_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24123_pll_tune(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
dprintk("frequency=%i\n", p->frequency);
- if (cx24123_pll_calculate(fe, p) != 0) {
+ if (cx24123_pll_calculate(fe) != 0) {
err("%s: cx24123_pll_calcutate failed\n", __func__);
return -EINVAL;
}
/* Write the new VCO/VGA */
- cx24123_pll_writereg(fe, p, state->VCAarg);
- cx24123_pll_writereg(fe, p, state->VGAarg);
+ cx24123_pll_writereg(fe, state->VCAarg);
+ cx24123_pll_writereg(fe, state->VGAarg);
/* Write the new bandselect and pll args */
- cx24123_pll_writereg(fe, p, state->bandselectarg);
- cx24123_pll_writereg(fe, p, state->pllarg);
+ cx24123_pll_writereg(fe, state->bandselectarg);
+ cx24123_pll_writereg(fe, state->pllarg);
/* set the FILTUNE voltage */
val = cx24123_readreg(state, 0x28) & ~0x3;
@@ -925,10 +924,10 @@ static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0;
}
-static int cx24123_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24123_set_frontend(struct dvb_frontend *fe)
{
struct cx24123_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
dprintk("\n");
@@ -936,16 +935,16 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
state->config->set_ts_params(fe, 0);
state->currentfreq = p->frequency;
- state->currentsymbolrate = p->u.qpsk.symbol_rate;
+ state->currentsymbolrate = p->symbol_rate;
cx24123_set_inversion(state, p->inversion);
- cx24123_set_fec(state, p->u.qpsk.fec_inner);
- cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ cx24123_set_fec(state, p->fec_inner);
+ cx24123_set_symbolrate(state, p->symbol_rate);
if (!state->config->dont_use_pll)
- cx24123_pll_tune(fe, p);
+ cx24123_pll_tune(fe);
else if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
else
err("it seems I don't have a tuner...");
@@ -960,9 +959,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int cx24123_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int cx24123_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24123_state *state = fe->demodulator_priv;
dprintk("\n");
@@ -971,12 +970,12 @@ static int cx24123_get_frontend(struct dvb_frontend *fe,
err("%s: Failed to get inversion status\n", __func__);
return -EREMOTEIO;
}
- if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+ if (cx24123_get_fec(state, &p->fec_inner) != 0) {
err("%s: Failed to get fec status\n", __func__);
return -EREMOTEIO;
}
p->frequency = state->currentfreq;
- p->u.qpsk.symbol_rate = state->currentsymbolrate;
+ p->symbol_rate = state->currentsymbolrate;
return 0;
}
@@ -1007,15 +1006,15 @@ static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
}
static int cx24123_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
{
int retval = 0;
- if (params != NULL)
- retval = cx24123_set_frontend(fe, params);
+ if (re_tune)
+ retval = cx24123_set_frontend(fe);
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
cx24123_read_status(fe, status);
@@ -1126,10 +1125,9 @@ error:
EXPORT_SYMBOL(cx24123_attach);
static struct dvb_frontend_ops cx24123_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Conexant CX24123/CX24109",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
index 03cab7b..cf0f546 100644
--- a/drivers/media/dvb/frontends/cxd2820r.h
+++ b/drivers/media/dvb/frontends/cxd2820r.h
@@ -63,19 +63,6 @@ struct cxd2820r_config {
*/
bool spec_inv;
- /* IFs for all used modes.
- * Default: none, must set
- * Values: <kHz>
- */
- u16 if_dvbt_6;
- u16 if_dvbt_7;
- u16 if_dvbt_8;
- u16 if_dvbt2_5;
- u16 if_dvbt2_6;
- u16 if_dvbt2_7;
- u16 if_dvbt2_8;
- u16 if_dvbc;
-
/* GPIOs for all used modes.
* Default: none, disabled
* Values: <see above>
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c
index b85f501..9454049 100644
--- a/drivers/media/dvb/frontends/cxd2820r_c.c
+++ b/drivers/media/dvb/frontends/cxd2820r_c.c
@@ -21,13 +21,13 @@
#include "cxd2820r_priv.h"
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i;
u8 buf[2];
+ u32 if_freq;
u16 if_ctl;
u64 num;
struct reg_val_mask tab[] = {
@@ -56,9 +56,9 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
/* program tuner */
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, params);
+ fe->ops.tuner_ops.set_params(fe);
- if (priv->delivery_system != SYS_DVBC_ANNEX_AC) {
+ if (priv->delivery_system != SYS_DVBC_ANNEX_A) {
for (i = 0; i < ARRAY_SIZE(tab); i++) {
ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
tab[i].val, tab[i].mask);
@@ -67,10 +67,20 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
}
}
- priv->delivery_system = SYS_DVBC_ANNEX_AC;
+ priv->delivery_system = SYS_DVBC_ANNEX_A;
priv->ber_running = 0; /* tune stops BER counter */
- num = priv->cfg.if_dvbc;
+ /* program IF frequency */
+ if (fe->ops.tuner_ops.get_if_frequency) {
+ ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+ if (ret)
+ goto error;
+ } else
+ if_freq = 0;
+
+ dbg("%s: if_freq=%d", __func__, if_freq);
+
+ num = if_freq / 1000; /* Hz => kHz */
num *= 0x4000;
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
buf[0] = (if_ctl >> 8) & 0x3f;
@@ -94,8 +104,7 @@ error:
return ret;
}
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index 036480f..93e1b12 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -240,422 +240,234 @@ error:
return ret;
}
-/* lock FE */
-static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)
-{
- int ret = 0;
- dbg("%s: active_fe=%d", __func__, active_fe);
-
- mutex_lock(&priv->fe_lock);
-
- /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
- if (priv->active_fe == active_fe)
- ;
- else if (priv->active_fe == -1)
- priv->active_fe = active_fe;
- else
- ret = -EBUSY;
-
- mutex_unlock(&priv->fe_lock);
-
- return ret;
-}
-
-/* unlock FE */
-static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)
-{
- dbg("%s: active_fe=%d", __func__, active_fe);
-
- mutex_lock(&priv->fe_lock);
-
- /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
- if (priv->active_fe == active_fe)
- priv->active_fe = -1;
-
- mutex_unlock(&priv->fe_lock);
-
- return;
-}
-
/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
{
return div_u64(dividend + (divisor / 2), divisor);
}
-static int cxd2820r_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+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);
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (priv->delivery_system) {
- case SYS_UNDEFINED:
- if (c->delivery_system == SYS_DVBT) {
- /* SLEEP => DVB-T */
- ret = cxd2820r_set_frontend_t(fe, p);
- } else {
- /* SLEEP => DVB-T2 */
- ret = cxd2820r_set_frontend_t2(fe, p);
- }
- break;
- case SYS_DVBT:
- if (c->delivery_system == SYS_DVBT) {
- /* DVB-T => DVB-T */
- ret = cxd2820r_set_frontend_t(fe, p);
- } else if (c->delivery_system == SYS_DVBT2) {
- /* DVB-T => DVB-T2 */
- ret = cxd2820r_sleep_t(fe);
- if (ret)
- break;
- ret = cxd2820r_set_frontend_t2(fe, p);
- }
- break;
- case SYS_DVBT2:
- if (c->delivery_system == SYS_DVBT2) {
- /* DVB-T2 => DVB-T2 */
- ret = cxd2820r_set_frontend_t2(fe, p);
- } else if (c->delivery_system == SYS_DVBT) {
- /* DVB-T2 => DVB-T */
- ret = cxd2820r_sleep_t2(fe);
- if (ret)
- break;
- ret = cxd2820r_set_frontend_t(fe, p);
- }
- break;
- default:
- dbg("%s: error state=%d", __func__,
- priv->delivery_system);
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
-
- ret = cxd2820r_set_frontend_c(fe, p);
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (c->delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_init_t(fe);
+ if (ret < 0)
+ goto err;
+ ret = cxd2820r_set_frontend_t(fe);
+ if (ret < 0)
+ goto err;
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_init_t(fe);
+ if (ret < 0)
+ goto err;
+ ret = cxd2820r_set_frontend_t2(fe);
+ if (ret < 0)
+ goto err;
+ break;
+ case SYS_DVBC_ANNEX_A:
+ ret = cxd2820r_init_c(fe);
+ if (ret < 0)
+ goto err;
+ ret = cxd2820r_set_frontend_c(fe);
+ if (ret < 0)
+ goto err;
+ break;
+ default:
+ dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system);
+ ret = -EINVAL;
+ break;
}
-
+err:
return ret;
}
-
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_read_status_t(fe, status);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_read_status_t2(fe, status);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_read_status_t(fe, status);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_read_status_t2(fe, status);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_read_status_c(fe, status);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
-static int cxd2820r_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+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);
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_get_frontend_t(fe, p);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_get_frontend_t2(fe, p);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
-
- ret = cxd2820r_get_frontend_c(fe, p);
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_get_frontend_t(fe);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_get_frontend_t2(fe);
+ break;
+ case SYS_DVBC_ANNEX_A:
+ ret = cxd2820r_get_frontend_c(fe);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_read_ber_t(fe, ber);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_read_ber_t2(fe, ber);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_read_ber_t(fe, ber);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_read_ber_t2(fe, ber);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_read_ber_c(fe, ber);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_read_signal_strength_t(fe, strength);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_read_signal_strength_t2(fe, strength);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __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);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_read_signal_strength_t2(fe, strength);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_read_signal_strength_c(fe, strength);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_read_snr_t(fe, snr);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_read_snr_t2(fe, snr);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_read_snr_t(fe, snr);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_read_snr_t2(fe, snr);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_read_snr_c(fe, snr);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
static int cxd2820r_init(struct dvb_frontend *fe)
{
- struct cxd2820r_priv *priv = fe->demodulator_priv;
- int ret;
- dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
- priv->delivery_system = SYS_UNDEFINED;
- /* delivery system is unknown at that (init) phase */
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- ret = cxd2820r_init_t(fe);
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
-
- ret = cxd2820r_init_c(fe);
- }
-
- return ret;
+ return 0;
}
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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_sleep_t(fe);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_sleep_t2(fe);
- break;
- default:
- ret = -EINVAL;
- }
-
- cxd2820r_unlock(priv, 0);
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+ switch (fe->dtv_property_cache.delivery_system) {
+ case SYS_DVBT:
+ ret = cxd2820r_sleep_t(fe);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_sleep_t2(fe);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_sleep_c(fe);
-
- cxd2820r_unlock(priv, 1);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
- struct dvb_frontend_tune_settings *s)
+ 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);
-
- if (fe->ops.info.type == FE_OFDM) {
- /* DVB-T/T2 */
- ret = cxd2820r_lock(priv, 0);
- if (ret)
- return ret;
-
- switch (fe->dtv_property_cache.delivery_system) {
- case SYS_DVBT:
- ret = cxd2820r_get_tune_settings_t(fe, s);
- break;
- case SYS_DVBT2:
- ret = cxd2820r_get_tune_settings_t2(fe, s);
- break;
- default:
- ret = -EINVAL;
- }
- } else {
- /* DVB-C */
- ret = cxd2820r_lock(priv, 1);
- if (ret)
- return ret;
+ dbg("%s: delsys=%d", __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);
+ break;
+ case SYS_DVBT2:
+ ret = cxd2820r_get_tune_settings_t2(fe, s);
+ break;
+ case SYS_DVBC_ANNEX_A:
ret = cxd2820r_get_tune_settings_c(fe, s);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
-
return ret;
}
-static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -664,7 +476,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
/* switch between DVB-T and DVB-T2 when tune fails */
- if (priv->last_tune_failed) {
+ if (priv->last_tune_failed && (priv->delivery_system != SYS_DVBC_ANNEX_A)) {
if (priv->delivery_system == SYS_DVBT)
c->delivery_system = SYS_DVBT2;
else
@@ -672,7 +484,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
}
/* set frontend */
- ret = cxd2820r_set_frontend(fe, p);
+ ret = cxd2820r_set_frontend(fe);
if (ret)
goto error;
@@ -727,9 +539,7 @@ static void cxd2820r_release(struct dvb_frontend *fe)
struct cxd2820r_priv *priv = fe->demodulator_priv;
dbg("%s", __func__);
- if (fe->ops.info.type == FE_OFDM)
- kfree(priv);
-
+ kfree(priv);
return;
}
@@ -742,128 +552,79 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
}
-static const struct dvb_frontend_ops cxd2820r_ops[2];
+static const struct dvb_frontend_ops cxd2820r_ops = {
+ .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
+ /* default: DVB-T/T2 */
+ .info = {
+ .name = "Sony CXD2820R (DVB-T/T2)",
+
+ .caps = FE_CAN_FEC_1_2 |
+ FE_CAN_FEC_2_3 |
+ FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 |
+ FE_CAN_FEC_7_8 |
+ FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_256 |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_MUTE_TS |
+ FE_CAN_2G_MODULATION
+ },
-struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
- struct i2c_adapter *i2c, struct dvb_frontend *fe)
-{
- int ret;
- struct cxd2820r_priv *priv = NULL;
- u8 tmp;
+ .release = cxd2820r_release,
+ .init = cxd2820r_init,
+ .sleep = cxd2820r_sleep,
- if (fe == NULL) {
- /* FE0 */
- /* allocate memory for the internal priv */
- priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
- if (priv == NULL)
- goto error;
+ .get_tune_settings = cxd2820r_get_tune_settings,
+ .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
- /* setup the priv */
- priv->i2c = i2c;
- memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
- mutex_init(&priv->fe_lock);
+ .get_frontend = cxd2820r_get_frontend,
- priv->active_fe = -1; /* NONE */
+ .get_frontend_algo = cxd2820r_get_frontend_algo,
+ .search = cxd2820r_search,
- /* check if the demod is there */
- priv->bank[0] = priv->bank[1] = 0xff;
- ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
- dbg("%s: chip id=%02x", __func__, tmp);
- if (ret || tmp != 0xe1)
- goto error;
+ .read_status = cxd2820r_read_status,
+ .read_snr = cxd2820r_read_snr,
+ .read_ber = cxd2820r_read_ber,
+ .read_ucblocks = cxd2820r_read_ucblocks,
+ .read_signal_strength = cxd2820r_read_signal_strength,
+};
- /* create frontends */
- memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],
- sizeof(struct dvb_frontend_ops));
- memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],
- sizeof(struct dvb_frontend_ops));
+struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend *fe)
+{
+ struct cxd2820r_priv *priv = NULL;
+ int ret;
+ u8 tmp;
- priv->fe[0].demodulator_priv = priv;
- priv->fe[1].demodulator_priv = priv;
+ priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL);
+ if (!priv)
+ goto error;
- return &priv->fe[0];
+ priv->i2c = i2c;
+ memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config));
- } else {
- /* FE1: FE0 given as pointer, just return FE1 we have
- * already created */
- priv = fe->demodulator_priv;
- return &priv->fe[1];
- }
+ priv->bank[0] = priv->bank[1] = 0xff;
+ ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
+ dbg("%s: chip id=%02x", __func__, tmp);
+ if (ret || tmp != 0xe1)
+ goto error;
+ memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops));
+ priv->fe.demodulator_priv = priv;
+ return &priv->fe;
error:
kfree(priv);
return NULL;
}
EXPORT_SYMBOL(cxd2820r_attach);
-static const struct dvb_frontend_ops cxd2820r_ops[2] = {
- {
- /* DVB-T/T2 */
- .info = {
- .name = "Sony CXD2820R (DVB-T/T2)",
- .type = FE_OFDM,
- .caps =
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK | FE_CAN_QAM_16 |
- FE_CAN_QAM_64 | FE_CAN_QAM_256 |
- FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO |
- FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO |
- FE_CAN_MUTE_TS |
- FE_CAN_2G_MODULATION
- },
-
- .release = cxd2820r_release,
- .init = cxd2820r_init,
- .sleep = cxd2820r_sleep,
-
- .get_tune_settings = cxd2820r_get_tune_settings,
- .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
-
- .get_frontend = cxd2820r_get_frontend,
-
- .get_frontend_algo = cxd2820r_get_frontend_algo,
- .search = cxd2820r_search,
-
- .read_status = cxd2820r_read_status,
- .read_snr = cxd2820r_read_snr,
- .read_ber = cxd2820r_read_ber,
- .read_ucblocks = cxd2820r_read_ucblocks,
- .read_signal_strength = cxd2820r_read_signal_strength,
- },
- {
- /* DVB-C */
- .info = {
- .name = "Sony CXD2820R (DVB-C)",
- .type = FE_QAM,
- .caps =
- FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
- FE_CAN_QAM_128 | FE_CAN_QAM_256 |
- FE_CAN_FEC_AUTO
- },
-
- .release = cxd2820r_release,
- .init = cxd2820r_init,
- .sleep = cxd2820r_sleep,
-
- .get_tune_settings = cxd2820r_get_tune_settings,
- .i2c_gate_ctrl = cxd2820r_i2c_gate_ctrl,
-
- .set_frontend = cxd2820r_set_frontend,
- .get_frontend = cxd2820r_get_frontend,
-
- .read_status = cxd2820r_read_status,
- .read_snr = cxd2820r_read_snr,
- .read_ber = cxd2820r_read_ber,
- .read_ucblocks = cxd2820r_read_ucblocks,
- .read_signal_strength = cxd2820r_read_signal_strength,
- },
-};
-
-
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h
index 9553913..9a9822c 100644
--- a/drivers/media/dvb/frontends/cxd2820r_priv.h
+++ b/drivers/media/dvb/frontends/cxd2820r_priv.h
@@ -48,12 +48,9 @@ struct reg_val_mask {
struct cxd2820r_priv {
struct i2c_adapter *i2c;
- struct dvb_frontend fe[2];
+ struct dvb_frontend fe;
struct cxd2820r_config cfg;
- struct mutex fe_lock; /* FE lock */
- int active_fe:2; /* FE lock, -1=NONE, 0=DVB-T/T2, 1=DVB-C */
-
bool ber_running;
u8 bank[2];
@@ -89,11 +86,9 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
/* cxd2820r_c.c */
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
@@ -114,11 +109,9 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
/* cxd2820r_t.c */
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
@@ -139,11 +132,9 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
/* cxd2820r_t2.c */
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p);
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params);
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);
int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c
index a04f9c8..1a02623 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t.c
@@ -21,13 +21,12 @@
#include "cxd2820r_priv.h"
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i;
- u32 if_khz, if_ctl;
+ int ret, i, bw_i;
+ u32 if_freq, if_ctl;
u64 num;
u8 buf[3], bw_param;
u8 bw_params1[][5] = {
@@ -57,6 +56,23 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+ switch (c->bandwidth_hz) {
+ case 6000000:
+ bw_i = 0;
+ bw_param = 2;
+ break;
+ case 7000000:
+ bw_i = 1;
+ bw_param = 1;
+ break;
+ case 8000000:
+ bw_i = 2;
+ bw_param = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* update GPIOs */
ret = cxd2820r_gpio(fe);
if (ret)
@@ -64,7 +80,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
/* program tuner */
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (priv->delivery_system != SYS_DVBT) {
for (i = 0; i < ARRAY_SIZE(tab); i++) {
@@ -78,27 +94,17 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
priv->delivery_system = SYS_DVBT;
priv->ber_running = 0; /* tune stops BER counter */
- switch (c->bandwidth_hz) {
- case 6000000:
- if_khz = priv->cfg.if_dvbt_6;
- i = 0;
- bw_param = 2;
- break;
- case 7000000:
- if_khz = priv->cfg.if_dvbt_7;
- i = 1;
- bw_param = 1;
- break;
- case 8000000:
- if_khz = priv->cfg.if_dvbt_8;
- i = 2;
- bw_param = 0;
- break;
- default:
- return -EINVAL;
- }
+ /* program IF frequency */
+ if (fe->ops.tuner_ops.get_if_frequency) {
+ ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+ if (ret)
+ goto error;
+ } else
+ if_freq = 0;
+
+ dbg("%s: if_freq=%d", __func__, if_freq);
- num = if_khz;
+ num = if_freq / 1000; /* Hz => kHz */
num *= 0x1000000;
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
buf[0] = ((if_ctl >> 16) & 0xff);
@@ -109,7 +115,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
if (ret)
goto error;
- ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[i], 5);
+ ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5);
if (ret)
goto error;
@@ -117,7 +123,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe,
if (ret)
goto error;
- ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[i], 2);
+ ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2);
if (ret)
goto error;
@@ -135,8 +141,7 @@ error:
return ret;
}
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c
index 6548588..3a5759e 100644
--- a/drivers/media/dvb/frontends/cxd2820r_t2.c
+++ b/drivers/media/dvb/frontends/cxd2820r_t2.c
@@ -21,13 +21,12 @@
#include "cxd2820r_priv.h"
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret, i;
- u32 if_khz, if_ctl;
+ int ret, i, bw_i;
+ u32 if_freq, if_ctl;
u64 num;
u8 buf[3], bw_param;
u8 bw_params1[][5] = {
@@ -71,6 +70,27 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+ switch (c->bandwidth_hz) {
+ case 5000000:
+ bw_i = 0;
+ bw_param = 3;
+ break;
+ case 6000000:
+ bw_i = 1;
+ bw_param = 2;
+ break;
+ case 7000000:
+ bw_i = 2;
+ bw_param = 1;
+ break;
+ case 8000000:
+ bw_i = 3;
+ bw_param = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* update GPIOs */
ret = cxd2820r_gpio(fe);
if (ret)
@@ -78,7 +98,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
/* program tuner */
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, params);
+ fe->ops.tuner_ops.set_params(fe);
if (priv->delivery_system != SYS_DVBT2) {
for (i = 0; i < ARRAY_SIZE(tab); i++) {
@@ -91,32 +111,17 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
priv->delivery_system = SYS_DVBT2;
- switch (c->bandwidth_hz) {
- case 5000000:
- if_khz = priv->cfg.if_dvbt2_5;
- i = 0;
- bw_param = 3;
- break;
- case 6000000:
- if_khz = priv->cfg.if_dvbt2_6;
- i = 1;
- bw_param = 2;
- break;
- case 7000000:
- if_khz = priv->cfg.if_dvbt2_7;
- i = 2;
- bw_param = 1;
- break;
- case 8000000:
- if_khz = priv->cfg.if_dvbt2_8;
- i = 3;
- bw_param = 0;
- break;
- default:
- return -EINVAL;
- }
+ /* program IF frequency */
+ if (fe->ops.tuner_ops.get_if_frequency) {
+ ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+ if (ret)
+ goto error;
+ } else
+ if_freq = 0;
+
+ dbg("%s: if_freq=%d", __func__, if_freq);
- num = if_khz;
+ num = if_freq / 1000; /* Hz => kHz */
num *= 0x1000000;
if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
buf[0] = ((if_ctl >> 16) & 0xff);
@@ -127,7 +132,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe,
if (ret)
goto error;
- ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[i], 5);
+ ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
if (ret)
goto error;
@@ -150,8 +155,7 @@ error:
}
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index dc1cb17..3b024bf 100644
--- a/drivers/media/dvb/frontends/dib0070.c
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -150,7 +150,7 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
} \
} while (0)
-static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib0070_set_bandwidth(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
@@ -335,7 +335,7 @@ static const struct dib0070_lna_match dib0070_lna[] = {
};
#define LPF 100
-static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib0070_tune_digital(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
@@ -507,7 +507,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
*tune_state = CT_TUNER_STEP_5;
} else if (*tune_state == CT_TUNER_STEP_5) {
- dib0070_set_bandwidth(fe, ch);
+ dib0070_set_bandwidth(fe);
*tune_state = CT_TUNER_STOP;
} else {
ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
@@ -516,7 +516,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
}
-static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dib0070_tune(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
uint32_t ret;
@@ -524,7 +524,7 @@ static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters
state->tune_state = CT_TUNER_START;
do {
- ret = dib0070_tune_digital(fe, p);
+ ret = dib0070_tune_digital(fe);
if (ret != FE_CALLBACK_TIME_NEVER)
msleep(ret/10);
else
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
index b174d1c..224d81e 100644
--- a/drivers/media/dvb/frontends/dib0090.c
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -717,6 +717,34 @@ static const u16 rf_ramp_pwm_cband_7090[] = {
(0 << 10) | 109, /* RF_RAMP4, LNA 4 */
};
+static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
+ 186,
+ 40,
+ 746,
+ (10 << 10) | 345,
+ (0 << 10) | 746,
+ (0 << 10) | 0,
+ (0 << 10) | 0,
+ (28 << 10) | 200,
+ (0 << 10) | 345,
+ (20 << 10) | 0,
+ (0 << 10) | 200,
+};
+
+static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
+ 86,
+ 40,
+ 345,
+ (0 << 10) | 0,
+ (0 << 10) | 0,
+ (0 << 10) | 0,
+ (0 << 10) | 0,
+ (28 << 10) | 200,
+ (0 << 10) | 345,
+ (20 << 10) | 0,
+ (0 << 10) | 200,
+};
+
static const u16 rf_ramp_pwm_cband_8090[] = {
345, /* max RF gain in 10th of dB */
29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
@@ -1076,8 +1104,16 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
- else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
- dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+ else if (state->identity.version == SOC_7090_P1G_11R1
+ || state->identity.version == SOC_7090_P1G_21R1) {
+ if (state->config->is_dib7090e) {
+ if (state->rf_ramp == NULL)
+ dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
+ else
+ dib0090_set_rframp_pwm(state, state->rf_ramp);
+ } else
+ dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+ }
} else {
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
@@ -1112,13 +1148,21 @@ void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
else
dib0090_write_reg(state, 0x32, (0 << 11));
- dib0090_write_reg(state, 0x04, 0x01);
+ dib0090_write_reg(state, 0x04, 0x03);
dib0090_write_reg(state, 0x39, (1 << 10));
}
}
EXPORT_SYMBOL(dib0090_pwm_gain_reset);
+void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+ if (DC_servo_cutoff < 4)
+ dib0090_write_reg(state, 0x04, DC_servo_cutoff);
+}
+EXPORT_SYMBOL(dib0090_set_dc_servo);
+
static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
{
u16 adc_val = dib0090_read_reg(state, 0x1d);
@@ -1305,7 +1349,7 @@ void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 *
EXPORT_SYMBOL(dib0090_get_current_gain);
-u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
{
struct dib0090_state *state = fe->tuner_priv;
u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
@@ -1342,9 +1386,57 @@ u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
return state->wbd_offset + wbd_tcold;
}
+EXPORT_SYMBOL(dib0090_get_wbd_target);
+u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+ return state->wbd_offset;
+}
EXPORT_SYMBOL(dib0090_get_wbd_offset);
+int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+
+ dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
+ | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
+
+ return 0;
+}
+EXPORT_SYMBOL(dib0090_set_switch);
+
+int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+
+ dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
+ | ((onoff & 1) << 15));
+ return 0;
+}
+EXPORT_SYMBOL(dib0090_set_vga);
+
+int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+
+ if ((!state->identity.p1g) || (!state->identity.in_soc)
+ || ((state->identity.version != SOC_7090_P1G_21R1)
+ && (state->identity.version != SOC_7090_P1G_11R1))) {
+ dprintk("%s() function can only be used for dib7090P", __func__);
+ return -ENODEV;
+ }
+
+ if (cfg_sensitivity)
+ state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
+ else
+ state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
+ dib0090_pwm_gain_reset(fe);
+
+ return 0;
+}
+EXPORT_SYMBOL(dib0090_update_rframp_7090);
+
static const u16 dib0090_defaults[] = {
25, 0x01,
@@ -1430,7 +1522,7 @@ static void dib0090_set_default_config(struct dib0090_state *state, const u16 *
#define POLY_MIN (u8) 0
#define POLY_MAX (u8) 8
-void dib0090_set_EFUSE(struct dib0090_state *state)
+static void dib0090_set_EFUSE(struct dib0090_state *state)
{
u8 c, h, n;
u16 e2, e4;
@@ -1505,7 +1597,10 @@ static int dib0090_reset(struct dvb_frontend *fe)
dib0090_set_EFUSE(state);
/* Congigure in function of the crystal */
- if (state->config->io.clock_khz >= 24000)
+ if (state->config->force_crystal_mode != 0)
+ dib0090_write_reg(state, 0x14,
+ state->config->force_crystal_mode & 3);
+ else if (state->config->io.clock_khz >= 24000)
dib0090_write_reg(state, 0x14, 1);
else
dib0090_write_reg(state, 0x14, 2);
@@ -1951,6 +2046,52 @@ static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
#endif
};
+static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
+#ifdef CONFIG_BAND_CBAND
+ { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+ { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+ { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+ { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
+ { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+ { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
+#endif
+};
+
+int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+ u8 cfg_sensitivity)
+{
+ struct dib0090_state *state = fe->tuner_priv;
+ const struct dib0090_tuning *tune =
+ dib0090_tuning_table_cband_7090e_sensitivity;
+ const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
+ { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+ { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
+ { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
+ };
+
+ if ((!state->identity.p1g) || (!state->identity.in_soc)
+ || ((state->identity.version != SOC_7090_P1G_21R1)
+ && (state->identity.version != SOC_7090_P1G_11R1))) {
+ dprintk("%s() function can only be used for dib7090", __func__);
+ return -ENODEV;
+ }
+
+ if (cfg_sensitivity)
+ tune = dib0090_tuning_table_cband_7090e_sensitivity;
+ else
+ tune = dib0090_tuning_table_cband_7090e_aci;
+
+ while (state->rf_request > tune->max_freq)
+ tune++;
+
+ dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
+ | (tune->lna_bias & 0x7fff));
+ dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
+ | ((tune->lna_tune << 6) & 0x07c0));
+ return 0;
+}
+EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
+
static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
{
int ret = 0;
@@ -2199,12 +2340,18 @@ static int dib0090_tune(struct dvb_frontend *fe)
if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
|| state->current_band & BAND_UHF) {
state->current_band = BAND_CBAND;
- tune = dib0090_tuning_table_cband_7090;
+ if (state->config->is_dib7090e)
+ tune = dib0090_tuning_table_cband_7090e_sensitivity;
+ else
+ tune = dib0090_tuning_table_cband_7090;
}
} else { /* Use the CBAND input for all band under UHF */
if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
state->current_band = BAND_CBAND;
- tune = dib0090_tuning_table_cband_7090;
+ if (state->config->is_dib7090e)
+ tune = dib0090_tuning_table_cband_7090e_sensitivity;
+ else
+ tune = dib0090_tuning_table_cband_7090;
}
}
} else
@@ -2419,7 +2566,7 @@ static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
return 0;
}
-static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int dib0090_set_params(struct dvb_frontend *fe)
{
struct dib0090_state *state = fe->tuner_priv;
u32 ret;
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h
index 13d8524..781dc49 100644
--- a/drivers/media/dvb/frontends/dib0090.h
+++ b/drivers/media/dvb/frontends/dib0090.h
@@ -71,6 +71,8 @@ struct dib0090_config {
u8 fref_clock_ratio;
u16 force_cband_input;
struct dib0090_wbd_slope *wbd;
+ u8 is_dib7090e;
+ u8 force_crystal_mode;
};
#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
@@ -78,13 +80,21 @@ extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c
extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
-extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
+extern u16 dib0090_get_wbd_target(struct dvb_frontend *tuner);
+extern u16 dib0090_get_wbd_offset(struct dvb_frontend *fe);
extern int dib0090_gain_control(struct dvb_frontend *fe);
extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
+extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff);
+extern int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3);
+extern int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff);
+extern int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+ u8 cfg_sensitivity);
+extern int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+ u8 cfg_sensitivity);
#else
-static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
+static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
@@ -106,7 +116,13 @@ static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
-static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
+static inline u16 dib0090_get_wbd_target(struct dvb_frontend *tuner)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return 0;
+}
+
+static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
@@ -134,6 +150,38 @@ static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
+
+static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int dib0090_set_switch(struct dvb_frontend *fe,
+ u8 sw1, u8 sw2, u8 sw3)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+
+static inline int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+
+static inline int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+ u8 cfg_sensitivity)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
+
+static inline int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+ u8 cfg_sensitivity)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
#endif
#endif
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 437904c..af91e0c 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -112,39 +112,37 @@ static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
}
};
-static int dib3000mb_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep);
+static int dib3000mb_get_frontend(struct dvb_frontend* fe);
-static int dib3000mb_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep, int tuner)
+static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
{
struct dib3000_state* state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
fe_code_rate_t fe_cr = FEC_NONE;
int search_state, seq;
if (tuner && fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fep);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
deb_setf("bandwidth: ");
- switch (ofdm->bandwidth) {
- case BANDWIDTH_8_MHZ:
+ switch (c->bandwidth_hz) {
+ case 8000000:
deb_setf("8 MHz\n");
wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
deb_setf("7 MHz\n");
wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
break;
- case BANDWIDTH_6_MHZ:
+ case 6000000:
deb_setf("6 MHz\n");
wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
break;
- case BANDWIDTH_AUTO:
+ case 0:
return -EOPNOTSUPP;
default:
err("unknown bandwidth value.");
@@ -154,7 +152,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
deb_setf("transmission mode: ");
- switch (ofdm->transmission_mode) {
+ switch (c->transmission_mode) {
case TRANSMISSION_MODE_2K:
deb_setf("2k\n");
wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
@@ -171,7 +169,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
}
deb_setf("guard: ");
- switch (ofdm->guard_interval) {
+ switch (c->guard_interval) {
case GUARD_INTERVAL_1_32:
deb_setf("1_32\n");
wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
@@ -196,7 +194,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
}
deb_setf("inversion: ");
- switch (fep->inversion) {
+ switch (c->inversion) {
case INVERSION_OFF:
deb_setf("off\n");
wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
@@ -212,8 +210,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
return -EINVAL;
}
- deb_setf("constellation: ");
- switch (ofdm->constellation) {
+ deb_setf("modulation: ");
+ switch (c->modulation) {
case QPSK:
deb_setf("qpsk\n");
wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
@@ -232,7 +230,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
return -EINVAL;
}
deb_setf("hierarchy: ");
- switch (ofdm->hierarchy_information) {
+ switch (c->hierarchy) {
case HIERARCHY_NONE:
deb_setf("none ");
/* fall through */
@@ -256,16 +254,16 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
}
deb_setf("hierarchy: ");
- if (ofdm->hierarchy_information == HIERARCHY_NONE) {
+ if (c->hierarchy == HIERARCHY_NONE) {
deb_setf("none\n");
wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
- fe_cr = ofdm->code_rate_HP;
- } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
+ fe_cr = c->code_rate_HP;
+ } else if (c->hierarchy != HIERARCHY_AUTO) {
deb_setf("on\n");
wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
- fe_cr = ofdm->code_rate_LP;
+ fe_cr = c->code_rate_LP;
}
deb_setf("fec: ");
switch (fe_cr) {
@@ -300,9 +298,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
}
seq = dib3000_seq
- [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]
- [ofdm->guard_interval == GUARD_INTERVAL_AUTO]
- [fep->inversion == INVERSION_AUTO];
+ [c->transmission_mode == TRANSMISSION_MODE_AUTO]
+ [c->guard_interval == GUARD_INTERVAL_AUTO]
+ [c->inversion == INVERSION_AUTO];
deb_setf("seq? %d\n", seq);
@@ -310,8 +308,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
- if (ofdm->transmission_mode == TRANSMISSION_MODE_2K) {
- if (ofdm->guard_interval == GUARD_INTERVAL_1_8) {
+ if (c->transmission_mode == TRANSMISSION_MODE_2K) {
+ if (c->guard_interval == GUARD_INTERVAL_1_8) {
wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
} else {
wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
@@ -339,10 +337,10 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
/* something has to be auto searched */
- if (ofdm->constellation == QAM_AUTO ||
- ofdm->hierarchy_information == HIERARCHY_AUTO ||
+ if (c->modulation == QAM_AUTO ||
+ c->hierarchy == HIERARCHY_AUTO ||
fe_cr == FEC_AUTO ||
- fep->inversion == INVERSION_AUTO) {
+ c->inversion == INVERSION_AUTO) {
int as_count=0;
deb_setf("autosearch enabled.\n");
@@ -361,10 +359,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
if (search_state == 1) {
- struct dvb_frontend_parameters feps;
- if (dib3000mb_get_frontend(fe, &feps) == 0) {
+ if (dib3000mb_get_frontend(fe) == 0) {
deb_setf("reading tuning data from frontend succeeded.\n");
- return dib3000mb_set_frontend(fe, &feps, 0);
+ return dib3000mb_set_frontend(fe, 0);
}
}
@@ -453,11 +450,10 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
return 0;
}
-static int dib3000mb_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dib3000mb_get_frontend(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dib3000_state* state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
fe_code_rate_t *cr;
u16 tps_val;
int inv_test1,inv_test2;
@@ -484,25 +480,25 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
else
inv_test2 = 2;
- fep->inversion =
+ c->inversion =
((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
INVERSION_ON : INVERSION_OFF;
- deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+ deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);
switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
case DIB3000_CONSTELLATION_QPSK:
deb_getf("QPSK ");
- ofdm->constellation = QPSK;
+ c->modulation = QPSK;
break;
case DIB3000_CONSTELLATION_16QAM:
deb_getf("QAM16 ");
- ofdm->constellation = QAM_16;
+ c->modulation = QAM_16;
break;
case DIB3000_CONSTELLATION_64QAM:
deb_getf("QAM64 ");
- ofdm->constellation = QAM_64;
+ c->modulation = QAM_64;
break;
default:
err("Unexpected constellation returned by TPS (%d)", tps_val);
@@ -512,24 +508,24 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
if (rd(DIB3000MB_REG_TPS_HRCH)) {
deb_getf("HRCH ON\n");
- cr = &ofdm->code_rate_LP;
- ofdm->code_rate_HP = FEC_NONE;
+ cr = &c->code_rate_LP;
+ c->code_rate_HP = FEC_NONE;
switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
case DIB3000_ALPHA_0:
deb_getf("HIERARCHY_NONE ");
- ofdm->hierarchy_information = HIERARCHY_NONE;
+ c->hierarchy = HIERARCHY_NONE;
break;
case DIB3000_ALPHA_1:
deb_getf("HIERARCHY_1 ");
- ofdm->hierarchy_information = HIERARCHY_1;
+ c->hierarchy = HIERARCHY_1;
break;
case DIB3000_ALPHA_2:
deb_getf("HIERARCHY_2 ");
- ofdm->hierarchy_information = HIERARCHY_2;
+ c->hierarchy = HIERARCHY_2;
break;
case DIB3000_ALPHA_4:
deb_getf("HIERARCHY_4 ");
- ofdm->hierarchy_information = HIERARCHY_4;
+ c->hierarchy = HIERARCHY_4;
break;
default:
err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
@@ -540,9 +536,9 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
} else {
deb_getf("HRCH OFF\n");
- cr = &ofdm->code_rate_HP;
- ofdm->code_rate_LP = FEC_NONE;
- ofdm->hierarchy_information = HIERARCHY_NONE;
+ cr = &c->code_rate_HP;
+ c->code_rate_LP = FEC_NONE;
+ c->hierarchy = HIERARCHY_NONE;
tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
}
@@ -577,19 +573,19 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
case DIB3000_GUARD_TIME_1_32:
deb_getf("GUARD_INTERVAL_1_32 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_32;
+ c->guard_interval = GUARD_INTERVAL_1_32;
break;
case DIB3000_GUARD_TIME_1_16:
deb_getf("GUARD_INTERVAL_1_16 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_16;
+ c->guard_interval = GUARD_INTERVAL_1_16;
break;
case DIB3000_GUARD_TIME_1_8:
deb_getf("GUARD_INTERVAL_1_8 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_8;
+ c->guard_interval = GUARD_INTERVAL_1_8;
break;
case DIB3000_GUARD_TIME_1_4:
deb_getf("GUARD_INTERVAL_1_4 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_4;
+ c->guard_interval = GUARD_INTERVAL_1_4;
break;
default:
err("Unexpected Guard Time returned by TPS (%d)", tps_val);
@@ -600,11 +596,11 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
case DIB3000_TRANSMISSION_MODE_2K:
deb_getf("TRANSMISSION_MODE_2K ");
- ofdm->transmission_mode = TRANSMISSION_MODE_2K;
+ c->transmission_mode = TRANSMISSION_MODE_2K;
break;
case DIB3000_TRANSMISSION_MODE_8K:
deb_getf("TRANSMISSION_MODE_8K ");
- ofdm->transmission_mode = TRANSMISSION_MODE_8K;
+ c->transmission_mode = TRANSMISSION_MODE_8K;
break;
default:
err("unexpected transmission mode return by TPS (%d)", tps_val);
@@ -701,9 +697,9 @@ static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)
return dib3000mb_fe_init(fe, 0);
}
-static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
+static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)
{
- return dib3000mb_set_frontend(fe, fep, 1);
+ return dib3000mb_set_frontend(fe, 1);
}
static void dib3000mb_release(struct dvb_frontend* fe)
@@ -794,10 +790,9 @@ error:
}
static struct dvb_frontend_ops dib3000mb_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "DiBcom 3000M-B DVB-T",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h
index 16c5265..9dc235a 100644
--- a/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ b/drivers/media/dvb/frontends/dib3000mb_priv.h
@@ -98,7 +98,7 @@ struct dib3000_state {
int timing_offset;
int timing_offset_comp_done;
- fe_bandwidth_t last_tuned_bw;
+ u32 last_tuned_bw;
u32 last_tuned_freq;
};
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 088e7fa..ffad181 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -40,7 +40,7 @@ struct dib3000mc_state {
u32 timf;
- fe_bandwidth_t current_bandwidth;
+ u32 current_bandwidth;
u16 dev_id;
@@ -438,11 +438,14 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
dib3000mc_write_word(state, reg, cfg[reg - 129]);
}
-static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_frontend_parameters *ch, u16 seq)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
+ struct dtv_frontend_properties *ch, u16 seq)
{
u16 value;
- dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
- dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 0);
+ u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+
+ dib3000mc_set_bandwidth(state, bw);
+ dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
// if (boost)
// dib3000mc_write_word(state, 100, (11 << 6) + 6);
@@ -471,22 +474,22 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
dib3000mc_write_word(state, 97,0);
dib3000mc_write_word(state, 98,0);
- dib3000mc_set_impulse_noise(state, 0, ch->u.ofdm.transmission_mode);
+ dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
value = 0;
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
default:
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
default:
case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
}
- switch (ch->u.ofdm.constellation) {
+ switch (ch->modulation) {
case QPSK: value |= (0 << 3); break;
case QAM_16: value |= (1 << 3); break;
default:
@@ -502,11 +505,11 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
value = 0;
- if (ch->u.ofdm.hierarchy_information == 1)
+ if (ch->hierarchy == 1)
value |= (1 << 4);
if (1 == 1)
value |= 1;
- switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
case FEC_2_3: value |= (2 << 1); break;
case FEC_3_4: value |= (3 << 1); break;
case FEC_5_6: value |= (5 << 1); break;
@@ -517,12 +520,12 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
dib3000mc_write_word(state, 181, value);
// diversity synchro delay add 50% SFN margin
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_8K: value = 256; break;
case TRANSMISSION_MODE_2K:
default: value = 64; break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_16: value *= 2; break;
case GUARD_INTERVAL_1_8: value *= 4; break;
case GUARD_INTERVAL_1_4: value *= 8; break;
@@ -540,27 +543,28 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_
msleep(30);
- dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->u.ofdm.transmission_mode);
+ dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
}
-static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *chan)
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
struct dib3000mc_state *state = demod->demodulator_priv;
u16 reg;
// u32 val;
- struct dvb_frontend_parameters schan;
+ struct dtv_frontend_properties schan;
schan = *chan;
/* TODO what is that ? */
/* a channel for autosearch */
- schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
- schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
- schan.u.ofdm.constellation = QAM_64;
- schan.u.ofdm.code_rate_HP = FEC_2_3;
- schan.u.ofdm.code_rate_LP = FEC_2_3;
- schan.u.ofdm.hierarchy_information = 0;
+ schan.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.guard_interval = GUARD_INTERVAL_1_32;
+ schan.modulation = QAM_64;
+ schan.code_rate_HP = FEC_2_3;
+ schan.code_rate_LP = FEC_2_3;
+ schan.hierarchy = 0;
dib3000mc_set_channel_cfg(state, &schan, 11);
@@ -586,8 +590,9 @@ static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
return 0; // still pending
}
-static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib3000mc_tune(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib3000mc_state *state = demod->demodulator_priv;
// ** configure demod **
@@ -603,8 +608,8 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parame
dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
}
- dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation);
- if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) {
+ dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
+ if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
dib3000mc_write_word(state, 26, 38528);
dib3000mc_write_word(state, 33, 8);
} else {
@@ -613,7 +618,8 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parame
}
if (dib3000mc_read_word(state, 509) & 0x80)
- dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 1);
+ dib3000mc_set_timing(state, ch->transmission_mode,
+ BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
return 0;
}
@@ -626,87 +632,87 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
-static int dib3000mc_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dib3000mc_get_frontend(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib3000mc_state *state = fe->demodulator_priv;
u16 tps = dib3000mc_read_word(state,458);
fep->inversion = INVERSION_AUTO;
- fep->u.ofdm.bandwidth = state->current_bandwidth;
+ fep->bandwidth_hz = state->current_bandwidth;
switch ((tps >> 8) & 0x1) {
- case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+ case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
}
switch (tps & 0x3) {
- case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+ case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
}
switch ((tps >> 13) & 0x3) {
- case 0: fep->u.ofdm.constellation = QPSK; break;
- case 1: fep->u.ofdm.constellation = QAM_16; break;
+ case 0: fep->modulation = QPSK; break;
+ case 1: fep->modulation = QAM_16; break;
case 2:
- default: fep->u.ofdm.constellation = QAM_64; break;
+ default: fep->modulation = QAM_64; break;
}
/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
/* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
- fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fep->hierarchy = HIERARCHY_NONE;
switch ((tps >> 5) & 0x7) {
- case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
- case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
- case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
- case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+ case 1: fep->code_rate_HP = FEC_1_2; break;
+ case 2: fep->code_rate_HP = FEC_2_3; break;
+ case 3: fep->code_rate_HP = FEC_3_4; break;
+ case 5: fep->code_rate_HP = FEC_5_6; break;
case 7:
- default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+ default: fep->code_rate_HP = FEC_7_8; break;
}
switch ((tps >> 2) & 0x7) {
- case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
- case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
- case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
- case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+ case 1: fep->code_rate_LP = FEC_1_2; break;
+ case 2: fep->code_rate_LP = FEC_2_3; break;
+ case 3: fep->code_rate_LP = FEC_3_4; break;
+ case 5: fep->code_rate_LP = FEC_5_6; break;
case 7:
- default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+ default: fep->code_rate_LP = FEC_7_8; break;
}
return 0;
}
-static int dib3000mc_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dib3000mc_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib3000mc_state *state = fe->demodulator_priv;
- int ret;
+ int ret;
dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
- state->current_bandwidth = fep->u.ofdm.bandwidth;
- dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+ state->current_bandwidth = fep->bandwidth_hz;
+ dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
/* maybe the parameter has been changed */
state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fep);
+ fe->ops.tuner_ops.set_params(fe);
msleep(100);
}
- if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
- fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
- fep->u.ofdm.constellation == QAM_AUTO ||
- fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->guard_interval == GUARD_INTERVAL_AUTO ||
+ fep->modulation == QAM_AUTO ||
+ fep->code_rate_HP == FEC_AUTO) {
int i = 1000, found;
- dib3000mc_autosearch_start(fe, fep);
+ dib3000mc_autosearch_start(fe);
do {
msleep(1);
found = dib3000mc_autosearch_is_irq(fe);
@@ -716,14 +722,14 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
if (found == 0 || found == 1)
return 0; // no channel found
- dib3000mc_get_frontend(fe, fep);
+ dib3000mc_get_frontend(fe);
}
- ret = dib3000mc_tune(fe, fep);
+ ret = dib3000mc_tune(fe);
/* make this a config parameter */
dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
- return ret;
+ return ret;
}
static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -897,9 +903,9 @@ error:
EXPORT_SYMBOL(dib3000mc_attach);
static struct dvb_frontend_ops dib3000mc_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "DiBcom 3000MC/P",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
index dbb76d7..148bf79 100644
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ b/drivers/media/dvb/frontends/dib7000m.c
@@ -38,7 +38,7 @@ struct dib7000m_state {
u16 wbd_ref;
u8 current_band;
- fe_bandwidth_t current_bandwidth;
+ u32 current_bandwidth;
struct dibx000_agc_config *current_agc;
u32 timf;
u32 timf_default;
@@ -313,6 +313,9 @@ static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
{
u32 timf;
+ if (!bw)
+ bw = 8000;
+
// store the current bandwidth for later use
state->current_bandwidth = bw;
@@ -742,8 +745,9 @@ static void dib7000m_update_timf(struct dib7000m_state *state)
dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
}
-static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_agc_startup(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000m_state *state = demod->demodulator_priv;
u16 cfg_72 = dib7000m_read_word(state, 72);
int ret = -1;
@@ -832,28 +836,29 @@ static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_
return ret;
}
-static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch,
+ u8 seq)
{
u16 value, est[4];
- dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
/* nfft, guard, qam, alpha */
value = 0;
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
default:
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
default:
case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
}
- switch (ch->u.ofdm.constellation) {
+ switch (ch->modulation) {
case QPSK: value |= (0 << 3); break;
case QAM_16: value |= (1 << 3); break;
default:
@@ -872,11 +877,11 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
value = 0;
if (1 != 0)
value |= (1 << 6);
- if (ch->u.ofdm.hierarchy_information == 1)
+ if (ch->hierarchy == 1)
value |= (1 << 4);
if (1 == 1)
value |= 1;
- switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
case FEC_2_3: value |= (2 << 1); break;
case FEC_3_4: value |= (3 << 1); break;
case FEC_5_6: value |= (5 << 1); break;
@@ -901,13 +906,13 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
dib7000m_write_word(state, 33, (0 << 4) | 0x5);
/* P_dvsy_sync_wait */
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_8K: value = 256; break;
case TRANSMISSION_MODE_4K: value = 128; break;
case TRANSMISSION_MODE_2K:
default: value = 64; break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_16: value *= 2; break;
case GUARD_INTERVAL_1_8: value *= 4; break;
case GUARD_INTERVAL_1_4: value *= 8; break;
@@ -925,7 +930,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
dib7000m_set_diversity_in(&state->demod, state->div_state);
/* channel estimation fine configuration */
- switch (ch->u.ofdm.constellation) {
+ switch (ch->modulation) {
case QAM_64:
est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
@@ -952,25 +957,26 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte
dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
}
-static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_autosearch_start(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000m_state *state = demod->demodulator_priv;
- struct dvb_frontend_parameters schan;
+ struct dtv_frontend_properties schan;
int ret = 0;
u32 value, factor;
schan = *ch;
- schan.u.ofdm.constellation = QAM_64;
- schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
- schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
- schan.u.ofdm.code_rate_HP = FEC_2_3;
- schan.u.ofdm.code_rate_LP = FEC_3_4;
- schan.u.ofdm.hierarchy_information = 0;
+ schan.modulation = QAM_64;
+ schan.guard_interval = GUARD_INTERVAL_1_32;
+ schan.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.code_rate_HP = FEC_2_3;
+ schan.code_rate_LP = FEC_3_4;
+ schan.hierarchy = 0;
dib7000m_set_channel(state, &schan, 7);
- factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
+ factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz);
if (factor >= 5000)
factor = 1;
else
@@ -1027,8 +1033,9 @@ static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
return dib7000m_autosearch_irq(state, 537);
}
-static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000m_tune(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000m_state *state = demod->demodulator_priv;
int ret = 0;
u16 value;
@@ -1055,7 +1062,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
//dump_reg(state);
/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
value = (6 << 8) | 0x80;
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
default:
@@ -1065,7 +1072,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
value = (0 << 4);
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K: value |= 0x6; break;
case TRANSMISSION_MODE_4K: value |= 0x7; break;
default:
@@ -1075,7 +1082,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
value = (0 << 4);
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K: value |= 0x6; break;
case TRANSMISSION_MODE_4K: value |= 0x7; break;
default:
@@ -1087,7 +1094,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
dib7000m_update_timf(state);
- dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
return ret;
}
@@ -1147,57 +1154,57 @@ static int dib7000m_identify(struct dib7000m_state *state)
}
-static int dib7000m_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dib7000m_get_frontend(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000m_state *state = fe->demodulator_priv;
u16 tps = dib7000m_read_word(state,480);
fep->inversion = INVERSION_AUTO;
- fep->u.ofdm.bandwidth = state->current_bandwidth;
+ fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
switch ((tps >> 8) & 0x3) {
- case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
- case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
- /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+ case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
+ /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
}
switch (tps & 0x3) {
- case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
- case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
- case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
- case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+ case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
}
switch ((tps >> 14) & 0x3) {
- case 0: fep->u.ofdm.constellation = QPSK; break;
- case 1: fep->u.ofdm.constellation = QAM_16; break;
+ case 0: fep->modulation = QPSK; break;
+ case 1: fep->modulation = QAM_16; break;
case 2:
- default: fep->u.ofdm.constellation = QAM_64; break;
+ default: fep->modulation = QAM_64; break;
}
/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
- fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fep->hierarchy = HIERARCHY_NONE;
switch ((tps >> 5) & 0x7) {
- case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
- case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
- case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
- case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+ case 1: fep->code_rate_HP = FEC_1_2; break;
+ case 2: fep->code_rate_HP = FEC_2_3; break;
+ case 3: fep->code_rate_HP = FEC_3_4; break;
+ case 5: fep->code_rate_HP = FEC_5_6; break;
case 7:
- default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+ default: fep->code_rate_HP = FEC_7_8; break;
}
switch ((tps >> 2) & 0x7) {
- case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
- case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
- case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
- case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+ case 1: fep->code_rate_LP = FEC_1_2; break;
+ case 2: fep->code_rate_LP = FEC_2_3; break;
+ case 3: fep->code_rate_LP = FEC_3_4; break;
+ case 5: fep->code_rate_LP = FEC_5_6; break;
case 7:
- default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+ default: fep->code_rate_LP = FEC_7_8; break;
}
/* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
@@ -1205,35 +1212,34 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe,
return 0;
}
-static int dib7000m_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
+static int dib7000m_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000m_state *state = fe->demodulator_priv;
int time, ret;
- dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
+ dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
- state->current_bandwidth = fep->u.ofdm.bandwidth;
- dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
+ dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, fep);
+ fe->ops.tuner_ops.set_params(fe);
/* start up the AGC */
state->agc_state = 0;
do {
- time = dib7000m_agc_startup(fe, fep);
+ time = dib7000m_agc_startup(fe);
if (time != -1)
msleep(time);
} while (time != -1);
- if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
- fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
- fep->u.ofdm.constellation == QAM_AUTO ||
- fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->guard_interval == GUARD_INTERVAL_AUTO ||
+ fep->modulation == QAM_AUTO ||
+ fep->code_rate_HP == FEC_AUTO) {
int i = 800, found;
- dib7000m_autosearch_start(fe, fep);
+ dib7000m_autosearch_start(fe);
do {
msleep(1);
found = dib7000m_autosearch_is_irq(fe);
@@ -1243,10 +1249,10 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
if (found == 0 || found == 1)
return 0; // no channel found
- dib7000m_get_frontend(fe, fep);
+ dib7000m_get_frontend(fe);
}
- ret = dib7000m_tune(fe, fep);
+ ret = dib7000m_tune(fe);
/* make this a config parameter */
dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
@@ -1430,9 +1436,9 @@ error:
EXPORT_SYMBOL(dib7000m_attach);
static struct dvb_frontend_ops dib7000m_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "DiBcom 7000MA/MB/PA/PB/MC",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
index ce8534f..5ceadc2 100644
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -70,6 +70,8 @@ struct dib7000p_state {
u8 i2c_write_buffer[4];
u8 i2c_read_buffer[2];
struct mutex i2c_buffer_lock;
+
+ u8 input_mode_mpeg;
};
enum dib7000p_power_mode {
@@ -78,8 +80,11 @@ enum dib7000p_power_mode {
DIB7000P_POWER_INTERFACE_ONLY,
};
+/* dib7090 specific fonctions */
static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
{
@@ -276,17 +281,23 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p
dib7000p_write_word(state, 774, reg_774);
dib7000p_write_word(state, 775, reg_775);
dib7000p_write_word(state, 776, reg_776);
- dib7000p_write_word(state, 899, reg_899);
dib7000p_write_word(state, 1280, reg_1280);
+ if (state->version != SOC7090)
+ dib7000p_write_word(state, 899, reg_899);
return 0;
}
static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
{
- u16 reg_908 = dib7000p_read_word(state, 908), reg_909 = dib7000p_read_word(state, 909);
+ u16 reg_908 = 0, reg_909 = 0;
u16 reg;
+ if (state->version != SOC7090) {
+ reg_908 = dib7000p_read_word(state, 908);
+ reg_909 = dib7000p_read_word(state, 909);
+ }
+
switch (no) {
case DIBX000_SLOW_ADC_ON:
if (state->version == SOC7090) {
@@ -342,8 +353,10 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad
reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
- dib7000p_write_word(state, 908, reg_908);
- dib7000p_write_word(state, 909, reg_909);
+ if (state->version != SOC7090) {
+ dib7000p_write_word(state, 908, reg_908);
+ dib7000p_write_word(state, 909, reg_909);
+ }
}
static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
@@ -398,6 +411,24 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
}
EXPORT_SYMBOL(dib7000p_set_wbd_ref);
+int dib7000p_get_agc_values(struct dvb_frontend *fe,
+ u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+ struct dib7000p_state *state = fe->demodulator_priv;
+
+ if (agc_global != NULL)
+ *agc_global = dib7000p_read_word(state, 394);
+ if (agc1 != NULL)
+ *agc1 = dib7000p_read_word(state, 392);
+ if (agc2 != NULL)
+ *agc2 = dib7000p_read_word(state, 393);
+ if (wbd != NULL)
+ *wbd = dib7000p_read_word(state, 397);
+
+ return 0;
+}
+EXPORT_SYMBOL(dib7000p_get_agc_values);
+
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
@@ -519,7 +550,7 @@ static u16 dib7000p_defaults[] = {
// auto search configuration
3, 2,
0x0004,
- 0x1000,
+ (1<<3)|(1<<11)|(1<<12)|(1<<13),
0x0814, /* Equal Lock */
12, 6,
@@ -595,13 +626,6 @@ static u16 dib7000p_defaults[] = {
1, 235,
0x0062,
- 2, 901,
- 0x0006,
- (3 << 10) | (1 << 6),
-
- 1, 905,
- 0x2c8e,
-
0,
};
@@ -618,15 +642,18 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
dib7000p_write_word(state, 770, 0xffff);
dib7000p_write_word(state, 771, 0xffff);
dib7000p_write_word(state, 772, 0x001f);
- dib7000p_write_word(state, 898, 0x0003);
dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
dib7000p_write_word(state, 770, 0);
dib7000p_write_word(state, 771, 0);
dib7000p_write_word(state, 772, 0);
- dib7000p_write_word(state, 898, 0);
dib7000p_write_word(state, 1280, 0);
+ if (state->version != SOC7090) {
+ dib7000p_write_word(state, 898, 0x0003);
+ dib7000p_write_word(state, 898, 0);
+ }
+
/* default */
dib7000p_reset_pll(state);
@@ -640,7 +667,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
- dib7000p_write_word(state, 273, (1<<6) | 30);
+ dib7000p_write_word(state, 273, (0<<6) | 30);
}
if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
dprintk("OUTPUT_MODE could not be reset.");
@@ -655,7 +682,7 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
dib7000p_set_bandwidth(state, 8000);
if (state->version == SOC7090) {
- dib7000p_write_word(state, 36, 0x5755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
+ dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
} else {
if (state->cfg.tuner_is_baseband)
dib7000p_write_word(state, 36, 0x0755);
@@ -664,6 +691,11 @@ static int dib7000p_demod_reset(struct dib7000p_state *state)
}
dib7000p_write_tab(state, dib7000p_defaults);
+ if (state->version != SOC7090) {
+ dib7000p_write_word(state, 901, 0x0006);
+ dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
+ dib7000p_write_word(state, 905, 0x2c8e);
+ }
dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
@@ -780,8 +812,9 @@ static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
}
}
-static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_agc_startup(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000p_state *state = demod->demodulator_priv;
int ret = -1;
u8 *agc_state = &state->agc_state;
@@ -904,15 +937,16 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
}
EXPORT_SYMBOL(dib7000p_ctrl_timf);
-static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
+static void dib7000p_set_channel(struct dib7000p_state *state,
+ struct dtv_frontend_properties *ch, u8 seq)
{
u16 value, est[4];
- dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
/* nfft, guard, qam, alpha */
value = 0;
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K:
value |= (0 << 7);
break;
@@ -924,7 +958,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
value |= (1 << 7);
break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_32:
value |= (0 << 5);
break;
@@ -939,7 +973,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
value |= (2 << 5);
break;
}
- switch (ch->u.ofdm.constellation) {
+ switch (ch->modulation) {
case QPSK:
value |= (0 << 3);
break;
@@ -970,11 +1004,11 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
value = 0;
if (1 != 0)
value |= (1 << 6);
- if (ch->u.ofdm.hierarchy_information == 1)
+ if (ch->hierarchy == 1)
value |= (1 << 4);
if (1 == 1)
value |= 1;
- switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
+ switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
case FEC_2_3:
value |= (2 << 1);
break;
@@ -1001,7 +1035,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
dib7000p_write_word(state, 33, 0x0005);
/* P_dvsy_sync_wait */
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_8K:
value = 256;
break;
@@ -1013,7 +1047,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
value = 64;
break;
}
- switch (ch->u.ofdm.guard_interval) {
+ switch (ch->guard_interval) {
case GUARD_INTERVAL_1_16:
value *= 2;
break;
@@ -1034,11 +1068,11 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
/* deactive the possibility of diversity reception if extended interleaver */
- state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
+ state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
dib7000p_set_diversity_in(&state->demod, state->div_state);
/* channel estimation fine configuration */
- switch (ch->u.ofdm.constellation) {
+ switch (ch->modulation) {
case QAM_64:
est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
@@ -1062,27 +1096,31 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte
dib7000p_write_word(state, 187 + value, est[value]);
}
-static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_autosearch_start(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000p_state *state = demod->demodulator_priv;
- struct dvb_frontend_parameters schan;
+ struct dtv_frontend_properties schan;
u32 value, factor;
u32 internal = dib7000p_get_internal_freq(state);
schan = *ch;
- schan.u.ofdm.constellation = QAM_64;
- schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
- schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
- schan.u.ofdm.code_rate_HP = FEC_2_3;
- schan.u.ofdm.code_rate_LP = FEC_3_4;
- schan.u.ofdm.hierarchy_information = 0;
+ schan.modulation = QAM_64;
+ schan.guard_interval = GUARD_INTERVAL_1_32;
+ schan.transmission_mode = TRANSMISSION_MODE_8K;
+ schan.code_rate_HP = FEC_2_3;
+ schan.code_rate_LP = FEC_3_4;
+ schan.hierarchy = 0;
dib7000p_set_channel(state, &schan, 7);
- factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
- if (factor >= 5000)
- factor = 1;
- else
+ factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+ if (factor >= 5000) {
+ if (state->version == SOC7090)
+ factor = 2;
+ else
+ factor = 1;
+ } else
factor = 6;
value = 30 * internal * factor;
@@ -1205,8 +1243,9 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32
dib7000p_write_word(state, 143, 0);
}
-static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
+static int dib7000p_tune(struct dvb_frontend *demod)
{
+ struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
struct dib7000p_state *state = demod->demodulator_priv;
u16 tmp = 0;
@@ -1239,7 +1278,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
tmp = (6 << 8) | 0x80;
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K:
tmp |= (2 << 12);
break;
@@ -1255,7 +1294,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
tmp = (0 << 4);
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K:
tmp |= 0x6;
break;
@@ -1271,7 +1310,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
tmp = (0 << 4);
- switch (ch->u.ofdm.transmission_mode) {
+ switch (ch->transmission_mode) {
case TRANSMISSION_MODE_2K:
tmp |= 0x6;
break;
@@ -1303,9 +1342,9 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet
}
if (state->cfg.spur_protect)
- dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
- dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+ dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
return 0;
}
@@ -1323,7 +1362,7 @@ static int dib7000p_sleep(struct dvb_frontend *demod)
{
struct dib7000p_state *state = demod->demodulator_priv;
if (state->version == SOC7090)
- return dib7090_set_output_mode(demod, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+ return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
}
@@ -1345,93 +1384,94 @@ static int dib7000p_identify(struct dib7000p_state *st)
return 0;
}
-static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7000p_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000p_state *state = fe->demodulator_priv;
u16 tps = dib7000p_read_word(state, 463);
fep->inversion = INVERSION_AUTO;
- fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
+ fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
switch ((tps >> 8) & 0x3) {
case 0:
- fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ fep->transmission_mode = TRANSMISSION_MODE_2K;
break;
case 1:
- fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ fep->transmission_mode = TRANSMISSION_MODE_8K;
break;
- /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+ /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
}
switch (tps & 0x3) {
case 0:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ fep->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ fep->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ fep->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ fep->guard_interval = GUARD_INTERVAL_1_4;
break;
}
switch ((tps >> 14) & 0x3) {
case 0:
- fep->u.ofdm.constellation = QPSK;
+ fep->modulation = QPSK;
break;
case 1:
- fep->u.ofdm.constellation = QAM_16;
+ fep->modulation = QAM_16;
break;
case 2:
default:
- fep->u.ofdm.constellation = QAM_64;
+ fep->modulation = QAM_64;
break;
}
/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
- fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fep->hierarchy = HIERARCHY_NONE;
switch ((tps >> 5) & 0x7) {
case 1:
- fep->u.ofdm.code_rate_HP = FEC_1_2;
+ fep->code_rate_HP = FEC_1_2;
break;
case 2:
- fep->u.ofdm.code_rate_HP = FEC_2_3;
+ fep->code_rate_HP = FEC_2_3;
break;
case 3:
- fep->u.ofdm.code_rate_HP = FEC_3_4;
+ fep->code_rate_HP = FEC_3_4;
break;
case 5:
- fep->u.ofdm.code_rate_HP = FEC_5_6;
+ fep->code_rate_HP = FEC_5_6;
break;
case 7:
default:
- fep->u.ofdm.code_rate_HP = FEC_7_8;
+ fep->code_rate_HP = FEC_7_8;
break;
}
switch ((tps >> 2) & 0x7) {
case 1:
- fep->u.ofdm.code_rate_LP = FEC_1_2;
+ fep->code_rate_LP = FEC_1_2;
break;
case 2:
- fep->u.ofdm.code_rate_LP = FEC_2_3;
+ fep->code_rate_LP = FEC_2_3;
break;
case 3:
- fep->u.ofdm.code_rate_LP = FEC_3_4;
+ fep->code_rate_LP = FEC_3_4;
break;
case 5:
- fep->u.ofdm.code_rate_LP = FEC_5_6;
+ fep->code_rate_LP = FEC_5_6;
break;
case 7:
default:
- fep->u.ofdm.code_rate_LP = FEC_7_8;
+ fep->code_rate_LP = FEC_7_8;
break;
}
@@ -1440,36 +1480,36 @@ static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa
return 0;
}
-static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib7000p_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000p_state *state = fe->demodulator_priv;
int time, ret;
- if (state->version == SOC7090) {
+ if (state->version == SOC7090)
dib7090_set_diversity_in(fe, 0);
- dib7090_set_output_mode(fe, OUTMODE_HIGH_Z);
- } else
+ else
dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
/* maybe the parameter has been changed */
state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, fep);
+ fe->ops.tuner_ops.set_params(fe);
/* start up the AGC */
state->agc_state = 0;
do {
- time = dib7000p_agc_startup(fe, fep);
+ time = dib7000p_agc_startup(fe);
if (time != -1)
msleep(time);
} while (time != -1);
- if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
- fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
int i = 800, found;
- dib7000p_autosearch_start(fe, fep);
+ dib7000p_autosearch_start(fe);
do {
msleep(1);
found = dib7000p_autosearch_is_irq(fe);
@@ -1479,15 +1519,19 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_pa
if (found == 0 || found == 1)
return 0;
- dib7000p_get_frontend(fe, fep);
+ dib7000p_get_frontend(fe);
}
- ret = dib7000p_tune(fe, fep);
+ ret = dib7000p_tune(fe);
/* make this a config parameter */
- if (state->version == SOC7090)
+ if (state->version == SOC7090) {
dib7090_set_output_mode(fe, state->cfg.output_mode);
- else
+ if (state->cfg.enMpegOutput == 0) {
+ dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
+ dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+ }
+ } else
dib7000p_set_output_mode(state, state->cfg.output_mode);
return ret;
@@ -1831,7 +1875,8 @@ static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg m
return num;
}
-int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num, u16 apb_address)
+static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num, u16 apb_address)
{
struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
u16 word;
@@ -1933,10 +1978,10 @@ static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[]
apb_address = 915;
break;
case 0x27:
- apb_address = 916;
+ apb_address = 917;
break;
case 0x28:
- apb_address = 917;
+ apb_address = 916;
break;
case 0x1d:
i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
@@ -2031,12 +2076,7 @@ static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32
static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
{
- u8 index_buf;
- u16 rx_copy_buf[22];
-
dprintk("Configure DibStream Tx");
- for (index_buf = 0; index_buf < 22; index_buf++)
- rx_copy_buf[index_buf] = dib7000p_read_word(state, 1536+index_buf);
dib7000p_write_word(state, 1615, 1);
dib7000p_write_word(state, 1603, P_Kin);
@@ -2048,9 +2088,6 @@ static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout
dib7000p_write_word(state, 1612, syncSize);
dib7000p_write_word(state, 1615, 0);
- for (index_buf = 0; index_buf < 22; index_buf++)
- dib7000p_write_word(state, 1536+index_buf, rx_copy_buf[index_buf]);
-
return 0;
}
@@ -2077,109 +2114,121 @@ static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout
return 0;
}
-static int dib7090_enDivOnHostBus(struct dib7000p_state *state)
-{
- u16 reg;
-
- dprintk("Enable Diversity on host bus");
- reg = (1 << 8) | (1 << 5);
- dib7000p_write_word(state, 1288, reg);
-
- return dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
-}
-
-static int dib7090_enAdcOnHostBus(struct dib7000p_state *state)
-{
- u16 reg;
-
- dprintk("Enable ADC on host bus");
- reg = (1 << 7) | (1 << 5);
- dib7000p_write_word(state, 1288, reg);
-
- return dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
-}
-
-static int dib7090_enMpegOnHostBus(struct dib7000p_state *state)
+static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
{
- u16 reg;
-
- dprintk("Enable Mpeg on host bus");
- reg = (1 << 9) | (1 << 5);
- dib7000p_write_word(state, 1288, reg);
+ u16 reg_1287 = dib7000p_read_word(state, 1287);
- return dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
-}
+ switch (onoff) {
+ case 1:
+ reg_1287 &= ~(1<<7);
+ break;
+ case 0:
+ reg_1287 |= (1<<7);
+ break;
+ }
-static int dib7090_enMpegInput(struct dib7000p_state *state)
-{
- dprintk("Enable Mpeg input");
- return dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
+ dib7000p_write_word(state, 1287, reg_1287);
}
-static int dib7090_enMpegMux(struct dib7000p_state *state, u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+static void dib7090_configMpegMux(struct dib7000p_state *state,
+ u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
{
- u16 reg = (1 << 7) | ((pulseWidth & 0x1f) << 2) | ((enSerialMode & 0x1) << 1) | (enSerialClkDiv2 & 0x1);
-
dprintk("Enable Mpeg mux");
- dib7000p_write_word(state, 1287, reg);
- reg &= ~(1 << 7);
- dib7000p_write_word(state, 1287, reg);
+ dib7090_enMpegMux(state, 0);
- reg = (1 << 4);
- dib7000p_write_word(state, 1288, reg);
+ /* If the input mode is MPEG do not divide the serial clock */
+ if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+ enSerialClkDiv2 = 0;
- return 0;
+ dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
+ | ((enSerialMode & 0x1) << 1)
+ | (enSerialClkDiv2 & 0x1));
+
+ dib7090_enMpegMux(state, 1);
}
-static int dib7090_disableMpegMux(struct dib7000p_state *state)
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
{
- u16 reg;
-
- dprintk("Disable Mpeg mux");
- dib7000p_write_word(state, 1288, 0);
-
- reg = dib7000p_read_word(state, 1287);
- reg &= ~(1 << 7);
- dib7000p_write_word(state, 1287, reg);
+ u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
- return 0;
+ switch (mode) {
+ case MPEG_ON_DIBTX:
+ dprintk("SET MPEG ON DIBSTREAM TX");
+ dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+ reg_1288 |= (1<<9);
+ break;
+ case DIV_ON_DIBTX:
+ dprintk("SET DIV_OUT ON DIBSTREAM TX");
+ dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+ reg_1288 |= (1<<8);
+ break;
+ case ADC_ON_DIBTX:
+ dprintk("SET ADC_OUT ON DIBSTREAM TX");
+ dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+ reg_1288 |= (1<<7);
+ break;
+ default:
+ break;
+ }
+ dib7000p_write_word(state, 1288, reg_1288);
}
-static int dib7090_set_input_mode(struct dvb_frontend *fe, int mode)
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
{
- struct dib7000p_state *state = fe->demodulator_priv;
+ u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
switch (mode) {
- case INPUT_MODE_DIVERSITY:
- dprintk("Enable diversity INPUT");
- dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+ case DEMOUT_ON_HOSTBUS:
+ dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+ dib7090_enMpegMux(state, 0);
+ reg_1288 |= (1<<6);
+ break;
+ case DIBTX_ON_HOSTBUS:
+ dprintk("SET DIBSTREAM TX ON HOST BUS");
+ dib7090_enMpegMux(state, 0);
+ reg_1288 |= (1<<5);
break;
- case INPUT_MODE_MPEG:
- dprintk("Enable Mpeg INPUT");
- dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
+ case MPEG_ON_HOSTBUS:
+ dprintk("SET MPEG MUX ON HOST BUS");
+ reg_1288 |= (1<<4);
break;
- case INPUT_MODE_OFF:
default:
- dprintk("Disable INPUT");
- dib7090_cfg_DibRx(state, 0, 0, 0, 0, 0, 0, 0);
break;
}
- return 0;
+ dib7000p_write_word(state, 1288, reg_1288);
}
-static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
+int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
{
+ struct dib7000p_state *state = fe->demodulator_priv;
+ u16 reg_1287;
+
switch (onoff) {
- case 0: /* only use the internal way - not the diversity input */
- dib7090_set_input_mode(fe, INPUT_MODE_MPEG);
- break;
- case 1: /* both ways */
- case 2: /* only the diversity input */
- dib7090_set_input_mode(fe, INPUT_MODE_DIVERSITY);
- break;
+ case 0: /* only use the internal way - not the diversity input */
+ dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
+ dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+ /* Do not divide the serial clock of MPEG MUX */
+ /* in SERIAL MODE in case input mode MPEG is used */
+ reg_1287 = dib7000p_read_word(state, 1287);
+ /* enSerialClkDiv2 == 1 ? */
+ if ((reg_1287 & 0x1) == 1) {
+ /* force enSerialClkDiv2 = 0 */
+ reg_1287 &= ~0x1;
+ dib7000p_write_word(state, 1287, reg_1287);
+ }
+ state->input_mode_mpeg = 1;
+ break;
+ case 1: /* both ways */
+ case 2: /* only the diversity input */
+ dprintk("%s ON : Enable diversity INPUT", __func__);
+ dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+ state->input_mode_mpeg = 0;
+ break;
}
+ dib7000p_set_diversity_in(&state->demod, onoff);
return 0;
}
@@ -2204,69 +2253,63 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
case OUTMODE_MPEG2_SERIAL:
if (prefer_mpeg_mux_use) {
- dprintk("Sip 7090P setting output mode TS_SERIAL using Mpeg Mux");
- dib7090_enMpegOnHostBus(state);
- dib7090_enMpegInput(state);
- if (state->cfg.enMpegOutput == 1)
- dib7090_enMpegMux(state, 3, 1, 1);
-
- } else { /* Use Smooth block */
- dprintk("Sip 7090P setting output mode TS_SERIAL using Smooth bloc");
- dib7090_disableMpegMux(state);
- dib7000p_write_word(state, 1288, (1 << 6));
- outreg |= (2 << 6) | (0 << 1);
+ dprintk("setting output mode TS_SERIAL using Mpeg Mux");
+ dib7090_configMpegMux(state, 3, 1, 1);
+ dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+ } else {/* Use Smooth block */
+ dprintk("setting output mode TS_SERIAL using Smooth bloc");
+ dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (2<<6) | (0 << 1);
}
break;
case OUTMODE_MPEG2_PAR_GATED_CLK:
if (prefer_mpeg_mux_use) {
- dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
- dib7090_enMpegOnHostBus(state);
- dib7090_enMpegInput(state);
- if (state->cfg.enMpegOutput == 1)
- dib7090_enMpegMux(state, 2, 0, 0);
- } else { /* Use Smooth block */
- dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Smooth block");
- dib7090_disableMpegMux(state);
- dib7000p_write_word(state, 1288, (1 << 6));
- outreg |= (0 << 6);
+ dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+ dib7090_configMpegMux(state, 2, 0, 0);
+ dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+ } else { /* Use Smooth block */
+ dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
+ dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (0<<6);
}
break;
case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
- dprintk("Sip 7090P setting output mode TS_PARALLEL_CONT using Smooth block");
- dib7090_disableMpegMux(state);
- dib7000p_write_word(state, 1288, (1 << 6));
- outreg |= (1 << 6);
+ dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
+ dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (1<<6);
break;
case OUTMODE_MPEG2_FIFO: /* Using Smooth block because not supported by new Mpeg Mux bloc */
- dprintk("Sip 7090P setting output mode TS_FIFO using Smooth block");
- dib7090_disableMpegMux(state);
- dib7000p_write_word(state, 1288, (1 << 6));
- outreg |= (5 << 6);
+ dprintk("setting output mode TS_FIFO using Smooth block");
+ dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (5<<6);
smo_mode |= (3 << 1);
fifo_threshold = 512;
break;
case OUTMODE_DIVERSITY:
- dprintk("Sip 7090P setting output mode MODE_DIVERSITY");
- dib7090_disableMpegMux(state);
- dib7090_enDivOnHostBus(state);
+ dprintk("setting output mode MODE_DIVERSITY");
+ dib7090_setDibTxMux(state, DIV_ON_DIBTX);
+ dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
break;
case OUTMODE_ANALOG_ADC:
- dprintk("Sip 7090P setting output mode MODE_ANALOG_ADC");
- dib7090_enAdcOnHostBus(state);
+ dprintk("setting output mode MODE_ANALOG_ADC");
+ dib7090_setDibTxMux(state, ADC_ON_DIBTX);
+ dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
break;
}
+ if (mode != OUTMODE_HIGH_Z)
+ outreg |= (1 << 10);
if (state->cfg.output_mpeg2_in_188_bytes)
smo_mode |= (1 << 5);
ret |= dib7000p_write_word(state, 235, smo_mode);
ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
- ret |= dib7000p_write_word(state, 1286, outreg | (1 << 10)); /* allways set Dout active = 1 !!! */
+ ret |= dib7000p_write_word(state, 1286, outreg);
return ret;
}
@@ -2296,13 +2339,6 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
}
EXPORT_SYMBOL(dib7090_tuner_sleep);
-int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
-{
- dprintk("AGC restart callback: %d", restart);
- return 0;
-}
-EXPORT_SYMBOL(dib7090_agc_restart);
-
int dib7090_get_adc_power(struct dvb_frontend *fe)
{
return dib7000p_get_adc_power(fe);
@@ -2391,9 +2427,9 @@ error:
EXPORT_SYMBOL(dib7000p_attach);
static struct dvb_frontend_ops dib7000p_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "DiBcom 7000PC",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 0179f94..b61b03a 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -56,11 +56,12 @@ extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart);
extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
extern int dib7090_get_adc_power(struct dvb_frontend *fe);
extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
extern int dib7090_slave_reset(struct dvb_frontend *fe);
+extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+ u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
#else
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
@@ -122,12 +123,6 @@ static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
return 0;
}
-static inline int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
@@ -151,6 +146,13 @@ static inline int dib7090_slave_reset(struct dvb_frontend *fe)
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
+
+static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
+ u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
#endif
#endif
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index fe284d5..9ca34f4 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -81,11 +81,15 @@ struct dib8000_state {
u8 i2c_write_buffer[4];
u8 i2c_read_buffer[2];
struct mutex i2c_buffer_lock;
+ u8 input_mode_mpeg;
+
+ u16 tuner_enable;
+ struct i2c_adapter dib8096p_tuner_adap;
};
enum dib8000_power_mode {
- DIB8000M_POWER_ALL = 0,
- DIB8000M_POWER_INTERFACE_ONLY,
+ DIB8000_POWER_ALL = 0,
+ DIB8000_POWER_INTERFACE_ONLY,
};
static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
@@ -428,20 +432,31 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow
/* by default everything is going to be powered off */
u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
+ reg_1280;
+
+ if (state->revision != 0x8090)
reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
+ else
+ reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
/* now, depending on the requested mode, we power on */
switch (mode) {
/* power up everything in the demod */
- case DIB8000M_POWER_ALL:
+ case DIB8000_POWER_ALL:
reg_774 = 0x0000;
reg_775 = 0x0000;
reg_776 = 0x0000;
reg_900 &= 0xfffc;
- reg_1280 &= 0x00ff;
+ if (state->revision != 0x8090)
+ reg_1280 &= 0x00ff;
+ else
+ reg_1280 &= 0x707f;
break;
- case DIB8000M_POWER_INTERFACE_ONLY:
- reg_1280 &= 0x00ff;
+ case DIB8000_POWER_INTERFACE_ONLY:
+ if (state->revision != 0x8090)
+ reg_1280 &= 0x00ff;
+ else
+ reg_1280 &= 0xfa7b;
break;
}
@@ -453,19 +468,67 @@ static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_pow
dib8000_write_word(state, 1280, reg_1280);
}
+static int dib8000_init_sdram(struct dib8000_state *state)
+{
+ u16 reg = 0;
+ dprintk("Init sdram");
+
+ reg = dib8000_read_word(state, 274)&0xfff0;
+ /* P_dintlv_delay_ram = 7 because of MobileSdram */
+ dib8000_write_word(state, 274, reg | 0x7);
+
+ dib8000_write_word(state, 1803, (7<<2));
+
+ reg = dib8000_read_word(state, 1280);
+ /* force restart P_restart_sdram */
+ dib8000_write_word(state, 1280, reg | (1<<2));
+
+ /* release restart P_restart_sdram */
+ dib8000_write_word(state, 1280, reg);
+
+ return 0;
+}
+
static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
{
int ret = 0;
- u16 reg_907 = dib8000_read_word(state, 907), reg_908 = dib8000_read_word(state, 908);
+ u16 reg, reg_907 = dib8000_read_word(state, 907);
+ u16 reg_908 = dib8000_read_word(state, 908);
switch (no) {
case DIBX000_SLOW_ADC_ON:
- reg_908 |= (1 << 1) | (1 << 0);
- ret |= dib8000_write_word(state, 908, reg_908);
- reg_908 &= ~(1 << 1);
+ if (state->revision != 0x8090) {
+ reg_908 |= (1 << 1) | (1 << 0);
+ ret |= dib8000_write_word(state, 908, reg_908);
+ reg_908 &= ~(1 << 1);
+ } else {
+ reg = dib8000_read_word(state, 1925);
+ /* en_slowAdc = 1 & reset_sladc = 1 */
+ dib8000_write_word(state, 1925, reg |
+ (1<<4) | (1<<2));
+
+ /* read acces to make it works... strange ... */
+ reg = dib8000_read_word(state, 1925);
+ msleep(20);
+ /* en_slowAdc = 1 & reset_sladc = 0 */
+ dib8000_write_word(state, 1925, reg & ~(1<<4));
+
+ reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
+ | (0x3 << 12));
+ /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
+ (Vin2 = Vcm) */
+ dib8000_write_word(state, 921, reg | (1 << 14)
+ | (3 << 12));
+ }
break;
case DIBX000_SLOW_ADC_OFF:
+ if (state->revision == 0x8090) {
+ reg = dib8000_read_word(state, 1925);
+ /* reset_sladc = 1 en_slowAdc = 0 */
+ dib8000_write_word(state, 1925,
+ (reg & ~(1<<2)) | (1<<4));
+ }
reg_908 |= (1 << 1) | (1 << 0);
break;
@@ -521,7 +584,12 @@ static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
static int dib8000_sad_calib(struct dib8000_state *state)
{
-/* internal */
+ if (state->revision == 0x8090) {
+ dprintk("%s: the sad calibration is not needed for the dib8096P",
+ __func__);
+ return 0;
+ }
+ /* internal */
dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096
@@ -546,48 +614,129 @@ EXPORT_SYMBOL(dib8000_set_wbd_ref);
static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
{
dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
- dib8000_write_word(state, 23, (u16) (((bw->internal * 1000) >> 16) & 0xffff)); /* P_sec_len */
- dib8000_write_word(state, 24, (u16) ((bw->internal * 1000) & 0xffff));
+ if (state->revision != 0x8090) {
+ dib8000_write_word(state, 23,
+ (u16) (((bw->internal * 1000) >> 16) & 0xffff));
+ dib8000_write_word(state, 24,
+ (u16) ((bw->internal * 1000) & 0xffff));
+ } else {
+ dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
+ dib8000_write_word(state, 24,
+ (u16) ((bw->internal / 2 * 1000) & 0xffff));
+ }
dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
- dib8000_write_word(state, 922, bw->sad_cfg);
+ if (state->revision != 0x8090)
+ dib8000_write_word(state, 922, bw->sad_cfg);
}
static void dib8000_reset_pll(struct dib8000_state *state)
{
const struct dibx000_bandwidth_config *pll = state->cfg.pll;
- u16 clk_cfg1;
-
- // clk_cfg0
- dib8000_write_word(state, 901, (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
-
- // clk_cfg1
- clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
- (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) |
- (pll->pll_range << 1) | (pll->pll_reset << 0);
-
- dib8000_write_word(state, 902, clk_cfg1);
- clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
- dib8000_write_word(state, 902, clk_cfg1);
-
- dprintk("clk_cfg1: 0x%04x", clk_cfg1); /* 0x507 1 0 1 000 0 0 11 1 */
-
- /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
- if (state->cfg.pll->ADClkSrc == 0)
- dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) |
- (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
- else if (state->cfg.refclksel != 0)
- dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
- ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) |
- (pll->ADClkSrc << 7) | (0 << 1));
- else
- dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
+ u16 clk_cfg1, reg;
+
+ if (state->revision != 0x8090) {
+ dib8000_write_word(state, 901,
+ (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
+
+ clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
+ (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
+ (1 << 3) | (pll->pll_range << 1) |
+ (pll->pll_reset << 0);
+
+ dib8000_write_word(state, 902, clk_cfg1);
+ clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
+ dib8000_write_word(state, 902, clk_cfg1);
+
+ dprintk("clk_cfg1: 0x%04x", clk_cfg1);
+
+ /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
+ if (state->cfg.pll->ADClkSrc == 0)
+ dib8000_write_word(state, 904,
+ (0 << 15) | (0 << 12) | (0 << 10) |
+ (pll->modulo << 8) |
+ (pll->ADClkSrc << 7) | (0 << 1));
+ else if (state->cfg.refclksel != 0)
+ dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+ ((state->cfg.refclksel & 0x3) << 10) |
+ (pll->modulo << 8) |
+ (pll->ADClkSrc << 7) | (0 << 1));
+ else
+ dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+ (3 << 10) | (pll->modulo << 8) |
+ (pll->ADClkSrc << 7) | (0 << 1));
+ } else {
+ dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
+ (pll->pll_range<<12) | (pll->pll_ratio<<6) |
+ (pll->pll_prediv));
+
+ reg = dib8000_read_word(state, 1857);
+ dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
+
+ reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
+ dib8000_write_word(state, 1858, reg | 1);
+
+ dib8000_write_word(state, 904, (pll->modulo << 8));
+ }
dib8000_reset_pll_common(state, pll);
}
+int dib8000_update_pll(struct dvb_frontend *fe,
+ struct dibx000_bandwidth_config *pll)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+ u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
+ u8 loopdiv, prediv;
+ u32 internal, xtal;
+
+ /* get back old values */
+ prediv = reg_1856 & 0x3f;
+ loopdiv = (reg_1856 >> 6) & 0x3f;
+
+ if ((pll != NULL) && (pll->pll_prediv != prediv ||
+ pll->pll_ratio != loopdiv)) {
+ dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+ reg_1856 &= 0xf000;
+ reg_1857 = dib8000_read_word(state, 1857);
+ /* disable PLL */
+ dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
+
+ dib8000_write_word(state, 1856, reg_1856 |
+ ((pll->pll_ratio & 0x3f) << 6) |
+ (pll->pll_prediv & 0x3f));
+
+ /* write new system clk into P_sec_len */
+ internal = dib8000_read32(state, 23) / 1000;
+ dprintk("Old Internal = %d", internal);
+ xtal = 2 * (internal / loopdiv) * prediv;
+ internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
+ dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
+ dprintk("New Internal = %d", internal);
+
+ dib8000_write_word(state, 23,
+ (u16) (((internal / 2) >> 16) & 0xffff));
+ dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
+ /* enable PLL */
+ dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
+
+ while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
+ dprintk("Waiting for PLL to lock");
+
+ /* verify */
+ reg_1856 = dib8000_read_word(state, 1856);
+ dprintk("PLL Updated with prediv = %d and loopdiv = %d",
+ reg_1856&0x3f, (reg_1856>>6)&0x3f);
+
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(dib8000_update_pll);
+
+
static int dib8000_reset_gpio(struct dib8000_state *st)
{
/* reset the GPIOs */
@@ -721,9 +870,6 @@ static const u16 dib8000_defaults[] = {
(3 << 5) | /* P_ctrl_pre_freq_step=3 */
(1 << 0), /* P_pre_freq_win_len=1 */
- 1, 903,
- (0 << 4) | 2, // P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW)
-
0,
};
@@ -740,7 +886,8 @@ static u16 dib8000_identify(struct i2c_device *client)
}
value = dib8000_i2c_read16(client, 897);
- if (value != 0x8000 && value != 0x8001 && value != 0x8002) {
+ if (value != 0x8000 && value != 0x8001 &&
+ value != 0x8002 && value != 0x8090) {
dprintk("wrong Device ID (%x)", value);
return 0;
}
@@ -755,6 +902,9 @@ static u16 dib8000_identify(struct i2c_device *client)
case 0x8002:
dprintk("found DiB8000C");
break;
+ case 0x8090:
+ dprintk("found DiB8096P");
+ break;
}
return value;
}
@@ -763,17 +913,19 @@ static int dib8000_reset(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
- dib8000_write_word(state, 1287, 0x0003); /* sram lead in, rdy */
-
if ((state->revision = dib8000_identify(&state->i2c)) == 0)
return -EINVAL;
+ /* sram lead in, rdy */
+ if (state->revision != 0x8090)
+ dib8000_write_word(state, 1287, 0x0003);
+
if (state->revision == 0x8000)
dprintk("error : dib8000 MA not supported");
dibx000_reset_i2c_master(&state->i2c_master);
- dib8000_set_power_mode(state, DIB8000M_POWER_ALL);
+ dib8000_set_power_mode(state, DIB8000_POWER_ALL);
/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
dib8000_set_adc_state(state, DIBX000_VBG_ENABLE);
@@ -782,8 +934,10 @@ static int dib8000_reset(struct dvb_frontend *fe)
dib8000_write_word(state, 770, 0xffff);
dib8000_write_word(state, 771, 0xffff);
dib8000_write_word(state, 772, 0xfffc);
- dib8000_write_word(state, 898, 0x000c); // sad
- dib8000_write_word(state, 1280, 0x004d);
+ if (state->revision == 0x8090)
+ dib8000_write_word(state, 1280, 0x0045);
+ else
+ dib8000_write_word(state, 1280, 0x004d);
dib8000_write_word(state, 1281, 0x000c);
dib8000_write_word(state, 770, 0x0000);
@@ -794,19 +948,25 @@ static int dib8000_reset(struct dvb_frontend *fe)
dib8000_write_word(state, 1281, 0x0000);
/* drives */
- if (state->cfg.drives)
- dib8000_write_word(state, 906, state->cfg.drives);
- else {
- dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
- dib8000_write_word(state, 906, 0x2d98); // min drive SDRAM - not optimal - adjust
+ if (state->revision != 0x8090) {
+ if (state->cfg.drives)
+ dib8000_write_word(state, 906, state->cfg.drives);
+ else {
+ dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
+ /* min drive SDRAM - not optimal - adjust */
+ dib8000_write_word(state, 906, 0x2d98);
+ }
}
dib8000_reset_pll(state);
+ if (state->revision != 0x8090)
+ dib8000_write_word(state, 898, 0x0004);
if (dib8000_reset_gpio(state) != 0)
dprintk("GPIO reset was not successful.");
- if (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)
+ if ((state->revision != 0x8090) &&
+ (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
dprintk("OUTPUT_MODE could not be resetted.");
state->current_agc = NULL;
@@ -832,6 +992,8 @@ static int dib8000_reset(struct dvb_frontend *fe)
l = *n++;
}
}
+ if (state->revision != 0x8090)
+ dib8000_write_word(state, 903, (0 << 4) | 2);
state->isdbt_cfg_loaded = 0;
//div_cfg override for special configs
@@ -844,10 +1006,12 @@ static int dib8000_reset(struct dvb_frontend *fe)
dib8000_set_bandwidth(fe, 6000);
dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
- dib8000_sad_calib(state);
- dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+ if (state->revision != 0x8090) {
+ dib8000_sad_calib(state);
+ dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+ }
- dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY);
+ dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
return 0;
}
@@ -879,6 +1043,8 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
{
struct dibx000_agc_config *agc = NULL;
int i;
+ u16 reg;
+
if (state->current_band == band && state->current_agc != NULL)
return 0;
state->current_band = band;
@@ -914,6 +1080,12 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
dib8000_write_word(state, 106, state->wbd_ref);
else // use default
dib8000_write_word(state, 106, agc->wbd_ref);
+
+ if (state->revision == 0x8090) {
+ reg = dib8000_read_word(state, 922) & (0x3 << 2);
+ dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
+ }
+
dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
dib8000_write_word(state, 108, agc->agc1_max);
dib8000_write_word(state, 109, agc->agc1_min);
@@ -925,7 +1097,10 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
dib8000_write_word(state, 75, agc->agc1_pt3);
- dib8000_write_word(state, 923, (dib8000_read_word(state, 923) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); /*LB : 929 -> 923 */
+ if (state->revision != 0x8090)
+ dib8000_write_word(state, 923,
+ (dib8000_read_word(state, 923) & 0xffe3) |
+ (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
return 0;
}
@@ -968,14 +1143,30 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
enum frontend_tune_state *tune_state = &state->tune_state;
-
int ret = 0;
+ u16 reg, upd_demod_gain_period = 0x8000;
switch (*tune_state) {
case CT_AGC_START:
// set power-up level: interf+analog+AGC
- dib8000_set_adc_state(state, DIBX000_ADC_ON);
+ if (state->revision != 0x8090)
+ dib8000_set_adc_state(state, DIBX000_ADC_ON);
+ else {
+ dib8000_set_power_mode(state, DIB8000_POWER_ALL);
+
+ reg = dib8000_read_word(state, 1947)&0xff00;
+ dib8000_write_word(state, 1946,
+ upd_demod_gain_period & 0xFFFF);
+ /* bit 14 = enDemodGain */
+ dib8000_write_word(state, 1947, reg | (1<<14) |
+ ((upd_demod_gain_period >> 16) & 0xFF));
+
+ /* enable adc i & q */
+ reg = dib8000_read_word(state, 1920);
+ dib8000_write_word(state, 1920, (reg | 0x3) &
+ (~(1 << 7)));
+ }
if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
*tune_state = CT_AGC_STOP;
@@ -1026,6 +1217,579 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
}
+static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
+{
+ u16 reg;
+
+ drive &= 0x7;
+
+ /* drive host bus 2, 3, 4 */
+ reg = dib8000_read_word(state, 1798) &
+ ~(0x7 | (0x7 << 6) | (0x7 << 12));
+ reg |= (drive<<12) | (drive<<6) | drive;
+ dib8000_write_word(state, 1798, reg);
+
+ /* drive host bus 5,6 */
+ reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
+ reg |= (drive<<8) | (drive<<2);
+ dib8000_write_word(state, 1799, reg);
+
+ /* drive host bus 7, 8, 9 */
+ reg = dib8000_read_word(state, 1800) &
+ ~(0x7 | (0x7 << 6) | (0x7 << 12));
+ reg |= (drive<<12) | (drive<<6) | drive;
+ dib8000_write_word(state, 1800, reg);
+
+ /* drive host bus 10, 11 */
+ reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
+ reg |= (drive<<8) | (drive<<2);
+ dib8000_write_word(state, 1801, reg);
+
+ /* drive host bus 12, 13, 14 */
+ reg = dib8000_read_word(state, 1802) &
+ ~(0x7 | (0x7 << 6) | (0x7 << 12));
+ reg |= (drive<<12) | (drive<<6) | drive;
+ dib8000_write_word(state, 1802, reg);
+}
+
+static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
+ u32 insertExtSynchro, u32 syncSize)
+{
+ u32 quantif = 3;
+ u32 nom = (insertExtSynchro * P_Kin+syncSize);
+ u32 denom = P_Kout;
+ u32 syncFreq = ((nom << quantif) / denom);
+
+ if ((syncFreq & ((1 << quantif) - 1)) != 0)
+ syncFreq = (syncFreq >> quantif) + 1;
+ else
+ syncFreq = (syncFreq >> quantif);
+
+ if (syncFreq != 0)
+ syncFreq = syncFreq - 1;
+
+ return syncFreq;
+}
+
+static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
+ u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
+ u32 syncWord, u32 syncSize)
+{
+ dprintk("Configure DibStream Tx");
+
+ dib8000_write_word(state, 1615, 1);
+ dib8000_write_word(state, 1603, P_Kin);
+ dib8000_write_word(state, 1605, P_Kout);
+ dib8000_write_word(state, 1606, insertExtSynchro);
+ dib8000_write_word(state, 1608, synchroMode);
+ dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
+ dib8000_write_word(state, 1610, syncWord & 0xffff);
+ dib8000_write_word(state, 1612, syncSize);
+ dib8000_write_word(state, 1615, 0);
+}
+
+static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
+ u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
+ u32 syncWord, u32 syncSize, u32 dataOutRate)
+{
+ u32 syncFreq;
+
+ dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
+
+ if ((P_Kin != 0) && (P_Kout != 0)) {
+ syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
+ insertExtSynchro, syncSize);
+ dib8000_write_word(state, 1542, syncFreq);
+ }
+
+ dib8000_write_word(state, 1554, 1);
+ dib8000_write_word(state, 1536, P_Kin);
+ dib8000_write_word(state, 1537, P_Kout);
+ dib8000_write_word(state, 1539, synchroMode);
+ dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
+ dib8000_write_word(state, 1541, syncWord & 0xffff);
+ dib8000_write_word(state, 1543, syncSize);
+ dib8000_write_word(state, 1544, dataOutRate);
+ dib8000_write_word(state, 1554, 0);
+}
+
+static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
+{
+ u16 reg_1287;
+
+ reg_1287 = dib8000_read_word(state, 1287);
+
+ switch (onoff) {
+ case 1:
+ reg_1287 &= ~(1 << 8);
+ break;
+ case 0:
+ reg_1287 |= (1 << 8);
+ break;
+ }
+
+ dib8000_write_word(state, 1287, reg_1287);
+}
+
+static void dib8096p_configMpegMux(struct dib8000_state *state,
+ u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+{
+ u16 reg_1287;
+
+ dprintk("Enable Mpeg mux");
+
+ dib8096p_enMpegMux(state, 0);
+
+ /* If the input mode is MPEG do not divide the serial clock */
+ if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+ enSerialClkDiv2 = 0;
+
+ reg_1287 = ((pulseWidth & 0x1f) << 3) |
+ ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
+ dib8000_write_word(state, 1287, reg_1287);
+
+ dib8096p_enMpegMux(state, 1);
+}
+
+static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
+{
+ u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
+
+ switch (mode) {
+ case MPEG_ON_DIBTX:
+ dprintk("SET MPEG ON DIBSTREAM TX");
+ dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+ reg_1288 |= (1 << 9); break;
+ case DIV_ON_DIBTX:
+ dprintk("SET DIV_OUT ON DIBSTREAM TX");
+ dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+ reg_1288 |= (1 << 8); break;
+ case ADC_ON_DIBTX:
+ dprintk("SET ADC_OUT ON DIBSTREAM TX");
+ dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+ reg_1288 |= (1 << 7); break;
+ default:
+ break;
+ }
+ dib8000_write_word(state, 1288, reg_1288);
+}
+
+static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
+{
+ u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
+
+ switch (mode) {
+ case DEMOUT_ON_HOSTBUS:
+ dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+ dib8096p_enMpegMux(state, 0);
+ reg_1288 |= (1 << 6);
+ break;
+ case DIBTX_ON_HOSTBUS:
+ dprintk("SET DIBSTREAM TX ON HOST BUS");
+ dib8096p_enMpegMux(state, 0);
+ reg_1288 |= (1 << 5);
+ break;
+ case MPEG_ON_HOSTBUS:
+ dprintk("SET MPEG MUX ON HOST BUS");
+ reg_1288 |= (1 << 4);
+ break;
+ default:
+ break;
+ }
+ dib8000_write_word(state, 1288, reg_1288);
+}
+
+static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+ u16 reg_1287;
+
+ switch (onoff) {
+ case 0: /* only use the internal way - not the diversity input */
+ dprintk("%s mode OFF : by default Enable Mpeg INPUT",
+ __func__);
+ /* outputRate = 8 */
+ dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+ /* Do not divide the serial clock of MPEG MUX in
+ SERIAL MODE in case input mode MPEG is used */
+ reg_1287 = dib8000_read_word(state, 1287);
+ /* enSerialClkDiv2 == 1 ? */
+ if ((reg_1287 & 0x1) == 1) {
+ /* force enSerialClkDiv2 = 0 */
+ reg_1287 &= ~0x1;
+ dib8000_write_word(state, 1287, reg_1287);
+ }
+ state->input_mode_mpeg = 1;
+ break;
+ case 1: /* both ways */
+ case 2: /* only the diversity input */
+ dprintk("%s ON : Enable diversity INPUT", __func__);
+ dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+ state->input_mode_mpeg = 0;
+ break;
+ }
+
+ dib8000_set_diversity_in(state->fe[0], onoff);
+ return 0;
+}
+
+static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+ u16 outreg, smo_mode, fifo_threshold;
+ u8 prefer_mpeg_mux_use = 1;
+ int ret = 0;
+
+ dib8096p_host_bus_drive(state, 1);
+
+ fifo_threshold = 1792;
+ smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
+ outreg = dib8000_read_word(state, 1286) &
+ ~((1 << 10) | (0x7 << 6) | (1 << 1));
+
+ switch (mode) {
+ case OUTMODE_HIGH_Z:
+ outreg = 0;
+ break;
+
+ case OUTMODE_MPEG2_SERIAL:
+ if (prefer_mpeg_mux_use) {
+ dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
+ dib8096p_configMpegMux(state, 3, 1, 1);
+ dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+ } else {/* Use Smooth block */
+ dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
+ dib8096p_setHostBusMux(state,
+ DEMOUT_ON_HOSTBUS);
+ outreg |= (2 << 6) | (0 << 1);
+ }
+ break;
+
+ case OUTMODE_MPEG2_PAR_GATED_CLK:
+ if (prefer_mpeg_mux_use) {
+ dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+ dib8096p_configMpegMux(state, 2, 0, 0);
+ dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+ } else { /* Use Smooth block */
+ dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
+ dib8096p_setHostBusMux(state,
+ DEMOUT_ON_HOSTBUS);
+ outreg |= (0 << 6);
+ }
+ break;
+
+ case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
+ dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
+ dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (1 << 6);
+ break;
+
+ case OUTMODE_MPEG2_FIFO:
+ /* Using Smooth block because not supported
+ by new Mpeg Mux bloc */
+ dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
+ dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+ outreg |= (5 << 6);
+ smo_mode |= (3 << 1);
+ fifo_threshold = 512;
+ break;
+
+ case OUTMODE_DIVERSITY:
+ dprintk("dib8096P setting output mode MODE_DIVERSITY");
+ dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
+ dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+ break;
+
+ case OUTMODE_ANALOG_ADC:
+ dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
+ dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
+ dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+ break;
+ }
+
+ if (mode != OUTMODE_HIGH_Z)
+ outreg |= (1<<10);
+
+ dprintk("output_mpeg2_in_188_bytes = %d",
+ state->cfg.output_mpeg2_in_188_bytes);
+ if (state->cfg.output_mpeg2_in_188_bytes)
+ smo_mode |= (1 << 5);
+
+ ret |= dib8000_write_word(state, 299, smo_mode);
+ /* synchronous fread */
+ ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
+ ret |= dib8000_write_word(state, 1286, outreg);
+
+ return ret;
+}
+
+static int map_addr_to_serpar_number(struct i2c_msg *msg)
+{
+ if (msg->buf[0] <= 15)
+ msg->buf[0] -= 1;
+ else if (msg->buf[0] == 17)
+ msg->buf[0] = 15;
+ else if (msg->buf[0] == 16)
+ msg->buf[0] = 17;
+ else if (msg->buf[0] == 19)
+ msg->buf[0] = 16;
+ else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
+ msg->buf[0] -= 3;
+ else if (msg->buf[0] == 28)
+ msg->buf[0] = 23;
+ else if (msg->buf[0] == 99)
+ msg->buf[0] = 99;
+ else
+ return -EINVAL;
+ return 0;
+}
+
+static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+ u8 n_overflow = 1;
+ u16 i = 1000;
+ u16 serpar_num = msg[0].buf[0];
+
+ while (n_overflow == 1 && i) {
+ n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+ i--;
+ if (i == 0)
+ dprintk("Tuner ITF: write busy (overflow)");
+ }
+ dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
+ dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
+
+ return num;
+}
+
+static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+ u8 n_overflow = 1, n_empty = 1;
+ u16 i = 1000;
+ u16 serpar_num = msg[0].buf[0];
+ u16 read_word;
+
+ while (n_overflow == 1 && i) {
+ n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+ i--;
+ if (i == 0)
+ dprintk("TunerITF: read busy (overflow)");
+ }
+ dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
+
+ i = 1000;
+ while (n_empty == 1 && i) {
+ n_empty = dib8000_read_word(state, 1984)&0x1;
+ i--;
+ if (i == 0)
+ dprintk("TunerITF: read busy (empty)");
+ }
+
+ read_word = dib8000_read_word(state, 1987);
+ msg[1].buf[0] = (read_word >> 8) & 0xff;
+ msg[1].buf[1] = (read_word) & 0xff;
+
+ return num;
+}
+
+static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+{
+ if (map_addr_to_serpar_number(&msg[0]) == 0) {
+ if (num == 1) /* write */
+ return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
+ else /* read */
+ return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
+ }
+ return num;
+}
+
+static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num, u16 apb_address)
+{
+ struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+ u16 word;
+
+ if (num == 1) { /* write */
+ dib8000_write_word(state, apb_address,
+ ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
+ } else {
+ word = dib8000_read_word(state, apb_address);
+ msg[1].buf[0] = (word >> 8) & 0xff;
+ msg[1].buf[1] = (word) & 0xff;
+ }
+ return num;
+}
+
+static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msg[], int num)
+{
+ struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+ u16 apb_address = 0, word;
+ int i = 0;
+
+ switch (msg[0].buf[0]) {
+ case 0x12:
+ apb_address = 1920;
+ break;
+ case 0x14:
+ apb_address = 1921;
+ break;
+ case 0x24:
+ apb_address = 1922;
+ break;
+ case 0x1a:
+ apb_address = 1923;
+ break;
+ case 0x22:
+ apb_address = 1924;
+ break;
+ case 0x33:
+ apb_address = 1926;
+ break;
+ case 0x34:
+ apb_address = 1927;
+ break;
+ case 0x35:
+ apb_address = 1928;
+ break;
+ case 0x36:
+ apb_address = 1929;
+ break;
+ case 0x37:
+ apb_address = 1930;
+ break;
+ case 0x38:
+ apb_address = 1931;
+ break;
+ case 0x39:
+ apb_address = 1932;
+ break;
+ case 0x2a:
+ apb_address = 1935;
+ break;
+ case 0x2b:
+ apb_address = 1936;
+ break;
+ case 0x2c:
+ apb_address = 1937;
+ break;
+ case 0x2d:
+ apb_address = 1938;
+ break;
+ case 0x2e:
+ apb_address = 1939;
+ break;
+ case 0x2f:
+ apb_address = 1940;
+ break;
+ case 0x30:
+ apb_address = 1941;
+ break;
+ case 0x31:
+ apb_address = 1942;
+ break;
+ case 0x32:
+ apb_address = 1943;
+ break;
+ case 0x3e:
+ apb_address = 1944;
+ break;
+ case 0x3f:
+ apb_address = 1945;
+ break;
+ case 0x40:
+ apb_address = 1948;
+ break;
+ case 0x25:
+ apb_address = 936;
+ break;
+ case 0x26:
+ apb_address = 937;
+ break;
+ case 0x27:
+ apb_address = 938;
+ break;
+ case 0x28:
+ apb_address = 939;
+ break;
+ case 0x1d:
+ /* get sad sel request */
+ i = ((dib8000_read_word(state, 921) >> 12)&0x3);
+ word = dib8000_read_word(state, 924+i);
+ msg[1].buf[0] = (word >> 8) & 0xff;
+ msg[1].buf[1] = (word) & 0xff;
+ return num;
+ case 0x1f:
+ if (num == 1) { /* write */
+ word = (u16) ((msg[0].buf[1] << 8) |
+ msg[0].buf[2]);
+ /* in the VGAMODE Sel are located on bit 0/1 */
+ word &= 0x3;
+ word = (dib8000_read_word(state, 921) &
+ ~(3<<12)) | (word<<12);
+ /* Set the proper input */
+ dib8000_write_word(state, 921, word);
+ return num;
+ }
+ }
+
+ if (apb_address != 0) /* R/W acces via APB */
+ return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
+ else /* R/W access via SERPAR */
+ return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
+
+ return 0;
+}
+
+static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
+ .master_xfer = dib8096p_tuner_xfer,
+ .functionality = dib8096p_i2c_func,
+};
+
+struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+ struct dib8000_state *st = fe->demodulator_priv;
+ return &st->dib8096p_tuner_adap;
+}
+EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
+
+int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+ u16 en_cur_state;
+
+ dprintk("sleep dib8096p: %d", onoff);
+
+ en_cur_state = dib8000_read_word(state, 1922);
+
+ /* LNAs and MIX are ON and therefore it is a valid configuration */
+ if (en_cur_state > 0xff)
+ state->tuner_enable = en_cur_state ;
+
+ if (onoff)
+ en_cur_state &= 0x00ff;
+ else {
+ if (state->tuner_enable != 0)
+ en_cur_state = state->tuner_enable;
+ }
+
+ dib8000_write_word(state, 1922, en_cur_state);
+
+ return 0;
+}
+EXPORT_SYMBOL(dib8096p_tuner_sleep);
+
static const s32 lut_1000ln_mant[] =
{
908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
@@ -1051,6 +1815,26 @@ s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
}
EXPORT_SYMBOL(dib8000_get_adc_power);
+int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+ int val = 0;
+
+ switch (IQ) {
+ case 1:
+ val = dib8000_read_word(state, 403);
+ break;
+ case 0:
+ val = dib8000_read_word(state, 404);
+ break;
+ }
+ if (val & 0x200)
+ val -= 1024;
+
+ return val;
+}
+EXPORT_SYMBOL(dib8090p_get_dc_power);
+
static void dib8000_update_timf(struct dib8000_state *state)
{
u32 timf = state->timf = dib8000_read32(state, 435);
@@ -1060,6 +1844,26 @@ static void dib8000_update_timf(struct dib8000_state *state)
dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
}
+u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+{
+ struct dib8000_state *state = fe->demodulator_priv;
+
+ switch (op) {
+ case DEMOD_TIMF_SET:
+ state->timf = timf;
+ break;
+ case DEMOD_TIMF_UPDATE:
+ dib8000_update_timf(state);
+ break;
+ case DEMOD_TIMF_GET:
+ break;
+ }
+ dib8000_set_bandwidth(state->fe[0], 6000);
+
+ return state->timf;
+}
+EXPORT_SYMBOL(dib8000_ctrl_timf);
+
static const u16 adc_target_16dB[11] = {
(1 << 13) - 825 - 117,
(1 << 13) - 837 - 117,
@@ -1086,6 +1890,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear
u16 init_prbs = 0xfff;
u16 ana_gain = 0;
+ if (state->revision == 0x8090)
+ dib8000_init_sdram(state);
+
if (state->ber_monitored_layer != LAYER_ALL)
dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
else
@@ -1418,7 +2225,10 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear
dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
state->differential_constellation = (seg_diff_mask != 0);
- dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+ if (state->revision != 0x8090)
+ dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+ else
+ dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff);
if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
@@ -1870,7 +2680,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
int ret = 0;
- u16 value, mode = fft_to_mode(state);
+ u16 lock, value, mode = fft_to_mode(state);
// we are already tuned - just resuming from suspend
if (state == NULL)
@@ -1924,7 +2734,11 @@ static int dib8000_tune(struct dvb_frontend *fe)
}
// we achieved a coff_cpil_lock - it's time to update the timf
- if ((dib8000_read_word(state, 568) >> 11) & 0x1)
+ if (state->revision != 0x8090)
+ lock = dib8000_read_word(state, 568);
+ else
+ lock = dib8000_read_word(state, 570);
+ if ((lock >> 11) & 0x1)
dib8000_update_timf(state);
//now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start
@@ -1946,11 +2760,14 @@ static int dib8000_wakeup(struct dvb_frontend *fe)
u8 index_frontend;
int ret;
- dib8000_set_power_mode(state, DIB8000M_POWER_ALL);
+ dib8000_set_power_mode(state, DIB8000_POWER_ALL);
dib8000_set_adc_state(state, DIBX000_ADC_ON);
if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
dprintk("could not start Slow ADC");
+ if (state->revision != 0x8090)
+ dib8000_sad_calib(state);
+
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
if (ret < 0)
@@ -1972,8 +2789,9 @@ static int dib8000_sleep(struct dvb_frontend *fe)
return ret;
}
- dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
- dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY);
+ if (state->revision != 0x8090)
+ dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
+ dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
}
@@ -1992,7 +2810,7 @@ int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tun
}
EXPORT_SYMBOL(dib8000_set_tune_state);
-static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib8000_get_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 i, val = 0;
@@ -2006,7 +2824,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
if (stat&FE_HAS_SYNC) {
dprintk("TMCC lock on the slave%i", index_frontend);
/* synchronize the cache with the other frontends */
- state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+ state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
if (sub_index_frontend != index_frontend) {
state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@@ -2028,7 +2846,10 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
- val = dib8000_read_word(state, 570);
+ if (state->revision == 0x8090)
+ val = dib8000_read_word(state, 572);
+ else
+ val = dib8000_read_word(state, 570);
fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
switch ((val & 0x30) >> 4) {
case 1:
@@ -2135,7 +2956,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
return 0;
}
-static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib8000_set_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
u8 nbr_pending, exit_condition, index_frontend;
@@ -2158,9 +2979,14 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
- dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
+ if (state->revision != 0x8090)
+ dib8000_set_output_mode(state->fe[index_frontend],
+ OUTMODE_HIGH_Z);
+ else
+ dib8096p_set_output_mode(state->fe[index_frontend],
+ OUTMODE_HIGH_Z);
if (state->fe[index_frontend]->ops.tuner_ops.set_params)
- state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend], fep);
+ state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
}
@@ -2215,7 +3041,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
- int i = 80000;
+ int i = 100;
u8 found = 0;
u8 tune_failed = 0;
@@ -2243,6 +3069,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
default:
dprintk("unhandled autosearch result");
case 1:
+ tune_failed |= (1 << index_frontend);
dprintk("autosearch failed for the frontend%i", index_frontend);
break;
}
@@ -2261,21 +3088,44 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
dprintk("tune success on frontend%i", index_frontend_success);
- dib8000_get_frontend(fe, fep);
+ dib8000_get_frontend(fe);
}
for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
ret = dib8000_tune(state->fe[index_frontend]);
/* set output mode and diversity input */
- dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
- for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
- dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
- dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
- }
+ if (state->revision != 0x8090) {
+ dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
+ for (index_frontend = 1;
+ (index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+ (state->fe[index_frontend] != NULL);
+ index_frontend++) {
+ dib8000_set_output_mode(state->fe[index_frontend],
+ OUTMODE_DIVERSITY);
+ dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
+ }
- /* turn off the diversity of the last chip */
- dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
+ /* turn off the diversity of the last chip */
+ dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
+ } else {
+ dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
+ if (state->cfg.enMpegOutput == 0) {
+ dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
+ dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+ }
+ for (index_frontend = 1;
+ (index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+ (state->fe[index_frontend] != NULL);
+ index_frontend++) {
+ dib8096p_set_output_mode(state->fe[index_frontend],
+ OUTMODE_DIVERSITY);
+ dib8096p_set_diversity_in(state->fe[index_frontend-1], 1);
+ }
+
+ /* turn off the diversity of the last chip */
+ dib8096p_set_diversity_in(state->fe[index_frontend-1], 0);
+ }
return ret;
}
@@ -2284,15 +3134,22 @@ static u16 dib8000_read_lock(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
+ if (state->revision == 0x8090)
+ return dib8000_read_word(state, 570);
return dib8000_read_word(state, 568);
}
static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
{
struct dib8000_state *state = fe->demodulator_priv;
- u16 lock_slave = 0, lock = dib8000_read_word(state, 568);
+ u16 lock_slave = 0, lock;
u8 index_frontend;
+ if (state->revision == 0x8090)
+ lock = dib8000_read_word(state, 570);
+ else
+ lock = dib8000_read_word(state, 568);
+
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
@@ -2330,14 +3187,26 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
{
struct dib8000_state *state = fe->demodulator_priv;
- *ber = (dib8000_read_word(state, 560) << 16) | dib8000_read_word(state, 561); // 13 segments
+
+ /* 13 segments */
+ if (state->revision == 0x8090)
+ *ber = (dib8000_read_word(state, 562) << 16) |
+ dib8000_read_word(state, 563);
+ else
+ *ber = (dib8000_read_word(state, 560) << 16) |
+ dib8000_read_word(state, 561);
return 0;
}
static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
{
struct dib8000_state *state = fe->demodulator_priv;
- *unc = dib8000_read_word(state, 565); // packet error on 13 seg
+
+ /* packet error on 13 seg */
+ if (state->revision == 0x8090)
+ *unc = dib8000_read_word(state, 567);
+ else
+ *unc = dib8000_read_word(state, 565);
return 0;
}
@@ -2370,14 +3239,20 @@ static u32 dib8000_get_snr(struct dvb_frontend *fe)
u32 n, s, exp;
u16 val;
- val = dib8000_read_word(state, 542);
+ if (state->revision != 0x8090)
+ val = dib8000_read_word(state, 542);
+ else
+ val = dib8000_read_word(state, 544);
n = (val >> 6) & 0xff;
exp = (val & 0x3f);
if ((exp & 0x20) != 0)
exp -= 0x40;
n <<= exp+16;
- val = dib8000_read_word(state, 543);
+ if (state->revision != 0x8090)
+ val = dib8000_read_word(state, 543);
+ else
+ val = dib8000_read_word(state, 545);
s = (val >> 6) & 0xff;
exp = (val & 0x3f);
if ((exp & 0x20) != 0)
@@ -2401,7 +3276,7 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
snr_master += dib8000_get_snr(state->fe[index_frontend]);
- if (snr_master != 0) {
+ if ((snr_master >> 16) != 0) {
snr_master = 10*intlog10(snr_master>>16);
*snr = snr_master / ((1 << 24) / 10);
}
@@ -2458,7 +3333,8 @@ struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int sla
EXPORT_SYMBOL(dib8000_get_slave_frontend);
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+ u8 default_addr, u8 first_addr, u8 is_dib8096p)
{
int k = 0, ret = 0;
u8 new_addr = 0;
@@ -2488,9 +3364,12 @@ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 defau
new_addr = first_addr + (k << 1);
client.addr = new_addr;
- dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */
- if (dib8000_identify(&client) == 0) {
+ if (!is_dib8096p)
dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */
+ if (dib8000_identify(&client) == 0) {
+ /* sram lead in, rdy */
+ if (!is_dib8096p)
+ dib8000_i2c_write16(&client, 1287, 0x0003);
client.addr = default_addr;
if (dib8000_identify(&client) == 0) {
dprintk("#%d: not identified", k);
@@ -2549,6 +3428,7 @@ static void dib8000_release(struct dvb_frontend *fe)
dvb_frontend_detach(st->fe[index_frontend]);
dibx000_exit_i2c_master(&st->i2c_master);
+ i2c_del_adapter(&st->dib8096p_tuner_adap);
kfree(st->fe[0]);
kfree(st);
}
@@ -2581,9 +3461,9 @@ int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
EXPORT_SYMBOL(dib8000_pid_filter);
static const struct dvb_frontend_ops dib8000_ops = {
+ .delsys = { SYS_ISDBT },
.info = {
.name = "DiBcom 8000 ISDB-T",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
@@ -2651,6 +3531,15 @@ struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, s
dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
+ /* init 8096p tuner adapter */
+ strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
+ sizeof(state->dib8096p_tuner_adap.name));
+ state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
+ state->dib8096p_tuner_adap.algo_data = NULL;
+ state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
+ i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
+ i2c_add_adapter(&state->dib8096p_tuner_adap);
+
dib8000_reset(fe);
dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h
index 617f9eb..39591bb 100644
--- a/drivers/media/dvb/frontends/dib8000.h
+++ b/drivers/media/dvb/frontends/dib8000.h
@@ -32,6 +32,7 @@ struct dib8000_config {
u8 div_cfg;
u8 output_mode;
u8 refclksel;
+ u8 enMpegOutput:1;
};
#define DEFAULT_DIB8000_I2C_ADDRESS 18
@@ -40,7 +41,8 @@ struct dib8000_config {
extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
+extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+ u8 default_addr, u8 first_addr, u8 is_dib8096p);
extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
@@ -50,6 +52,13 @@ extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_st
extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
+extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
+extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
+extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
+extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+ uint8_t op, uint32_t timf);
+extern int dib8000_update_pll(struct dvb_frontend *fe,
+ struct dibx000_bandwidth_config *pll);
extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
@@ -66,7 +75,9 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe
return NULL;
}
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
+ int no_of_demods, u8 default_addr, u8 first_addr,
+ u8 is_dib8096p)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
@@ -109,11 +120,38 @@ static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
+static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return 0;
+}
static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
+static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return 0;
+}
+static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+ uint8_t op, uint32_t timf)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return 0;
+}
+static inline int dib8000_update_pll(struct dvb_frontend *fe,
+ struct dibx000_bandwidth_config *pll)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
index 660f806..863ef3c 100644
--- a/drivers/media/dvb/frontends/dib9000.c
+++ b/drivers/media/dvb/frontends/dib9000.c
@@ -1136,7 +1136,7 @@ static int dib9000_fw_init(struct dib9000_state *state)
return 0;
}
-static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_frontend_parameters *ch)
+static void dib9000_fw_set_channel_head(struct dib9000_state *state)
{
u8 b[9];
u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
@@ -1157,7 +1157,7 @@ static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_
dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
}
-static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+static int dib9000_fw_get_channel(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
struct dibDVBTChannel {
@@ -1309,7 +1309,7 @@ error:
return ret;
}
-static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
struct dibDVBTChannel {
@@ -1454,7 +1454,7 @@ static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_fron
return 0;
}
-static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+static int dib9000_fw_tune(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
@@ -1462,7 +1462,7 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
switch (state->tune_state) {
case CT_DEMOD_START:
- dib9000_fw_set_channel_head(state, ch);
+ dib9000_fw_set_channel_head(state);
/* write the channel context - a channel is initialized to 0, so it is OK */
dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
@@ -1471,7 +1471,7 @@ static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_paramete
if (search)
dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
else {
- dib9000_fw_set_channel_union(fe, ch);
+ dib9000_fw_set_channel_union(fe);
dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
}
state->tune_state = CT_DEMOD_STEP_1;
@@ -1867,7 +1867,7 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron
return 0;
}
-static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib9000_get_frontend(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend, sub_index_frontend;
@@ -1883,7 +1883,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
dprintk("TPS lock on the slave%i", index_frontend);
/* synchronize the cache with the other frontends */
- state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+ state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
sub_index_frontend++) {
if (sub_index_frontend != index_frontend) {
@@ -1911,7 +1911,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
}
/* get the channel from master chip */
- ret = dib9000_fw_get_channel(fe, fep);
+ ret = dib9000_fw_get_channel(fe);
if (ret != 0)
goto return_value;
@@ -1958,7 +1958,7 @@ static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_fronte
return 0;
}
-static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int dib9000_set_frontend(struct dvb_frontend *fe)
{
struct dib9000_state *state = fe->demodulator_priv;
int sleep_time, sleep_time_slave;
@@ -1983,8 +1983,10 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
fe->dtv_property_cache.delivery_system = SYS_DVBT;
/* set the master status */
- if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
- fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
+ state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
+ state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
+ state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
/* no channel specified, autosearch the channel */
state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
} else
@@ -2008,9 +2010,9 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
index_frontend_success = 0;
do {
- sleep_time = dib9000_fw_tune(state->fe[0], NULL);
+ sleep_time = dib9000_fw_tune(state->fe[0]);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
- sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+ sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
if (sleep_time == FE_CALLBACK_TIME_NEVER)
sleep_time = sleep_time_slave;
else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
@@ -2052,7 +2054,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
/* synchronize all the channel cache */
state->get_frontend_internal = 1;
- dib9000_get_frontend(state->fe[0], fep);
+ dib9000_get_frontend(state->fe[0]);
state->get_frontend_internal = 0;
/* retune the other frontends with the found channel */
@@ -2068,7 +2070,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
sleep_time = FE_CALLBACK_TIME_NEVER;
for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
if (index_frontend != index_frontend_success) {
- sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+ sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
if (sleep_time == FE_CALLBACK_TIME_NEVER)
sleep_time = sleep_time_slave;
else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
@@ -2495,9 +2497,9 @@ error:
EXPORT_SYMBOL(dib9000_attach);
static struct dvb_frontend_ops dib9000_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "DiBcom 9000",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index 5e01147..5f48488 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -146,14 +146,8 @@ enum dibx000_adc_states {
DIBX000_VBG_DISABLE,
};
-#define BANDWIDTH_TO_KHZ(v) ((v) == BANDWIDTH_8_MHZ ? 8000 : \
- (v) == BANDWIDTH_7_MHZ ? 7000 : \
- (v) == BANDWIDTH_6_MHZ ? 6000 : 8000)
-
-#define BANDWIDTH_TO_INDEX(v) ( \
- (v) == 8000 ? BANDWIDTH_8_MHZ : \
- (v) == 7000 ? BANDWIDTH_7_MHZ : \
- (v) == 6000 ? BANDWIDTH_6_MHZ : BANDWIDTH_8_MHZ )
+#define BANDWIDTH_TO_KHZ(v) ((v) / 1000)
+#define BANDWIDTH_TO_HZ(v) ((v) * 1000)
/* Chip output mode. */
#define OUTMODE_HIGH_Z 0
@@ -276,4 +270,11 @@ struct dibSubbandSelection {
#define DEMOD_TIMF_GET 0x01
#define DEMOD_TIMF_UPDATE 0x02
+#define MPEG_ON_DIBTX 1
+#define DIV_ON_DIBTX 2
+#define ADC_ON_DIBTX 3
+#define DEMOUT_ON_HOSTBUS 4
+#define DIBTX_ON_HOSTBUS 5
+#define MPEG_ON_HOSTBUS 6
+
#endif
diff --git a/drivers/media/dvb/frontends/drxd.h b/drivers/media/dvb/frontends/drxd.h
index 7113535..3439873 100644
--- a/drivers/media/dvb/frontends/drxd.h
+++ b/drivers/media/dvb/frontends/drxd.h
@@ -48,8 +48,6 @@ struct drxd_config {
u8 disable_i2c_gate_ctrl;
u32 IF;
- int (*pll_set) (void *priv, void *priv_params,
- u8 pll_addr, u8 demoda_addr, s32 *off);
s16(*osc_deviation) (void *priv, s16 dev, int flag);
};
diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c
index 88e46f4..7bf39cd 100644
--- a/drivers/media/dvb/frontends/drxd_hard.c
+++ b/drivers/media/dvb/frontends/drxd_hard.c
@@ -120,7 +120,7 @@ enum EIFFilter {
struct drxd_state {
struct dvb_frontend frontend;
struct dvb_frontend_ops ops;
- struct dvb_frontend_parameters param;
+ struct dtv_frontend_properties props;
const struct firmware *fw;
struct device *dev;
@@ -914,14 +914,13 @@ static int load_firmware(struct drxd_state *state, const char *fw_name)
return -EIO;
}
- state->microcode = kmalloc(fw->size, GFP_KERNEL);
+ state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
if (state->microcode == NULL) {
release_firmware(fw);
printk(KERN_ERR "drxd: firmware load failure: no memory\n");
return -ENOMEM;
}
- memcpy(state->microcode, fw->data, fw->size);
state->microcode_length = fw->size;
release_firmware(fw);
return 0;
@@ -1622,14 +1621,14 @@ static int CorrectSysClockDeviation(struct drxd_state *state)
break;
}
- switch (state->param.u.ofdm.bandwidth) {
- case BANDWIDTH_8_MHZ:
+ switch (state->props.bandwidth_hz) {
+ case 8000000:
bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
break;
- case BANDWIDTH_6_MHZ:
+ case 6000000:
bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
break;
default:
@@ -1804,7 +1803,7 @@ static int StartDiversity(struct drxd_state *state)
status = WriteTable(state, state->m_StartDiversityEnd);
if (status < 0)
break;
- if (state->param.u.ofdm.bandwidth == BANDWIDTH_8_MHZ) {
+ if (state->props.bandwidth_hz == 8000000) {
status = WriteTable(state, state->m_DiversityDelay8MHZ);
if (status < 0)
break;
@@ -1906,7 +1905,7 @@ static int SetCfgNoiseCalibration(struct drxd_state *state,
static int DRX_Start(struct drxd_state *state, s32 off)
{
- struct dvb_ofdm_parameters *p = &state->param.u.ofdm;
+ struct dtv_frontend_properties *p = &state->props;
int status;
u16 transmissionParams = 0;
@@ -1971,7 +1970,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
if (status < 0)
break;
- mirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+ mirrorFreqSpect = (state->props.inversion == INVERSION_ON);
switch (p->transmission_mode) {
default: /* Not set, detect it automatically */
@@ -2021,7 +2020,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
break;
}
- switch (p->hierarchy_information) {
+ switch (p->hierarchy) {
case HIERARCHY_1:
transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1;
if (state->type_A) {
@@ -2147,7 +2146,7 @@ static int DRX_Start(struct drxd_state *state, s32 off)
if (status < 0)
break;
- switch (p->constellation) {
+ switch (p->modulation) {
default:
operationMode |= SC_RA_RAM_OP_AUTO_CONST__M;
/* fall through , try first guess
@@ -2331,9 +2330,11 @@ static int DRX_Start(struct drxd_state *state, s32 off)
by SC for fix for some 8K,1/8 guard but is restored by
InitEC and ResetEC
functions */
- switch (p->bandwidth) {
- case BANDWIDTH_AUTO:
- case BANDWIDTH_8_MHZ:
+ switch (p->bandwidth_hz) {
+ case 0:
+ p->bandwidth_hz = 8000000;
+ /* fall through */
+ case 8000000:
/* (64/7)*(8/8)*1000000 */
bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
@@ -2341,14 +2342,14 @@ static int DRX_Start(struct drxd_state *state, s32 off)
status = Write16(state,
FE_AG_REG_IND_DEL__A, 50, 0x0000);
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
/* (64/7)*(7/8)*1000000 */
bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
bandwidthParam = 0x4807; /*binary:0100 1000 0000 0111 */
status = Write16(state,
FE_AG_REG_IND_DEL__A, 59, 0x0000);
break;
- case BANDWIDTH_6_MHZ:
+ case 6000000:
/* (64/7)*(6/8)*1000000 */
bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
bandwidthParam = 0x0F07; /*binary: 0000 1111 0000 0111 */
@@ -2887,41 +2888,26 @@ static int drxd_sleep(struct dvb_frontend *fe)
return 0;
}
-static int drxd_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
-{
- return 0;
-}
-
static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
return drxd_config_i2c(fe, enable);
}
-static int drxd_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int drxd_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct drxd_state *state = fe->demodulator_priv;
s32 off = 0;
- state->param = *param;
+ state->props = *p;
DRX_Stop(state);
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
- /* FIXME: move PLL drivers */
- if (state->config.pll_set &&
- state->config.pll_set(state->priv, param,
- state->config.pll_address,
- state->config.demoda_address, &off) < 0) {
- printk(KERN_ERR "Error in pll_set\n");
- return -1;
- }
-
msleep(200);
return DRX_Start(state, off);
@@ -2935,10 +2921,9 @@ static void drxd_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops drxd_ops = {
-
+ .delsys = { SYS_DVBT},
.info = {
.name = "Micronas DRXD DVB-T",
- .type = FE_OFDM,
.frequency_min = 47125000,
.frequency_max = 855250000,
.frequency_stepsize = 166667,
@@ -2958,7 +2943,6 @@ static struct dvb_frontend_ops drxd_ops = {
.i2c_gate_ctrl = drxd_i2c_gate_ctrl,
.set_frontend = drxd_set_frontend,
- .get_frontend = drxd_get_frontend,
.get_tune_settings = drxd_get_tune_settings,
.read_status = drxd_read_status,
diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h
index 58baf41..0209818 100644
--- a/drivers/media/dvb/frontends/drxk.h
+++ b/drivers/media/dvb/frontends/drxk.h
@@ -8,6 +8,8 @@
* struct drxk_config - Configure the initial parameters for DRX-K
*
* adr: I2C Address of the DRX-K
+ * parallel_ts: true means that the device uses parallel TS,
+ * Serial otherwise.
* single_master: Device is on the single master mode
* no_i2c_bridge: Don't switch the I2C bridge to talk with tuner
* antenna_gpio: GPIO bit used to control the antenna
@@ -22,22 +24,23 @@ struct drxk_config {
u8 adr;
bool single_master;
bool no_i2c_bridge;
+ bool parallel_ts;
bool antenna_dvbt;
u16 antenna_gpio;
+ int chunk_size;
+
const char *microcode_name;
};
#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
&& defined(MODULE))
extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend **fe_t);
+ struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend *drxk_attach(const struct drxk_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend **fe_t)
+ struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index f6431ef..6980ed7 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -368,10 +368,10 @@ static int i2c_read(struct i2c_adapter *adap,
}
if (debug > 2) {
int i;
- dprintk(2, ": read from ");
+ dprintk(2, ": read from");
for (i = 0; i < len; i++)
printk(KERN_CONT " %02x", msg[i]);
- printk(KERN_CONT "Value = ");
+ printk(KERN_CONT ", value = ");
for (i = 0; i < alen; i++)
printk(KERN_CONT " %02x", answ[i]);
printk(KERN_CONT "\n");
@@ -660,7 +660,6 @@ static int init_state(struct drxk_state *state)
/* io_pad_cfg_mode output mode is drive always */
/* io_pad_cfg_drive is set to power 2 (23 mA) */
u32 ulGPIOCfg = 0x0113;
- u32 ulSerialMode = 1;
u32 ulInvertTSClock = 0;
u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
u32 ulTSClockkStrength = DRXK_MPEG_OUTPUT_CLK_DRIVE_STRENGTH;
@@ -681,7 +680,8 @@ static int init_state(struct drxk_state *state)
state->m_hasOOB = false;
state->m_hasAudio = false;
- state->m_ChunkSize = 124;
+ if (!state->m_ChunkSize)
+ state->m_ChunkSize = 124;
state->m_oscClockFreq = 0;
state->m_smartAntInverted = false;
@@ -810,8 +810,6 @@ static int init_state(struct drxk_state *state)
/* MPEG output configuration */
state->m_enableMPEGOutput = true; /* If TRUE; enable MPEG ouput */
state->m_insertRSByte = false; /* If TRUE; insert RS byte */
- state->m_enableParallel = true; /* If TRUE;
- parallel out otherwise serial */
state->m_invertDATA = false; /* If TRUE; invert DATA signals */
state->m_invertERR = false; /* If TRUE; invert ERR signal */
state->m_invertSTR = false; /* If TRUE; invert STR signals */
@@ -856,8 +854,6 @@ static int init_state(struct drxk_state *state)
state->m_bPowerDown = false;
state->m_currentPowerMode = DRX_POWER_DOWN;
- state->m_enableParallel = (ulSerialMode == 0);
-
state->m_rfmirror = (ulRfMirror == 0);
state->m_IfAgcPol = false;
return 0;
@@ -946,6 +942,9 @@ static int GetDeviceCapabilities(struct drxk_state *state)
status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo);
if (status < 0)
goto error;
+
+printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo);
+
/* driver 0.9.0 */
switch ((sioTopJtagidLo >> 29) & 0xF) {
case 0:
@@ -963,7 +962,8 @@ static int GetDeviceCapabilities(struct drxk_state *state)
default:
state->m_deviceSpin = DRXK_SPIN_UNKNOWN;
status = -EINVAL;
- printk(KERN_ERR "drxk: Spin unknown\n");
+ printk(KERN_ERR "drxk: Spin %d unknown\n",
+ (sioTopJtagidLo >> 29) & 0xF);
goto error2;
}
switch ((sioTopJtagidLo >> 12) & 0xFF) {
@@ -1190,7 +1190,9 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
u16 sioPdrMclkCfg = 0;
u16 sioPdrMdxCfg = 0;
- dprintk(1, "\n");
+ dprintk(1, ": mpeg %s, %s mode\n",
+ mpegEnable ? "enable" : "disable",
+ state->m_enableParallel ? "parallel" : "serial");
/* stop lock indicator process */
status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
@@ -1846,6 +1848,7 @@ static int SetOperationMode(struct drxk_state *state,
*/
switch (oMode) {
case OM_DVBT:
+ dprintk(1, ": DVB-T\n");
state->m_OperationMode = oMode;
status = SetDVBTStandard(state, oMode);
if (status < 0)
@@ -1853,6 +1856,8 @@ static int SetOperationMode(struct drxk_state *state,
break;
case OM_QAM_ITU_A: /* fallthrough */
case OM_QAM_ITU_C:
+ dprintk(1, ": DVB-C Annex %c\n",
+ (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C');
state->m_OperationMode = oMode;
status = SetQAMStandard(state, oMode);
if (status < 0)
@@ -1881,7 +1886,7 @@ static int Start(struct drxk_state *state, s32 offsetFreq,
state->m_DrxkState != DRXK_DTV_STARTED)
goto error;
- state->m_bMirrorFreqSpect = (state->param.inversion == INVERSION_ON);
+ state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON);
if (IntermediateFrequency < 0) {
state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect;
@@ -2503,7 +2508,7 @@ static int GetQAMSignalToNoise(struct drxk_state *state,
u16 qamSlErrPower = 0; /* accum. error between
raw and sliced symbols */
u32 qamSlSigPower = 0; /* used for MER, depends of
- QAM constellation */
+ QAM modulation */
u32 qamSlMer = 0; /* QAM MER */
dprintk(1, "\n");
@@ -2517,7 +2522,7 @@ static int GetQAMSignalToNoise(struct drxk_state *state,
return -EINVAL;
}
- switch (state->param.u.qam.modulation) {
+ switch (state->props.modulation) {
case QAM_16:
qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
break;
@@ -2748,7 +2753,7 @@ static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality)
if (status < 0)
break;
- switch (state->param.u.qam.modulation) {
+ switch (state->props.modulation) {
case QAM_16:
SignalToNoiseRel = SignalToNoise - 200;
break;
@@ -3813,7 +3818,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
/*== Write channel settings to device =====================================*/
/* mode */
- switch (state->param.u.ofdm.transmission_mode) {
+ switch (state->props.transmission_mode) {
case TRANSMISSION_MODE_AUTO:
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
@@ -3827,7 +3832,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
}
/* guard */
- switch (state->param.u.ofdm.guard_interval) {
+ switch (state->props.guard_interval) {
default:
case GUARD_INTERVAL_AUTO:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
@@ -3847,7 +3852,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
}
/* hierarchy */
- switch (state->param.u.ofdm.hierarchy_information) {
+ switch (state->props.hierarchy) {
case HIERARCHY_AUTO:
case HIERARCHY_NONE:
default:
@@ -3867,8 +3872,8 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
}
- /* constellation */
- switch (state->param.u.ofdm.constellation) {
+ /* modulation */
+ switch (state->props.modulation) {
case QAM_AUTO:
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
@@ -3911,7 +3916,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
#endif
/* coderate */
- switch (state->param.u.ofdm.code_rate_HP) {
+ switch (state->props.code_rate_HP) {
case FEC_AUTO:
default:
operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
@@ -3940,9 +3945,11 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
/* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
functions */
- switch (state->param.u.ofdm.bandwidth) {
- case BANDWIDTH_AUTO:
- case BANDWIDTH_8_MHZ:
+ switch (state->props.bandwidth_hz) {
+ case 0:
+ state->props.bandwidth_hz = 8000000;
+ /* fall though */
+ case 8000000:
bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
if (status < 0)
@@ -3961,7 +3968,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
if (status < 0)
goto error;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
if (status < 0)
@@ -3980,7 +3987,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
if (status < 0)
goto error;
break;
- case BANDWIDTH_6_MHZ:
+ case 6000000:
bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
if (status < 0)
@@ -4187,7 +4194,7 @@ error:
/**
* \brief Setup of the QAM Measurement intervals for signal quality
* \param demod instance of demod.
-* \param constellation current constellation.
+* \param modulation current modulation.
* \return DRXStatus_t.
*
* NOTE:
@@ -4196,7 +4203,7 @@ error:
*
*/
static int SetQAMMeasurement(struct drxk_state *state,
- enum EDrxkConstellation constellation,
+ enum EDrxkConstellation modulation,
u32 symbolRate)
{
u32 fecBitsDesired = 0; /* BER accounting period */
@@ -4210,11 +4217,11 @@ static int SetQAMMeasurement(struct drxk_state *state,
fecRsPrescale = 1;
/* fecBitsDesired = symbolRate [kHz] *
FrameLenght [ms] *
- (constellation + 1) *
+ (modulation + 1) *
SyncLoss (== 1) *
ViterbiLoss (==1)
*/
- switch (constellation) {
+ switch (modulation) {
case DRX_CONSTELLATION_QAM16:
fecBitsDesired = 4 * symbolRate;
break;
@@ -5281,12 +5288,12 @@ static int QAMSetSymbolrate(struct drxk_state *state)
/* Select & calculate correct IQM rate */
adcFrequency = (state->m_sysClockFreq * 1000) / 3;
ratesel = 0;
- /* printk(KERN_DEBUG "drxk: SR %d\n", state->param.u.qam.symbol_rate); */
- if (state->param.u.qam.symbol_rate <= 1188750)
+ /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */
+ if (state->props.symbol_rate <= 1188750)
ratesel = 3;
- else if (state->param.u.qam.symbol_rate <= 2377500)
+ else if (state->props.symbol_rate <= 2377500)
ratesel = 2;
- else if (state->param.u.qam.symbol_rate <= 4755000)
+ else if (state->props.symbol_rate <= 4755000)
ratesel = 1;
status = write16(state, IQM_FD_RATESEL__A, ratesel);
if (status < 0)
@@ -5295,7 +5302,7 @@ static int QAMSetSymbolrate(struct drxk_state *state)
/*
IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
*/
- symbFreq = state->param.u.qam.symbol_rate * (1 << ratesel);
+ symbFreq = state->props.symbol_rate * (1 << ratesel);
if (symbFreq == 0) {
/* Divide by zero */
status = -EINVAL;
@@ -5311,7 +5318,7 @@ static int QAMSetSymbolrate(struct drxk_state *state)
/*
LcSymbFreq = round (.125 * symbolrate / adcFreq * (1<<15))
*/
- symbFreq = state->param.u.qam.symbol_rate;
+ symbFreq = state->props.symbol_rate;
if (adcFrequency == 0) {
/* Divide by zero */
status = -EINVAL;
@@ -5412,7 +5419,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
goto error;
/* Set params */
- switch (state->param.u.qam.modulation) {
+ switch (state->props.modulation) {
case QAM_256:
state->m_Constellation = DRX_CONSTELLATION_QAM256;
break;
@@ -5435,7 +5442,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
}
if (status < 0)
goto error;
- setParamParameters[0] = state->m_Constellation; /* constellation */
+ setParamParameters[0] = state->m_Constellation; /* modulation */
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
if (state->m_OperationMode == OM_QAM_ITU_C)
setParamParameters[2] = QAM_TOP_ANNEX_C;
@@ -5457,7 +5464,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
if (status < 0)
goto error;
- setParamParameters[0] = state->m_Constellation; /* constellation */
+ setParamParameters[0] = state->m_Constellation; /* modulation */
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
}
@@ -5466,7 +5473,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
/*
* STEP 3: enable the system in a mode where the ADC provides valid
- * signal setup constellation independent registers
+ * signal setup modulation independent registers
*/
#if 0
status = SetFrequency(channel, tunerFreqOffset));
@@ -5478,7 +5485,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
goto error;
/* Setup BER measurement */
- status = SetQAMMeasurement(state, state->m_Constellation, state->param.u. qam.symbol_rate);
+ status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate);
if (status < 0)
goto error;
@@ -5560,8 +5567,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
if (status < 0)
goto error;
- /* STEP 4: constellation specific setup */
- switch (state->param.u.qam.modulation) {
+ /* STEP 4: modulation specific setup */
+ switch (state->props.modulation) {
case QAM_16:
status = SetQAM16(state);
break;
@@ -5591,7 +5598,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
goto error;
/* Re-configure MPEG output, requires knowledge of channel bitrate */
- /* extAttr->currentChannel.constellation = channel->constellation; */
+ /* extAttr->currentChannel.modulation = channel->modulation; */
/* extAttr->currentChannel.symbolrate = channel->symbolrate; */
status = MPEGTSDtoSetup(state, state->m_OperationMode);
if (status < 0)
@@ -6167,7 +6174,7 @@ error:
return status;
}
-static void drxk_c_release(struct dvb_frontend *fe)
+static void drxk_release(struct dvb_frontend *fe)
{
struct drxk_state *state = fe->demodulator_priv;
@@ -6175,24 +6182,12 @@ static void drxk_c_release(struct dvb_frontend *fe)
kfree(state);
}
-static int drxk_c_init(struct dvb_frontend *fe)
-{
- struct drxk_state *state = fe->demodulator_priv;
-
- dprintk(1, "\n");
- if (mutex_trylock(&state->ctlock) == 0)
- return -EBUSY;
- SetOperationMode(state, OM_QAM_ITU_A);
- return 0;
-}
-
-static int drxk_c_sleep(struct dvb_frontend *fe)
+static int drxk_sleep(struct dvb_frontend *fe)
{
struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n");
ShutDown(state);
- mutex_unlock(&state->ctlock);
return 0;
}
@@ -6204,9 +6199,10 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
return ConfigureI2CBridge(state, enable ? true : false);
}
-static int drxk_set_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int drxk_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ u32 delsys = p->delivery_system, old_delsys;
struct drxk_state *state = fe->demodulator_priv;
u32 IF;
@@ -6218,14 +6214,39 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
return -EINVAL;
}
-
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
- state->param = *p;
+
+ old_delsys = state->props.delivery_system;
+ state->props = *p;
+
+ if (old_delsys != delsys) {
+ ShutDown(state);
+ switch (delsys) {
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ if (!state->m_hasDVBC)
+ return -EINVAL;
+ state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false;
+ if (state->m_itut_annex_c)
+ SetOperationMode(state, OM_QAM_ITU_C);
+ else
+ SetOperationMode(state, OM_QAM_ITU_A);
+ break;
+ case SYS_DVBT:
+ if (!state->m_hasDVBT)
+ return -EINVAL;
+ SetOperationMode(state, OM_DVBT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
fe->ops.tuner_ops.get_if_frequency(fe, &IF);
Start(state, 0, IF);
@@ -6234,13 +6255,6 @@ static int drxk_set_parameters(struct dvb_frontend *fe,
return 0;
}
-static int drxk_c_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
-{
- dprintk(1, "\n");
- return 0;
-}
-
static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct drxk_state *state = fe->demodulator_priv;
@@ -6300,102 +6314,54 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-static int drxk_c_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
+static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
*sets)
{
- dprintk(1, "\n");
- sets->min_delay_ms = 3000;
- sets->max_drift = 0;
- sets->step_size = 0;
- return 0;
-}
-
-static void drxk_t_release(struct dvb_frontend *fe)
-{
- /*
- * There's nothing to release here, as the state struct
- * is already freed by drxk_c_release.
- */
-}
-
-static int drxk_t_init(struct dvb_frontend *fe)
-{
- struct drxk_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
dprintk(1, "\n");
- if (mutex_trylock(&state->ctlock) == 0)
- return -EBUSY;
- SetOperationMode(state, OM_DVBT);
- return 0;
-}
-
-static int drxk_t_sleep(struct dvb_frontend *fe)
-{
- struct drxk_state *state = fe->demodulator_priv;
-
- dprintk(1, "\n");
- mutex_unlock(&state->ctlock);
- return 0;
-}
-
-static int drxk_t_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
-{
- dprintk(1, "\n");
-
- return 0;
+ switch (p->delivery_system) {
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ sets->min_delay_ms = 3000;
+ sets->max_drift = 0;
+ sets->step_size = 0;
+ return 0;
+ default:
+ /*
+ * For DVB-T, let it use the default DVB core way, that is:
+ * fepriv->step_size = fe->ops.info.frequency_stepsize * 2
+ */
+ return -EINVAL;
+ }
}
-static struct dvb_frontend_ops drxk_c_ops = {
+static struct dvb_frontend_ops drxk_ops = {
+ /* .delsys will be filled dynamically */
.info = {
- .name = "DRXK DVB-C",
- .type = FE_QAM,
- .frequency_stepsize = 62500,
- .frequency_min = 47000000,
- .frequency_max = 862000000,
- .symbol_rate_min = 870000,
- .symbol_rate_max = 11700000,
- .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
- FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
- .release = drxk_c_release,
- .init = drxk_c_init,
- .sleep = drxk_c_sleep,
+ .name = "DRXK",
+ .frequency_min = 47000000,
+ .frequency_max = 865000000,
+ /* For DVB-C */
+ .symbol_rate_min = 870000,
+ .symbol_rate_max = 11700000,
+ /* For DVB-T */
+ .frequency_stepsize = 166667,
+
+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_MUTE_TS |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
+ },
+
+ .release = drxk_release,
+ .sleep = drxk_sleep,
.i2c_gate_ctrl = drxk_gate_ctrl,
.set_frontend = drxk_set_parameters,
- .get_frontend = drxk_c_get_frontend,
- .get_tune_settings = drxk_c_get_tune_settings,
-
- .read_status = drxk_read_status,
- .read_ber = drxk_read_ber,
- .read_signal_strength = drxk_read_signal_strength,
- .read_snr = drxk_read_snr,
- .read_ucblocks = drxk_read_ucblocks,
-};
-
-static struct dvb_frontend_ops drxk_t_ops = {
- .info = {
- .name = "DRXK DVB-T",
- .type = FE_OFDM,
- .frequency_min = 47125000,
- .frequency_max = 865000000,
- .frequency_stepsize = 166667,
- .frequency_tolerance = 0,
- .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
- FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
- FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 |
- FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO |
- FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
- .release = drxk_t_release,
- .init = drxk_t_init,
- .sleep = drxk_t_sleep,
- .i2c_gate_ctrl = drxk_gate_ctrl,
-
- .set_frontend = drxk_set_parameters,
- .get_frontend = drxk_t_get_frontend,
+ .get_tune_settings = drxk_get_tune_settings,
.read_status = drxk_read_status,
.read_ber = drxk_read_ber,
@@ -6405,9 +6371,10 @@ static struct dvb_frontend_ops drxk_t_ops = {
};
struct dvb_frontend *drxk_attach(const struct drxk_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend **fe_t)
+ struct i2c_adapter *i2c)
{
+ int n;
+
struct drxk_state *state = NULL;
u8 adr = config->adr;
@@ -6423,6 +6390,12 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
state->no_i2c_bridge = config->no_i2c_bridge;
state->antenna_gpio = config->antenna_gpio;
state->antenna_dvbt = config->antenna_dvbt;
+ state->m_ChunkSize = config->chunk_size;
+
+ if (config->parallel_ts)
+ state->m_enableParallel = true;
+ else
+ state->m_enableParallel = false;
/* NOTE: as more UIO bits will be used, add them to the mask */
state->UIO_mask = config->antenna_gpio;
@@ -6434,21 +6407,30 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
state->m_GPIO &= ~state->antenna_gpio;
mutex_init(&state->mutex);
- mutex_init(&state->ctlock);
- memcpy(&state->c_frontend.ops, &drxk_c_ops,
- sizeof(struct dvb_frontend_ops));
- memcpy(&state->t_frontend.ops, &drxk_t_ops,
- sizeof(struct dvb_frontend_ops));
- state->c_frontend.demodulator_priv = state;
- state->t_frontend.demodulator_priv = state;
+ memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
+ state->frontend.demodulator_priv = state;
init_state(state);
if (init_drxk(state) < 0)
goto error;
- *fe_t = &state->t_frontend;
- return &state->c_frontend;
+ /* Initialize the supported delivery systems */
+ n = 0;
+ if (state->m_hasDVBC) {
+ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
+ state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
+ strlcat(state->frontend.ops.info.name, " DVB-C",
+ sizeof(state->frontend.ops.info.name));
+ }
+ if (state->m_hasDVBT) {
+ state->frontend.ops.delsys[n++] = SYS_DVBT;
+ strlcat(state->frontend.ops.info.name, " DVB-T",
+ sizeof(state->frontend.ops.info.name));
+ }
+
+ printk(KERN_INFO "drxk: frontend initialized.\n");
+ return &state->frontend;
error:
printk(KERN_ERR "drxk: not found\n");
diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h
index a05c32e..3a58b73 100644
--- a/drivers/media/dvb/frontends/drxk_hard.h
+++ b/drivers/media/dvb/frontends/drxk_hard.h
@@ -195,9 +195,8 @@ struct DRXKOfdmScCmd_t {
};
struct drxk_state {
- struct dvb_frontend c_frontend;
- struct dvb_frontend t_frontend;
- struct dvb_frontend_parameters param;
+ struct dvb_frontend frontend;
+ struct dtv_frontend_properties props;
struct device *dev;
struct i2c_adapter *i2c;
@@ -205,7 +204,6 @@ struct drxk_state {
void *priv;
struct mutex mutex;
- struct mutex ctlock;
u32 m_Instance; /**< Channel 1,2,3 or 4 */
@@ -263,6 +261,8 @@ struct drxk_state {
u8 m_TSDataStrength;
u8 m_TSClockkStrength;
+ bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */
+
enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width */
u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case
static clockrate is selected */
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
index 90bf573..9387770 100644
--- a/drivers/media/dvb/frontends/ds3000.c
+++ b/drivers/media/dvb/frontends/ds3000.c
@@ -934,20 +934,6 @@ error2:
}
EXPORT_SYMBOL(ds3000_attach);
-static int ds3000_set_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
-static int ds3000_get_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
s32 carrier_offset_khz)
{
@@ -967,8 +953,7 @@ static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
return 0;
}
-static int ds3000_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int ds3000_set_frontend(struct dvb_frontend *fe)
{
struct ds3000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -994,15 +979,15 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
div4 = 0;
/* calculate and set freq divider */
- if (p->frequency < 1146000) {
+ if (c->frequency < 1146000) {
ds3000_tuner_writereg(state, 0x10, 0x11);
div4 = 1;
- ndiv = ((p->frequency * (6 + 8) * 4) +
+ ndiv = ((c->frequency * (6 + 8) * 4) +
(DS3000_XTAL_FREQ / 2)) /
DS3000_XTAL_FREQ - 1024;
} else {
ds3000_tuner_writereg(state, 0x10, 0x01);
- ndiv = ((p->frequency * (6 + 8) * 2) +
+ ndiv = ((c->frequency * (6 + 8) * 2) +
(DS3000_XTAL_FREQ / 2)) /
DS3000_XTAL_FREQ - 1024;
}
@@ -1101,7 +1086,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
msleep(60);
offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ
- / (6 + 8) / (div4 + 1) / 2 - p->frequency;
+ / (6 + 8) / (div4 + 1) / 2 - c->frequency;
/* ds3000 global reset */
ds3000_writereg(state, 0x07, 0x80);
@@ -1220,13 +1205,13 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
}
static int ds3000_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
{
- if (p) {
- int ret = ds3000_set_frontend(fe, p);
+ if (re_tune) {
+ int ret = ds3000_set_frontend(fe);
if (ret)
return ret;
}
@@ -1279,10 +1264,9 @@ static int ds3000_sleep(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops ds3000_ops = {
-
+ .delsys = { SYS_DVBS, SYS_DVBS2},
.info = {
.name = "Montage Technology DS3000/TS2020",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
@@ -1312,8 +1296,6 @@ static struct dvb_frontend_ops ds3000_ops = {
.diseqc_send_burst = ds3000_diseqc_send_burst,
.get_frontend_algo = ds3000_get_algo,
- .set_property = ds3000_set_property,
- .get_property = ds3000_get_property,
.set_frontend = ds3000_set_frontend,
.tune = ds3000_tune,
};
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 62a65ef..1ab3483 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -61,8 +61,7 @@ struct dvb_pll_desc {
u32 min;
u32 max;
u32 iffreq;
- void (*set)(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params);
+ void (*set)(struct dvb_frontend *fe, u8 *buf);
u8 *initdata;
u8 *initdata2;
u8 *sleepdata;
@@ -93,10 +92,10 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
},
};
-static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
{
- if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth)
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ if (bw == 7000000)
buf[3] |= 0x10;
}
@@ -186,10 +185,10 @@ static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
/* Philips TDA6650/TDA6651
* used in Panasonic ENV77H11D5
*/
-static void tda665x_bw(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
{
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ if (bw == 8000000)
buf[3] |= 0x08;
}
@@ -220,10 +219,10 @@ static struct dvb_pll_desc dvb_pll_tda665x = {
/* Infineon TUA6034
* used in LG TDTP E102P
*/
-static void tua6034_bw(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
{
- if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth)
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ if (bw == 7000000)
buf[3] |= 0x08;
}
@@ -244,10 +243,10 @@ static struct dvb_pll_desc dvb_pll_tua6034 = {
/* ALPS TDED4
* used in Nebula-Cards and USB boxes
*/
-static void tded4_bw(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
{
- if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ if (bw == 8000000)
buf[3] |= 0x04;
}
@@ -319,11 +318,11 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
},
};
-static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_pll_priv *priv = fe->tuner_priv;
- u32 b_w = (params->u.qpsk.symbol_rate * 27) / 32000;
+ u32 b_w = (c->symbol_rate * 27) / 32000;
struct i2c_msg msg = {
.addr = priv->pll_i2c_address,
.flags = 0,
@@ -392,8 +391,7 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
}
};
-static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
{
struct dvb_pll_priv *priv = fe->tuner_priv;
struct i2c_msg msg = {
@@ -537,30 +535,29 @@ static struct dvb_pll_desc *pll_list[] = {
/* code */
static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
- const struct dvb_frontend_parameters *params)
+ const u32 frequency)
{
struct dvb_pll_priv *priv = fe->tuner_priv;
struct dvb_pll_desc *desc = priv->pll_desc;
u32 div;
int i;
- if (params->frequency != 0 && (params->frequency < desc->min ||
- params->frequency > desc->max))
+ if (frequency && (frequency < desc->min || frequency > desc->max))
return -EINVAL;
for (i = 0; i < desc->count; i++) {
- if (params->frequency > desc->entries[i].limit)
+ if (frequency > desc->entries[i].limit)
continue;
break;
}
if (debug)
printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
- params->frequency, i, desc->count);
+ frequency, i, desc->count);
if (i == desc->count)
return -EINVAL;
- div = (params->frequency + desc->iffreq +
+ div = (frequency + desc->iffreq +
desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
buf[0] = div >> 8;
buf[1] = div & 0xff;
@@ -568,7 +565,7 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
buf[3] = desc->entries[i].cb;
if (desc->set)
- desc->set(fe, buf, params);
+ desc->set(fe, buf);
if (debug)
printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
@@ -611,9 +608,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
return -EINVAL;
}
-static int dvb_pll_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int dvb_pll_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_pll_priv *priv = fe->tuner_priv;
u8 buf[4];
struct i2c_msg msg =
@@ -625,7 +622,8 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
if (priv->i2c == NULL)
return -EINVAL;
- if ((result = dvb_pll_configure(fe, buf, params)) < 0)
+ result = dvb_pll_configure(fe, buf, c->frequency);
+ if (result < 0)
return result;
else
frequency = result;
@@ -637,15 +635,15 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
}
priv->frequency = frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+ priv->bandwidth = c->bandwidth_hz;
return 0;
}
static int dvb_pll_calc_regs(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
u8 *buf, int buf_len)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_pll_priv *priv = fe->tuner_priv;
int result;
u32 frequency = 0;
@@ -653,7 +651,8 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
if (buf_len < 5)
return -EINVAL;
- if ((result = dvb_pll_configure(fe, buf+1, params)) < 0)
+ result = dvb_pll_configure(fe, buf + 1, c->frequency);
+ if (result < 0)
return result;
else
frequency = result;
@@ -661,7 +660,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
buf[0] = priv->pll_i2c_address;
priv->frequency = frequency;
- priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+ priv->bandwidth = c->bandwidth_hz;
return 5;
}
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index a7fc7e5..dcfc902 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -68,15 +68,18 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+/*
+ * Only needed if it actually reads something from the hardware
+ */
+static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe)
{
return 0;
}
-static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe)
{
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -171,10 +174,9 @@ error:
}
static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Dummy DVB-T",
- .type = FE_OFDM,
.frequency_min = 0,
.frequency_max = 863250000,
.frequency_stepsize = 62500,
@@ -203,10 +205,9 @@ static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
};
static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "Dummy DVB-C",
- .type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 51000000,
.frequency_max = 858000000,
@@ -233,10 +234,9 @@ static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
};
static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Dummy DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 250, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/ec100.c b/drivers/media/dvb/frontends/ec100.c
index 2414dc6..c56fddb 100644
--- a/drivers/media/dvb/frontends/ec100.c
+++ b/drivers/media/dvb/frontends/ec100.c
@@ -76,19 +76,19 @@ static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
return 0;
}
-static int ec100_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int ec100_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct ec100_state *state = fe->demodulator_priv;
int ret;
u8 tmp, tmp2;
- deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
- params->u.ofdm.bandwidth);
+ deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency,
+ c->bandwidth_hz);
/* program tuner */
if (fe->ops.tuner_ops.set_params)
- fe->ops.tuner_ops.set_params(fe, params);
+ fe->ops.tuner_ops.set_params(fe);
ret = ec100_write_reg(state, 0x04, 0x06);
if (ret)
@@ -108,16 +108,16 @@ static int ec100_set_frontend(struct dvb_frontend *fe,
B 0x1b | 0xb7 | 0x00 | 0x49
B 0x1c | 0x55 | 0x64 | 0x72 */
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
tmp = 0xb7;
tmp2 = 0x55;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
tmp = 0x00;
tmp2 = 0x64;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
default:
tmp = 0x49;
tmp2 = 0x72;
@@ -306,9 +306,9 @@ error:
EXPORT_SYMBOL(ec100_attach);
static struct dvb_frontend_ops ec100_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "E3C EC100 DVB-T",
- .type = FE_OFDM,
.caps =
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
diff --git a/drivers/media/dvb/frontends/hd29l2.c b/drivers/media/dvb/frontends/hd29l2.c
new file mode 100644
index 0000000..a003181
--- /dev/null
+++ b/drivers/media/dvb/frontends/hd29l2.c
@@ -0,0 +1,861 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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.
+ */
+
+#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)
+{
+ int ret;
+ u8 buf[2 + len];
+ struct i2c_msg msg[1] = {
+ {
+ .addr = priv->cfg.i2c_addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ buf[0] = 0x00;
+ buf[1] = reg;
+ memcpy(&buf[2], val, len);
+
+ ret = i2c_transfer(priv->i2c, msg, 1);
+ if (ret == 1) {
+ ret = 0;
+ } else {
+ warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+
+ return ret;
+}
+
+/* read multiple registers */
+static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
+{
+ int ret;
+ u8 buf[2] = { 0x00, reg };
+ struct i2c_msg msg[2] = {
+ {
+ .addr = priv->cfg.i2c_addr,
+ .flags = 0,
+ .len = 2,
+ .buf = buf,
+ }, {
+ .addr = priv->cfg.i2c_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = val,
+ }
+ };
+
+ ret = i2c_transfer(priv->i2c, msg, 2);
+ if (ret == 2) {
+ ret = 0;
+ } else {
+ warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+ ret = -EREMOTEIO;
+ }
+
+ return ret;
+}
+
+/* write single register */
+static int hd29l2_wr_reg(struct hd29l2_priv *priv, u8 reg, u8 val)
+{
+ return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int hd29l2_rd_reg(struct hd29l2_priv *priv, u8 reg, u8 *val)
+{
+ return hd29l2_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
+{
+ int ret;
+ u8 tmp;
+
+ /* no need for read if whole reg is written */
+ if (mask != 0xff) {
+ ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ val &= mask;
+ tmp &= ~mask;
+ val |= tmp;
+ }
+
+ return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+ int ret, i;
+ u8 tmp;
+
+ ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+ if (ret)
+ return ret;
+
+ tmp &= mask;
+
+ /* find position of the first bit */
+ for (i = 0; i < 8; i++) {
+ if ((mask >> i) & 0x01)
+ break;
+ }
+ *val = tmp >> i;
+
+ return 0;
+}
+
+static int hd29l2_soft_reset(struct hd29l2_priv *priv)
+{
+ int ret;
+ u8 tmp;
+
+ ret = hd29l2_rd_reg(priv, 0x26, &tmp);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_wr_reg(priv, 0x26, 0x0d);
+ if (ret)
+ goto err;
+
+ usleep_range(10000, 20000);
+
+ ret = hd29l2_wr_reg(priv, 0x26, tmp);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ int ret, i;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 tmp;
+
+ dbg("%s: enable=%d", __func__, enable);
+
+ /* set tuner address for demod */
+ if (!priv->tuner_i2c_addr_programmed && enable) {
+ /* no need to set tuner address every time, once is enough */
+ ret = hd29l2_wr_reg(priv, 0x9d, priv->cfg.tuner_i2c_addr << 1);
+ if (ret)
+ goto err;
+
+ priv->tuner_i2c_addr_programmed = true;
+ }
+
+ /* open / close gate */
+ ret = hd29l2_wr_reg(priv, 0x9f, enable);
+ if (ret)
+ goto err;
+
+ /* wait demod ready */
+ for (i = 10; i; i--) {
+ ret = hd29l2_rd_reg(priv, 0x9e, &tmp);
+ if (ret)
+ goto err;
+
+ if (tmp == enable)
+ break;
+
+ usleep_range(5000, 10000);
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ int ret;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 buf[2];
+
+ *status = 0;
+
+ ret = hd29l2_rd_reg(priv, 0x05, &buf[0]);
+ if (ret)
+ goto err;
+
+ if (buf[0] & 0x01) {
+ /* full lock */
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_LOCK;
+ } else {
+ ret = hd29l2_rd_reg(priv, 0x0d, &buf[1]);
+ if (ret)
+ goto err;
+
+ if ((buf[1] & 0xfe) == 0x78)
+ /* partial lock */
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC;
+ }
+
+ priv->fe_status = *status;
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ int ret;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 buf[2];
+ u16 tmp;
+
+ if (!(priv->fe_status & FE_HAS_LOCK)) {
+ *snr = 0;
+ ret = 0;
+ goto err;
+ }
+
+ ret = hd29l2_rd_regs(priv, 0x0b, buf, 2);
+ if (ret)
+ goto err;
+
+ tmp = (buf[0] << 8) | buf[1];
+
+ /* report SNR in dB * 10 */
+ #define LOG10_20736_24 72422627 /* log10(20736) << 24 */
+ if (tmp)
+ *snr = (LOG10_20736_24 - intlog10(tmp)) / ((1 << 24) / 100);
+ else
+ *snr = 0;
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ int ret;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 buf[2];
+ u16 tmp;
+
+ *strength = 0;
+
+ ret = hd29l2_rd_regs(priv, 0xd5, buf, 2);
+ if (ret)
+ goto err;
+
+ tmp = buf[0] << 8 | buf[1];
+ tmp = ~tmp & 0x0fff;
+
+ /* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+ *strength = tmp * 0xffff / 0x0fff;
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ int ret;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 buf[2];
+
+ if (!(priv->fe_status & FE_HAS_SYNC)) {
+ *ber = 0;
+ ret = 0;
+ goto err;
+ }
+
+ ret = hd29l2_rd_regs(priv, 0xd9, buf, 2);
+ if (ret) {
+ *ber = 0;
+ goto err;
+ }
+
+ /* LDPC BER */
+ *ber = ((buf[0] & 0x0f) << 8) | buf[1];
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ /* no way to read? */
+ *ucblocks = 0;
+ return 0;
+}
+
+static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
+{
+ int ret, i;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u8 tmp, buf[3];
+ u8 modulation, carrier, guard_interval, interleave, code_rate;
+ u64 num64;
+ 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);
+
+ /* as for now we detect always params automatically */
+ auto_mode = true;
+
+ /* program tuner */
+ if (fe->ops.tuner_ops.set_params)
+ fe->ops.tuner_ops.set_params(fe);
+
+ /* get and program IF */
+ if (fe->ops.tuner_ops.get_if_frequency)
+ fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+ else
+ if_freq = 0;
+
+ if (if_freq) {
+ /* normal IF */
+
+ /* calc IF control value */
+ num64 = if_freq;
+ num64 *= 0x800000;
+ num64 = div_u64(num64, HD29L2_XTAL);
+ num64 -= 0x800000;
+ if_ctl = num64;
+
+ tmp = 0xfc; /* tuner type normal */
+ } else {
+ /* zero IF */
+ if_ctl = 0;
+ tmp = 0xfe; /* tuner type Zero-IF */
+ }
+
+ buf[0] = ((if_ctl >> 0) & 0xff);
+ buf[1] = ((if_ctl >> 8) & 0xff);
+ buf[2] = ((if_ctl >> 16) & 0xff);
+
+ /* program IF control */
+ ret = hd29l2_wr_regs(priv, 0x14, buf, 3);
+ if (ret)
+ goto err;
+
+ /* program tuner type */
+ ret = hd29l2_wr_reg(priv, 0xab, tmp);
+ if (ret)
+ goto err;
+
+ dbg("%s: if_freq=%d if_ctl=%x", __func__, if_freq, if_ctl);
+
+ if (auto_mode) {
+ /*
+ * use auto mode
+ */
+
+ /* disable quick mode */
+ ret = hd29l2_wr_reg_mask(priv, 0xac, 0 << 7, 0x80);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_wr_reg_mask(priv, 0x82, 1 << 1, 0x02);
+ if (ret)
+ goto err;
+
+ /* enable auto mode */
+ ret = hd29l2_wr_reg_mask(priv, 0x7d, 1 << 6, 0x40);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_wr_reg_mask(priv, 0x81, 1 << 3, 0x08);
+ if (ret)
+ goto err;
+
+ /* soft reset */
+ ret = hd29l2_soft_reset(priv);
+ if (ret)
+ goto err;
+
+ /* detect modulation */
+ for (i = 30; i; i--) {
+ msleep(100);
+
+ ret = hd29l2_rd_reg(priv, 0x0d, &tmp);
+ if (ret)
+ goto err;
+
+ if ((((tmp & 0xf0) >= 0x10) &&
+ ((tmp & 0x0f) == 0x08)) || (tmp >= 0x2c))
+ break;
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0)
+ /* detection failed */
+ return DVBFE_ALGO_SEARCH_FAILED;
+
+ /* read modulation */
+ ret = hd29l2_rd_reg_mask(priv, 0x7d, &modulation, 0x07);
+ if (ret)
+ goto err;
+ } else {
+ /*
+ * use manual mode
+ */
+
+ modulation = HD29L2_QAM64;
+ carrier = HD29L2_CARRIER_MULTI;
+ guard_interval = HD29L2_PN945;
+ interleave = HD29L2_INTERLEAVER_420;
+ code_rate = HD29L2_CODE_RATE_08;
+
+ tmp = (code_rate << 3) | modulation;
+ ret = hd29l2_wr_reg_mask(priv, 0x7d, tmp, 0x5f);
+ if (ret)
+ goto err;
+
+ tmp = (carrier << 2) | guard_interval;
+ ret = hd29l2_wr_reg_mask(priv, 0x81, tmp, 0x0f);
+ if (ret)
+ goto err;
+
+ tmp = interleave;
+ ret = hd29l2_wr_reg_mask(priv, 0x82, tmp, 0x03);
+ if (ret)
+ goto err;
+ }
+
+ /* 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);
+ goto err;
+ }
+
+ /* program registers according to modulation */
+ for (i = 0; i < ARRAY_SIZE(reg_mod_vals_tab); i++) {
+ ret = hd29l2_wr_reg(priv, reg_mod_vals_tab[i].reg,
+ reg_mod_vals_tab[i].val[modulation]);
+ if (ret)
+ goto err;
+ }
+
+ /* read guard interval */
+ ret = hd29l2_rd_reg_mask(priv, 0x81, &guard_interval, 0x03);
+ if (ret)
+ goto err;
+
+ /* read carrier mode */
+ ret = hd29l2_rd_reg_mask(priv, 0x81, &carrier, 0x04);
+ if (ret)
+ goto err;
+
+ dbg("%s: modulation=%d guard_interval=%d carrier=%d",
+ __func__, modulation, guard_interval, carrier);
+
+ if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) &&
+ (guard_interval == HD29L2_PN945)) {
+ dbg("%s: C=3780 && QAM64 && PN945", __func__);
+
+ ret = hd29l2_wr_reg(priv, 0x42, 0x33);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_wr_reg(priv, 0xdd, 0x01);
+ if (ret)
+ goto err;
+ }
+
+ usleep_range(10000, 20000);
+
+ /* soft reset */
+ ret = hd29l2_soft_reset(priv);
+ if (ret)
+ goto err;
+
+ /* wait demod lock */
+ for (i = 30; i; i--) {
+ msleep(100);
+
+ /* read lock bit */
+ ret = hd29l2_rd_reg_mask(priv, 0x05, &tmp, 0x01);
+ if (ret)
+ goto err;
+
+ if (tmp)
+ break;
+ }
+
+ dbg("%s: loop=%d", __func__, i);
+
+ if (i == 0)
+ return DVBFE_ALGO_SEARCH_AGAIN;
+
+ return DVBFE_ALGO_SEARCH_SUCCESS;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int hd29l2_get_frontend_algo(struct dvb_frontend *fe)
+{
+ return DVBFE_ALGO_CUSTOM;
+}
+
+static int hd29l2_get_frontend(struct dvb_frontend *fe)
+{
+ int ret;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u8 buf[3];
+ u32 if_ctl;
+ char *str_constellation, *str_code_rate, *str_constellation_code_rate,
+ *str_guard_interval, *str_carrier, *str_guard_interval_carrier,
+ *str_interleave, *str_interleave_;
+
+ ret = hd29l2_rd_reg(priv, 0x7d, &buf[0]);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_rd_regs(priv, 0x81, &buf[1], 2);
+ if (ret)
+ goto err;
+
+ /* constellation, 0x7d[2:0] */
+ switch ((buf[0] >> 0) & 0x07) {
+ case 0: /* QAM4NR */
+ str_constellation = "QAM4NR";
+ c->modulation = QAM_AUTO; /* FIXME */
+ break;
+ case 1: /* QAM4 */
+ str_constellation = "QAM4";
+ c->modulation = QPSK; /* FIXME */
+ break;
+ case 2:
+ str_constellation = "QAM16";
+ c->modulation = QAM_16;
+ break;
+ case 3:
+ str_constellation = "QAM32";
+ c->modulation = QAM_32;
+ break;
+ case 4:
+ str_constellation = "QAM64";
+ c->modulation = QAM_64;
+ break;
+ default:
+ str_constellation = "?";
+ }
+
+ /* LDPC code rate, 0x7d[4:3] */
+ switch ((buf[0] >> 3) & 0x03) {
+ case 0: /* 0.4 */
+ str_code_rate = "0.4";
+ c->fec_inner = FEC_AUTO; /* FIXME */
+ break;
+ case 1: /* 0.6 */
+ str_code_rate = "0.6";
+ c->fec_inner = FEC_3_5;
+ break;
+ case 2: /* 0.8 */
+ str_code_rate = "0.8";
+ c->fec_inner = FEC_4_5;
+ break;
+ default:
+ str_code_rate = "?";
+ }
+
+ /* constellation & code rate set, 0x7d[6] */
+ switch ((buf[0] >> 6) & 0x01) {
+ case 0:
+ str_constellation_code_rate = "manual";
+ break;
+ case 1:
+ str_constellation_code_rate = "auto";
+ break;
+ default:
+ str_constellation_code_rate = "?";
+ }
+
+ /* frame header, 0x81[1:0] */
+ switch ((buf[1] >> 0) & 0x03) {
+ case 0: /* PN945 */
+ str_guard_interval = "PN945";
+ c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+ break;
+ case 1: /* PN595 */
+ str_guard_interval = "PN595";
+ c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+ break;
+ case 2: /* PN420 */
+ str_guard_interval = "PN420";
+ c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+ break;
+ default:
+ str_guard_interval = "?";
+ }
+
+ /* carrier, 0x81[2] */
+ switch ((buf[1] >> 2) & 0x01) {
+ case 0:
+ str_carrier = "C=1";
+ break;
+ case 1:
+ str_carrier = "C=3780";
+ break;
+ default:
+ str_carrier = "?";
+ }
+
+ /* frame header & carrier set, 0x81[3] */
+ switch ((buf[1] >> 3) & 0x01) {
+ case 0:
+ str_guard_interval_carrier = "manual";
+ break;
+ case 1:
+ str_guard_interval_carrier = "auto";
+ break;
+ default:
+ str_guard_interval_carrier = "?";
+ }
+
+ /* interleave, 0x82[0] */
+ switch ((buf[2] >> 0) & 0x01) {
+ case 0:
+ str_interleave = "M=720";
+ break;
+ case 1:
+ str_interleave = "M=240";
+ break;
+ default:
+ str_interleave = "?";
+ }
+
+ /* interleave set, 0x82[1] */
+ switch ((buf[2] >> 1) & 0x01) {
+ case 0:
+ str_interleave_ = "manual";
+ break;
+ case 1:
+ str_interleave_ = "auto";
+ break;
+ default:
+ str_interleave_ = "?";
+ }
+
+ /*
+ * We can read out current detected NCO and use that value next
+ * time instead of calculating new value from targed IF.
+ * I think it will not effect receiver sensitivity but gaining lock
+ * after tune could be easier...
+ */
+ ret = hd29l2_rd_regs(priv, 0xb1, &buf[0], 3);
+ if (ret)
+ goto err;
+
+ 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);
+
+ return 0;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static int hd29l2_init(struct dvb_frontend *fe)
+{
+ int ret, i;
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ u8 tmp;
+ static const struct reg_val tab[] = {
+ { 0x3a, 0x06 },
+ { 0x3b, 0x03 },
+ { 0x3c, 0x04 },
+ { 0xaf, 0x06 },
+ { 0xb0, 0x1b },
+ { 0x80, 0x64 },
+ { 0x10, 0x38 },
+ };
+
+ dbg("%s:", __func__);
+
+ /* reset demod */
+ /* it is recommended to HW reset chip using RST_N pin */
+ if (fe->callback) {
+ ret = fe->callback(fe, DVB_FRONTEND_COMPONENT_DEMOD, 0, 0);
+ if (ret)
+ goto err;
+
+ /* reprogramming needed because HW reset clears registers */
+ priv->tuner_i2c_addr_programmed = false;
+ }
+
+ /* init */
+ for (i = 0; i < ARRAY_SIZE(tab); i++) {
+ ret = hd29l2_wr_reg(priv, tab[i].reg, tab[i].val);
+ if (ret)
+ goto err;
+ }
+
+ /* TS params */
+ ret = hd29l2_rd_reg(priv, 0x36, &tmp);
+ if (ret)
+ goto err;
+
+ tmp &= 0x1b;
+ tmp |= priv->cfg.ts_mode;
+ ret = hd29l2_wr_reg(priv, 0x36, tmp);
+ if (ret)
+ goto err;
+
+ ret = hd29l2_rd_reg(priv, 0x31, &tmp);
+ tmp &= 0xef;
+
+ if (!(priv->cfg.ts_mode >> 7))
+ /* set b4 for serial TS */
+ tmp |= 0x10;
+
+ ret = hd29l2_wr_reg(priv, 0x31, tmp);
+ if (ret)
+ goto err;
+
+ return ret;
+err:
+ dbg("%s: failed=%d", __func__, ret);
+ return ret;
+}
+
+static void hd29l2_release(struct dvb_frontend *fe)
+{
+ struct hd29l2_priv *priv = fe->demodulator_priv;
+ kfree(priv);
+}
+
+static struct dvb_frontend_ops hd29l2_ops;
+
+struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+ struct i2c_adapter *i2c)
+{
+ int ret;
+ struct hd29l2_priv *priv = NULL;
+ u8 tmp;
+
+ /* allocate memory for the internal state */
+ priv = kzalloc(sizeof(struct hd29l2_priv), GFP_KERNEL);
+ if (priv == NULL)
+ goto err;
+
+ /* setup the state */
+ priv->i2c = i2c;
+ memcpy(&priv->cfg, config, sizeof(struct hd29l2_config));
+
+
+ /* check if the demod is there */
+ ret = hd29l2_rd_reg(priv, 0x00, &tmp);
+ if (ret)
+ goto err;
+
+ /* create dvb_frontend */
+ memcpy(&priv->fe.ops, &hd29l2_ops, sizeof(struct dvb_frontend_ops));
+ priv->fe.demodulator_priv = priv;
+
+ return &priv->fe;
+err:
+ kfree(priv);
+ return NULL;
+}
+EXPORT_SYMBOL(hd29l2_attach);
+
+static struct dvb_frontend_ops hd29l2_ops = {
+ .delsys = { SYS_DVBT },
+ .info = {
+ .name = "HDIC HD29L2 DMB-TH",
+ .frequency_min = 474000000,
+ .frequency_max = 858000000,
+ .frequency_stepsize = 10000,
+ .caps = FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_BANDWIDTH_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO |
+ FE_CAN_RECOVER
+ },
+
+ .release = hd29l2_release,
+
+ .init = hd29l2_init,
+
+ .get_frontend_algo = hd29l2_get_frontend_algo,
+ .search = hd29l2_search,
+ .get_frontend = hd29l2_get_frontend,
+
+ .read_status = hd29l2_read_status,
+ .read_snr = hd29l2_read_snr,
+ .read_signal_strength = hd29l2_read_signal_strength,
+ .read_ber = hd29l2_read_ber,
+ .read_ucblocks = hd29l2_read_ucblocks,
+
+ .i2c_gate_ctrl = hd29l2_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("HDIC HD29L2 DMB-TH demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/hd29l2.h b/drivers/media/dvb/frontends/hd29l2.h
new file mode 100644
index 0000000..a7a6443
--- /dev/null
+++ b/drivers/media/dvb/frontends/hd29l2.h
@@ -0,0 +1,66 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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 HD29L2_H
+#define HD29L2_H
+
+#include <linux/dvb/frontend.h>
+
+struct hd29l2_config {
+ /*
+ * demodulator I2C address
+ */
+ u8 i2c_addr;
+
+ /*
+ * tuner I2C address
+ * only needed when tuner is behind demod I2C-gate
+ */
+ u8 tuner_i2c_addr;
+
+ /*
+ * TS settings
+ */
+#define HD29L2_TS_SERIAL 0x00
+#define HD29L2_TS_PARALLEL 0x80
+#define HD29L2_TS_CLK_NORMAL 0x40
+#define HD29L2_TS_CLK_INVERTED 0x00
+#define HD29L2_TS_CLK_GATED 0x20
+#define HD29L2_TS_CLK_FREE 0x00
+ u8 ts_mode;
+};
+
+
+#if defined(CONFIG_DVB_HD29L2) || \
+ (defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
+extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+ struct i2c_adapter *i2c);
+#else
+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__);
+ return NULL;
+}
+#endif
+
+#endif /* HD29L2_H */
diff --git a/drivers/media/dvb/frontends/hd29l2_priv.h b/drivers/media/dvb/frontends/hd29l2_priv.h
new file mode 100644
index 0000000..ba16dc3
--- /dev/null
+++ b/drivers/media/dvb/frontends/hd29l2_priv.h
@@ -0,0 +1,314 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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 HD29L2_PRIV
+#define HD29L2_PRIV
+
+#include <linux/dvb/version.h>
+#include "dvb_frontend.h"
+#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 */
+
+
+#define HD29L2_QAM4NR 0x00
+#define HD29L2_QAM4 0x01
+#define HD29L2_QAM16 0x02
+#define HD29L2_QAM32 0x03
+#define HD29L2_QAM64 0x04
+
+#define HD29L2_CODE_RATE_04 0x00
+#define HD29L2_CODE_RATE_06 0x08
+#define HD29L2_CODE_RATE_08 0x10
+
+#define HD29L2_PN945 0x00
+#define HD29L2_PN595 0x01
+#define HD29L2_PN420 0x02
+
+#define HD29L2_CARRIER_SINGLE 0x00
+#define HD29L2_CARRIER_MULTI 0x01
+
+#define HD29L2_INTERLEAVER_720 0x00
+#define HD29L2_INTERLEAVER_420 0x01
+
+struct reg_val {
+ u8 reg;
+ u8 val;
+};
+
+struct reg_mod_vals {
+ u8 reg;
+ u8 val[5];
+};
+
+struct hd29l2_priv {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend fe;
+ struct hd29l2_config cfg;
+ u8 tuner_i2c_addr_programmed:1;
+
+ fe_status_t fe_status;
+};
+
+static const struct reg_mod_vals reg_mod_vals_tab[] = {
+ /* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */
+ { 0x01, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+ { 0x02, { 0x07, 0x07, 0x07, 0x07, 0x07 } },
+ { 0x03, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+ { 0x04, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x05, { 0x61, 0x60, 0x60, 0x61, 0x60 } },
+ { 0x06, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+ { 0x07, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+ { 0x08, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x09, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x0a, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+ { 0x0d, { 0x78, 0x78, 0x88, 0x78, 0x78 } },
+ { 0x0e, { 0xa0, 0x90, 0xa0, 0xa0, 0xa0 } },
+ { 0x0f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x10, { 0xa0, 0xa0, 0x58, 0x38, 0x38 } },
+ { 0x11, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x12, { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a } },
+ { 0x13, { 0xa2, 0xa2, 0xa2, 0xa2, 0xa2 } },
+ { 0x17, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+ { 0x18, { 0x21, 0x21, 0x42, 0x52, 0x42 } },
+ { 0x19, { 0x21, 0x21, 0x62, 0x72, 0x62 } },
+ { 0x1a, { 0x32, 0x43, 0xa9, 0xb9, 0xa9 } },
+ { 0x1b, { 0x32, 0x43, 0xb9, 0xd8, 0xb9 } },
+ { 0x1c, { 0x02, 0x02, 0x03, 0x02, 0x03 } },
+ { 0x1d, { 0x0c, 0x0c, 0x01, 0x02, 0x02 } },
+ { 0x1e, { 0x02, 0x02, 0x02, 0x01, 0x02 } },
+ { 0x1f, { 0x02, 0x02, 0x01, 0x02, 0x04 } },
+ { 0x20, { 0x01, 0x02, 0x01, 0x01, 0x01 } },
+ { 0x21, { 0x08, 0x08, 0x0a, 0x0a, 0x0a } },
+ { 0x22, { 0x06, 0x06, 0x04, 0x05, 0x05 } },
+ { 0x23, { 0x06, 0x06, 0x05, 0x03, 0x05 } },
+ { 0x24, { 0x08, 0x08, 0x05, 0x07, 0x07 } },
+ { 0x25, { 0x16, 0x10, 0x10, 0x0a, 0x10 } },
+ { 0x26, { 0x14, 0x14, 0x04, 0x04, 0x04 } },
+ { 0x27, { 0x58, 0x58, 0x58, 0x5c, 0x58 } },
+ { 0x28, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0x29, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0x2a, { 0x08, 0x0a, 0x08, 0x08, 0x08 } },
+ { 0x2b, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+ { 0x2c, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+ { 0x2d, { 0x05, 0x06, 0x06, 0x06, 0x06 } },
+ { 0x2e, { 0x21, 0x21, 0x21, 0x21, 0x21 } },
+ { 0x2f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x30, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+ { 0x33, { 0xb7, 0xb7, 0xb7, 0xb7, 0xb7 } },
+ { 0x34, { 0x81, 0x81, 0x81, 0x81, 0x81 } },
+ { 0x35, { 0x80, 0x80, 0x80, 0x80, 0x80 } },
+ { 0x37, { 0x70, 0x70, 0x70, 0x70, 0x70 } },
+ { 0x38, { 0x04, 0x04, 0x02, 0x02, 0x02 } },
+ { 0x39, { 0x07, 0x07, 0x05, 0x05, 0x05 } },
+ { 0x3a, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+ { 0x3b, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+ { 0x3c, { 0x07, 0x06, 0x04, 0x04, 0x04 } },
+ { 0x3d, { 0xf0, 0xf0, 0xf0, 0xf0, 0x80 } },
+ { 0x3e, { 0x60, 0x60, 0x60, 0x60, 0xff } },
+ { 0x3f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x40, { 0x5b, 0x5b, 0x5b, 0x57, 0x50 } },
+ { 0x41, { 0x30, 0x30, 0x30, 0x30, 0x18 } },
+ { 0x42, { 0x20, 0x20, 0x20, 0x00, 0x30 } },
+ { 0x43, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x44, { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f } },
+ { 0x45, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x46, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0x47, { 0x00, 0x00, 0x95, 0x00, 0x95 } },
+ { 0x48, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+ { 0x49, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+ { 0x4a, { 0x40, 0x40, 0x33, 0x11, 0x11 } },
+ { 0x4b, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+ { 0x4c, { 0x40, 0x40, 0x99, 0x11, 0x11 } },
+ { 0x4d, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+ { 0x4e, { 0x40, 0x40, 0x66, 0x77, 0x77 } },
+ { 0x4f, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+ { 0x50, { 0x40, 0x40, 0x88, 0x33, 0x11 } },
+ { 0x51, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+ { 0x52, { 0x40, 0x40, 0x88, 0x02, 0x02 } },
+ { 0x53, { 0x40, 0x40, 0x00, 0x02, 0x02 } },
+ { 0x54, { 0x00, 0x00, 0x88, 0x33, 0x33 } },
+ { 0x55, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+ { 0x56, { 0x00, 0x00, 0x00, 0x0b, 0x00 } },
+ { 0x57, { 0x40, 0x40, 0x0a, 0x0b, 0x0a } },
+ { 0x58, { 0xaa, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x59, { 0x7a, 0x40, 0x02, 0x02, 0x02 } },
+ { 0x5a, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+ { 0x5b, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+ { 0x5c, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+ { 0x5d, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+ { 0x5e, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+ { 0x5f, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+ { 0x60, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+ { 0x61, { 0x40, 0x40, 0x10, 0x30, 0x30 } },
+ { 0x62, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+ { 0x63, { 0x40, 0x40, 0x05, 0x30, 0x30 } },
+ { 0x64, { 0x40, 0x40, 0x06, 0x00, 0x30 } },
+ { 0x65, { 0x40, 0x40, 0x06, 0x08, 0x30 } },
+ { 0x66, { 0x40, 0x40, 0x00, 0x00, 0x20 } },
+ { 0x67, { 0x40, 0x40, 0x01, 0x04, 0x20 } },
+ { 0x68, { 0x00, 0x00, 0x30, 0x00, 0x20 } },
+ { 0x69, { 0xa0, 0xa0, 0x00, 0x08, 0x20 } },
+ { 0x6a, { 0x00, 0x00, 0x30, 0x00, 0x25 } },
+ { 0x6b, { 0xa0, 0xa0, 0x00, 0x06, 0x25 } },
+ { 0x6c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x6d, { 0xa0, 0x60, 0x0c, 0x03, 0x0c } },
+ { 0x6e, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x6f, { 0xa0, 0x60, 0x04, 0x01, 0x04 } },
+ { 0x70, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+ { 0x71, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+ { 0x72, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+ { 0x73, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+ { 0x74, { 0x06, 0x06, 0x09, 0x05, 0x05 } },
+ { 0x75, { 0x06, 0x06, 0x0a, 0x10, 0x10 } },
+ { 0x76, { 0x10, 0x10, 0x06, 0x0a, 0x0a } },
+ { 0x77, { 0x12, 0x18, 0x28, 0x10, 0x28 } },
+ { 0x78, { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 } },
+ { 0x79, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+ { 0x7a, { 0x02, 0x02, 0x01, 0x04, 0x03 } },
+ { 0x7b, { 0x01, 0x02, 0x03, 0x03, 0x03 } },
+ { 0x7c, { 0x28, 0x28, 0x28, 0x28, 0x28 } },
+ { 0x7f, { 0x25, 0x92, 0x5f, 0x17, 0x2d } },
+ { 0x80, { 0x64, 0x64, 0x64, 0x74, 0x64 } },
+ { 0x83, { 0x06, 0x03, 0x04, 0x04, 0x04 } },
+ { 0x84, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+ { 0x85, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+ { 0x86, { 0x00, 0x00, 0x11, 0x11, 0x11 } },
+ { 0x87, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+ { 0x88, { 0x09, 0x09, 0x09, 0x09, 0x09 } },
+ { 0x89, { 0x20, 0x20, 0x30, 0x20, 0x20 } },
+ { 0x8a, { 0x03, 0x03, 0x02, 0x03, 0x02 } },
+ { 0x8b, { 0x00, 0x07, 0x09, 0x00, 0x09 } },
+ { 0x8c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x8d, { 0x4f, 0x4f, 0x4f, 0x3f, 0x4f } },
+ { 0x8e, { 0xf0, 0xf0, 0x60, 0xf0, 0xa0 } },
+ { 0x8f, { 0xe8, 0xe8, 0xe8, 0xe8, 0xe8 } },
+ { 0x90, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+ { 0x91, { 0x40, 0x40, 0x70, 0x70, 0x10 } },
+ { 0x92, { 0x00, 0x00, 0x00, 0x00, 0x04 } },
+ { 0x93, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+ { 0x94, { 0x00, 0x00, 0x00, 0x00, 0x03 } },
+ { 0x95, { 0x09, 0x09, 0x47, 0x47, 0x47 } },
+ { 0x96, { 0x80, 0xa0, 0xa0, 0x40, 0xa0 } },
+ { 0x97, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+ { 0x98, { 0x50, 0x50, 0x50, 0x30, 0x50 } },
+ { 0x99, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+ { 0x9a, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0x9b, { 0x40, 0x40, 0x40, 0x30, 0x40 } },
+ { 0x9c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa0, { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 } },
+ { 0xa1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa2, { 0x30, 0x30, 0x00, 0x30, 0x00 } },
+ { 0xa3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa5, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xa8, { 0x77, 0x77, 0x77, 0x77, 0x77 } },
+ { 0xa9, { 0x02, 0x02, 0x02, 0x02, 0x02 } },
+ { 0xaa, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+ { 0xac, { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f } },
+ { 0xad, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+ { 0xae, { 0x78, 0x78, 0x78, 0x78, 0x78 } },
+ { 0xaf, { 0x06, 0x06, 0x06, 0x06, 0x07 } },
+ { 0xb0, { 0x1b, 0x1b, 0x1b, 0x19, 0x1b } },
+ { 0xb1, { 0x18, 0x17, 0x17, 0x18, 0x17 } },
+ { 0xb2, { 0x35, 0x82, 0x82, 0x38, 0x82 } },
+ { 0xb3, { 0xb6, 0xce, 0xc7, 0x5c, 0xb0 } },
+ { 0xb4, { 0x3f, 0x3e, 0x3e, 0x3f, 0x3e } },
+ { 0xb5, { 0x70, 0x58, 0x50, 0x68, 0x50 } },
+ { 0xb6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xb7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xb8, { 0x03, 0x03, 0x01, 0x01, 0x01 } },
+ { 0xb9, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xba, { 0x06, 0x06, 0x0a, 0x05, 0x0a } },
+ { 0xbb, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xbc, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xbd, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xbe, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xbf, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc3, { 0x00, 0x00, 0x88, 0x66, 0x88 } },
+ { 0xc4, { 0x10, 0x10, 0x00, 0x00, 0x00 } },
+ { 0xc5, { 0x00, 0x00, 0x44, 0x60, 0x44 } },
+ { 0xc6, { 0x10, 0x0a, 0x00, 0x00, 0x00 } },
+ { 0xc7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc8, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xc9, { 0x90, 0x04, 0x00, 0x00, 0x00 } },
+ { 0xca, { 0x90, 0x08, 0x01, 0x01, 0x01 } },
+ { 0xcb, { 0xa0, 0x04, 0x00, 0x44, 0x00 } },
+ { 0xcc, { 0xa0, 0x10, 0x03, 0x00, 0x03 } },
+ { 0xcd, { 0x06, 0x06, 0x06, 0x05, 0x06 } },
+ { 0xce, { 0x05, 0x05, 0x01, 0x01, 0x01 } },
+ { 0xcf, { 0x40, 0x20, 0x18, 0x18, 0x18 } },
+ { 0xd0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xd1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xd2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xd3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xd4, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+ { 0xd5, { 0x05, 0x05, 0x05, 0x03, 0x05 } },
+ { 0xd6, { 0xac, 0x22, 0xca, 0x8f, 0xca } },
+ { 0xd7, { 0x20, 0x20, 0x20, 0x20, 0x20 } },
+ { 0xd8, { 0x01, 0x01, 0x01, 0x01, 0x01 } },
+ { 0xd9, { 0x00, 0x00, 0x0f, 0x00, 0x0f } },
+ { 0xda, { 0x00, 0xff, 0xff, 0x0e, 0xff } },
+ { 0xdb, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0xdc, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0xdd, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+ { 0xde, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0xdf, { 0x42, 0x42, 0x44, 0x44, 0x04 } },
+ { 0xe0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xe1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xe2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xe3, { 0x00, 0x00, 0x26, 0x06, 0x26 } },
+ { 0xe4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xe5, { 0x01, 0x0a, 0x01, 0x01, 0x01 } },
+ { 0xe6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xe7, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+ { 0xe8, { 0x63, 0x63, 0x63, 0x63, 0x63 } },
+ { 0xe9, { 0x59, 0x59, 0x59, 0x59, 0x59 } },
+ { 0xea, { 0x80, 0x80, 0x20, 0x80, 0x80 } },
+ { 0xeb, { 0x37, 0x37, 0x78, 0x37, 0x77 } },
+ { 0xec, { 0x1f, 0x1f, 0x25, 0x25, 0x25 } },
+ { 0xed, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+ { 0xee, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 0xef, { 0x70, 0x70, 0x58, 0x38, 0x58 } },
+ { 0xf0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+};
+
+#endif /* HD29L2_PRIV */
diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h
index 1c6fb4b..93b086e 100644
--- a/drivers/media/dvb/frontends/it913x-fe-priv.h
+++ b/drivers/media/dvb/frontends/it913x-fe-priv.h
@@ -22,126 +22,126 @@ struct adctable { u32 adcFrequency;
/* clock and coeff tables only table 3 is used with IT9137*/
/* TODO other tables relate AF9035 may be removed */
static struct adctable tab1[] = {
- { 20156250, BANDWIDTH_6_MHZ,
+ { 20156250, 6000000,
0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c },
- { 20156250, BANDWIDTH_7_MHZ,
+ { 20156250, 7000000,
0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196 },
- { 20156250, BANDWIDTH_8_MHZ,
+ { 20156250, 8000000,
0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0 },
- { 20156250, BANDWIDTH_5_MHZ,
+ { 20156250, 5000000,
0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122 }
};
static struct adctable tab2[] = {
- { 20187500, BANDWIDTH_6_MHZ,
+ { 20187500, 6000000,
0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c },
- { 20187500, BANDWIDTH_7_MHZ,
+ { 20187500, 7000000,
0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196 },
- { 20187500, BANDWIDTH_8_MHZ,
+ { 20187500, 8000000,
0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0 },
- { 20187500, BANDWIDTH_5_MHZ,
+ { 20187500, 5000000,
0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122 }
};
static struct adctable tab3[] = {
- { 20250000, BANDWIDTH_6_MHZ,
+ { 20250000, 6000000,
0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b },
- { 20250000, BANDWIDTH_7_MHZ,
+ { 20250000, 7000000,
0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195 },
- { 20250000, BANDWIDTH_8_MHZ,
+ { 20250000, 8000000,
0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce },
- { 20250000, BANDWIDTH_5_MHZ,
+ { 20250000, 5000000,
0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121 }
};
static struct adctable tab4[] = {
- { 20583333, BANDWIDTH_6_MHZ,
+ { 20583333, 6000000,
0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155 },
- { 20583333, BANDWIDTH_7_MHZ,
+ { 20583333, 7000000,
0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e },
- { 20583333, BANDWIDTH_8_MHZ,
+ { 20583333, 8000000,
0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7 },
- { 20583333, BANDWIDTH_5_MHZ,
+ { 20583333, 5000000,
0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c }
};
static struct adctable tab5[] = {
- { 20416667, BANDWIDTH_6_MHZ,
+ { 20416667, 6000000,
0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158 },
- { 20416667, BANDWIDTH_7_MHZ,
+ { 20416667, 7000000,
0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191 },
- { 20416667, BANDWIDTH_8_MHZ,
+ { 20416667, 8000000,
0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb },
- { 20416667, BANDWIDTH_5_MHZ,
+ { 20416667, 5000000,
0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f }
};
static struct adctable tab6[] = {
- { 20480000, BANDWIDTH_6_MHZ,
+ { 20480000, 6000000,
0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157 },
- { 20480000, BANDWIDTH_7_MHZ,
+ { 20480000, 7000000,
0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190 },
- { 20480000, BANDWIDTH_8_MHZ,
+ { 20480000, 8000000,
0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9 },
- { 20480000, BANDWIDTH_5_MHZ,
+ { 20480000, 5000000,
0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e }
};
static struct adctable tab7[] = {
- { 20500000, BANDWIDTH_6_MHZ,
+ { 20500000, 6000000,
0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157 },
- { 20500000, BANDWIDTH_7_MHZ,
+ { 20500000, 7000000,
0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190 },
- { 20500000, BANDWIDTH_8_MHZ,
+ { 20500000, 8000000,
0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9 },
- { 20500000, BANDWIDTH_5_MHZ,
+ { 20500000, 5000000,
0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d }
};
static struct adctable tab8[] = {
- { 20625000, BANDWIDTH_6_MHZ,
+ { 20625000, 6000000,
0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154 },
- { 20625000, BANDWIDTH_7_MHZ,
+ { 20625000, 7000000,
0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d },
- { 20625000, BANDWIDTH_8_MHZ,
+ { 20625000, 8000000,
0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6 },
- { 20625000, BANDWIDTH_5_MHZ,
+ { 20625000, 5000000,
0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c }
@@ -153,8 +153,7 @@ struct table {
};
static struct table fe_clockTable[] = {
- {12000000, tab3}, /* FPGA */
- {16384000, tab6}, /* 16.38MHz */
+ {12000000, tab3}, /* 12.00MHz */
{20480000, tab6}, /* 20.48MHz */
{36000000, tab3}, /* 36.00MHz */
{30000000, tab1}, /* 30.00MHz */
@@ -164,7 +163,6 @@ static struct table fe_clockTable[] = {
{34000000, tab2}, /* 34.00MHz */
{24000000, tab1}, /* 24.00MHz */
{22000000, tab8}, /* 22.00MHz */
- {12000000, tab3} /* 12.00MHz */
};
/* fe get */
@@ -205,6 +203,10 @@ fe_modulation_t fe_con[] = {
/* Standard demodulator functions */
static struct it913xset set_solo_fe[] = {
+ {PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+ {PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+ {PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+ {PRO_LINK, GPIOH5_O, {0x01}, 0x01},
{PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
{PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
@@ -228,13 +230,127 @@ static struct it913xset init_1[] = {
{PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
{PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
{PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+ {PRO_DMOD, 0xec57, {0x00, 0x00}, 0x02},
{PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
{PRO_LINK, PADMISCDR8, {0x00}, 0x01},
{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
};
-/* ---------IT9137 0x38 tuner init---------- */
-static struct it913xset it9137_set[] = {
+
+/* Version 1 types */
+static struct it913xset it9135_v1[] = {
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a}, 0x01},
+ {PRO_DMOD, 0x007e, {0x04}, 0x01},
+ {PRO_DMOD, 0x0081, {0x0a}, 0x01},
+ {PRO_DMOD, 0x008a, {0x01}, 0x01},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06}, 0x01},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009f, {0xe1}, 0x01},
+ {PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+ {PRO_DMOD, 0x00a3, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a5, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a6, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a9, {0x00}, 0x01},
+ {PRO_DMOD, 0x00aa, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00c2, {0x05}, 0x01},
+ {PRO_DMOD, 0x00c6, {0x19}, 0x01},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf016, {0x10}, 0x01},
+ {PRO_DMOD, 0xf017, {0x04}, 0x01},
+ {PRO_DMOD, 0xf018, {0x05}, 0x01},
+ {PRO_DMOD, 0xf019, {0x04}, 0x01},
+ {PRO_DMOD, 0xf01a, {0x05}, 0x01},
+ {PRO_DMOD, 0xf021, {0x03}, 0x01},
+ {PRO_DMOD, 0xf022, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf023, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf02b, {0x00}, 0x01},
+ {PRO_DMOD, 0xf02c, {0x01}, 0x01},
+ {PRO_DMOD, 0xf064, {0x03}, 0x01},
+ {PRO_DMOD, 0xf065, {0xf9}, 0x01},
+ {PRO_DMOD, 0xf066, {0x03}, 0x01},
+ {PRO_DMOD, 0xf067, {0x01}, 0x01},
+ {PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+ {PRO_DMOD, 0xf070, {0x03}, 0x01},
+ {PRO_DMOD, 0xf072, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf073, {0x03}, 0x01},
+ {PRO_DMOD, 0xf078, {0x00}, 0x01},
+ {PRO_DMOD, 0xf087, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+ {PRO_DMOD, 0xf09c, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09d, {0x20}, 0x01},
+ {PRO_DMOD, 0xf09e, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+ {PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14d, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf15b, {0x08}, 0x01},
+ {PRO_DMOD, 0xf15d, {0x03}, 0x01},
+ {PRO_DMOD, 0xf15e, {0x05}, 0x01},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01}, 0x01},
+ {PRO_DMOD, 0xf167, {0x40}, 0x01},
+ {PRO_DMOD, 0xf168, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf17a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf17b, {0x00}, 0x01},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+ {PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+ {PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+ {PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf40f, {0x40}, 0x01},
+ {PRO_DMOD, 0xf410, {0x08}, 0x01},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15}, 0x01},
+ {PRO_DMOD, 0xf562, {0x20}, 0x01},
+ {PRO_DMOD, 0xf5df, {0xfb}, 0x01},
+ {PRO_DMOD, 0xf5e0, {0x00}, 0x01},
+ {PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+ {PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+ {PRO_DMOD, 0xf600, {0x05}, 0x01},
+ {PRO_DMOD, 0xf601, {0x08}, 0x01},
+ {PRO_DMOD, 0xf602, {0x0b}, 0x01},
+ {PRO_DMOD, 0xf603, {0x0e}, 0x01},
+ {PRO_DMOD, 0xf604, {0x11}, 0x01},
+ {PRO_DMOD, 0xf605, {0x14}, 0x01},
+ {PRO_DMOD, 0xf606, {0x17}, 0x01},
+ {PRO_DMOD, 0xf607, {0x1f}, 0x01},
+ {PRO_DMOD, 0xf60e, {0x00}, 0x01},
+ {PRO_DMOD, 0xf60f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf610, {0x32}, 0x01},
+ {PRO_DMOD, 0xf611, {0x10}, 0x01},
+ {PRO_DMOD, 0xf707, {0xfc}, 0x01},
+ {PRO_DMOD, 0xf708, {0x00}, 0x01},
+ {PRO_DMOD, 0xf709, {0x37}, 0x01},
+ {PRO_DMOD, 0xf70a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40}, 0x01},
+ {PRO_DMOD, 0xf810, {0x54}, 0x01},
+ {PRO_DMOD, 0xf811, {0x5a}, 0x01},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_38[] = {
{PRO_DMOD, 0x0043, {0x00}, 0x01},
{PRO_DMOD, 0x0046, {0x38}, 0x01},
{PRO_DMOD, 0x0051, {0x01}, 0x01},
@@ -244,7 +360,7 @@ static struct it913xset it9137_set[] = {
{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
{PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
- 0xd0, 0xc3, 0x01 }, 0x0a},
+ 0xd0, 0xc3, 0x01}, 0x0a},
{PRO_DMOD, 0x008e, {0x01}, 0x01},
{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
{PRO_DMOD, 0x0099, {0x01}, 0x01},
@@ -262,15 +378,25 @@ static struct it913xset it9137_set[] = {
{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
{PRO_DMOD, 0x00fc, { 0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
- 0x00, 0x02, 0xc8, 0x05, 0x7b }, 0x0c},
+ 0x00, 0x02, 0xc8, 0x05, 0x7b}, 0x0c},
{PRO_DMOD, 0x0109, {0x02}, 0x01},
- {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
- {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0xbc, 0xa0}, 0x04},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+ {PRO_DMOD, 0x011a, {0xc8, 0x7b, 0x8a, 0xa0}, 0x04},
{PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
- {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8}, 0x04},
+ {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8, 0x59}, 0x05},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf085, {0x00, 0x02, 0x00}, 0x03},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
{PRO_DMOD, 0xf130, {0x04}, 0x01},
{PRO_DMOD, 0xf132, {0x04}, 0x01},
{PRO_DMOD, 0xf144, {0x1a}, 0x01},
@@ -301,7 +427,7 @@ static struct it913xset it9137_set[] = {
{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
{PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
- 0x1f }, 0x08},
+ 0x1f}, 0x08},
{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
{PRO_DMOD, 0xf78b, {0x01}, 0x01},
@@ -309,21 +435,605 @@ static struct it913xset it9137_set[] = {
{PRO_DMOD, 0xf905, {0x01}, 0x01},
{PRO_DMOD, 0xfb06, {0x03}, 0x01},
{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
- {PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
- {PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
- {PRO_LINK, GPIOH5_O, {0x00}, 0x01},
- {PRO_LINK, GPIOH5_O, {0x01}, 0x01},
- {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_51[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x51}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x06, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+ {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc0, 0x96,
+ 0xcf, 0xc3, 0x01}, 0x0a},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+ {PRO_DMOD, 0x00c4, {0x00}, 0x01},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+ {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x03, 0x02, 0x02, 0x09, 0x50, 0x7a, 0x77,
+ 0x01, 0x02, 0xb0, 0x02, 0x7a}, 0x0c},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+ {PRO_DMOD, 0x011a, {0xc0, 0x7a, 0xac, 0x8c}, 0x04},
+ {PRO_DMOD, 0x0122, {0x02, 0x70, 0xa4}, 0x03},
+ {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+ {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+ {PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+ {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc0, 0x59}, 0x05},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+ {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+ 0x1f}, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_52[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x52}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x10}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xa0, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+ {PRO_DMOD, 0x0081, { 0x0a, 0x12, 0x03, 0x0a, 0x03, 0xb3, 0x97,
+ 0xc0, 0x9e, 0x01}, 0x0a},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+ {PRO_DMOD, 0x00c4, {0x00}, 0x01},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+ {PRO_DMOD, 0x00f3, {0x05, 0x91, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x03, 0x02, 0x02, 0x09, 0x50, 0x74, 0x77,
+ 0x02, 0x02, 0xae, 0x02, 0x6e}, 0x0c},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+ {PRO_DMOD, 0x011a, {0xcd, 0x62, 0xa4, 0x8c}, 0x04},
+ {PRO_DMOD, 0x0122, {0x03, 0x18, 0x9e}, 0x03},
+ {PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+ {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+ {PRO_DMOD, 0x0137, {0x00, 0x00, 0x07, 0x00, 0x06}, 0x05},
+ {PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xb6, 0x59}, 0x05},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+ {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+ 0x1f}, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
};
+/* Version 2 types */
+static struct it913xset it9135_v2[] = {
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a}, 0x01},
+ {PRO_DMOD, 0x007e, {0x04}, 0x01},
+ {PRO_DMOD, 0x0081, {0x0a}, 0x01},
+ {PRO_DMOD, 0x008a, {0x01}, 0x01},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06}, 0x01},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009f, {0xe1}, 0x01},
+ {PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+ {PRO_DMOD, 0x00a3, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a5, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a6, {0x01}, 0x01},
+ {PRO_DMOD, 0x00a9, {0x00}, 0x01},
+ {PRO_DMOD, 0x00aa, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00c2, {0x05}, 0x01},
+ {PRO_DMOD, 0x00c6, {0x19}, 0x01},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf02b, {0x00}, 0x01},
+ {PRO_DMOD, 0xf064, {0x03}, 0x01},
+ {PRO_DMOD, 0xf065, {0xf9}, 0x01},
+ {PRO_DMOD, 0xf066, {0x03}, 0x01},
+ {PRO_DMOD, 0xf067, {0x01}, 0x01},
+ {PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+ {PRO_DMOD, 0xf070, {0x03}, 0x01},
+ {PRO_DMOD, 0xf072, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf073, {0x03}, 0x01},
+ {PRO_DMOD, 0xf078, {0x00}, 0x01},
+ {PRO_DMOD, 0xf087, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+ {PRO_DMOD, 0xf09c, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09d, {0x20}, 0x01},
+ {PRO_DMOD, 0xf09e, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+ {PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14d, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf15b, {0x08}, 0x01},
+ {PRO_DMOD, 0xf15d, {0x03}, 0x01},
+ {PRO_DMOD, 0xf15e, {0x05}, 0x01},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01}, 0x01},
+ {PRO_DMOD, 0xf167, {0x40}, 0x01},
+ {PRO_DMOD, 0xf168, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf17a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf17b, {0x00}, 0x01},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+ {PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+ {PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+ {PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf40f, {0x40}, 0x01},
+ {PRO_DMOD, 0xf410, {0x08}, 0x01},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15}, 0x01},
+ {PRO_DMOD, 0xf562, {0x20}, 0x01},
+ {PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+ {PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+ {PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+ {PRO_DMOD, 0xf600, {0x05}, 0x01},
+ {PRO_DMOD, 0xf601, {0x08}, 0x01},
+ {PRO_DMOD, 0xf602, {0x0b}, 0x01},
+ {PRO_DMOD, 0xf603, {0x0e}, 0x01},
+ {PRO_DMOD, 0xf604, {0x11}, 0x01},
+ {PRO_DMOD, 0xf605, {0x14}, 0x01},
+ {PRO_DMOD, 0xf606, {0x17}, 0x01},
+ {PRO_DMOD, 0xf607, {0x1f}, 0x01},
+ {PRO_DMOD, 0xf60e, {0x00}, 0x01},
+ {PRO_DMOD, 0xf60f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf610, {0x32}, 0x01},
+ {PRO_DMOD, 0xf611, {0x10}, 0x01},
+ {PRO_DMOD, 0xf707, {0xfc}, 0x01},
+ {PRO_DMOD, 0xf708, {0x00}, 0x01},
+ {PRO_DMOD, 0xf709, {0x37}, 0x01},
+ {PRO_DMOD, 0xf70a, {0x00}, 0x01},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40}, 0x01},
+ {PRO_DMOD, 0xf810, {0x54}, 0x01},
+ {PRO_DMOD, 0xf811, {0x5a}, 0x01},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_60[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x60}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+ {PRO_DMOD, 0x006a, {0x03}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04}, 0x01},
+ {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+ {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbe, 0xa0, 0xc6, 0xb6, 0x01}, 0x07},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+ {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x03, 0x03, 0x02, 0x0a, 0x50, 0x7b, 0x8c,
+ 0x00, 0x02, 0xbe, 0x00}, 0x0b},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+ {PRO_DMOD, 0x011a, {0xbe}, 0x01},
+ {PRO_DMOD, 0x0124, {0xae}, 0x01},
+ {PRO_DMOD, 0x0127, {0x00}, 0x01},
+ {PRO_DMOD, 0x012a, {0x56, 0x50, 0x47, 0x42}, 0x04},
+ {PRO_DMOD, 0x0137, {0x00}, 0x01},
+ {PRO_DMOD, 0x013b, {0x08}, 0x01},
+ {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+ {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x19, 0x19, 0x8c, 0x8c, 0x8c,
+ 0x6e, 0x8c, 0x50, 0x8c, 0x8c, 0xac, 0xc6,
+ 0x33}, 0x0f},
+ {PRO_DMOD, 0x0151, {0x28}, 0x01},
+ {PRO_DMOD, 0x0153, {0xbc}, 0x01},
+ {PRO_DMOD, 0x0178, {0x09}, 0x01},
+ {PRO_DMOD, 0x0181, {0x94, 0x6e}, 0x02},
+ {PRO_DMOD, 0x0185, {0x24}, 0x01},
+ {PRO_DMOD, 0x0187, {0x00, 0x00, 0xbe, 0x02, 0x80}, 0x05},
+ {PRO_DMOD, 0xed02, {0xff}, 0x01},
+ {PRO_DMOD, 0xee42, {0xff}, 0x01},
+ {PRO_DMOD, 0xee82, {0xff}, 0x01},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf087, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17
+ , 0x1f}, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_61[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x61}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x06}, 0x01},
+ {PRO_DMOD, 0x006a, {0x03}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x90, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04}, 0x01},
+ {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+ {PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbc, 0x9c, 0xcc, 0xa8, 0x01}, 0x07},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+ {PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x03, 0x03, 0x02, 0x08, 0x50, 0x7b, 0x8c,
+ 0x01, 0x02, 0xc8, 0x00}, 0x0b},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+ {PRO_DMOD, 0x011a, {0xc6}, 0x01},
+ {PRO_DMOD, 0x0124, {0xa8}, 0x01},
+ {PRO_DMOD, 0x0127, {0x00}, 0x01},
+ {PRO_DMOD, 0x012a, {0x59, 0x50, 0x47, 0x42}, 0x04},
+ {PRO_DMOD, 0x0137, {0x00}, 0x01},
+ {PRO_DMOD, 0x013b, {0x05}, 0x01},
+ {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+ {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x59, 0x59, 0x8c, 0x8c, 0x8c,
+ 0x7b, 0x8c, 0x50, 0x8c, 0x8c, 0xa8, 0xc6,
+ 0x33}, 0x0f},
+ {PRO_DMOD, 0x0151, {0x28}, 0x01},
+ {PRO_DMOD, 0x0153, {0xcc}, 0x01},
+ {PRO_DMOD, 0x0178, {0x09}, 0x01},
+ {PRO_DMOD, 0x0181, {0x9c, 0x76}, 0x02},
+ {PRO_DMOD, 0x0185, {0x28}, 0x01},
+ {PRO_DMOD, 0x0187, {0x01, 0x00, 0xaa, 0x02, 0x80}, 0x05},
+ {PRO_DMOD, 0xed02, {0xff}, 0x01},
+ {PRO_DMOD, 0xee42, {0xff}, 0x01},
+ {PRO_DMOD, 0xee82, {0xff}, 0x01},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf087, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+ 0x1f}, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_62[] = {
+ {PRO_DMOD, 0x0043, {0x00}, 0x01},
+ {PRO_DMOD, 0x0046, {0x62}, 0x01},
+ {PRO_DMOD, 0x0051, {0x01}, 0x01},
+ {PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0x0068, {0x0a}, 0x01},
+ {PRO_DMOD, 0x006a, {0x03}, 0x01},
+ {PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+ {PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+ {PRO_DMOD, 0x007e, {0x04}, 0x01},
+ {PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+ {PRO_DMOD, 0x0084, { 0x0a, 0x33, 0xb8, 0x9c, 0xb2, 0xa6, 0x01},
+ 0x07},
+ {PRO_DMOD, 0x008e, {0x01}, 0x01},
+ {PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+ {PRO_DMOD, 0x0099, {0x01}, 0x01},
+ {PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+ {PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+ {PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+ {PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+ {PRO_DMOD, 0x00b0, {0x01}, 0x01},
+ {PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+ {PRO_DMOD, 0x00b6, {0x14}, 0x01},
+ {PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+ {PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+ {PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+ {PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+ {PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+ {PRO_DMOD, 0x00fc, { 0x02, 0x03, 0x02, 0x09, 0x50, 0x6e, 0x8c,
+ 0x02, 0x02, 0xc2, 0x00}, 0x0b},
+ {PRO_DMOD, 0x0109, {0x02}, 0x01},
+ {PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+ {PRO_DMOD, 0x011a, {0xb8}, 0x01},
+ {PRO_DMOD, 0x0124, {0xa8}, 0x01},
+ {PRO_DMOD, 0x0127, {0x00}, 0x01},
+ {PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+ {PRO_DMOD, 0x0137, {0x00}, 0x01},
+ {PRO_DMOD, 0x013b, {0x05}, 0x01},
+ {PRO_DMOD, 0x013f, {0x5b}, 0x01},
+ {PRO_DMOD, 0x0141, { 0x59, 0xf9, 0x59, 0x19, 0x8c, 0x8c, 0x8c,
+ 0x7b, 0x8c, 0x50, 0x70, 0x8c, 0x96, 0xd0,
+ 0x33}, 0x0f},
+ {PRO_DMOD, 0x0151, {0x28}, 0x01},
+ {PRO_DMOD, 0x0153, {0xb2}, 0x01},
+ {PRO_DMOD, 0x0178, {0x09}, 0x01},
+ {PRO_DMOD, 0x0181, {0x9c, 0x6e}, 0x02},
+ {PRO_DMOD, 0x0185, {0x24}, 0x01},
+ {PRO_DMOD, 0x0187, {0x00, 0x00, 0xb8, 0x02, 0x80}, 0x05},
+ {PRO_DMOD, 0xed02, {0xff}, 0x01},
+ {PRO_DMOD, 0xee42, {0xff}, 0x01},
+ {PRO_DMOD, 0xee82, {0xff}, 0x01},
+ {PRO_DMOD, 0xf000, {0x0f}, 0x01},
+ {PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+ {PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+ {PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+ {PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+ {PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+ {PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+ {PRO_DMOD, 0xf087, {0x00}, 0x01},
+ {PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+ {PRO_DMOD, 0xf130, {0x04}, 0x01},
+ {PRO_DMOD, 0xf132, {0x04}, 0x01},
+ {PRO_DMOD, 0xf144, {0x1a}, 0x01},
+ {PRO_DMOD, 0xf146, {0x00}, 0x01},
+ {PRO_DMOD, 0xf14a, {0x01}, 0x01},
+ {PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf14f, {0x04}, 0x01},
+ {PRO_DMOD, 0xf158, {0x7f}, 0x01},
+ {PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+ {PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+ {PRO_DMOD, 0xf163, {0x05}, 0x01},
+ {PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+ {PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+ {PRO_DMOD, 0xf183, {0x01}, 0x01},
+ {PRO_DMOD, 0xf19d, {0x40}, 0x01},
+ {PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+ {PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+ {PRO_DMOD, 0xf204, {0x10}, 0x01},
+ {PRO_DMOD, 0xf214, {0x00}, 0x01},
+ {PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+ {PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+ {PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+ {PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+ {PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+ {PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+ {PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+ {PRO_DMOD, 0xf600, { 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+ 0x1f}, 0x08},
+ {PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+ {PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+ {PRO_DMOD, 0xf78b, {0x01}, 0x01},
+ {PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+ {PRO_DMOD, 0xf905, {0x01}, 0x01},
+ {PRO_DMOD, 0xfb06, {0x03}, 0x01},
+ {PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* Tuner setting scripts (still keeping it9137) */
static struct it913xset it9137_tuner_off[] = {
{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off */
{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+ {PRO_DMOD, 0xec06, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00}, 0x0c},
+ {PRO_DMOD, 0xec12, {0x00, 0x00, 0x00, 0x00}, 0x04},
+ {PRO_DMOD, 0xec17, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00}, 0x09},
+ {PRO_DMOD, 0xec22, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00}, 0x0a},
+ {PRO_DMOD, 0xec20, {0x00}, 0x01},
{PRO_DMOD, 0xec3f, {0x01}, 0x01},
{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
};
+static struct it913xset set_it9135_template[] = {
+ {PRO_DMOD, 0xee06, {0x00}, 0x01},
+ {PRO_DMOD, 0xec56, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4c, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4d, {0x00}, 0x01},
+ {PRO_DMOD, 0xec4e, {0x00}, 0x01},
+ {PRO_DMOD, 0x011e, {0x00}, 0x01}, /* Older Devices */
+ {PRO_DMOD, 0x011f, {0x00}, 0x01},
+ {0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
static struct it913xset set_it9137_template[] = {
{PRO_DMOD, 0xee06, {0x00}, 0x01},
{PRO_DMOD, 0xec56, {0x00}, 0x01},
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c
index d4bd24e..ccc36bf 100644
--- a/drivers/media/dvb/frontends/it913x-fe.c
+++ b/drivers/media/dvb/frontends/it913x-fe.c
@@ -46,13 +46,17 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
dprintk(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(format, arg...) \
+ printk(KERN_INFO "it913x-fe: " format "\n" , ## arg)
struct it913x_fe_state {
struct dvb_frontend frontend;
struct i2c_adapter *i2c_adap;
+ struct ite_config *config;
u8 i2c_addr;
u32 frequency;
- u8 adf;
+ fe_modulation_t constellation;
+ fe_transmit_mode_t transmission_mode;
u32 crystalFrequency;
u32 adcFrequency;
u8 tuner_type;
@@ -62,6 +66,7 @@ struct it913x_fe_state {
u8 tun_fdiv;
u8 tun_clk_mode;
u32 tun_fn_min;
+ u32 ucblocks;
};
static int it913x_read_reg(struct it913x_fe_state *state,
@@ -211,20 +216,24 @@ static int it913x_init_tuner(struct it913x_fe_state *state)
state->tun_fn_min /= (state->tun_fdiv * nv_val);
deb_info("Tuner fn_min %d", state->tun_fn_min);
- for (i = 0; i < 50; i++) {
- reg = it913x_read_reg_u8(state, 0xec82);
- if (reg > 0)
- break;
- if (reg < 0)
- return -ENODEV;
- udelay(2000);
+ if (state->config->chip_ver > 1)
+ msleep(50);
+ else {
+ for (i = 0; i < 50; i++) {
+ reg = it913x_read_reg_u8(state, 0xec82);
+ if (reg > 0)
+ break;
+ if (reg < 0)
+ return -ENODEV;
+ udelay(2000);
+ }
}
return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
}
static int it9137_set_tuner(struct it913x_fe_state *state,
- enum fe_bandwidth bandwidth, u32 frequency_m)
+ u32 bandwidth, u32 frequency_m)
{
struct it913xset *set_tuner = set_it9137_template;
int ret, reg;
@@ -237,6 +246,11 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
u8 lna_band;
u8 bw;
+ if (state->config->firmware_ver == 1)
+ set_tuner = set_it9135_template;
+ else
+ set_tuner = set_it9137_template;
+
deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
if (frequency >= 51000 && frequency <= 440000) {
@@ -273,16 +287,21 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
return -EINVAL;
set_tuner[0].reg[0] = lna_band;
- if (bandwidth == BANDWIDTH_5_MHZ)
+ switch (bandwidth) {
+ case 5000000:
bw = 0;
- else if (bandwidth == BANDWIDTH_6_MHZ)
+ break;
+ case 6000000:
bw = 2;
- else if (bandwidth == BANDWIDTH_7_MHZ)
+ break;
+ case 7000000:
bw = 4;
- else if (bandwidth == BANDWIDTH_8_MHZ)
- bw = 6;
- else
+ break;
+ default:
+ case 8000000:
bw = 6;
+ break;
+ }
set_tuner[1].reg[0] = bw;
set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
@@ -361,7 +380,7 @@ static int it9137_set_tuner(struct it913x_fe_state *state,
}
static int it913x_fe_select_bw(struct it913x_fe_state *state,
- enum fe_bandwidth bandwidth, u32 adcFrequency)
+ u32 bandwidth, u32 adcFrequency)
{
int ret, i;
u8 buffer[256];
@@ -374,17 +393,21 @@ static int it913x_fe_select_bw(struct it913x_fe_state *state,
deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
- if (bandwidth == BANDWIDTH_5_MHZ)
+ switch (bandwidth) {
+ case 5000000:
bw = 3;
- else if (bandwidth == BANDWIDTH_6_MHZ)
+ break;
+ case 6000000:
bw = 0;
- else if (bandwidth == BANDWIDTH_7_MHZ)
+ break;
+ case 7000000:
bw = 1;
- else if (bandwidth == BANDWIDTH_8_MHZ)
- bw = 2;
- else
+ break;
+ default:
+ case 8000000:
bw = 2;
-
+ break;
+ }
ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
if (state->table == NULL)
@@ -492,31 +515,79 @@ static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
return 0;
}
-static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr)
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct it913x_fe_state *state = fe->demodulator_priv;
- int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
- ret = (ret * 0xff) / 0x64;
- ret |= (ret << 0x8);
- *snr = ~ret;
- return 0;
+ int ret;
+ u8 reg[3];
+ u32 snr_val, snr_min, snr_max;
+ u32 temp;
+
+ ret = it913x_read_reg(state, 0x2c, reg, sizeof(reg));
+
+ snr_val = (u32)(reg[2] << 16) | (reg[1] << 8) | reg[0];
+
+ ret |= it913x_read_reg(state, 0xf78b, reg, 1);
+ if (reg[0])
+ snr_val /= reg[0];
+
+ if (state->transmission_mode == TRANSMISSION_MODE_2K)
+ snr_val *= 4;
+ else if (state->transmission_mode == TRANSMISSION_MODE_4K)
+ snr_val *= 2;
+
+ if (state->constellation == QPSK) {
+ snr_min = 0xb4711;
+ snr_max = 0x191451;
+ } else if (state->constellation == QAM_16) {
+ snr_min = 0x4f0d5;
+ snr_max = 0xc7925;
+ } else if (state->constellation == QAM_64) {
+ snr_min = 0x256d0;
+ snr_max = 0x626be;
+ } else
+ return -EINVAL;
+
+ if (snr_val < snr_min)
+ *snr = 0;
+ else if (snr_val < snr_max) {
+ temp = (snr_val - snr_min) >> 5;
+ temp *= 0xffff;
+ temp /= (snr_max - snr_min) >> 5;
+ *snr = (u16)temp;
+ } else
+ *snr = 0xffff;
+
+ return (ret < 0) ? -ENODEV : 0;
}
static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- *ber = 0;
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 reg[5];
+ /* Read Aborted Packets and Pre-Viterbi error rate 5 bytes */
+ ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+ state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+ *ber = (u32)(reg[4] << 16) | (reg[3] << 8) | reg[2];
return 0;
}
static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
- *ucblocks = 0;
- return 0;
+ struct it913x_fe_state *state = fe->demodulator_priv;
+ int ret;
+ u8 reg[2];
+ /* Aborted Packets */
+ ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+ state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+ *ucblocks = state->ucblocks;
+ return ret;
}
-static int it913x_fe_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int it913x_fe_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct it913x_fe_state *state = fe->demodulator_priv;
int ret;
u8 reg[8];
@@ -524,26 +595,30 @@ static int it913x_fe_get_frontend(struct dvb_frontend *fe,
ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
if (reg[3] < 3)
- p->u.ofdm.constellation = fe_con[reg[3]];
+ p->modulation = fe_con[reg[3]];
if (reg[0] < 3)
- p->u.ofdm.transmission_mode = fe_mode[reg[0]];
+ p->transmission_mode = fe_mode[reg[0]];
if (reg[1] < 4)
- p->u.ofdm.guard_interval = fe_gi[reg[1]];
+ p->guard_interval = fe_gi[reg[1]];
if (reg[2] < 4)
- p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
+ p->hierarchy = fe_hi[reg[2]];
+
+ p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+ p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
- p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
- p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+ /* Update internal state to reflect the autodetected props */
+ state->constellation = p->modulation;
+ state->transmission_mode = p->transmission_mode;
return 0;
}
-static int it913x_fe_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int it913x_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct it913x_fe_state *state = fe->demodulator_priv;
int ret, i;
u8 empty_ch, last_ch;
@@ -551,7 +626,7 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe,
state->it913x_status = 0;
/* Set bw*/
- ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
+ ret = it913x_fe_select_bw(state, p->bandwidth_hz,
state->adcFrequency);
/* Training Mode Off */
@@ -571,20 +646,25 @@ static int it913x_fe_set_frontend(struct dvb_frontend *fe,
i = 1;
else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
i = 2;
- else
- return -EOPNOTSUPP;
+ else
+ return -EOPNOTSUPP;
ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
switch (state->tuner_type) {
- case IT9137: /* Tuner type 0x38 */
+ case IT9135_38:
+ case IT9135_51:
+ case IT9135_52:
+ case IT9135_60:
+ case IT9135_61:
+ case IT9135_62:
ret = it9137_set_tuner(state,
- p->u.ofdm.bandwidth, p->frequency);
+ p->bandwidth_hz, p->frequency);
break;
default:
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -678,16 +758,19 @@ static u32 compute_div(u32 a, u32 b, u32 x)
static int it913x_fe_start(struct it913x_fe_state *state)
{
- struct it913xset *set_fe;
+ struct it913xset *set_lna;
struct it913xset *set_mode;
int ret;
- u8 adf = (state->adf & 0xf);
+ u8 adf = (state->config->adf & 0xf);
u32 adc, xtal;
u8 b[4];
- ret = it913x_init_tuner(state);
+ if (state->config->chip_ver == 1)
+ ret = it913x_init_tuner(state);
+
+ info("ADF table value :%02x", adf);
- if (adf < 12) {
+ if (adf < 10) {
state->crystalFrequency = fe_clockTable[adf].xtal ;
state->table = fe_clockTable[adf].table;
state->adcFrequency = state->table->adcFrequency;
@@ -698,9 +781,6 @@ static int it913x_fe_start(struct it913x_fe_state *state)
} else
return -EINVAL;
- deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
- state->crystalFrequency, state->adcFrequency, adc, xtal);
-
/* Set LED indicator on GPIOH3 */
ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
@@ -721,22 +801,71 @@ static int it913x_fe_start(struct it913x_fe_state *state)
b[2] = (adc >> 16) & 0xff;
ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
+ if (state->config->adc_x2)
+ ret |= it913x_write_reg(state, PRO_DMOD, ADC_X_2, 0x01);
+ b[0] = 0;
+ b[1] = 0;
+ b[2] = 0;
+ ret |= it913x_write(state, PRO_DMOD, 0x0029, b, 3);
+
+ info("Crystal Frequency :%d Adc Frequency :%d ADC X2: %02x",
+ state->crystalFrequency, state->adcFrequency,
+ state->config->adc_x2);
+ deb_info("Xtal value :%04x Adc value :%04x", xtal, adc);
+
+ if (ret < 0)
+ return -ENODEV;
+
+ /* v1 or v2 tuner script */
+ if (state->config->chip_ver > 1)
+ ret = it913x_fe_script_loader(state, it9135_v2);
+ else
+ ret = it913x_fe_script_loader(state, it9135_v1);
+ if (ret < 0)
+ return ret;
+
+ /* LNA Scripts */
switch (state->tuner_type) {
- case IT9137: /* Tuner type 0x38 */
- set_fe = it9137_set;
+ case IT9135_51:
+ set_lna = it9135_51;
+ break;
+ case IT9135_52:
+ set_lna = it9135_52;
+ break;
+ case IT9135_60:
+ set_lna = it9135_60;
+ break;
+ case IT9135_61:
+ set_lna = it9135_61;
break;
+ case IT9135_62:
+ set_lna = it9135_62;
+ break;
+ case IT9135_38:
default:
- return -EINVAL;
+ set_lna = it9135_38;
}
+ info("Tuner LNA type :%02x", state->tuner_type);
+
+ ret = it913x_fe_script_loader(state, set_lna);
+ if (ret < 0)
+ return ret;
+
+ if (state->config->chip_ver == 2) {
+ ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x1);
+ ret |= it913x_write_reg(state, PRO_LINK, PADODPU, 0x0);
+ ret |= it913x_write_reg(state, PRO_LINK, AGC_O_D, 0x0);
+ ret |= it913x_init_tuner(state);
+ }
+ if (ret < 0)
+ return -ENODEV;
- /* set the demod */
- ret = it913x_fe_script_loader(state, set_fe);
/* Always solo frontend */
set_mode = set_solo_fe;
ret |= it913x_fe_script_loader(state, set_mode);
ret |= it913x_fe_suspend(state);
- return 0;
+ return (ret < 0) ? -ENODEV : 0;
}
static int it913x_fe_init(struct dvb_frontend *fe)
@@ -746,17 +875,11 @@ static int it913x_fe_init(struct dvb_frontend *fe)
/* Power Up Tuner - common all versions */
ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
- ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
-
ret |= it913x_fe_script_loader(state, init_1);
- switch (state->tuner_type) {
- case IT9137:
- ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
- break;
- default:
- return -EINVAL;
- }
+ ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+ ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
return (ret < 0) ? -ENODEV : 0;
}
@@ -770,19 +893,34 @@ static void it913x_fe_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops it913x_fe_ofdm_ops;
struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
- u8 i2c_addr, u8 adf, u8 type)
+ u8 i2c_addr, struct ite_config *config)
{
struct it913x_fe_state *state = NULL;
int ret;
+
/* allocate memory for the internal state */
state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
if (state == NULL)
+ return NULL;
+ if (config == NULL)
goto error;
state->i2c_adap = i2c_adap;
state->i2c_addr = i2c_addr;
- state->adf = adf;
- state->tuner_type = type;
+ state->config = config;
+
+ switch (state->config->tuner_id_0) {
+ case IT9135_51:
+ case IT9135_52:
+ case IT9135_60:
+ case IT9135_61:
+ case IT9135_62:
+ state->tuner_type = state->config->tuner_id_0;
+ break;
+ default:
+ case IT9135_38:
+ state->tuner_type = IT9135_38;
+ }
ret = it913x_fe_start(state);
if (ret < 0)
@@ -802,10 +940,9 @@ error:
EXPORT_SYMBOL(it913x_fe_attach);
static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "it913x-fe DVB-T",
- .type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 1680000000,
.frequency_stepsize = 62500,
@@ -835,5 +972,5 @@ static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_VERSION("1.07");
+MODULE_VERSION("1.13");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb/frontends/it913x-fe.h
index 9d97f32..c4a908e 100644
--- a/drivers/media/dvb/frontends/it913x-fe.h
+++ b/drivers/media/dvb/frontends/it913x-fe.h
@@ -23,13 +23,27 @@
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
+
+struct ite_config {
+ u8 chip_ver;
+ u16 chip_type;
+ u32 firmware;
+ u8 firmware_ver;
+ u8 adc_x2;
+ u8 tuner_id_0;
+ u8 tuner_id_1;
+ u8 dual_mode;
+ u8 adf;
+};
+
#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
defined(MODULE))
extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
- u8 i2c_addr, u8 adf, u8 type);
+ u8 i2c_addr, struct ite_config *config);
#else
static inline struct dvb_frontend *it913x_fe_attach(
- struct i2c_adapter *i2c_adap, u8 i2c_addr, u8 adf, u8 type)
+ struct i2c_adapter *i2c_adap,
+ u8 i2c_addr, struct ite_config *config)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
@@ -134,6 +148,16 @@ static inline struct dvb_frontend *it913x_fe_attach(
#define COEFF_1_2048 0x0001
#define XTAL_CLK 0x0025
#define BFS_FCW 0x0029
+
+/* Error Regs */
+#define RSD_ABORT_PKT_LSB 0x0032
+#define RSD_ABORT_PKT_MSB 0x0033
+#define RSD_BIT_ERR_0_7 0x0034
+#define RSD_BIT_ERR_8_15 0x0035
+#define RSD_BIT_ERR_23_16 0x0036
+#define RSD_BIT_COUNT_LSB 0x0037
+#define RSD_BIT_COUNT_MSB 0x0038
+
#define TPSD_LOCK 0x003c
#define TRAINING_MODE 0x0040
#define ADC_X_2 0x0045
@@ -144,8 +168,14 @@ static inline struct dvb_frontend *it913x_fe_attach(
#define EST_SIGNAL_LEVEL 0x004a
#define FREE_BAND 0x004b
#define SUSPEND_FLAG 0x004c
-/* Build in tuners */
+/* Build in tuner types */
#define IT9137 0x38
+#define IT9135_38 0x38
+#define IT9135_51 0x51
+#define IT9135_52 0x52
+#define IT9135_60 0x60
+#define IT9135_61 0x61
+#define IT9135_62 0x62
enum {
CMD_DEMOD_READ = 0,
@@ -193,4 +223,11 @@ enum {
WRITE_CMD,
};
+enum {
+ IT9135_AUTO = 0,
+ IT9137_FW,
+ IT9135_V1_FW,
+ IT9135_V2_FW,
+};
+
#endif /* IT913X_FE_H */
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
index aa9ccb8..3164575 100644
--- a/drivers/media/dvb/frontends/itd1000.c
+++ b/drivers/media/dvb/frontends/itd1000.c
@@ -250,13 +250,14 @@ static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
itd1000_set_vco(state, freq_khz);
}
-static int itd1000_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int itd1000_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct itd1000_state *state = fe->tuner_priv;
u8 pllcon1;
- itd1000_set_lo(state, p->frequency);
- itd1000_set_lpf_bw(state, p->u.qpsk.symbol_rate);
+ itd1000_set_lo(state, c->frequency);
+ itd1000_set_lpf_bw(state, c->symbol_rate);
pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
index 9a517a4..bc5a820 100644
--- a/drivers/media/dvb/frontends/ix2505v.c
+++ b/drivers/media/dvb/frontends/ix2505v.c
@@ -129,12 +129,12 @@ static int ix2505v_release(struct dvb_frontend *fe)
* 1 -> 8 -> 6
*/
-static int ix2505v_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int ix2505v_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct ix2505v_state *state = fe->tuner_priv;
- u32 frequency = params->frequency;
- u32 b_w = (params->u.qpsk.symbol_rate * 27) / 32000;
+ u32 frequency = c->frequency;
+ u32 b_w = (c->symbol_rate * 27) / 32000;
u32 div_factor, N , A, x;
int ret = 0, len;
u8 gain, cc, ref, psc, local_osc, lpf;
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index 445fa10..36fcf55 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -117,18 +117,17 @@ static int reset_and_configure (struct l64781_state* state)
return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
}
-static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
+static int apply_frontend_param(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct l64781_state* state = fe->demodulator_priv;
/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
/* QPSK, QAM_16, QAM_64 */
static const u8 qam_tab [] = { 2, 4, 0, 6 };
- static const u8 bw_tab [] = { 8, 7, 6 }; /* 8Mhz, 7MHz, 6MHz */
static const u8 guard_tab [] = { 1, 2, 4, 8 };
/* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
static const u32 ppm = 8000;
- struct dvb_ofdm_parameters *p = &param->u.ofdm;
u32 ddfs_offset_fixed;
/* u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
/* bw_tab[p->bandWidth]<<10)/15625; */
@@ -137,18 +136,29 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
u8 val0x04;
u8 val0x05;
u8 val0x06;
- int bw = p->bandwidth - BANDWIDTH_8_MHZ;
+ int bw;
+
+ switch (p->bandwidth_hz) {
+ case 8000000:
+ bw = 8;
+ break;
+ case 7000000:
+ bw = 7;
+ break;
+ case 6000000:
+ bw = 6;
+ break;
+ default:
+ return -EINVAL;
+ }
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- if (param->inversion != INVERSION_ON &&
- param->inversion != INVERSION_OFF)
- return -EINVAL;
-
- if (bw < 0 || bw > 2)
+ if (p->inversion != INVERSION_ON &&
+ p->inversion != INVERSION_OFF)
return -EINVAL;
if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
@@ -156,14 +166,14 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
p->code_rate_HP != FEC_7_8)
return -EINVAL;
- if (p->hierarchy_information != HIERARCHY_NONE &&
+ if (p->hierarchy != HIERARCHY_NONE &&
(p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
p->code_rate_LP != FEC_7_8))
return -EINVAL;
- if (p->constellation != QPSK && p->constellation != QAM_16 &&
- p->constellation != QAM_64)
+ if (p->modulation != QPSK && p->modulation != QAM_16 &&
+ p->modulation != QAM_64)
return -EINVAL;
if (p->transmission_mode != TRANSMISSION_MODE_2K &&
@@ -174,22 +184,22 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
p->guard_interval > GUARD_INTERVAL_1_4)
return -EINVAL;
- if (p->hierarchy_information < HIERARCHY_NONE ||
- p->hierarchy_information > HIERARCHY_4)
+ if (p->hierarchy < HIERARCHY_NONE ||
+ p->hierarchy > HIERARCHY_4)
return -EINVAL;
- ddfs_offset_fixed = 0x4000-(ppm<<16)/bw_tab[p->bandwidth]/1000000;
+ ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
/* This works up to 20000 ppm, it overflows if too large ppm! */
init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
- bw_tab[p->bandwidth] & 0xFFFFFF);
+ bw & 0xFFFFFF);
/* SPI bias calculation is slightly modified to fit in 32bit */
/* will work for high ppm only... */
spi_bias = 378 * (1 << 10);
spi_bias *= 16;
- spi_bias *= bw_tab[p->bandwidth];
- spi_bias *= qam_tab[p->constellation];
+ spi_bias *= bw;
+ spi_bias *= qam_tab[p->modulation];
spi_bias /= p->code_rate_HP + 1;
spi_bias /= (guard_tab[p->guard_interval] + 32);
spi_bias *= 1000;
@@ -199,10 +209,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
val0x04 = (p->transmission_mode << 2) | p->guard_interval;
val0x05 = fec_tab[p->code_rate_HP];
- if (p->hierarchy_information != HIERARCHY_NONE)
+ if (p->hierarchy != HIERARCHY_NONE)
val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
- val0x06 = (p->hierarchy_information << 2) | p->constellation;
+ val0x06 = (p->hierarchy << 2) | p->modulation;
l64781_writereg (state, 0x04, val0x04);
l64781_writereg (state, 0x05, val0x05);
@@ -220,7 +230,7 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
l64781_writereg (state, 0x1b, spi_bias & 0xff);
l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
- (param->inversion == INVERSION_ON ? 0x80 : 0x00));
+ (p->inversion == INVERSION_ON ? 0x80 : 0x00));
l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
@@ -233,8 +243,9 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
return 0;
}
-static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* param)
+static int get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct l64781_state* state = fe->demodulator_priv;
int tmp;
@@ -242,98 +253,95 @@ static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters*
tmp = l64781_readreg(state, 0x04);
switch(tmp & 3) {
case 0:
- param->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ p->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
- param->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ p->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
- param->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ p->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- param->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ p->guard_interval = GUARD_INTERVAL_1_4;
break;
}
switch((tmp >> 2) & 3) {
case 0:
- param->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ p->transmission_mode = TRANSMISSION_MODE_2K;
break;
case 1:
- param->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ p->transmission_mode = TRANSMISSION_MODE_8K;
break;
default:
- printk("Unexpected value for transmission_mode\n");
+ printk(KERN_WARNING "Unexpected value for transmission_mode\n");
}
-
-
tmp = l64781_readreg(state, 0x05);
switch(tmp & 7) {
case 0:
- param->u.ofdm.code_rate_HP = FEC_1_2;
+ p->code_rate_HP = FEC_1_2;
break;
case 1:
- param->u.ofdm.code_rate_HP = FEC_2_3;
+ p->code_rate_HP = FEC_2_3;
break;
case 2:
- param->u.ofdm.code_rate_HP = FEC_3_4;
+ p->code_rate_HP = FEC_3_4;
break;
case 3:
- param->u.ofdm.code_rate_HP = FEC_5_6;
+ p->code_rate_HP = FEC_5_6;
break;
case 4:
- param->u.ofdm.code_rate_HP = FEC_7_8;
+ p->code_rate_HP = FEC_7_8;
break;
default:
printk("Unexpected value for code_rate_HP\n");
}
switch((tmp >> 3) & 7) {
case 0:
- param->u.ofdm.code_rate_LP = FEC_1_2;
+ p->code_rate_LP = FEC_1_2;
break;
case 1:
- param->u.ofdm.code_rate_LP = FEC_2_3;
+ p->code_rate_LP = FEC_2_3;
break;
case 2:
- param->u.ofdm.code_rate_LP = FEC_3_4;
+ p->code_rate_LP = FEC_3_4;
break;
case 3:
- param->u.ofdm.code_rate_LP = FEC_5_6;
+ p->code_rate_LP = FEC_5_6;
break;
case 4:
- param->u.ofdm.code_rate_LP = FEC_7_8;
+ p->code_rate_LP = FEC_7_8;
break;
default:
printk("Unexpected value for code_rate_LP\n");
}
-
tmp = l64781_readreg(state, 0x06);
switch(tmp & 3) {
case 0:
- param->u.ofdm.constellation = QPSK;
+ p->modulation = QPSK;
break;
case 1:
- param->u.ofdm.constellation = QAM_16;
+ p->modulation = QAM_16;
break;
case 2:
- param->u.ofdm.constellation = QAM_64;
+ p->modulation = QAM_64;
break;
default:
- printk("Unexpected value for constellation\n");
+ printk(KERN_WARNING "Unexpected value for modulation\n");
}
switch((tmp >> 2) & 7) {
case 0:
- param->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ p->hierarchy = HIERARCHY_NONE;
break;
case 1:
- param->u.ofdm.hierarchy_information = HIERARCHY_1;
+ p->hierarchy = HIERARCHY_1;
break;
case 2:
- param->u.ofdm.hierarchy_information = HIERARCHY_2;
+ p->hierarchy = HIERARCHY_2;
break;
case 3:
- param->u.ofdm.hierarchy_information = HIERARCHY_4;
+ p->hierarchy = HIERARCHY_4;
break;
default:
printk("Unexpected value for hierarchy\n");
@@ -341,12 +349,12 @@ static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters*
tmp = l64781_readreg (state, 0x1d);
- param->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
+ p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
tmp = (int) (l64781_readreg (state, 0x08) |
(l64781_readreg (state, 0x09) << 8) |
(l64781_readreg (state, 0x0a) << 16));
- param->frequency += tmp;
+ p->frequency += tmp;
return 0;
}
@@ -564,10 +572,9 @@ error:
}
static struct dvb_frontend_ops l64781_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "LSI L64781 DVB-T",
- .type = FE_OFDM,
/* .frequency_min = ???,*/
/* .frequency_max = ???,*/
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
index 3272881..1d2c473 100644
--- a/drivers/media/dvb/frontends/lgdt3305.c
+++ b/drivers/media/dvb/frontends/lgdt3305.c
@@ -266,7 +266,7 @@ fail:
}
static int lgdt3305_set_modulation(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
u8 opermode;
int ret;
@@ -279,7 +279,7 @@ static int lgdt3305_set_modulation(struct lgdt3305_state *state,
opermode &= ~0x03;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
opermode |= 0x03;
break;
@@ -298,11 +298,11 @@ fail:
}
static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
int val;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
val = 0;
break;
@@ -321,11 +321,11 @@ static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
/* ------------------------------------------------------------------------ */
static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
u16 agc_ref;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
agc_ref = 0x32c4;
break;
@@ -348,11 +348,11 @@ static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
}
static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
u16 ifbw, rfbw, agcdelay;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
agcdelay = 0x04c0;
rfbw = 0x8000;
@@ -398,11 +398,11 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
}
static int lgdt3305_agc_setup(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
int lockdten, acqen;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
lockdten = 0;
acqen = 0;
@@ -432,15 +432,15 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
return -EINVAL;
}
- return lgdt3305_rfagc_loop(state, param);
+ return lgdt3305_rfagc_loop(state, p);
}
static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
u16 usref = 0;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
if (state->cfg->usref_8vsb)
usref = state->cfg->usref_8vsb;
@@ -473,14 +473,14 @@ static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
/* ------------------------------------------------------------------------ */
static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param,
+ struct dtv_frontend_properties *p,
int inversion)
{
int ret;
lg_dbg("(%d)\n", inversion);
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
inversion ? 0xf9 : 0x79);
@@ -497,13 +497,13 @@ static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
}
static int lgdt3305_set_if(struct lgdt3305_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
u16 if_freq_khz;
u8 nco1, nco2, nco3, nco4;
u64 nco;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
if_freq_khz = state->cfg->vsb_if_khz;
break;
@@ -517,7 +517,7 @@ static int lgdt3305_set_if(struct lgdt3305_state *state,
nco = if_freq_khz / 10;
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
nco <<= 24;
do_div(nco, 625);
@@ -677,37 +677,37 @@ fail:
return ret;
}
-static int lgdt3304_set_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int lgdt3304_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt3305_state *state = fe->demodulator_priv;
int ret;
- lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+ lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
if (fe->ops.tuner_ops.set_params) {
- ret = fe->ops.tuner_ops.set_params(fe, param);
+ ret = fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if (lg_fail(ret))
goto fail;
- state->current_frequency = param->frequency;
+ state->current_frequency = p->frequency;
}
- ret = lgdt3305_set_modulation(state, param);
+ ret = lgdt3305_set_modulation(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_passband_digital_agc(state, param);
+ ret = lgdt3305_passband_digital_agc(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_agc_setup(state, param);
+ ret = lgdt3305_agc_setup(state, p);
if (lg_fail(ret))
goto fail;
/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
lgdt3305_write_reg(state, 0x030d, 0x00);
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
@@ -718,7 +718,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe,
case QAM_64:
case QAM_256:
lgdt3305_write_reg(state, 0x030d, 0x14);
- ret = lgdt3305_set_if(state, param);
+ ret = lgdt3305_set_if(state, p);
if (lg_fail(ret))
goto fail;
break;
@@ -727,13 +727,13 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe,
}
- ret = lgdt3305_spectral_inversion(state, param,
+ ret = lgdt3305_spectral_inversion(state, p,
state->cfg->spectral_inversion
? 1 : 0);
if (lg_fail(ret))
goto fail;
- state->current_modulation = param->u.vsb.modulation;
+ state->current_modulation = p->modulation;
ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
if (lg_fail(ret))
@@ -747,34 +747,34 @@ fail:
return ret;
}
-static int lgdt3305_set_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int lgdt3305_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt3305_state *state = fe->demodulator_priv;
int ret;
- lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+ lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
if (fe->ops.tuner_ops.set_params) {
- ret = fe->ops.tuner_ops.set_params(fe, param);
+ ret = fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if (lg_fail(ret))
goto fail;
- state->current_frequency = param->frequency;
+ state->current_frequency = p->frequency;
}
- ret = lgdt3305_set_modulation(state, param);
+ ret = lgdt3305_set_modulation(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_passband_digital_agc(state, param);
+ ret = lgdt3305_passband_digital_agc(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_set_agc_power_ref(state, param);
+ ret = lgdt3305_set_agc_power_ref(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_agc_setup(state, param);
+ ret = lgdt3305_agc_setup(state, p);
if (lg_fail(ret))
goto fail;
@@ -786,20 +786,20 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe,
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_set_if(state, param);
+ ret = lgdt3305_set_if(state, p);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_spectral_inversion(state, param,
+ ret = lgdt3305_spectral_inversion(state, p,
state->cfg->spectral_inversion
? 1 : 0);
if (lg_fail(ret))
goto fail;
- ret = lgdt3305_set_filter_extension(state, param);
+ ret = lgdt3305_set_filter_extension(state, p);
if (lg_fail(ret))
goto fail;
- state->current_modulation = param->u.vsb.modulation;
+ state->current_modulation = p->modulation;
ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
if (lg_fail(ret))
@@ -813,15 +813,15 @@ fail:
return ret;
}
-static int lgdt3305_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int lgdt3305_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt3305_state *state = fe->demodulator_priv;
lg_dbg("\n");
- param->u.vsb.modulation = state->current_modulation;
- param->frequency = state->current_frequency;
+ p->modulation = state->current_modulation;
+ p->frequency = state->current_frequency;
return 0;
}
@@ -1166,9 +1166,9 @@ fail:
EXPORT_SYMBOL(lgdt3305_attach);
static struct dvb_frontend_ops lgdt3304_ops = {
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
@@ -1188,9 +1188,9 @@ static struct dvb_frontend_ops lgdt3304_ops = {
};
static struct dvb_frontend_ops lgdt3305_ops = {
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 43971e6..c990d35 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -288,6 +288,8 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
int err;
u8 buf[2];
+ *ucblocks = 0;
+
switch (state->config->demod_chip) {
case LGDT3302:
err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
@@ -302,14 +304,16 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
"Only LGDT3302 and LGDT3303 are supported chips.\n");
err = -ENODEV;
}
+ if (err < 0)
+ return err;
*ucblocks = (buf[0] << 8) | buf[1];
return 0;
}
-static int lgdt330x_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int lgdt330x_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
/*
* Array of byte pairs <address, value>
* to initialize 8VSB for lgdt3303 chip 50 MHz IF
@@ -343,10 +347,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
static u8 top_ctrl_cfg[] = { TOP_CONTROL, 0x03 };
- int err;
+ int err = 0;
/* Change only if we are actually changing the modulation */
- if (state->current_modulation != param->u.vsb.modulation) {
- switch(param->u.vsb.modulation) {
+ if (state->current_modulation != p->modulation) {
+ switch (p->modulation) {
case VSB_8:
dprintk("%s: VSB_8 MODE\n", __func__);
@@ -395,9 +399,14 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
}
break;
default:
- printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, param->u.vsb.modulation);
+ printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, p->modulation);
return -1;
}
+ if (err < 0)
+ printk(KERN_WARNING "lgdt330x: %s: error blasting "
+ "bytes to lgdt3303 for modulation type(%d)\n",
+ __func__, p->modulation);
+
/*
* select serial or parallel MPEG harware interface
* Serial: 0x04 for LGDT3302 or 0x40 for LGDT3303
@@ -410,29 +419,29 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
sizeof(top_ctrl_cfg));
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
- state->current_modulation = param->u.vsb.modulation;
+ state->current_modulation = p->modulation;
}
/* Tune to the specified frequency */
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
/* Keep track of the new frequency */
/* FIXME this is the wrong way to do this... */
/* The tuner is shared with the video4linux analog API */
- state->current_frequency = param->frequency;
+ state->current_frequency = p->frequency;
lgdt330x_SwReset(state);
return 0;
}
-static int lgdt330x_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* param)
+static int lgdt330x_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt330x_state *state = fe->demodulator_priv;
- param->frequency = state->current_frequency;
+ p->frequency = state->current_frequency;
return 0;
}
@@ -762,9 +771,9 @@ error:
}
static struct dvb_frontend_ops lgdt3302_ops = {
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name= "LG Electronics LGDT3302 VSB/QAM Frontend",
- .type = FE_ATSC,
.frequency_min= 54000000,
.frequency_max= 858000000,
.frequency_stepsize= 62500,
@@ -785,9 +794,9 @@ static struct dvb_frontend_ops lgdt3302_ops = {
};
static struct dvb_frontend_ops lgdt3303_ops = {
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name= "LG Electronics LGDT3303 VSB/QAM Frontend",
- .type = FE_ATSC,
.frequency_min= 54000000,
.frequency_max= 858000000,
.frequency_stepsize= 62500,
diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c
index bb37ed2..2cec804 100644
--- a/drivers/media/dvb/frontends/lgs8gl5.c
+++ b/drivers/media/dvb/frontends/lgs8gl5.c
@@ -311,18 +311,18 @@ lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
static int
-lgs8gl5_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+lgs8gl5_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgs8gl5_state *state = fe->demodulator_priv;
dprintk("%s\n", __func__);
- if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ)
+ if (p->bandwidth_hz != 8000000)
return -EINVAL;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -336,22 +336,21 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe,
static int
-lgs8gl5_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+lgs8gl5_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgs8gl5_state *state = fe->demodulator_priv;
u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
- struct dvb_ofdm_parameters *o = &p->u.ofdm;
p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
- o->code_rate_HP = FEC_1_2;
- o->code_rate_LP = FEC_7_8;
- o->guard_interval = GUARD_INTERVAL_1_32;
- o->transmission_mode = TRANSMISSION_MODE_2K;
- o->constellation = QAM_64;
- o->hierarchy_information = HIERARCHY_NONE;
- o->bandwidth = BANDWIDTH_8_MHZ;
+ p->code_rate_HP = FEC_1_2;
+ p->code_rate_LP = FEC_7_8;
+ p->guard_interval = GUARD_INTERVAL_1_32;
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ p->modulation = QAM_64;
+ p->hierarchy = HIERARCHY_NONE;
+ p->bandwidth_hz = 8000000;
return 0;
}
@@ -413,9 +412,9 @@ EXPORT_SYMBOL(lgs8gl5_attach);
static struct dvb_frontend_ops lgs8gl5_ops = {
+ .delsys = { SYS_DMBTH },
.info = {
.name = "Legend Silicon LGS-8GL5 DMB-TH",
- .type = FE_OFDM,
.frequency_min = 474000000,
.frequency_max = 858000000,
.frequency_stepsize = 10000,
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
index 1172b54..4de1d35 100644
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -669,16 +669,16 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
return lgs8gxx_write_reg(priv, buf[0], buf[1]);
}
-static int lgs8gxx_set_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fe_params)
+static int lgs8gxx_set_fe(struct dvb_frontend *fe)
{
+
struct lgs8gxx_state *priv = fe->demodulator_priv;
dprintk("%s\n", __func__);
/* set frequency */
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fe_params);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -691,9 +691,9 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe,
return 0;
}
-static int lgs8gxx_get_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fe_params)
+static int lgs8gxx_get_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
dprintk("%s\n", __func__);
/* TODO: get real readings from device */
@@ -701,21 +701,21 @@ static int lgs8gxx_get_fe(struct dvb_frontend *fe,
fe_params->inversion = INVERSION_OFF;
/* bandwidth */
- fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ fe_params->bandwidth_hz = 8000000;
- fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
- fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
+ fe_params->code_rate_HP = FEC_AUTO;
+ fe_params->code_rate_LP = FEC_AUTO;
- fe_params->u.ofdm.constellation = QAM_AUTO;
+ fe_params->modulation = QAM_AUTO;
/* transmission mode */
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+ fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
/* guard interval */
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+ fe_params->guard_interval = GUARD_INTERVAL_AUTO;
/* hierarchy */
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fe_params->hierarchy = HIERARCHY_NONE;
return 0;
}
@@ -994,9 +994,9 @@ static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
}
static struct dvb_frontend_ops lgs8gxx_ops = {
+ .delsys = { SYS_DMBTH },
.info = {
.name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
- .type = FE_OFDM,
.frequency_min = 474000000,
.frequency_max = 858000000,
.frequency_stepsize = 10000,
diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c
index c283112..9ae40ab 100644
--- a/drivers/media/dvb/frontends/mb86a16.c
+++ b/drivers/media/dvb/frontends/mb86a16.c
@@ -1621,13 +1621,13 @@ err:
return -EREMOTEIO;
}
-static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mb86a16_state *state = fe->demodulator_priv;
state->frequency = p->frequency / 1000;
- state->srate = p->u.qpsk.symbol_rate / 1000;
+ state->srate = p->symbol_rate / 1000;
if (!mb86a16_set_fe(state)) {
dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK");
@@ -1814,9 +1814,9 @@ static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops mb86a16_ops = {
+ .delsys = { SYS_DVBS },
.info = {
.name = "Fujitsu MB86A16 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 3000,
diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
index 0f867a5..7fa3e47 100644
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -61,244 +61,111 @@ static struct regdata mb86a20s_init[] = {
{ 0x70, 0xff },
{ 0x08, 0x01 },
{ 0x09, 0x3e },
- { 0x50, 0xd1 },
- { 0x51, 0x22 },
+ { 0x50, 0xd1 }, { 0x51, 0x22 },
{ 0x39, 0x01 },
{ 0x71, 0x00 },
- { 0x28, 0x2a },
- { 0x29, 0x00 },
- { 0x2a, 0xff },
- { 0x2b, 0x80 },
- { 0x28, 0x20 },
- { 0x29, 0x33 },
- { 0x2a, 0xdf },
- { 0x2b, 0xa9 },
+ { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
+ { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
+ { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
{ 0x3b, 0x21 },
{ 0x3c, 0x3a },
{ 0x01, 0x0d },
- { 0x04, 0x08 },
- { 0x05, 0x05 },
- { 0x04, 0x0e },
- { 0x05, 0x00 },
- { 0x04, 0x0f },
- { 0x05, 0x14 },
- { 0x04, 0x0b },
- { 0x05, 0x8c },
- { 0x04, 0x00 },
- { 0x05, 0x00 },
- { 0x04, 0x01 },
- { 0x05, 0x07 },
- { 0x04, 0x02 },
- { 0x05, 0x0f },
- { 0x04, 0x03 },
- { 0x05, 0xa0 },
- { 0x04, 0x09 },
- { 0x05, 0x00 },
- { 0x04, 0x0a },
- { 0x05, 0xff },
- { 0x04, 0x27 },
- { 0x05, 0x64 },
- { 0x04, 0x28 },
- { 0x05, 0x00 },
- { 0x04, 0x1e },
- { 0x05, 0xff },
- { 0x04, 0x29 },
- { 0x05, 0x0a },
- { 0x04, 0x32 },
- { 0x05, 0x0a },
- { 0x04, 0x14 },
- { 0x05, 0x02 },
- { 0x04, 0x04 },
- { 0x05, 0x00 },
- { 0x04, 0x05 },
- { 0x05, 0x22 },
- { 0x04, 0x06 },
- { 0x05, 0x0e },
- { 0x04, 0x07 },
- { 0x05, 0xd8 },
- { 0x04, 0x12 },
- { 0x05, 0x00 },
- { 0x04, 0x13 },
- { 0x05, 0xff },
+ { 0x04, 0x08 }, { 0x05, 0x05 },
+ { 0x04, 0x0e }, { 0x05, 0x00 },
+ { 0x04, 0x0f }, { 0x05, 0x14 },
+ { 0x04, 0x0b }, { 0x05, 0x8c },
+ { 0x04, 0x00 }, { 0x05, 0x00 },
+ { 0x04, 0x01 }, { 0x05, 0x07 },
+ { 0x04, 0x02 }, { 0x05, 0x0f },
+ { 0x04, 0x03 }, { 0x05, 0xa0 },
+ { 0x04, 0x09 }, { 0x05, 0x00 },
+ { 0x04, 0x0a }, { 0x05, 0xff },
+ { 0x04, 0x27 }, { 0x05, 0x64 },
+ { 0x04, 0x28 }, { 0x05, 0x00 },
+ { 0x04, 0x1e }, { 0x05, 0xff },
+ { 0x04, 0x29 }, { 0x05, 0x0a },
+ { 0x04, 0x32 }, { 0x05, 0x0a },
+ { 0x04, 0x14 }, { 0x05, 0x02 },
+ { 0x04, 0x04 }, { 0x05, 0x00 },
+ { 0x04, 0x05 }, { 0x05, 0x22 },
+ { 0x04, 0x06 }, { 0x05, 0x0e },
+ { 0x04, 0x07 }, { 0x05, 0xd8 },
+ { 0x04, 0x12 }, { 0x05, 0x00 },
+ { 0x04, 0x13 }, { 0x05, 0xff },
+ { 0x04, 0x15 }, { 0x05, 0x4e },
+ { 0x04, 0x16 }, { 0x05, 0x20 },
{ 0x52, 0x01 },
- { 0x50, 0xa7 },
- { 0x51, 0x00 },
- { 0x50, 0xa8 },
- { 0x51, 0xff },
- { 0x50, 0xa9 },
- { 0x51, 0xff },
- { 0x50, 0xaa },
- { 0x51, 0x00 },
- { 0x50, 0xab },
- { 0x51, 0xff },
- { 0x50, 0xac },
- { 0x51, 0xff },
- { 0x50, 0xad },
- { 0x51, 0x00 },
- { 0x50, 0xae },
- { 0x51, 0xff },
- { 0x50, 0xaf },
- { 0x51, 0xff },
+ { 0x50, 0xa7 }, { 0x51, 0xff },
+ { 0x50, 0xa8 }, { 0x51, 0xff },
+ { 0x50, 0xa9 }, { 0x51, 0xff },
+ { 0x50, 0xaa }, { 0x51, 0xff },
+ { 0x50, 0xab }, { 0x51, 0xff },
+ { 0x50, 0xac }, { 0x51, 0xff },
+ { 0x50, 0xad }, { 0x51, 0xff },
+ { 0x50, 0xae }, { 0x51, 0xff },
+ { 0x50, 0xaf }, { 0x51, 0xff },
{ 0x5e, 0x07 },
- { 0x50, 0xdc },
- { 0x51, 0x01 },
- { 0x50, 0xdd },
- { 0x51, 0xf4 },
- { 0x50, 0xde },
- { 0x51, 0x01 },
- { 0x50, 0xdf },
- { 0x51, 0xf4 },
- { 0x50, 0xe0 },
- { 0x51, 0x01 },
- { 0x50, 0xe1 },
- { 0x51, 0xf4 },
- { 0x50, 0xb0 },
- { 0x51, 0x07 },
- { 0x50, 0xb2 },
- { 0x51, 0xff },
- { 0x50, 0xb3 },
- { 0x51, 0xff },
- { 0x50, 0xb4 },
- { 0x51, 0xff },
- { 0x50, 0xb5 },
- { 0x51, 0xff },
- { 0x50, 0xb6 },
- { 0x51, 0xff },
- { 0x50, 0xb7 },
- { 0x51, 0xff },
- { 0x50, 0x50 },
- { 0x51, 0x02 },
- { 0x50, 0x51 },
- { 0x51, 0x04 },
+ { 0x50, 0xdc }, { 0x51, 0x01 },
+ { 0x50, 0xdd }, { 0x51, 0xf4 },
+ { 0x50, 0xde }, { 0x51, 0x01 },
+ { 0x50, 0xdf }, { 0x51, 0xf4 },
+ { 0x50, 0xe0 }, { 0x51, 0x01 },
+ { 0x50, 0xe1 }, { 0x51, 0xf4 },
+ { 0x50, 0xb0 }, { 0x51, 0x07 },
+ { 0x50, 0xb2 }, { 0x51, 0xff },
+ { 0x50, 0xb3 }, { 0x51, 0xff },
+ { 0x50, 0xb4 }, { 0x51, 0xff },
+ { 0x50, 0xb5 }, { 0x51, 0xff },
+ { 0x50, 0xb6 }, { 0x51, 0xff },
+ { 0x50, 0xb7 }, { 0x51, 0xff },
+ { 0x50, 0x50 }, { 0x51, 0x02 },
+ { 0x50, 0x51 }, { 0x51, 0x04 },
{ 0x45, 0x04 },
{ 0x48, 0x04 },
- { 0x50, 0xd5 },
- { 0x51, 0x01 }, /* Serial */
- { 0x50, 0xd6 },
- { 0x51, 0x1f },
- { 0x50, 0xd2 },
- { 0x51, 0x03 },
- { 0x50, 0xd7 },
- { 0x51, 0x3f },
+ { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */
+ { 0x50, 0xd6 }, { 0x51, 0x1f },
+ { 0x50, 0xd2 }, { 0x51, 0x03 },
+ { 0x50, 0xd7 }, { 0x51, 0x3f },
+ { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
+ { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
+ { 0x04, 0x40 }, { 0x05, 0x01 },
+ { 0x28, 0x00 }, { 0x29, 0x10 },
+ { 0x28, 0x05 }, { 0x29, 0x02 },
{ 0x1c, 0x01 },
- { 0x28, 0x06 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x03 },
- { 0x28, 0x07 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x0d },
- { 0x28, 0x08 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x02 },
- { 0x28, 0x09 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x01 },
- { 0x28, 0x0a },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x21 },
- { 0x28, 0x0b },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x29 },
- { 0x28, 0x0c },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x16 },
- { 0x28, 0x0d },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x31 },
- { 0x28, 0x0e },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x0e },
- { 0x28, 0x0f },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x4e },
- { 0x28, 0x10 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x46 },
- { 0x28, 0x11 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x0f },
- { 0x28, 0x12 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x56 },
- { 0x28, 0x13 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x35 },
- { 0x28, 0x14 },
- { 0x29, 0x00 },
- { 0x2a, 0x01 },
- { 0x2b, 0xbe },
- { 0x28, 0x15 },
- { 0x29, 0x00 },
- { 0x2a, 0x01 },
- { 0x2b, 0x84 },
- { 0x28, 0x16 },
- { 0x29, 0x00 },
- { 0x2a, 0x03 },
- { 0x2b, 0xee },
- { 0x28, 0x17 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x98 },
- { 0x28, 0x18 },
- { 0x29, 0x00 },
- { 0x2a, 0x00 },
- { 0x2b, 0x9f },
- { 0x28, 0x19 },
- { 0x29, 0x00 },
- { 0x2a, 0x07 },
- { 0x2b, 0xb2 },
- { 0x28, 0x1a },
- { 0x29, 0x00 },
- { 0x2a, 0x06 },
- { 0x2b, 0xc2 },
- { 0x28, 0x1b },
- { 0x29, 0x00 },
- { 0x2a, 0x07 },
- { 0x2b, 0x4a },
- { 0x28, 0x1c },
- { 0x29, 0x00 },
- { 0x2a, 0x01 },
- { 0x2b, 0xbc },
- { 0x28, 0x1d },
- { 0x29, 0x00 },
- { 0x2a, 0x04 },
- { 0x2b, 0xba },
- { 0x28, 0x1e },
- { 0x29, 0x00 },
- { 0x2a, 0x06 },
- { 0x2b, 0x14 },
- { 0x50, 0x1e },
- { 0x51, 0x5d },
- { 0x50, 0x22 },
- { 0x51, 0x00 },
- { 0x50, 0x23 },
- { 0x51, 0xc8 },
- { 0x50, 0x24 },
- { 0x51, 0x00 },
- { 0x50, 0x25 },
- { 0x51, 0xf0 },
- { 0x50, 0x26 },
- { 0x51, 0x00 },
- { 0x50, 0x27 },
- { 0x51, 0xc3 },
- { 0x50, 0x39 },
- { 0x51, 0x02 },
- { 0x50, 0xd5 },
- { 0x51, 0x01 },
+ { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
+ { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
+ { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
+ { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
+ { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
+ { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
+ { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
+ { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
+ { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
+ { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
+ { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
+ { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
+ { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
+ { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
+ { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
+ { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
+ { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
+ { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
+ { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
+ { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
+ { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
+ { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
+ { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
+ { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
+ { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
+ { 0x50, 0x1e }, { 0x51, 0x5d },
+ { 0x50, 0x22 }, { 0x51, 0x00 },
+ { 0x50, 0x23 }, { 0x51, 0xc8 },
+ { 0x50, 0x24 }, { 0x51, 0x00 },
+ { 0x50, 0x25 }, { 0x51, 0xf0 },
+ { 0x50, 0x26 }, { 0x51, 0x00 },
+ { 0x50, 0x27 }, { 0x51, 0xc3 },
+ { 0x50, 0x39 }, { 0x51, 0x02 },
+ { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
{ 0xd0, 0x00 },
};
@@ -485,18 +352,23 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
return 0;
}
-static int mb86a20s_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int mb86a20s_set_frontend(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
int rc;
+#if 0
+ /*
+ * FIXME: Properly implement the set frontend properties
+ */
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+#endif
dprintk("\n");
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
dprintk("Calling tuner set parameters\n");
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
/*
* Make it more reliable: if, for some reason, the initial
@@ -520,22 +392,212 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe,
return rc;
}
-static int mb86a20s_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int mb86a20s_get_modulation(struct mb86a20s_state *state,
+ unsigned layer)
+{
+ int rc;
+ static unsigned char reg[] = {
+ [0] = 0x86, /* Layer A */
+ [1] = 0x8a, /* Layer B */
+ [2] = 0x8e, /* Layer C */
+ };
+
+ if (layer > ARRAY_SIZE(reg))
+ return -EINVAL;
+ rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+ if (rc < 0)
+ return rc;
+ rc = mb86a20s_readreg(state, 0x6e);
+ if (rc < 0)
+ return rc;
+ switch ((rc & 0x70) >> 4) {
+ case 0:
+ return DQPSK;
+ case 1:
+ return QPSK;
+ case 2:
+ return QAM_16;
+ case 3:
+ return QAM_64;
+ default:
+ return QAM_AUTO;
+ }
+}
+
+static int mb86a20s_get_fec(struct mb86a20s_state *state,
+ unsigned layer)
{
+ int rc;
- /* FIXME: For now, it does nothing */
+ static unsigned char reg[] = {
+ [0] = 0x87, /* Layer A */
+ [1] = 0x8b, /* Layer B */
+ [2] = 0x8f, /* Layer C */
+ };
- fe->dtv_property_cache.bandwidth_hz = 6000000;
- fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
- fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
- fe->dtv_property_cache.isdbt_partial_reception = 0;
+ if (layer > ARRAY_SIZE(reg))
+ return -EINVAL;
+ rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+ if (rc < 0)
+ return rc;
+ rc = mb86a20s_readreg(state, 0x6e);
+ if (rc < 0)
+ return rc;
+ switch (rc) {
+ case 0:
+ return FEC_1_2;
+ case 1:
+ return FEC_2_3;
+ case 2:
+ return FEC_3_4;
+ case 3:
+ return FEC_5_6;
+ case 4:
+ return FEC_7_8;
+ default:
+ return FEC_AUTO;
+ }
+}
+
+static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
+ unsigned layer)
+{
+ int rc;
+
+ static unsigned char reg[] = {
+ [0] = 0x88, /* Layer A */
+ [1] = 0x8c, /* Layer B */
+ [2] = 0x90, /* Layer C */
+ };
+
+ if (layer > ARRAY_SIZE(reg))
+ return -EINVAL;
+ rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+ if (rc < 0)
+ return rc;
+ rc = mb86a20s_readreg(state, 0x6e);
+ if (rc < 0)
+ return rc;
+ if (rc > 3)
+ return -EINVAL; /* Not used */
+ return rc;
+}
+
+static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
+ unsigned layer)
+{
+ int rc, count;
+
+ static unsigned char reg[] = {
+ [0] = 0x89, /* Layer A */
+ [1] = 0x8d, /* Layer B */
+ [2] = 0x91, /* Layer C */
+ };
+
+ if (layer > ARRAY_SIZE(reg))
+ return -EINVAL;
+ rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+ if (rc < 0)
+ return rc;
+ rc = mb86a20s_readreg(state, 0x6e);
+ if (rc < 0)
+ return rc;
+ count = (rc >> 4) & 0x0f;
+
+ return count;
+}
+
+static int mb86a20s_get_frontend(struct dvb_frontend *fe)
+{
+ struct mb86a20s_state *state = fe->demodulator_priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ int i, rc;
+
+ /* Fixed parameters */
+ p->delivery_system = SYS_ISDBT;
+ p->bandwidth_hz = 6000000;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+
+ /* Check for partial reception */
+ rc = mb86a20s_writereg(state, 0x6d, 0x85);
+ if (rc >= 0)
+ rc = mb86a20s_readreg(state, 0x6e);
+ if (rc >= 0)
+ p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
+
+ /* Get per-layer data */
+ p->isdbt_layer_enabled = 0;
+ for (i = 0; i < 3; i++) {
+ rc = mb86a20s_get_segment_count(state, i);
+ if (rc >= 0 && rc < 14)
+ p->layer[i].segment_count = rc;
+ if (rc == 0x0f)
+ continue;
+ p->isdbt_layer_enabled |= 1 << i;
+ rc = mb86a20s_get_modulation(state, i);
+ if (rc >= 0)
+ p->layer[i].modulation = rc;
+ rc = mb86a20s_get_fec(state, i);
+ if (rc >= 0)
+ p->layer[i].fec = rc;
+ rc = mb86a20s_get_interleaving(state, i);
+ if (rc >= 0)
+ p->layer[i].interleaving = rc;
+ }
+
+ p->isdbt_sb_mode = 0;
+ rc = mb86a20s_writereg(state, 0x6d, 0x84);
+ if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
+ p->isdbt_sb_mode = 1;
+ /* At least, one segment should exist */
+ if (!p->isdbt_sb_segment_count)
+ p->isdbt_sb_segment_count = 1;
+ } else
+ p->isdbt_sb_segment_count = 0;
+
+ /* Get transmission mode and guard interval */
+ p->transmission_mode = TRANSMISSION_MODE_AUTO;
+ p->guard_interval = GUARD_INTERVAL_AUTO;
+ rc = mb86a20s_readreg(state, 0x07);
+ if (rc >= 0) {
+ if ((rc & 0x60) == 0x20) {
+ switch (rc & 0x0c >> 2) {
+ case 0:
+ p->transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ p->transmission_mode = TRANSMISSION_MODE_4K;
+ break;
+ case 2:
+ p->transmission_mode = TRANSMISSION_MODE_8K;
+ break;
+ }
+ }
+ if (!(rc & 0x10)) {
+ switch (rc & 0x3) {
+ case 0:
+ p->guard_interval = GUARD_INTERVAL_1_4;
+ break;
+ case 1:
+ p->guard_interval = GUARD_INTERVAL_1_8;
+ break;
+ case 2:
+ p->guard_interval = GUARD_INTERVAL_1_16;
+ break;
+ }
+ }
+ }
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
return 0;
}
static int mb86a20s_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
@@ -544,8 +606,8 @@ static int mb86a20s_tune(struct dvb_frontend *fe,
dprintk("\n");
- if (params != NULL)
- rc = mb86a20s_set_frontend(fe, params);
+ if (re_tune)
+ rc = mb86a20s_set_frontend(fe);
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
mb86a20s_read_status(fe, status);
@@ -608,10 +670,10 @@ error:
EXPORT_SYMBOL(mb86a20s_attach);
static struct dvb_frontend_ops mb86a20s_ops = {
+ .delsys = { SYS_ISDBT },
/* Use dib8000 values per default */
.info = {
.name = "Fujitsu mb86A20s",
- .type = FE_OFDM,
.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 83e6f1a..e20bf13 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -531,9 +531,9 @@ static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
return 0;
}
-static int mt312_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int mt312_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[5], config_val;
@@ -553,16 +553,16 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
|| (p->inversion > INVERSION_ON))
return -EINVAL;
- if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
- || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
+ if ((p->symbol_rate < fe->ops.info.symbol_rate_min)
+ || (p->symbol_rate > fe->ops.info.symbol_rate_max))
return -EINVAL;
- if ((p->u.qpsk.fec_inner < FEC_NONE)
- || (p->u.qpsk.fec_inner > FEC_AUTO))
+ if ((p->fec_inner < FEC_NONE)
+ || (p->fec_inner > FEC_AUTO))
return -EINVAL;
- if ((p->u.qpsk.fec_inner == FEC_4_5)
- || (p->u.qpsk.fec_inner == FEC_8_9))
+ if ((p->fec_inner == FEC_4_5)
+ || (p->fec_inner == FEC_8_9))
return -EINVAL;
switch (state->id) {
@@ -574,7 +574,7 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
ret = mt312_readreg(state, CONFIG, &config_val);
if (ret < 0)
return ret;
- if (p->u.qpsk.symbol_rate >= 30000000) {
+ if (p->symbol_rate >= 30000000) {
/* Note that 30MS/s should use 90MHz */
if (state->freq_mult == 6) {
/* We are running 60MHz */
@@ -603,25 +603,25 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
}
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
/* sr = (u16)(sr * 256.0 / 1000000.0) */
- sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
+ sr = mt312_div(p->symbol_rate * 4, 15625);
/* SYM_RATE */
buf[0] = (sr >> 8) & 0x3f;
buf[1] = (sr >> 0) & 0xff;
/* VIT_MODE */
- buf[2] = inv_tab[p->inversion] | fec_tab[p->u.qpsk.fec_inner];
+ buf[2] = inv_tab[p->inversion] | fec_tab[p->fec_inner];
/* QPSK_CTRL */
buf[3] = 0x40; /* swap I and Q before QPSK demodulation */
- if (p->u.qpsk.symbol_rate < 10000000)
+ if (p->symbol_rate < 10000000)
buf[3] |= 0x04; /* use afc mode */
/* GO */
@@ -636,9 +636,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int mt312_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int mt312_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mt312_state *state = fe->demodulator_priv;
int ret;
@@ -646,11 +646,11 @@ static int mt312_get_frontend(struct dvb_frontend *fe,
if (ret < 0)
return ret;
- ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate);
+ ret = mt312_get_symbol_rate(state, &p->symbol_rate);
if (ret < 0)
return ret;
- ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner);
+ ret = mt312_get_code_rate(state, &p->fec_inner);
if (ret < 0)
return ret;
@@ -738,10 +738,9 @@ static void mt312_release(struct dvb_frontend *fe)
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
static struct dvb_frontend_ops mt312_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Zarlink ???? DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
/* FIXME: adjust freq to real used xtal */
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index 319672f..2c3b50e 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -111,20 +111,20 @@ static int mt352_sleep(struct dvb_frontend* fe)
}
static void mt352_calc_nominal_rate(struct mt352_state* state,
- enum fe_bandwidth bandwidth,
+ u32 bandwidth,
unsigned char *buf)
{
u32 adc_clock = 20480; /* 20.340 MHz */
u32 bw,value;
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
bw = 6;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
bw = 7;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
default:
bw = 8;
break;
@@ -166,15 +166,14 @@ static void mt352_calc_input_freq(struct mt352_state* state,
buf[1] = lsb(value);
}
-static int mt352_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int mt352_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *op = &fe->dtv_property_cache;
struct mt352_state* state = fe->demodulator_priv;
unsigned char buf[13];
static unsigned char tuner_go[] = { 0x5d, 0x01 };
static unsigned char fsm_go[] = { 0x5e, 0x01 };
unsigned int tps = 0;
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
switch (op->code_rate_HP) {
case FEC_2_3:
@@ -213,14 +212,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
case FEC_AUTO:
break;
case FEC_NONE:
- if (op->hierarchy_information == HIERARCHY_AUTO ||
- op->hierarchy_information == HIERARCHY_NONE)
+ if (op->hierarchy == HIERARCHY_AUTO ||
+ op->hierarchy == HIERARCHY_NONE)
break;
default:
return -EINVAL;
}
- switch (op->constellation) {
+ switch (op->modulation) {
case QPSK:
break;
case QAM_AUTO:
@@ -262,7 +261,7 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
return -EINVAL;
}
- switch (op->hierarchy_information) {
+ switch (op->hierarchy) {
case HIERARCHY_AUTO:
case HIERARCHY_NONE:
break;
@@ -288,12 +287,12 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
buf[3] = 0x50; // old
// buf[3] = 0xf4; // pinnacle
- mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
+ mt352_calc_nominal_rate(state, op->bandwidth_hz, buf+4);
mt352_calc_input_freq(state, buf+6);
if (state->config.no_tuner) {
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -302,7 +301,7 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
_mt352_write(fe, fsm_go, 2);
} else {
if (fe->ops.tuner_ops.calc_regs) {
- fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
+ fe->ops.tuner_ops.calc_regs(fe, buf+8, 5);
buf[8] <<= 1;
_mt352_write(fe, buf, sizeof(buf));
_mt352_write(fe, tuner_go, 2);
@@ -312,14 +311,13 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
return 0;
}
-static int mt352_get_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int mt352_get_parameters(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *op = &fe->dtv_property_cache;
struct mt352_state* state = fe->demodulator_priv;
u16 tps;
u16 div;
u8 trl;
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
static const u8 tps_fec_to_api[8] =
{
FEC_1_2,
@@ -348,16 +346,16 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
switch ( (tps >> 13) & 3)
{
case 0:
- op->constellation = QPSK;
+ op->modulation = QPSK;
break;
case 1:
- op->constellation = QAM_16;
+ op->modulation = QAM_16;
break;
case 2:
- op->constellation = QAM_64;
+ op->modulation = QAM_64;
break;
default:
- op->constellation = QAM_AUTO;
+ op->modulation = QAM_AUTO;
break;
}
@@ -385,36 +383,36 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
switch ( (tps >> 10) & 7)
{
case 0:
- op->hierarchy_information = HIERARCHY_NONE;
+ op->hierarchy = HIERARCHY_NONE;
break;
case 1:
- op->hierarchy_information = HIERARCHY_1;
+ op->hierarchy = HIERARCHY_1;
break;
case 2:
- op->hierarchy_information = HIERARCHY_2;
+ op->hierarchy = HIERARCHY_2;
break;
case 3:
- op->hierarchy_information = HIERARCHY_4;
+ op->hierarchy = HIERARCHY_4;
break;
default:
- op->hierarchy_information = HIERARCHY_AUTO;
+ op->hierarchy = HIERARCHY_AUTO;
break;
}
- param->frequency = ( 500 * (div - IF_FREQUENCYx6) ) / 3 * 1000;
+ op->frequency = (500 * (div - IF_FREQUENCYx6)) / 3 * 1000;
if (trl == 0x72)
- op->bandwidth = BANDWIDTH_8_MHZ;
+ op->bandwidth_hz = 8000000;
else if (trl == 0x64)
- op->bandwidth = BANDWIDTH_7_MHZ;
+ op->bandwidth_hz = 7000000;
else
- op->bandwidth = BANDWIDTH_6_MHZ;
+ op->bandwidth_hz = 6000000;
if (mt352_read_register(state, STATUS_2) & 0x02)
- param->inversion = INVERSION_OFF;
+ op->inversion = INVERSION_OFF;
else
- param->inversion = INVERSION_ON;
+ op->inversion = INVERSION_ON;
return 0;
}
@@ -569,10 +567,9 @@ error:
}
static struct dvb_frontend_ops mt352_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Zarlink MT352 DVB-T",
- .type = FE_OFDM,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 166667,
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index eac2065..49ca78d 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -528,9 +528,9 @@ static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware
return 0;
};
-static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct nxt200x_state* state = fe->demodulator_priv;
u8 buf[5];
@@ -546,7 +546,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
}
/* set additional params */
- switch (p->u.vsb.modulation) {
+ switch (p->modulation) {
case QAM_64:
case QAM_256:
/* Set punctured clock for QAM */
@@ -566,7 +566,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
if (fe->ops.tuner_ops.calc_regs) {
/* get tuning information */
- fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+ fe->ops.tuner_ops.calc_regs(fe, buf, 5);
/* write frequency information */
nxt200x_writetuner(state, buf);
@@ -576,7 +576,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
nxt200x_agc_reset(state);
/* set target power level */
- switch (p->u.vsb.modulation) {
+ switch (p->modulation) {
case QAM_64:
case QAM_256:
buf[0] = 0x74;
@@ -620,7 +620,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
}
/* write sdmx input */
- switch (p->u.vsb.modulation) {
+ switch (p->modulation) {
case QAM_64:
buf[0] = 0x68;
break;
@@ -714,7 +714,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
}
/* write agc ucgp0 */
- switch (p->u.vsb.modulation) {
+ switch (p->modulation) {
case QAM_64:
buf[0] = 0x02;
break;
@@ -1203,10 +1203,9 @@ error:
}
static struct dvb_frontend_ops nxt200x_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Nextwave NXT200X VSB/QAM frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 860000000,
.frequency_stepsize = 166666, /* stepsize is just a guess */
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index 6599b8f..90ae6c7 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -81,22 +81,21 @@ static void nxt6000_reset(struct nxt6000_state* state)
nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
}
-static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t bandwidth)
+static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth)
{
u16 nominal_rate;
int result;
switch (bandwidth) {
-
- case BANDWIDTH_6_MHZ:
+ case 6000000:
nominal_rate = 0x55B7;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
nominal_rate = 0x6400;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
nominal_rate = 0x7249;
break;
@@ -457,23 +456,31 @@ static int nxt6000_init(struct dvb_frontend* fe)
return 0;
}
-static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
+static int nxt6000_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct nxt6000_state* state = fe->demodulator_priv;
int result;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
+ result = nxt6000_set_bandwidth(state, p->bandwidth_hz);
+ if (result < 0)
return result;
- if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0)
+
+ result = nxt6000_set_guard_interval(state, p->guard_interval);
+ if (result < 0)
return result;
- if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0)
+
+ result = nxt6000_set_transmission_mode(state, p->transmission_mode);
+ if (result < 0)
return result;
- if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
+
+ result = nxt6000_set_inversion(state, p->inversion);
+ if (result < 0)
return result;
msleep(500);
@@ -566,10 +573,9 @@ error:
}
static struct dvb_frontend_ops nxt6000_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "NxtWave NXT6000 DVB-T",
- .type = FE_OFDM,
.frequency_min = 0,
.frequency_max = 863250000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 38e67ac..5ef9218 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -306,9 +306,9 @@ static int modulation_fw_class(fe_modulation_t modulation)
}
}
-static int or51132_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int or51132_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int ret;
struct or51132_state* state = fe->demodulator_priv;
const struct firmware *fw;
@@ -317,8 +317,8 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
/* Upload new firmware only if we need a different one */
if (modulation_fw_class(state->current_modulation) !=
- modulation_fw_class(param->u.vsb.modulation)) {
- switch(modulation_fw_class(param->u.vsb.modulation)) {
+ modulation_fw_class(p->modulation)) {
+ switch (modulation_fw_class(p->modulation)) {
case MOD_FWCLASS_VSB:
dprintk("set_parameters VSB MODE\n");
fwname = OR51132_VSB_FIRMWARE;
@@ -335,7 +335,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
break;
default:
printk("or51132: Modulation type(%d) UNSUPPORTED\n",
- param->u.vsb.modulation);
+ p->modulation);
return -1;
}
printk("or51132: Waiting for firmware upload(%s)...\n",
@@ -357,13 +357,13 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
state->config->set_ts_params(fe, clock_mode);
}
/* Change only if we are actually changing the modulation */
- if (state->current_modulation != param->u.vsb.modulation) {
- state->current_modulation = param->u.vsb.modulation;
+ if (state->current_modulation != p->modulation) {
+ state->current_modulation = p->modulation;
or51132_setmode(fe);
}
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -371,13 +371,13 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
or51132_setmode(fe);
/* Update current frequency */
- state->current_frequency = param->frequency;
+ state->current_frequency = p->frequency;
return 0;
}
-static int or51132_get_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int or51132_get_parameters(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct or51132_state* state = fe->demodulator_priv;
int status;
int retry = 1;
@@ -389,21 +389,28 @@ start:
return -EREMOTEIO;
}
switch(status&0xff) {
- case 0x06: param->u.vsb.modulation = VSB_8; break;
- case 0x43: param->u.vsb.modulation = QAM_64; break;
- case 0x45: param->u.vsb.modulation = QAM_256; break;
- default:
- if (retry--) goto start;
- printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
- status&0xff);
- return -EREMOTEIO;
+ case 0x06:
+ p->modulation = VSB_8;
+ break;
+ case 0x43:
+ p->modulation = QAM_64;
+ break;
+ case 0x45:
+ p->modulation = QAM_256;
+ break;
+ default:
+ if (retry--)
+ goto start;
+ printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+ status&0xff);
+ return -EREMOTEIO;
}
/* FIXME: Read frequency from frontend, take AFC into account */
- param->frequency = state->current_frequency;
+ p->frequency = state->current_frequency;
/* FIXME: How to read inversion setting? Receiver 6 register? */
- param->inversion = INVERSION_AUTO;
+ p->inversion = INVERSION_AUTO;
return 0;
}
@@ -579,10 +586,9 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
}
static struct dvb_frontend_ops or51132_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Oren OR51132 VSB/QAM Frontend",
- .type = FE_ATSC,
.frequency_min = 44000000,
.frequency_max = 958000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index c709ce6..c625b57 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -218,15 +218,15 @@ static int or51211_setmode(struct dvb_frontend* fe, int mode)
return 0;
}
-static int or51211_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *param)
+static int or51211_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct or51211_state* state = fe->demodulator_priv;
/* Change only if we are actually changing the channel */
- if (state->current_frequency != param->frequency) {
+ if (state->current_frequency != p->frequency) {
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -234,7 +234,7 @@ static int or51211_set_parameters(struct dvb_frontend* fe,
or51211_setmode(fe,0);
/* Update current frequency */
- state->current_frequency = param->frequency;
+ state->current_frequency = p->frequency;
}
return 0;
}
@@ -544,10 +544,9 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
}
static struct dvb_frontend_ops or51211_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Oren OR51211 VSB Frontend",
- .type = FE_ATSC,
.frequency_min = 44000000,
.frequency_max = 958000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index 0e2f61a..f71b062 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -631,9 +631,9 @@ static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s5h1409_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1409_state *state = fe->demodulator_priv;
dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -642,12 +642,12 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
state->current_frequency = p->frequency;
- s5h1409_enable_modulation(fe, p->u.vsb.modulation);
+ s5h1409_enable_modulation(fe, p->modulation);
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -879,7 +879,36 @@ static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
- return s5h1409_read_snr(fe, signal_strength);
+ /* borrowed from lgdt330x.c
+ *
+ * Calculate strength from SNR up to 35dB
+ * Even though the SNR can go higher than 35dB,
+ * there is some comfort factor in having a range of
+ * strong signals that can show at 100%
+ */
+ u16 snr;
+ u32 tmp;
+ int ret = s5h1409_read_snr(fe, &snr);
+
+ *signal_strength = 0;
+
+ if (0 == ret) {
+ /* The following calculation method was chosen
+ * purely for the sake of code re-use from the
+ * other demod drivers that use this method */
+
+ /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+ tmp = (snr * ((1 << 24) / 10));
+
+ /* Convert from 8.24 fixed-point to
+ * scale the range 0 - 35*2^24 into 0 - 65535*/
+ if (tmp >= 8960 * 0x10000)
+ *signal_strength = 0xffff;
+ else
+ *signal_strength = tmp / 8960;
+ }
+
+ return ret;
}
static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -896,13 +925,13 @@ static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
return s5h1409_read_ucblocks(fe, ber);
}
-static int s5h1409_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s5h1409_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1409_state *state = fe->demodulator_priv;
p->frequency = state->current_frequency;
- p->u.vsb.modulation = state->current_modulation;
+ p->modulation = state->current_modulation;
return 0;
}
@@ -967,10 +996,9 @@ error:
EXPORT_SYMBOL(s5h1409_attach);
static struct dvb_frontend_ops s5h1409_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Samsung S5H1409 QAM/8VSB Frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index d8adf1e..6cc4b7a 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -585,9 +585,9 @@ static int s5h1411_register_reset(struct dvb_frontend *fe)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1411_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s5h1411_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1411_state *state = fe->demodulator_priv;
dprintk("%s(frequency=%d)\n", __func__, p->frequency);
@@ -596,13 +596,13 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe,
state->current_frequency = p->frequency;
- s5h1411_enable_modulation(fe, p->u.vsb.modulation);
+ s5h1411_enable_modulation(fe, p->modulation);
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -794,7 +794,36 @@ static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
- return s5h1411_read_snr(fe, signal_strength);
+ /* borrowed from lgdt330x.c
+ *
+ * Calculate strength from SNR up to 35dB
+ * Even though the SNR can go higher than 35dB,
+ * there is some comfort factor in having a range of
+ * strong signals that can show at 100%
+ */
+ u16 snr;
+ u32 tmp;
+ int ret = s5h1411_read_snr(fe, &snr);
+
+ *signal_strength = 0;
+
+ if (0 == ret) {
+ /* The following calculation method was chosen
+ * purely for the sake of code re-use from the
+ * other demod drivers that use this method */
+
+ /* Convert from SNR in dB * 10 to 8.24 fixed-point */
+ tmp = (snr * ((1 << 24) / 10));
+
+ /* Convert from 8.24 fixed-point to
+ * scale the range 0 - 35*2^24 into 0 - 65535*/
+ if (tmp >= 8960 * 0x10000)
+ *signal_strength = 0xffff;
+ else
+ *signal_strength = tmp / 8960;
+ }
+
+ return ret;
}
static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -811,13 +840,13 @@ static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
return s5h1411_read_ucblocks(fe, ber);
}
-static int s5h1411_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s5h1411_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1411_state *state = fe->demodulator_priv;
p->frequency = state->current_frequency;
- p->u.vsb.modulation = state->current_modulation;
+ p->modulation = state->current_modulation;
return 0;
}
@@ -886,10 +915,9 @@ error:
EXPORT_SYMBOL(s5h1411_attach);
static struct dvb_frontend_ops s5h1411_ops = {
-
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
.info = {
.name = "Samsung S5H1411 QAM/8VSB Frontend",
- .type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 3879d2e..2322257 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -472,15 +472,15 @@ static void s5h1420_reset(struct s5h1420_state* state)
}
static void s5h1420_setsymbolrate(struct s5h1420_state* state,
- struct dvb_frontend_parameters *p)
+ struct dtv_frontend_properties *p)
{
u8 v;
u64 val;
dprintk("enter %s\n", __func__);
- val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
- if (p->u.qpsk.symbol_rate < 29000000)
+ val = ((u64) p->symbol_rate / 1000ULL) * (1ULL<<24);
+ if (p->symbol_rate < 29000000)
val *= 2;
do_div(val, (state->fclk / 1000));
@@ -543,7 +543,7 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
}
static void s5h1420_setfec_inversion(struct s5h1420_state* state,
- struct dvb_frontend_parameters *p)
+ struct dtv_frontend_properties *p)
{
u8 inversion = 0;
u8 vit08, vit09;
@@ -555,11 +555,11 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
else if (p->inversion == INVERSION_ON)
inversion = state->config->invert ? 0 : 0x08;
- if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+ if ((p->fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
vit08 = 0x3f;
vit09 = 0;
} else {
- switch(p->u.qpsk.fec_inner) {
+ switch (p->fec_inner) {
case FEC_1_2:
vit08 = 0x01; vit09 = 0x10;
break;
@@ -628,9 +628,9 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
return INVERSION_OFF;
}
-static int s5h1420_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int s5h1420_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1420_state* state = fe->demodulator_priv;
int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
@@ -639,17 +639,16 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
dprintk("enter %s\n", __func__);
/* check if we should do a fast-tune */
- memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
s5h1420_get_tune_settings(fe, &fesettings);
frequency_delta = p->frequency - state->tunedfreq;
if ((frequency_delta > -fesettings.max_drift) &&
(frequency_delta < fesettings.max_drift) &&
(frequency_delta != 0) &&
- (state->fec_inner == p->u.qpsk.fec_inner) &&
- (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+ (state->fec_inner == p->fec_inner) &&
+ (state->symbol_rate == p->symbol_rate)) {
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
if (fe->ops.tuner_ops.get_frequency) {
@@ -669,13 +668,13 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
s5h1420_reset(state);
/* set s5h1420 fclk PLL according to desired symbol rate */
- if (p->u.qpsk.symbol_rate > 33000000)
+ if (p->symbol_rate > 33000000)
state->fclk = 80000000;
- else if (p->u.qpsk.symbol_rate > 28500000)
+ else if (p->symbol_rate > 28500000)
state->fclk = 59000000;
- else if (p->u.qpsk.symbol_rate > 25000000)
+ else if (p->symbol_rate > 25000000)
state->fclk = 86000000;
- else if (p->u.qpsk.symbol_rate > 1900000)
+ else if (p->symbol_rate > 1900000)
state->fclk = 88000000;
else
state->fclk = 44000000;
@@ -705,7 +704,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
/* TODO DC offset removal, config parameter ? */
- if (p->u.qpsk.symbol_rate > 29000000)
+ if (p->symbol_rate > 29000000)
s5h1420_writereg(state, QPSK01, 0xae | 0x10);
else
s5h1420_writereg(state, QPSK01, 0xac | 0x10);
@@ -718,15 +717,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
s5h1420_writereg(state, Loop01, 0xF0);
s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
- if (p->u.qpsk.symbol_rate > 20000000)
+ if (p->symbol_rate > 20000000)
s5h1420_writereg(state, Loop04, 0x79);
else
s5h1420_writereg(state, Loop04, 0x58);
s5h1420_writereg(state, Loop05, 0x6b);
- if (p->u.qpsk.symbol_rate >= 8000000)
+ if (p->symbol_rate >= 8000000)
s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
- else if (p->u.qpsk.symbol_rate >= 4000000)
+ else if (p->symbol_rate >= 4000000)
s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
else
s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
@@ -744,7 +743,7 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
/* set tuner PLL */
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
s5h1420_setfreqoffset(state, 0);
@@ -757,8 +756,8 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
/* start QPSK */
s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
- state->fec_inner = p->u.qpsk.fec_inner;
- state->symbol_rate = p->u.qpsk.symbol_rate;
+ state->fec_inner = p->fec_inner;
+ state->symbol_rate = p->symbol_rate;
state->postlocked = 0;
state->tunedfreq = p->frequency;
@@ -766,15 +765,15 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
return 0;
}
-static int s5h1420_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int s5h1420_get_frontend(struct dvb_frontend* fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s5h1420_state* state = fe->demodulator_priv;
p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
p->inversion = s5h1420_getinversion(state);
- p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state);
- p->u.qpsk.fec_inner = s5h1420_getfec(state);
+ p->symbol_rate = s5h1420_getsymbolrate(state);
+ p->fec_inner = s5h1420_getfec(state);
return 0;
}
@@ -782,29 +781,30 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe,
static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
struct dvb_frontend_tune_settings* fesettings)
{
- if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ if (p->symbol_rate > 20000000) {
fesettings->min_delay_ms = 50;
fesettings->step_size = 2000;
fesettings->max_drift = 8000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+ } else if (p->symbol_rate > 12000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 1500;
fesettings->max_drift = 9000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+ } else if (p->symbol_rate > 8000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 1000;
fesettings->max_drift = 8000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+ } else if (p->symbol_rate > 4000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 500;
fesettings->max_drift = 7000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+ } else if (p->symbol_rate > 2000000) {
fesettings->min_delay_ms = 200;
- fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->step_size = (p->symbol_rate / 8000);
fesettings->max_drift = 14 * fesettings->step_size;
} else {
fesettings->min_delay_ms = 200;
- fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->step_size = (p->symbol_rate / 8000);
fesettings->max_drift = 18 * fesettings->step_size;
}
@@ -937,10 +937,9 @@ error:
EXPORT_SYMBOL(s5h1420_attach);
static struct dvb_frontend_ops s5h1420_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/s5h1432.c b/drivers/media/dvb/frontends/s5h1432.c
index 0c6dcb9..8352ce1 100644
--- a/drivers/media/dvb/frontends/s5h1432.c
+++ b/drivers/media/dvb/frontends/s5h1432.c
@@ -178,9 +178,9 @@ static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1432_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s5h1432_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 dvb_bandwidth = 8;
struct s5h1432_state *state = fe->demodulator_priv;
@@ -188,26 +188,26 @@ static int s5h1432_set_frontend(struct dvb_frontend *fe,
/*current_frequency = p->frequency; */
/*state->current_frequency = p->frequency; */
} else {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
msleep(300);
s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
- switch (p->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
dvb_bandwidth = 6;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
dvb_bandwidth = 7;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
dvb_bandwidth = 8;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
default:
return 0;
}
- /*fe->ops.tuner_ops.set_params(fe, p); */
+ /*fe->ops.tuner_ops.set_params(fe); */
/*Soft Reset chip*/
msleep(30);
s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
@@ -215,23 +215,23 @@ static int s5h1432_set_frontend(struct dvb_frontend *fe,
s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
- switch (p->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
dvb_bandwidth = 6;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
dvb_bandwidth = 7;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
dvb_bandwidth = 8;
s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
break;
default:
return 0;
}
- /*fe->ops.tuner_ops.set_params(fe,p); */
+ /*fe->ops.tuner_ops.set_params(fe); */
/*Soft Reset chip*/
msleep(30);
s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
@@ -329,12 +329,6 @@ static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
return 0;
}
-static int s5h1432_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
-{
- return 0;
-}
-
static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *tune)
{
@@ -381,10 +375,9 @@ error:
EXPORT_SYMBOL(s5h1432_attach);
static struct dvb_frontend_ops s5h1432_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Samsung s5h1432 DVB-T Frontend",
- .type = FE_OFDM,
.frequency_min = 177000000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
@@ -397,7 +390,6 @@ static struct dvb_frontend_ops s5h1432_ops = {
.init = s5h1432_init,
.sleep = s5h1432_sleep,
.set_frontend = s5h1432_set_frontend,
- .get_frontend = s5h1432_get_frontend,
.get_tune_settings = s5h1432_get_tune_settings,
.read_status = s5h1432_read_status,
.read_ber = s5h1432_read_ber,
diff --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb/frontends/s921.c
index ca0103d..cd2288c 100644
--- a/drivers/media/dvb/frontends/s921.c
+++ b/drivers/media/dvb/frontends/s921.c
@@ -262,9 +262,9 @@ static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
s921_i2c_writeregdata(state, state->config->demod_address, \
regdata, ARRAY_SIZE(regdata))
-static int s921_pll_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s921_pll_tune(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s921_state *state = fe->demodulator_priv;
int band, rc, i;
unsigned long f_offset;
@@ -414,9 +414,9 @@ static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
return 0;
}
-static int s921_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s921_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s921_state *state = fe->demodulator_priv;
int rc;
@@ -424,7 +424,7 @@ static int s921_set_frontend(struct dvb_frontend *fe,
/* FIXME: We don't know how to use non-auto mode */
- rc = s921_pll_tune(fe, p);
+ rc = s921_pll_tune(fe);
if (rc < 0)
return rc;
@@ -433,19 +433,20 @@ static int s921_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int s921_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int s921_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct s921_state *state = fe->demodulator_priv;
/* FIXME: Probably it is possible to get it from regs f1 and f2 */
p->frequency = state->currentfreq;
+ p->delivery_system = SYS_ISDBT;
return 0;
}
static int s921_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
+ bool re_tune,
unsigned int mode_flags,
unsigned int *delay,
fe_status_t *status)
@@ -454,8 +455,8 @@ static int s921_tune(struct dvb_frontend *fe,
dprintk("\n");
- if (params != NULL)
- rc = s921_set_frontend(fe, params);
+ if (re_tune)
+ rc = s921_set_frontend(fe);
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
s921_read_status(fe, status);
@@ -510,10 +511,10 @@ rcor:
EXPORT_SYMBOL(s921_attach);
static struct dvb_frontend_ops s921_ops = {
+ .delsys = { SYS_ISDBT },
/* Use dib8000 values per default */
.info = {
.name = "Sharp S921",
- .type = FE_OFDM,
.frequency_min = 470000000,
/*
* Max should be 770MHz instead, according with Sharp docs,
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c
index 4b0c99a..a68a648 100644
--- a/drivers/media/dvb/frontends/si21xx.c
+++ b/drivers/media/dvb/frontends/si21xx.c
@@ -690,20 +690,7 @@ static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
return status;
}
-static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
-static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
-static int si21xx_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *dfp)
+static int si21xx_set_frontend(struct dvb_frontend *fe)
{
struct si21xx_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -877,10 +864,9 @@ static void si21xx_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops si21xx_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "SL SI21XX DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125, /* kHz for QPSK frontends */
@@ -908,8 +894,6 @@ static struct dvb_frontend_ops si21xx_ops = {
.set_tone = si21xx_set_tone,
.set_voltage = si21xx_set_voltage,
- .set_property = si21xx_set_property,
- .get_property = si21xx_get_property,
.set_frontend = si21xx_set_frontend,
};
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index b85eb60..e37274c 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -168,13 +168,13 @@ static int sp8870_read_data_valid_signal(struct sp8870_state* state)
return (sp8870_readreg(state, 0x0D02) > 0);
}
-static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
+static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
{
int known_parameters = 1;
*reg0xc05 = 0x000;
- switch (p->u.ofdm.constellation) {
+ switch (p->modulation) {
case QPSK:
break;
case QAM_16:
@@ -190,7 +190,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
return -EINVAL;
};
- switch (p->u.ofdm.hierarchy_information) {
+ switch (p->hierarchy) {
case HIERARCHY_NONE:
break;
case HIERARCHY_1:
@@ -209,7 +209,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
return -EINVAL;
};
- switch (p->u.ofdm.code_rate_HP) {
+ switch (p->code_rate_HP) {
case FEC_1_2:
break;
case FEC_2_3:
@@ -245,9 +245,9 @@ static int sp8870_wake_up(struct sp8870_state* state)
return sp8870_writereg(state, 0xC18, 0x00D);
}
-static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct sp8870_state* state = fe->demodulator_priv;
int err;
u16 reg0xc05;
@@ -260,7 +260,7 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
// set tuner parameters
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -277,15 +277,15 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
sp8870_writereg(state, 0x030A, 0x0000);
// filter for 6/7/8 Mhz channel
- if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+ if (p->bandwidth_hz == 6000000)
sp8870_writereg(state, 0x0311, 0x0002);
- else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+ else if (p->bandwidth_hz == 7000000)
sp8870_writereg(state, 0x0311, 0x0001);
else
sp8870_writereg(state, 0x0311, 0x0000);
// scan order: 2k first = 0x0000, 8k first = 0x0001
- if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
+ if (p->transmission_mode == TRANSMISSION_MODE_2K)
sp8870_writereg(state, 0x0338, 0x0000);
else
sp8870_writereg(state, 0x0338, 0x0001);
@@ -459,8 +459,9 @@ static int lockups;
/* only for debugging: counter for channel switches */
static int switches;
-static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int sp8870_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct sp8870_state* state = fe->demodulator_priv;
/*
@@ -479,7 +480,8 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
for (trials = 1; trials <= MAXTRIALS; trials++) {
- if ((err = sp8870_set_frontend_parameters(fe, p)))
+ err = sp8870_set_frontend_parameters(fe);
+ if (err)
return err;
for (check_count = 0; check_count < MAXCHECKS; check_count++) {
@@ -579,10 +581,9 @@ error:
}
static struct dvb_frontend_ops sp8870_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Spase SP8870 DVB-T",
- .type = FE_OFDM,
.frequency_min = 470000000,
.frequency_max = 860000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 4a7c3d8..f4096cc 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -209,13 +209,13 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
return 0;
};
-static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
+static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
{
int known_parameters = 1;
*reg0xc05 = 0x000;
- switch (p->u.ofdm.constellation) {
+ switch (p->modulation) {
case QPSK:
break;
case QAM_16:
@@ -231,7 +231,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
return -EINVAL;
};
- switch (p->u.ofdm.hierarchy_information) {
+ switch (p->hierarchy) {
case HIERARCHY_NONE:
break;
case HIERARCHY_1:
@@ -250,7 +250,7 @@ static int configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05)
return -EINVAL;
};
- switch (p->u.ofdm.code_rate_HP) {
+ switch (p->code_rate_HP) {
case FEC_1_2:
break;
case FEC_2_3:
@@ -303,17 +303,30 @@ static void divide (int n, int d, int *quotient_i, int *quotient_f)
}
static void sp887x_correct_offsets (struct sp887x_state* state,
- struct dvb_frontend_parameters *p,
+ struct dtv_frontend_properties *p,
int actual_freq)
{
static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
- int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
+ int bw_index;
int freq_offset = actual_freq - p->frequency;
int sysclock = 61003; //[kHz]
int ifreq = 36000000;
int freq;
int frequency_shift;
+ switch (p->bandwidth_hz) {
+ default:
+ case 8000000:
+ bw_index = 0;
+ break;
+ case 7000000:
+ bw_index = 1;
+ break;
+ case 6000000:
+ bw_index = 2;
+ break;
+ }
+
if (p->inversion == INVERSION_ON)
freq = ifreq - freq_offset;
else
@@ -333,17 +346,17 @@ static void sp887x_correct_offsets (struct sp887x_state* state,
sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
}
-static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct sp887x_state* state = fe->demodulator_priv;
unsigned actual_freq;
int err;
u16 val, reg0xc05;
- if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ &&
- p->u.ofdm.bandwidth != BANDWIDTH_7_MHZ &&
- p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ)
+ if (p->bandwidth_hz != 8000000 &&
+ p->bandwidth_hz != 7000000 &&
+ p->bandwidth_hz != 6000000)
return -EINVAL;
if ((err = configure_reg0xc05(p, &reg0xc05)))
@@ -353,7 +366,7 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
/* setup the PLL */
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
if (fe->ops.tuner_ops.get_frequency) {
@@ -369,9 +382,9 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
sp887x_correct_offsets(state, p, actual_freq);
/* filter for 6/7/8 Mhz channel */
- if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+ if (p->bandwidth_hz == 6000000)
val = 2;
- else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+ else if (p->bandwidth_hz == 7000000)
val = 1;
else
val = 0;
@@ -379,16 +392,16 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
sp887x_writereg(state, 0x311, val);
/* scan order: 2k first = 0, 8k first = 1 */
- if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)
+ if (p->transmission_mode == TRANSMISSION_MODE_2K)
sp887x_writereg(state, 0x338, 0x000);
else
sp887x_writereg(state, 0x338, 0x001);
sp887x_writereg(state, 0xc05, reg0xc05);
- if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+ if (p->bandwidth_hz == 6000000)
val = 2 << 3;
- else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+ else if (p->bandwidth_hz == 7000000)
val = 3 << 3;
else
val = 0 << 3;
@@ -579,10 +592,9 @@ error:
}
static struct dvb_frontend_ops sp887x_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Spase SP887x DVB-T",
- .type = FE_OFDM,
.frequency_min = 50500000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 8408ef8..38565be 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -1431,7 +1431,7 @@ static void stb0899_set_iterations(struct stb0899_state *state)
stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
}
-static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe)
{
struct stb0899_state *state = fe->demodulator_priv;
struct stb0899_params *i_params = &state->params;
@@ -1441,8 +1441,8 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_fron
u32 SearchRange, gain;
- i_params->freq = p->frequency;
- i_params->srate = p->u.qpsk.symbol_rate;
+ i_params->freq = props->frequency;
+ i_params->srate = props->symbol_rate;
state->delsys = props->delivery_system;
dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
@@ -1568,34 +1568,15 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_fron
return DVBFE_ALGO_SEARCH_ERROR;
}
-/*
- * stb0899_track
- * periodically check the signal level against a specified
- * threshold level and perform derotator centering.
- * called once we have a lock from a successful search
- * event.
- *
- * Will be called periodically called to maintain the
- * lock.
- *
- * Will be used to get parameters as well as info from
- * the decoded baseband header
- *
- * Once a new lock has established, the internal state
- * frequency (internal->freq) is updated
- */
-static int stb0899_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
-{
- return 0;
-}
-static int stb0899_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stb0899_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stb0899_state *state = fe->demodulator_priv;
struct stb0899_internal *internal = &state->internal;
dprintk(state->verbose, FE_DEBUG, 1, "Get params");
- p->u.qpsk.symbol_rate = internal->srate;
+ p->symbol_rate = internal->srate;
return 0;
}
@@ -1606,10 +1587,9 @@ static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops stb0899_ops = {
-
+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.info = {
.name = "STB0899 Multistandard",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 0,
@@ -1632,8 +1612,7 @@ static struct dvb_frontend_ops stb0899_ops = {
.get_frontend_algo = stb0899_frontend_algo,
.search = stb0899_search,
- .track = stb0899_track,
- .get_frontend = stb0899_get_frontend,
+ .get_frontend = stb0899_get_frontend,
.read_status = stb0899_read_status,
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c
index ed69964..a0c3c52 100644
--- a/drivers/media/dvb/frontends/stb6000.c
+++ b/drivers/media/dvb/frontends/stb6000.c
@@ -75,9 +75,9 @@ static int stb6000_sleep(struct dvb_frontend *fe)
return (ret == 1) ? 0 : ret;
}
-static int stb6000_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int stb6000_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stb6000_priv *priv = fe->tuner_priv;
unsigned int n, m;
int ret;
@@ -93,8 +93,8 @@ static int stb6000_set_params(struct dvb_frontend *fe,
dprintk("%s:\n", __func__);
- freq_mhz = params->frequency / 1000;
- bandwidth = params->u.qpsk.symbol_rate / 1000000;
+ freq_mhz = p->frequency / 1000;
+ bandwidth = p->symbol_rate / 1000000;
if (bandwidth > 31)
bandwidth = 31;
diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c
index bc1a8af..def88ab 100644
--- a/drivers/media/dvb/frontends/stb6100.c
+++ b/drivers/media/dvb/frontends/stb6100.c
@@ -327,7 +327,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
int rc;
const struct stb6100_lkup *ptr;
struct stb6100_state *state = fe->tuner_priv;
- struct dvb_frontend_parameters p;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
u32 srate = 0, fvco, nint, nfrac;
u8 regs[STB6100_NUMREGS];
@@ -337,9 +337,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
if (fe->ops.get_frontend) {
dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
- fe->ops.get_frontend(fe, &p);
+ fe->ops.get_frontend(fe);
}
- srate = p.u.qpsk.symbol_rate;
+ srate = p->symbol_rate;
/* Set up tuner cleanly, LPF calibration on */
rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
index 0aa3962..fb5548a 100644
--- a/drivers/media/dvb/frontends/stv0288.c
+++ b/drivers/media/dvb/frontends/stv0288.c
@@ -452,14 +452,7 @@ static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
return 0;
}
-static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
- dprintk("%s(..)\n", __func__);
- return 0;
-}
-
-static int stv0288_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *dfp)
+static int stv0288_set_frontend(struct dvb_frontend *fe)
{
struct stv0288_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -481,10 +474,8 @@ static int stv0288_set_frontend(struct dvb_frontend *fe,
state->config->set_ts_params(fe, 0);
/* only frequency & symbol_rate are used for tuner*/
- dfp->frequency = c->frequency;
- dfp->u.qpsk.symbol_rate = c->symbol_rate;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, dfp);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -545,10 +536,9 @@ static void stv0288_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops stv0288_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "ST STV0288 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1000, /* kHz for QPSK frontends */
@@ -578,7 +568,6 @@ static struct dvb_frontend_ops stv0288_ops = {
.set_voltage = stv0288_set_voltage,
.set_property = stv0288_set_property,
- .get_property = stv0288_get_property,
.set_frontend = stv0288_set_frontend,
};
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 84d88f33..85c157a 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -404,8 +404,9 @@ static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
return 0;
}
-static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stv0297_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0297_state *state = fe->demodulator_priv;
int u_threshold;
int initial_u;
@@ -417,7 +418,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
unsigned long timeout;
fe_spectral_inversion_t inversion;
- switch (p->u.qam.modulation) {
+ switch (p->modulation) {
case QAM_16:
case QAM_32:
case QAM_64:
@@ -455,7 +456,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
stv0297_init(fe);
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -519,16 +520,16 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
/* set parameters */
- stv0297_set_qam(state, p->u.qam.modulation);
- stv0297_set_symbolrate(state, p->u.qam.symbol_rate / 1000);
- stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
+ stv0297_set_qam(state, p->modulation);
+ stv0297_set_symbolrate(state, p->symbol_rate / 1000);
+ stv0297_set_sweeprate(state, sweeprate, p->symbol_rate / 1000);
stv0297_set_carrieroffset(state, carrieroffset);
stv0297_set_inversion(state, inversion);
/* kick off lock */
/* Disable corner detection for higher QAMs */
- if (p->u.qam.modulation == QAM_128 ||
- p->u.qam.modulation == QAM_256)
+ if (p->modulation == QAM_128 ||
+ p->modulation == QAM_256)
stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
else
stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
@@ -613,8 +614,9 @@ timeout:
return 0;
}
-static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static int stv0297_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0297_state *state = fe->demodulator_priv;
int reg_00, reg_83;
@@ -625,24 +627,24 @@ static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
if (state->config->invert)
p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
- p->u.qam.symbol_rate = stv0297_get_symbolrate(state) * 1000;
- p->u.qam.fec_inner = FEC_NONE;
+ p->symbol_rate = stv0297_get_symbolrate(state) * 1000;
+ p->fec_inner = FEC_NONE;
switch ((reg_00 >> 4) & 0x7) {
case 0:
- p->u.qam.modulation = QAM_16;
+ p->modulation = QAM_16;
break;
case 1:
- p->u.qam.modulation = QAM_32;
+ p->modulation = QAM_32;
break;
case 2:
- p->u.qam.modulation = QAM_128;
+ p->modulation = QAM_128;
break;
case 3:
- p->u.qam.modulation = QAM_256;
+ p->modulation = QAM_256;
break;
case 4:
- p->u.qam.modulation = QAM_64;
+ p->modulation = QAM_64;
break;
}
@@ -688,10 +690,9 @@ error:
}
static struct dvb_frontend_ops stv0297_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "ST STV0297 DVB-C",
- .type = FE_QAM,
.frequency_min = 47000000,
.frequency_max = 862000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 42684be..057b5f8 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -559,8 +559,9 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0299_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0299_state* state = fe->demodulator_priv;
int invval = 0;
@@ -579,24 +580,25 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- stv0299_set_FEC (state, p->u.qpsk.fec_inner);
- stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
+ stv0299_set_FEC(state, p->fec_inner);
+ stv0299_set_symbolrate(fe, p->symbol_rate);
stv0299_writeregI(state, 0x22, 0x00);
stv0299_writeregI(state, 0x23, 0x00);
state->tuner_frequency = p->frequency;
- state->fec_inner = p->u.qpsk.fec_inner;
- state->symbol_rate = p->u.qpsk.symbol_rate;
+ state->fec_inner = p->fec_inner;
+ state->symbol_rate = p->symbol_rate;
return 0;
}
-static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0299_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0299_state* state = fe->demodulator_priv;
s32 derot_freq;
int invval;
@@ -614,8 +616,8 @@ static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if (state->config->invert) invval = (~invval) & 1;
p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
- p->u.qpsk.fec_inner = stv0299_get_fec (state);
- p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state);
+ p->fec_inner = stv0299_get_fec(state);
+ p->symbol_rate = stv0299_get_symbolrate(state);
return 0;
}
@@ -646,14 +648,15 @@ static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
struct stv0299_state* state = fe->demodulator_priv;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
fesettings->min_delay_ms = state->config->min_delay_ms;
- if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
- fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
+ if (p->symbol_rate < 10000000) {
+ fesettings->step_size = p->symbol_rate / 32000;
fesettings->max_drift = 5000;
} else {
- fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
- fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
+ fesettings->step_size = p->symbol_rate / 16000;
+ fesettings->max_drift = p->symbol_rate / 2000;
}
return 0;
}
@@ -705,10 +708,9 @@ error:
}
static struct dvb_frontend_ops stv0299_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "ST STV0299 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/stv0367.c b/drivers/media/dvb/frontends/stv0367.c
index e57ab53..fdd20c7 100644
--- a/drivers/media/dvb/frontends/stv0367.c
+++ b/drivers/media/dvb/frontends/stv0367.c
@@ -1577,9 +1577,9 @@ int stv0367ter_init(struct dvb_frontend *fe)
return 0;
}
-static int stv0367ter_algo(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int stv0367ter_algo(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0367_state *state = fe->demodulator_priv;
struct stv0367ter_state *ter_state = state->ter_state;
int offset = 0, tempo = 0;
@@ -1591,7 +1591,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
dprintk("%s:\n", __func__);
- ter_state->frequency = param->frequency;
+ ter_state->frequency = p->frequency;
ter_state->force = FE_TER_FORCENONE
+ stv0367_readbits(state, F367TER_FORCE) * 2;
ter_state->if_iq_mode = state->config->if_iq_mode;
@@ -1620,7 +1620,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
usleep_range(5000, 7000);
- switch (param->inversion) {
+ switch (p->inversion) {
case INVERSION_AUTO:
default:
dprintk("%s: inversion AUTO\n", __func__);
@@ -1636,10 +1636,10 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
case INVERSION_OFF:
if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
stv0367_writebits(state, F367TER_IQ_INVERT,
- param->inversion);
+ p->inversion);
else
stv0367_writebits(state, F367TER_INV_SPECTR,
- param->inversion);
+ p->inversion);
break;
}
@@ -1806,10 +1806,9 @@ static int stv0367ter_algo(struct dvb_frontend *fe,
return 0;
}
-static int stv0367ter_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int stv0367ter_set_frontend(struct dvb_frontend *fe)
{
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0367_state *state = fe->demodulator_priv;
struct stv0367ter_state *ter_state = state->ter_state;
@@ -1822,12 +1821,12 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
- switch (op->transmission_mode) {
+ switch (p->transmission_mode) {
default:
case TRANSMISSION_MODE_AUTO:
case TRANSMISSION_MODE_2K:
@@ -1841,34 +1840,34 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
break;
}
- switch (op->guard_interval) {
+ switch (p->guard_interval) {
default:
case GUARD_INTERVAL_1_32:
case GUARD_INTERVAL_1_16:
case GUARD_INTERVAL_1_8:
case GUARD_INTERVAL_1_4:
- ter_state->guard = op->guard_interval;
+ ter_state->guard = p->guard_interval;
break;
case GUARD_INTERVAL_AUTO:
ter_state->guard = GUARD_INTERVAL_1_32;
break;
}
- switch (op->bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
ter_state->bw = FE_TER_CHAN_BW_6M;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
ter_state->bw = FE_TER_CHAN_BW_7M;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
default:
ter_state->bw = FE_TER_CHAN_BW_8M;
}
ter_state->hierarchy = FE_TER_HIER_NONE;
- switch (param->inversion) {
+ switch (p->inversion) {
case INVERSION_OFF:
case INVERSION_ON:
num_trials = 1;
@@ -1885,14 +1884,14 @@ static int stv0367ter_set_frontend(struct dvb_frontend *fe,
while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) {
if (!ter_state->first_lock) {
- if (param->inversion == INVERSION_AUTO)
+ if (p->inversion == INVERSION_AUTO)
ter_state->sense = SenseTrials[index];
}
- stv0367ter_algo(fe,/* &pLook, result,*/ param);
+ stv0367ter_algo(fe);
if ((ter_state->state == FE_TER_LOCKOK) &&
- (param->inversion == INVERSION_AUTO) &&
+ (p->inversion == INVERSION_AUTO) &&
(index == 1)) {
/* invert spectrum sense */
SenseTrials[index] = SenseTrials[0];
@@ -1927,50 +1926,48 @@ static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-static int stv0367ter_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int stv0367ter_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0367_state *state = fe->demodulator_priv;
struct stv0367ter_state *ter_state = state->ter_state;
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int error = 0;
enum stv0367_ter_mode mode;
int constell = 0,/* snr = 0,*/ Data = 0;
- param->frequency = stv0367_get_tuner_freq(fe);
- if ((int)param->frequency < 0)
- param->frequency = c->frequency;
+ p->frequency = stv0367_get_tuner_freq(fe);
+ if ((int)p->frequency < 0)
+ p->frequency = -p->frequency;
constell = stv0367_readbits(state, F367TER_TPS_CONST);
if (constell == 0)
- op->constellation = QPSK;
+ p->modulation = QPSK;
else if (constell == 1)
- op->constellation = QAM_16;
+ p->modulation = QAM_16;
else
- op->constellation = QAM_64;
+ p->modulation = QAM_64;
- param->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
+ p->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
/* Get the Hierarchical mode */
Data = stv0367_readbits(state, F367TER_TPS_HIERMODE);
switch (Data) {
case 0:
- op->hierarchy_information = HIERARCHY_NONE;
+ p->hierarchy = HIERARCHY_NONE;
break;
case 1:
- op->hierarchy_information = HIERARCHY_1;
+ p->hierarchy = HIERARCHY_1;
break;
case 2:
- op->hierarchy_information = HIERARCHY_2;
+ p->hierarchy = HIERARCHY_2;
break;
case 3:
- op->hierarchy_information = HIERARCHY_4;
+ p->hierarchy = HIERARCHY_4;
break;
default:
- op->hierarchy_information = HIERARCHY_AUTO;
+ p->hierarchy = HIERARCHY_AUTO;
break; /* error */
}
@@ -1982,22 +1979,22 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe,
switch (Data) {
case 0:
- op->code_rate_HP = FEC_1_2;
+ p->code_rate_HP = FEC_1_2;
break;
case 1:
- op->code_rate_HP = FEC_2_3;
+ p->code_rate_HP = FEC_2_3;
break;
case 2:
- op->code_rate_HP = FEC_3_4;
+ p->code_rate_HP = FEC_3_4;
break;
case 3:
- op->code_rate_HP = FEC_5_6;
+ p->code_rate_HP = FEC_5_6;
break;
case 4:
- op->code_rate_HP = FEC_7_8;
+ p->code_rate_HP = FEC_7_8;
break;
default:
- op->code_rate_HP = FEC_AUTO;
+ p->code_rate_HP = FEC_AUTO;
break; /* error */
}
@@ -2005,19 +2002,19 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe,
switch (mode) {
case FE_TER_MODE_2K:
- op->transmission_mode = TRANSMISSION_MODE_2K;
+ p->transmission_mode = TRANSMISSION_MODE_2K;
break;
/* case FE_TER_MODE_4K:
- op->transmission_mode = TRANSMISSION_MODE_4K;
+ p->transmission_mode = TRANSMISSION_MODE_4K;
break;*/
case FE_TER_MODE_8K:
- op->transmission_mode = TRANSMISSION_MODE_8K;
+ p->transmission_mode = TRANSMISSION_MODE_8K;
break;
default:
- op->transmission_mode = TRANSMISSION_MODE_AUTO;
+ p->transmission_mode = TRANSMISSION_MODE_AUTO;
}
- op->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
+ p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
return error;
}
@@ -2265,9 +2262,9 @@ static void stv0367_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops stv0367ter_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "ST STV0367 DVB-T",
- .type = FE_OFDM,
.frequency_min = 47000000,
.frequency_max = 862000000,
.frequency_stepsize = 15625,
@@ -2822,9 +2819,8 @@ int stv0367cab_init(struct dvb_frontend *fe)
}
static
enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
- struct dvb_frontend_parameters *param)
+ struct dtv_frontend_properties *p)
{
- struct dvb_qam_parameters *op = &param->u.qam;
struct stv0367cab_state *cab_state = state->cab_state;
enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC;
u32 QAMFEC_Lock, QAM_Lock, u32_tmp,
@@ -2839,7 +2835,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
/* A max lock time of 25 ms is allowed for delayed AGC */
AGCTimeOut = 25;
/* 100000 symbols needed by the TRL as a maximum value */
- TRLTimeOut = 100000000 / op->symbol_rate;
+ TRLTimeOut = 100000000 / p->symbol_rate;
/* CRLSymbols is the needed number of symbols to achieve a lock
within [-4%, +4%] of the symbol rate.
CRL timeout is calculated
@@ -2849,7 +2845,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
A characterization must be performed
with these echoes to get new timeout values.
*/
- switch (op->modulation) {
+ switch (p->modulation) {
case QAM_16:
CRLSymbols = 150000;
EQLTimeOut = 100;
@@ -2883,9 +2879,9 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
} else
#endif
CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) /
- (op->symbol_rate / 1000);
+ (p->symbol_rate / 1000);
- CRLTimeOut = (1000 * CRLTimeOut) / op->symbol_rate;
+ CRLTimeOut = (1000 * CRLTimeOut) / p->symbol_rate;
/* Timeouts below 50ms are coerced */
if (CRLTimeOut < 50)
CRLTimeOut = 50;
@@ -2915,7 +2911,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
stv0367cab_set_derot_freq(state, cab_state->adc_clk,
(1000 * (s32)state->config->if_khz + cab_state->derot_offset));
/* Disable the Allpass Filter when the symbol rate is out of range */
- if ((op->symbol_rate > 10800000) | (op->symbol_rate < 1800000)) {
+ if ((p->symbol_rate > 10800000) | (p->symbol_rate < 1800000)) {
stv0367_writebits(state, F367CAB_ADJ_EN, 0);
stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
}
@@ -2999,7 +2995,7 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
if (QAMFEC_Lock) {
signalType = FE_CAB_DATAOK;
- cab_state->modulation = op->modulation;
+ cab_state->modulation = p->modulation;
cab_state->spect_inv = stv0367_readbits(state,
F367CAB_QUAD_INV);
#if 0
@@ -3081,20 +3077,19 @@ enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
return signalType;
}
-static int stv0367cab_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int stv0367cab_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0367_state *state = fe->demodulator_priv;
struct stv0367cab_state *cab_state = state->cab_state;
- struct dvb_qam_parameters *op = &param->u.qam;
enum stv0367cab_mod QAMSize = 0;
dprintk("%s: freq = %d, srate = %d\n", __func__,
- param->frequency, op->symbol_rate);
+ p->frequency, p->symbol_rate);
cab_state->derot_offset = 0;
- switch (op->modulation) {
+ switch (p->modulation) {
case QAM_16:
QAMSize = FE_CAB_MOD_QAM16;
break;
@@ -3120,77 +3115,76 @@ static int stv0367cab_set_frontend(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
stv0367cab_SetQamSize(
state,
- op->symbol_rate,
+ p->symbol_rate,
QAMSize);
stv0367cab_set_srate(state,
cab_state->adc_clk,
cab_state->mclk,
- op->symbol_rate,
+ p->symbol_rate,
QAMSize);
/* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */
- cab_state->state = stv0367cab_algo(state, param);
+ cab_state->state = stv0367cab_algo(state, p);
return 0;
}
-static int stv0367cab_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int stv0367cab_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0367_state *state = fe->demodulator_priv;
struct stv0367cab_state *cab_state = state->cab_state;
- struct dvb_qam_parameters *op = &param->u.qam;
enum stv0367cab_mod QAMSize;
dprintk("%s:\n", __func__);
- op->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
+ p->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
switch (QAMSize) {
case FE_CAB_MOD_QAM16:
- op->modulation = QAM_16;
+ p->modulation = QAM_16;
break;
case FE_CAB_MOD_QAM32:
- op->modulation = QAM_32;
+ p->modulation = QAM_32;
break;
case FE_CAB_MOD_QAM64:
- op->modulation = QAM_64;
+ p->modulation = QAM_64;
break;
case FE_CAB_MOD_QAM128:
- op->modulation = QAM_128;
+ p->modulation = QAM_128;
break;
case QAM_256:
- op->modulation = QAM_256;
+ p->modulation = QAM_256;
break;
default:
break;
}
- param->frequency = stv0367_get_tuner_freq(fe);
+ p->frequency = stv0367_get_tuner_freq(fe);
- dprintk("%s: tuner frequency = %d\n", __func__, param->frequency);
+ dprintk("%s: tuner frequency = %d\n", __func__, p->frequency);
if (state->config->if_khz == 0) {
- param->frequency +=
+ p->frequency +=
(stv0367cab_get_derot_freq(state, cab_state->adc_clk) -
cab_state->adc_clk / 4000);
return 0;
}
if (state->config->if_khz > cab_state->adc_clk / 1000)
- param->frequency += (state->config->if_khz
+ p->frequency += (state->config->if_khz
- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
- cab_state->adc_clk / 1000);
else
- param->frequency += (state->config->if_khz
+ p->frequency += (state->config->if_khz
- stv0367cab_get_derot_freq(state, cab_state->adc_clk));
return 0;
@@ -3386,9 +3380,9 @@ static int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks)
};
static struct dvb_frontend_ops stv0367cab_ops = {
+ .delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "ST STV0367 DVB-C",
- .type = FE_QAM,
.frequency_min = 47000000,
.frequency_max = 862000000,
.frequency_stepsize = 62500,
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
index 0ca316d..7f1bada 100644
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -973,22 +973,6 @@ static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe)
return DVBFE_ALGO_CUSTOM;
}
-static int stb0900_set_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
-
- return 0;
-}
-
-static int stb0900_get_property(struct dvb_frontend *fe,
- struct dtv_property *tvp)
-{
- dprintk("%s(..)\n", __func__);
-
- return 0;
-}
-
void stv0900_start_search(struct stv0900_internal *intp,
enum fe_stv0900_demod_num demod)
{
@@ -1574,8 +1558,7 @@ static int stv0900_status(struct stv0900_internal *intp,
return locked;
}
-static enum dvbfe_search stv0900_search(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static enum dvbfe_search stv0900_search(struct dvb_frontend *fe)
{
struct stv0900_state *state = fe->demodulator_priv;
struct stv0900_internal *intp = state->internal;
@@ -1675,12 +1658,6 @@ static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status)
return 0;
}
-static int stv0900_track(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
-{
- return 0;
-}
-
static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts)
{
@@ -1866,24 +1843,23 @@ static int stv0900_sleep(struct dvb_frontend *fe)
return 0;
}
-static int stv0900_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int stv0900_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct stv0900_state *state = fe->demodulator_priv;
struct stv0900_internal *intp = state->internal;
enum fe_stv0900_demod_num demod = state->demod;
struct stv0900_signal_info p_result = intp->result[demod];
p->frequency = p_result.locked ? p_result.frequency : 0;
- p->u.qpsk.symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
+ p->symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
return 0;
}
static struct dvb_frontend_ops stv0900_ops = {
-
+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.info = {
.name = "STV0900 frontend",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
@@ -1907,10 +1883,7 @@ static struct dvb_frontend_ops stv0900_ops = {
.diseqc_send_burst = stv0900_send_burst,
.diseqc_recv_slave_reply = stv0900_recv_slave_reply,
.set_tone = stv0900_set_tone,
- .set_property = stb0900_set_property,
- .get_property = stb0900_get_property,
.search = stv0900_search,
- .track = stv0900_track,
.read_status = stv0900_read_status,
.read_ber = stv0900_read_ber,
.read_signal_strength = stv0900_read_signal_strength,
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index ebda419..4aef187 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -3427,17 +3427,17 @@ err:
return -1;
}
-static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
{
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *props = &fe->dtv_property_cache;
- if (p->frequency == 0)
+ if (props->frequency == 0)
return DVBFE_ALGO_SEARCH_INVALID;
state->delsys = props->delivery_system;
- state->frequency = p->frequency;
- state->srate = p->u.qpsk.symbol_rate;
+ state->frequency = props->frequency;
+ state->srate = props->symbol_rate;
state->search_mode = STV090x_SEARCH_AUTO;
state->algo = STV090x_COLD_SEARCH;
state->fec = STV090x_PRERR;
@@ -4712,10 +4712,9 @@ int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
EXPORT_SYMBOL(stv090x_set_gpio);
static struct dvb_frontend_ops stv090x_ops = {
-
+ .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.info = {
.name = "STV090x Multistandard",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 0,
@@ -4743,7 +4742,7 @@ static struct dvb_frontend_ops stv090x_ops = {
.read_status = stv090x_read_status,
.read_ber = stv090x_read_per,
.read_signal_strength = stv090x_read_signal_strength,
- .read_snr = stv090x_read_cnr
+ .read_snr = stv090x_read_cnr,
};
diff --git a/drivers/media/dvb/frontends/stv6110.c b/drivers/media/dvb/frontends/stv6110.c
index 2dca7c8..20b5fa9 100644
--- a/drivers/media/dvb/frontends/stv6110.c
+++ b/drivers/media/dvb/frontends/stv6110.c
@@ -347,8 +347,7 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
return 0;
}
-static int stv6110_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int stv6110_set_params(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 bandwidth = carrier_width(c->symbol_rate, c->rolloff);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 6ca533e..1bff7f4 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -224,47 +224,86 @@ static int tda10021_init (struct dvb_frontend *fe)
return 0;
}
-static int tda10021_set_parameters (struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+struct qam_params {
+ u8 conf, agcref, lthr, mseth, aref;
+};
+
+static int tda10021_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ unsigned qam = c->modulation;
+ bool is_annex_c;
+ u32 reg0x3d;
struct tda10021_state* state = fe->demodulator_priv;
+ static const struct qam_params qam_params[] = {
+ /* Modulation Conf AGCref LTHR MSETH AREF */
+ [QPSK] = { 0x14, 0x78, 0x78, 0x8c, 0x96 },
+ [QAM_16] = { 0x00, 0x8c, 0x87, 0xa2, 0x91 },
+ [QAM_32] = { 0x04, 0x8c, 0x64, 0x74, 0x96 },
+ [QAM_64] = { 0x08, 0x6a, 0x46, 0x43, 0x6a },
+ [QAM_128] = { 0x0c, 0x78, 0x36, 0x34, 0x7e },
+ [QAM_256] = { 0x10, 0x5c, 0x26, 0x23, 0x6b },
+ };
+
+ switch (delsys) {
+ case SYS_DVBC_ANNEX_A:
+ is_annex_c = false;
+ break;
+ case SYS_DVBC_ANNEX_C:
+ is_annex_c = true;
+ break;
+ default:
+ return -EINVAL;
+ }
- //table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256
- //CONF
- static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c, 0x10 };
- //AGCREF value
- static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78, 0x5c };
- //LTHR value
- static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36, 0x26 };
- //MSETH
- static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34, 0x23 };
- //AREF
- static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e, 0x6b };
-
- int qam = p->u.qam.modulation;
-
- if (qam < 0 || qam > 5)
+ /*
+ * gcc optimizes the code bellow the same way as it would code:
+ * "if (qam > 5) return -EINVAL;"
+ * Yet, the code is clearer, as it shows what QAM standards are
+ * supported by the driver, and avoids the usage of magic numbers on
+ * it.
+ */
+ switch (qam) {
+ case QPSK:
+ case QAM_16:
+ case QAM_32:
+ case QAM_64:
+ case QAM_128:
+ case QAM_256:
+ break;
+ default:
return -EINVAL;
+ }
- if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF)
+ if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
return -EINVAL;
- //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
+ /*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
- _tda10021_writereg (state, 0x34, state->pwm);
-
- _tda10021_writereg (state, 0x01, reg0x01[qam]);
- _tda10021_writereg (state, 0x05, reg0x05[qam]);
- _tda10021_writereg (state, 0x08, reg0x08[qam]);
- _tda10021_writereg (state, 0x09, reg0x09[qam]);
-
- tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
+ tda10021_set_symbolrate(state, c->symbol_rate);
+ _tda10021_writereg(state, 0x34, state->pwm);
+
+ _tda10021_writereg(state, 0x01, qam_params[qam].agcref);
+ _tda10021_writereg(state, 0x05, qam_params[qam].lthr);
+ _tda10021_writereg(state, 0x08, qam_params[qam].mseth);
+ _tda10021_writereg(state, 0x09, qam_params[qam].aref);
+
+ /*
+ * Bit 0 == 0 means roll-off = 0.15 (Annex A)
+ * == 1 means roll-off = 0.13 (Annex C)
+ */
+ reg0x3d = tda10021_readreg (state, 0x3d);
+ if (is_annex_c)
+ _tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
+ else
+ _tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
+ tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
return 0;
}
@@ -347,8 +386,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda10021_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda10021_state* state = fe->demodulator_priv;
int sync;
s8 afc = 0;
@@ -360,17 +400,17 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
"DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
state->frontend.dvb->num, afc,
- -((s32)p->u.qam.symbol_rate * afc) >> 10);
+ -((s32)p->symbol_rate * afc) >> 10);
}
p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
- p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+ p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
- p->u.qam.fec_inner = FEC_NONE;
+ p->fec_inner = FEC_NONE;
p->frequency = ((p->frequency + 31250) / 62500) * 62500;
if (sync & 2)
- p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
+ p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
return 0;
}
@@ -444,10 +484,9 @@ error:
}
static struct dvb_frontend_ops tda10021_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
.info = {
.name = "Philips TDA10021 DVB-C",
- .type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 47000000,
.frequency_max = 862000000,
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
index a3c34ee..ca1e0d5 100644
--- a/drivers/media/dvb/frontends/tda10023.c
+++ b/drivers/media/dvb/frontends/tda10023.c
@@ -298,42 +298,80 @@ static int tda10023_init (struct dvb_frontend *fe)
return 0;
}
-static int tda10023_set_parameters (struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+struct qam_params {
+ u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd;
+};
+
+static int tda10023_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ u32 delsys = c->delivery_system;
+ unsigned qam = c->modulation;
+ bool is_annex_c;
struct tda10023_state* state = fe->demodulator_priv;
-
- static int qamvals[6][6] = {
- // QAM LOCKTHR MSETH AREF AGCREFNYQ ERAGCNYQ_THD
- { (5<<2), 0x78, 0x8c, 0x96, 0x78, 0x4c }, // 4 QAM
- { (0<<2), 0x87, 0xa2, 0x91, 0x8c, 0x57 }, // 16 QAM
- { (1<<2), 0x64, 0x74, 0x96, 0x8c, 0x57 }, // 32 QAM
- { (2<<2), 0x46, 0x43, 0x6a, 0x6a, 0x44 }, // 64 QAM
- { (3<<2), 0x36, 0x34, 0x7e, 0x78, 0x4c }, // 128 QAM
- { (4<<2), 0x26, 0x23, 0x6c, 0x5c, 0x3c }, // 256 QAM
+ static const struct qam_params qam_params[] = {
+ /* Modulation QAM LOCKTHR MSETH AREF AGCREFNYQ ERAGCNYQ_THD */
+ [QPSK] = { (5<<2), 0x78, 0x8c, 0x96, 0x78, 0x4c },
+ [QAM_16] = { (0<<2), 0x87, 0xa2, 0x91, 0x8c, 0x57 },
+ [QAM_32] = { (1<<2), 0x64, 0x74, 0x96, 0x8c, 0x57 },
+ [QAM_64] = { (2<<2), 0x46, 0x43, 0x6a, 0x6a, 0x44 },
+ [QAM_128] = { (3<<2), 0x36, 0x34, 0x7e, 0x78, 0x4c },
+ [QAM_256] = { (4<<2), 0x26, 0x23, 0x6c, 0x5c, 0x3c },
};
- int qam = p->u.qam.modulation;
+ switch (delsys) {
+ case SYS_DVBC_ANNEX_A:
+ is_annex_c = false;
+ break;
+ case SYS_DVBC_ANNEX_C:
+ is_annex_c = true;
+ break;
+ default:
+ return -EINVAL;
+ }
- if (qam < 0 || qam > 5)
+ /*
+ * gcc optimizes the code bellow the same way as it would code:
+ * "if (qam > 5) return -EINVAL;"
+ * Yet, the code is clearer, as it shows what QAM standards are
+ * supported by the driver, and avoids the usage of magic numbers on
+ * it.
+ */
+ switch (qam) {
+ case QPSK:
+ case QAM_16:
+ case QAM_32:
+ case QAM_64:
+ case QAM_128:
+ case QAM_256:
+ break;
+ default:
return -EINVAL;
+ }
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- tda10023_set_symbolrate (state, p->u.qam.symbol_rate);
- tda10023_writereg (state, 0x05, qamvals[qam][1]);
- tda10023_writereg (state, 0x08, qamvals[qam][2]);
- tda10023_writereg (state, 0x09, qamvals[qam][3]);
- tda10023_writereg (state, 0xb4, qamvals[qam][4]);
- tda10023_writereg (state, 0xb6, qamvals[qam][5]);
-
-// tda10023_writereg (state, 0x04, (p->inversion?0x12:0x32));
-// tda10023_writebit (state, 0x04, 0x60, (p->inversion?0:0x20));
- tda10023_writebit (state, 0x04, 0x40, 0x40);
- tda10023_setup_reg0 (state, qamvals[qam][0]);
+ tda10023_set_symbolrate(state, c->symbol_rate);
+ tda10023_writereg(state, 0x05, qam_params[qam].lockthr);
+ tda10023_writereg(state, 0x08, qam_params[qam].mseth);
+ tda10023_writereg(state, 0x09, qam_params[qam].aref);
+ tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq);
+ tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd);
+#if 0
+ tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32));
+ tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20));
+#endif
+ tda10023_writebit(state, 0x04, 0x40, 0x40);
+
+ if (is_annex_c)
+ tda10023_writebit(state, 0x3d, 0xfc, 0x03);
+ else
+ tda10023_writebit(state, 0x3d, 0xfc, 0x02);
+
+ tda10023_setup_reg0(state, qam_params[qam].qam);
return 0;
}
@@ -418,8 +456,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda10023_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda10023_state* state = fe->demodulator_priv;
int sync,inv;
s8 afc = 0;
@@ -433,17 +472,17 @@ static int tda10023_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" :
"DVB: TDA10023(%d): [AFC (%d) %dHz]\n",
state->frontend.dvb->num, afc,
- -((s32)p->u.qam.symbol_rate * afc) >> 10);
+ -((s32)p->symbol_rate * afc) >> 10);
}
p->inversion = (inv&0x20?0:1);
- p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+ p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
- p->u.qam.fec_inner = FEC_NONE;
+ p->fec_inner = FEC_NONE;
p->frequency = ((p->frequency + 31250) / 62500) * 62500;
if (sync & 2)
- p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
+ p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
return 0;
}
@@ -534,10 +573,9 @@ error:
}
static struct dvb_frontend_ops tda10023_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
.info = {
.name = "Philips TDA10023 DVB-C",
- .type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 47000000,
.frequency_max = 862000000,
@@ -557,7 +595,6 @@ static struct dvb_frontend_ops tda10023_ops = {
.set_frontend = tda10023_set_parameters,
.get_frontend = tda10023_get_frontend,
-
.read_status = tda10023_read_status,
.read_ber = tda10023_read_ber,
.read_signal_strength = tda10023_read_signal_strength,
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 7f10594..71fb632 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -153,7 +153,7 @@ struct tda10048_state {
u32 pll_pfactor;
u32 sample_freq;
- enum fe_bandwidth bandwidth;
+ u32 bandwidth;
};
static struct init_tab {
@@ -341,21 +341,14 @@ static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
{
struct tda10048_state *state = fe->demodulator_priv;
u64 t, z;
- u32 b = 8000000;
dprintk(1, "%s()\n", __func__);
if (sample_freq_hz == 0)
return -EINVAL;
- if (bw == BANDWIDTH_6_MHZ)
- b = 6000000;
- else
- if (bw == BANDWIDTH_7_MHZ)
- b = 7000000;
-
/* WREF = (B / (7 * fs)) * 2^31 */
- t = b * 10;
+ t = bw * 10;
/* avoid warning: this decimal constant is unsigned only in ISO C90 */
/* t *= 2147483648 on 32bit platforms */
t *= (2048 * 1024);
@@ -378,25 +371,18 @@ static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
{
struct tda10048_state *state = fe->demodulator_priv;
u64 t;
- u32 b = 8000000;
dprintk(1, "%s()\n", __func__);
if (sample_freq_hz == 0)
return -EINVAL;
- if (bw == BANDWIDTH_6_MHZ)
- b = 6000000;
- else
- if (bw == BANDWIDTH_7_MHZ)
- b = 7000000;
-
/* INVWREF = ((7 * fs) / B) * 2^5 */
t = sample_freq_hz;
t *= 7;
t *= 32;
t *= 10;
- do_div(t, b);
+ do_div(t, bw);
t += 5;
do_div(t, 10);
@@ -407,16 +393,16 @@ static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
}
static int tda10048_set_bandwidth(struct dvb_frontend *fe,
- enum fe_bandwidth bw)
+ u32 bw)
{
struct tda10048_state *state = fe->demodulator_priv;
dprintk(1, "%s(bw=%d)\n", __func__, bw);
/* Bandwidth setting may need to be adjusted */
switch (bw) {
- case BANDWIDTH_6_MHZ:
- case BANDWIDTH_7_MHZ:
- case BANDWIDTH_8_MHZ:
+ case 6000000:
+ case 7000000:
+ case 8000000:
tda10048_set_wref(fe, state->sample_freq, bw);
tda10048_set_invwref(fe, state->sample_freq, bw);
break;
@@ -430,7 +416,7 @@ static int tda10048_set_bandwidth(struct dvb_frontend *fe,
return 0;
}
-static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
+static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
{
struct tda10048_state *state = fe->demodulator_priv;
struct tda10048_config *config = &state->config;
@@ -441,13 +427,13 @@ static int tda10048_set_if(struct dvb_frontend *fe, enum fe_bandwidth bw)
/* based on target bandwidth and clk we calculate pll factors */
switch (bw) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
if_freq_khz = config->dtv6_if_freq_khz;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
if_freq_khz = config->dtv7_if_freq_khz;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
if_freq_khz = config->dtv8_if_freq_khz;
break;
default:
@@ -601,7 +587,7 @@ static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
/* Retrieve the demod settings */
static int tda10048_get_tps(struct tda10048_state *state,
- struct dvb_ofdm_parameters *p)
+ struct dtv_frontend_properties *p)
{
u8 val;
@@ -612,27 +598,27 @@ static int tda10048_get_tps(struct tda10048_state *state,
val = tda10048_readreg(state, TDA10048_OUT_CONF2);
switch ((val & 0x60) >> 5) {
case 0:
- p->constellation = QPSK;
+ p->modulation = QPSK;
break;
case 1:
- p->constellation = QAM_16;
+ p->modulation = QAM_16;
break;
case 2:
- p->constellation = QAM_64;
+ p->modulation = QAM_64;
break;
}
switch ((val & 0x18) >> 3) {
case 0:
- p->hierarchy_information = HIERARCHY_NONE;
+ p->hierarchy = HIERARCHY_NONE;
break;
case 1:
- p->hierarchy_information = HIERARCHY_1;
+ p->hierarchy = HIERARCHY_1;
break;
case 2:
- p->hierarchy_information = HIERARCHY_2;
+ p->hierarchy = HIERARCHY_2;
break;
case 3:
- p->hierarchy_information = HIERARCHY_4;
+ p->hierarchy = HIERARCHY_4;
break;
}
switch (val & 0x07) {
@@ -738,17 +724,17 @@ static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
/* TODO: Support manual tuning with specific params */
-static int tda10048_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int tda10048_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda10048_state *state = fe->demodulator_priv;
dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
/* Update the I/F pll's if the bandwidth changes */
- if (p->u.ofdm.bandwidth != state->bandwidth) {
- tda10048_set_if(fe, p->u.ofdm.bandwidth);
- tda10048_set_bandwidth(fe, p->u.ofdm.bandwidth);
+ if (p->bandwidth_hz != state->bandwidth) {
+ tda10048_set_if(fe, p->bandwidth_hz);
+ tda10048_set_bandwidth(fe, p->bandwidth_hz);
}
if (fe->ops.tuner_ops.set_params) {
@@ -756,7 +742,7 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -797,8 +783,8 @@ static int tda10048_init(struct dvb_frontend *fe)
tda10048_set_inversion(fe, config->inversion);
/* Establish default RF values */
- tda10048_set_if(fe, BANDWIDTH_8_MHZ);
- tda10048_set_bandwidth(fe, BANDWIDTH_8_MHZ);
+ tda10048_set_if(fe, 8000000);
+ tda10048_set_bandwidth(fe, 8000000);
/* Ensure we leave the gate closed */
tda10048_i2c_gate_ctrl(fe, 0);
@@ -1042,9 +1028,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
-static int tda10048_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int tda10048_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda10048_state *state = fe->demodulator_priv;
dprintk(1, "%s()\n", __func__);
@@ -1052,7 +1038,7 @@ static int tda10048_get_frontend(struct dvb_frontend *fe,
p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
& 0x20 ? INVERSION_ON : INVERSION_OFF;
- return tda10048_get_tps(state, &p->u.ofdm);
+ return tda10048_get_tps(state, p);
}
static int tda10048_get_tune_settings(struct dvb_frontend *fe,
@@ -1126,7 +1112,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
memcpy(&state->config, config, sizeof(*config));
state->i2c = i2c;
state->fwloaded = config->no_firmware;
- state->bandwidth = BANDWIDTH_8_MHZ;
+ state->bandwidth = 8000000;
/* check if the demod is present */
if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
@@ -1152,11 +1138,11 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
tda10048_establish_defaults(&state->frontend);
/* Set the xtal and freq defaults */
- if (tda10048_set_if(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+ if (tda10048_set_if(&state->frontend, 8000000) != 0)
goto error;
/* Default bandwidth */
- if (tda10048_set_bandwidth(&state->frontend, BANDWIDTH_8_MHZ) != 0)
+ if (tda10048_set_bandwidth(&state->frontend, 8000000) != 0)
goto error;
/* Leave the gate closed */
@@ -1171,10 +1157,9 @@ error:
EXPORT_SYMBOL(tda10048_attach);
static struct dvb_frontend_ops tda10048_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "NXP TDA10048HN DVB-T",
- .type = FE_OFDM,
.frequency_min = 177000000,
.frequency_max = 858000000,
.frequency_stepsize = 166666,
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index ea485d9..ae6f22a 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -224,22 +224,22 @@ static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
}
static int tda10045h_set_bandwidth(struct tda1004x_state *state,
- fe_bandwidth_t bandwidth)
+ u32 bandwidth)
{
static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
break;
@@ -253,7 +253,7 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
}
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
- fe_bandwidth_t bandwidth)
+ u32 bandwidth)
{
static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
@@ -270,7 +270,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
else
tda10046_clk53m = 1;
switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
+ case 6000000:
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
sizeof(bandwidth_6mhz_53M));
@@ -283,7 +283,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
}
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
sizeof(bandwidth_7mhz_53M));
@@ -296,7 +296,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
}
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
sizeof(bandwidth_8mhz_53M));
@@ -409,7 +409,7 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
msleep(10);
/* set parameters */
- tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ);
+ tda10045h_set_bandwidth(state, 8000000);
ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
release_firmware(fw);
@@ -473,7 +473,7 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
break;
}
- tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
+ tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */
/* let the PLLs settle */
msleep(120);
}
@@ -697,9 +697,9 @@ static int tda10046_init(struct dvb_frontend* fe)
return 0;
}
-static int tda1004x_set_fe(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fe_params)
+static int tda1004x_set_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
struct tda1004x_state* state = fe->demodulator_priv;
int tmp;
int inversion;
@@ -718,7 +718,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// set frequency
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fe_params);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
@@ -726,37 +726,37 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Hardcoded to use auto as much as possible on the TDA10045 as it
// is very unreliable if AUTO mode is _not_ used.
if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
- fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+ fe_params->code_rate_HP = FEC_AUTO;
+ fe_params->guard_interval = GUARD_INTERVAL_AUTO;
+ fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
}
// Set standard params.. or put them to auto
- if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
- (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
- (fe_params->u.ofdm.constellation == QAM_AUTO) ||
- (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+ if ((fe_params->code_rate_HP == FEC_AUTO) ||
+ (fe_params->code_rate_LP == FEC_AUTO) ||
+ (fe_params->modulation == QAM_AUTO) ||
+ (fe_params->hierarchy == HIERARCHY_AUTO)) {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
- tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
+ tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); /* turn off modulation bits */
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits
} else {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0); // disable auto
// set HP FEC
- tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP);
+ tmp = tda1004x_encode_fec(fe_params->code_rate_HP);
if (tmp < 0)
return tmp;
tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
// set LP FEC
- tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP);
+ tmp = tda1004x_encode_fec(fe_params->code_rate_LP);
if (tmp < 0)
return tmp;
tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
- // set constellation
- switch (fe_params->u.ofdm.constellation) {
+ /* set modulation */
+ switch (fe_params->modulation) {
case QPSK:
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0);
break;
@@ -774,7 +774,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// set hierarchy
- switch (fe_params->u.ofdm.hierarchy_information) {
+ switch (fe_params->hierarchy) {
case HIERARCHY_NONE:
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
break;
@@ -799,11 +799,11 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// set bandwidth
switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
- tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
+ tda10045h_set_bandwidth(state, fe_params->bandwidth_hz);
break;
case TDA1004X_DEMOD_TDA10046:
- tda10046h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
+ tda10046h_set_bandwidth(state, fe_params->bandwidth_hz);
break;
}
@@ -825,7 +825,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// set guard interval
- switch (fe_params->u.ofdm.guard_interval) {
+ switch (fe_params->guard_interval) {
case GUARD_INTERVAL_1_32:
tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
@@ -856,7 +856,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// set transmission mode
- switch (fe_params->u.ofdm.transmission_mode) {
+ switch (fe_params->transmission_mode) {
case TRANSMISSION_MODE_2K:
tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
@@ -895,8 +895,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
return 0;
}
-static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+static int tda1004x_get_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
struct tda1004x_state* state = fe->demodulator_priv;
dprintk("%s\n", __func__);
@@ -913,13 +914,13 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
case TDA1004X_DEMOD_TDA10045:
switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
case 0x14:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ fe_params->bandwidth_hz = 8000000;
break;
case 0xdb:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ fe_params->bandwidth_hz = 7000000;
break;
case 0x4f:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ fe_params->bandwidth_hz = 6000000;
break;
}
break;
@@ -927,73 +928,73 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
case 0x5c:
case 0x54:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+ fe_params->bandwidth_hz = 8000000;
break;
case 0x6a:
case 0x60:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+ fe_params->bandwidth_hz = 7000000;
break;
case 0x7b:
case 0x70:
- fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+ fe_params->bandwidth_hz = 6000000;
break;
}
break;
}
// FEC
- fe_params->u.ofdm.code_rate_HP =
+ fe_params->code_rate_HP =
tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);
- fe_params->u.ofdm.code_rate_LP =
+ fe_params->code_rate_LP =
tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);
- // constellation
+ /* modulation */
switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {
case 0:
- fe_params->u.ofdm.constellation = QPSK;
+ fe_params->modulation = QPSK;
break;
case 1:
- fe_params->u.ofdm.constellation = QAM_16;
+ fe_params->modulation = QAM_16;
break;
case 2:
- fe_params->u.ofdm.constellation = QAM_64;
+ fe_params->modulation = QAM_64;
break;
}
// transmission mode
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+ fe_params->transmission_mode = TRANSMISSION_MODE_2K;
if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+ fe_params->transmission_mode = TRANSMISSION_MODE_8K;
// guard interval
switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
case 0:
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+ fe_params->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+ fe_params->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+ fe_params->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+ fe_params->guard_interval = GUARD_INTERVAL_1_4;
break;
}
// hierarchy
switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
case 0:
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ fe_params->hierarchy = HIERARCHY_NONE;
break;
case 1:
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_1;
+ fe_params->hierarchy = HIERARCHY_1;
break;
case 2:
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_2;
+ fe_params->hierarchy = HIERARCHY_2;
break;
case 3:
- fe_params->u.ofdm.hierarchy_information = HIERARCHY_4;
+ fe_params->hierarchy = HIERARCHY_4;
break;
}
@@ -1231,9 +1232,9 @@ static void tda1004x_release(struct dvb_frontend* fe)
}
static struct dvb_frontend_ops tda10045_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "Philips TDA10045H DVB-T",
- .type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 858000000,
.frequency_stepsize = 166667,
@@ -1301,9 +1302,9 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
}
static struct dvb_frontend_ops tda10046_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "Philips TDA10046H DVB-T",
- .type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 858000000,
.frequency_stepsize = 166667,
diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c
index 0c37434..a992050 100644
--- a/drivers/media/dvb/frontends/tda10071.c
+++ b/drivers/media/dvb/frontends/tda10071.c
@@ -636,8 +636,7 @@ error:
return ret;
}
-static int tda10071_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tda10071_set_frontend(struct dvb_frontend *fe)
{
struct tda10071_priv *priv = fe->demodulator_priv;
struct tda10071_cmd cmd;
@@ -777,8 +776,7 @@ error:
return ret;
}
-static int tda10071_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int tda10071_get_frontend(struct dvb_frontend *fe)
{
struct tda10071_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1217,9 +1215,9 @@ error:
EXPORT_SYMBOL(tda10071_attach);
static struct dvb_frontend_ops tda10071_ops = {
+ .delsys = { SYS_DVBT, SYS_DVBT2 },
.info = {
.name = "NXP TDA10071",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_tolerance = 5000,
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index f2c8faa..fcfe2e0 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -267,7 +267,7 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic
}
static int tda10086_set_inversion(struct tda10086_state *state,
- struct dvb_frontend_parameters *fe_params)
+ struct dtv_frontend_properties *fe_params)
{
u8 invval = 0x80;
@@ -292,7 +292,7 @@ static int tda10086_set_inversion(struct tda10086_state *state,
}
static int tda10086_set_symbol_rate(struct tda10086_state *state,
- struct dvb_frontend_parameters *fe_params)
+ struct dtv_frontend_properties *fe_params)
{
u8 dfn = 0;
u8 afs = 0;
@@ -303,7 +303,7 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
u32 tmp;
u32 bdr;
u32 bdri;
- u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
+ u32 symbol_rate = fe_params->symbol_rate;
dprintk ("%s %i\n", __func__, symbol_rate);
@@ -367,13 +367,13 @@ static int tda10086_set_symbol_rate(struct tda10086_state *state,
}
static int tda10086_set_fec(struct tda10086_state *state,
- struct dvb_frontend_parameters *fe_params)
+ struct dtv_frontend_properties *fe_params)
{
u8 fecval;
- dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);
+ dprintk("%s %i\n", __func__, fe_params->fec_inner);
- switch(fe_params->u.qpsk.fec_inner) {
+ switch (fe_params->fec_inner) {
case FEC_1_2:
fecval = 0x00;
break;
@@ -409,9 +409,9 @@ static int tda10086_set_fec(struct tda10086_state *state,
return 0;
}
-static int tda10086_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fe_params)
+static int tda10086_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
struct tda10086_state *state = fe->demodulator_priv;
int ret;
u32 freq = 0;
@@ -425,7 +425,7 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
/* set params */
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, fe_params);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
@@ -452,13 +452,14 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
tda10086_write_mask(state, 0x10, 0x40, 0x40);
tda10086_write_mask(state, 0x00, 0x01, 0x00);
- state->symbol_rate = fe_params->u.qpsk.symbol_rate;
+ state->symbol_rate = fe_params->symbol_rate;
state->frequency = fe_params->frequency;
return 0;
}
-static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+static int tda10086_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
struct tda10086_state* state = fe->demodulator_priv;
u8 val;
int tmp;
@@ -467,7 +468,7 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
dprintk ("%s\n", __func__);
/* check for invalid symbol rate */
- if (fe_params->u.qpsk.symbol_rate < 500000)
+ if (fe_params->symbol_rate < 500000)
return -EINVAL;
/* calculate the updated frequency (note: we convert from Hz->kHz) */
@@ -516,34 +517,34 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
tmp |= 0xffffff00;
tmp = (tmp * 480 * (1<<1)) / 128;
tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
- fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
+ fe_params->symbol_rate = state->symbol_rate + tmp;
/* the FEC */
val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
switch(val) {
case 0x00:
- fe_params->u.qpsk.fec_inner = FEC_1_2;
+ fe_params->fec_inner = FEC_1_2;
break;
case 0x01:
- fe_params->u.qpsk.fec_inner = FEC_2_3;
+ fe_params->fec_inner = FEC_2_3;
break;
case 0x02:
- fe_params->u.qpsk.fec_inner = FEC_3_4;
+ fe_params->fec_inner = FEC_3_4;
break;
case 0x03:
- fe_params->u.qpsk.fec_inner = FEC_4_5;
+ fe_params->fec_inner = FEC_4_5;
break;
case 0x04:
- fe_params->u.qpsk.fec_inner = FEC_5_6;
+ fe_params->fec_inner = FEC_5_6;
break;
case 0x05:
- fe_params->u.qpsk.fec_inner = FEC_6_7;
+ fe_params->fec_inner = FEC_6_7;
break;
case 0x06:
- fe_params->u.qpsk.fec_inner = FEC_7_8;
+ fe_params->fec_inner = FEC_7_8;
break;
case 0x07:
- fe_params->u.qpsk.fec_inner = FEC_8_9;
+ fe_params->fec_inner = FEC_8_9;
break;
}
@@ -664,29 +665,31 @@ static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
- if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+ if (p->symbol_rate > 20000000) {
fesettings->min_delay_ms = 50;
fesettings->step_size = 2000;
fesettings->max_drift = 8000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+ } else if (p->symbol_rate > 12000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 1500;
fesettings->max_drift = 9000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+ } else if (p->symbol_rate > 8000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 1000;
fesettings->max_drift = 8000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+ } else if (p->symbol_rate > 4000000) {
fesettings->min_delay_ms = 100;
fesettings->step_size = 500;
fesettings->max_drift = 7000;
- } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+ } else if (p->symbol_rate > 2000000) {
fesettings->min_delay_ms = 200;
- fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->step_size = p->symbol_rate / 8000;
fesettings->max_drift = 14 * fesettings->step_size;
} else {
fesettings->min_delay_ms = 200;
- fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+ fesettings->step_size = p->symbol_rate / 8000;
fesettings->max_drift = 18 * fesettings->step_size;
}
@@ -701,10 +704,9 @@ static void tda10086_release(struct dvb_frontend* fe)
}
static struct dvb_frontend_ops tda10086_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Philips TDA10086 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c
index 1b1bf20..86da3d8 100644
--- a/drivers/media/dvb/frontends/tda18271c2dd.c
+++ b/drivers/media/dvb/frontends/tda18271c2dd.c
@@ -1123,55 +1123,51 @@ static int release(struct dvb_frontend *fe)
return 0;
}
-/*
- * As defined on EN 300 429 Annex A and on ITU-T J.83 annex A, the DVB-C
- * roll-off factor is 0.15.
- * According with the specs, the amount of the needed bandwith is given by:
- * Bw = Symbol_rate * (1 + 0.15)
- * As such, the maximum symbol rate supported by 6 MHz is
- * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
- *NOTE: For ITU-T J.83 Annex C, the roll-off factor is 0.13. So:
- * max_symbol_rate = 6 MHz / 1.13 = 5309735 Baud
- * That means that an adjustment is needed for Japan,
- * but, as currently DRX-K is hardcoded to Annex A, let's stick
- * with 0.15 roll-off factor.
- */
-#define MAX_SYMBOL_RATE_6MHz 5217391
-static int set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int set_params(struct dvb_frontend *fe)
{
struct tda_state *state = fe->tuner_priv;
int status = 0;
int Standard;
+ u32 bw = fe->dtv_property_cache.bandwidth_hz;
+ u32 delsys = fe->dtv_property_cache.delivery_system;
- state->m_Frequency = params->frequency;
+ state->m_Frequency = fe->dtv_property_cache.frequency;
- if (fe->ops.info.type == FE_OFDM)
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (delsys) {
+ case SYS_DVBT:
+ case SYS_DVBT2:
+ switch (bw) {
+ case 6000000:
Standard = HF_DVBT_6MHZ;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
Standard = HF_DVBT_7MHZ;
break;
- default:
- case BANDWIDTH_8_MHZ:
+ case 8000000:
Standard = HF_DVBT_8MHZ;
break;
+ default:
+ return -EINVAL;
}
- else if (fe->ops.info.type == FE_QAM) {
- if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz)
+ case SYS_DVBC_ANNEX_A:
+ case SYS_DVBC_ANNEX_C:
+ if (bw <= 6000000)
Standard = HF_DVBC_6MHZ;
+ else if (bw <= 7000000)
+ Standard = HF_DVBC_7MHZ;
else
Standard = HF_DVBC_8MHZ;
- } else
+ break;
+ default:
return -EINVAL;
+ }
do {
- status = RFTrackingFiltersCorrection(state, params->frequency);
+ status = RFTrackingFiltersCorrection(state, state->m_Frequency);
if (status < 0)
break;
- status = ChannelConfiguration(state, params->frequency, Standard);
+ status = ChannelConfiguration(state, state->m_Frequency,
+ Standard);
if (status < 0)
break;
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 9369f74..15912c9 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -315,18 +315,19 @@ static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda8083_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda8083_state* state = fe->demodulator_priv;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
tda8083_set_inversion (state, p->inversion);
- tda8083_set_fec (state, p->u.qpsk.fec_inner);
- tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate);
+ tda8083_set_fec(state, p->fec_inner);
+ tda8083_set_symbolrate(state, p->symbol_rate);
tda8083_writereg (state, 0x00, 0x3c);
tda8083_writereg (state, 0x00, 0x04);
@@ -334,16 +335,17 @@ static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return 0;
}
-static int tda8083_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int tda8083_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda8083_state* state = fe->demodulator_priv;
/* FIXME: get symbolrate & frequency offset...*/
/*p->frequency = ???;*/
p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
INVERSION_ON : INVERSION_OFF;
- p->u.qpsk.fec_inner = tda8083_get_fec (state);
- /*p->u.qpsk.symbol_rate = tda8083_get_symbolrate (state);*/
+ p->fec_inner = tda8083_get_fec(state);
+ /*p->symbol_rate = tda8083_get_symbolrate (state);*/
return 0;
}
@@ -438,10 +440,9 @@ error:
}
static struct dvb_frontend_ops tda8083_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "Philips TDA8083 DVB-S",
- .type = FE_QPSK,
.frequency_min = 920000, /* TDA8060 */
.frequency_max = 2200000, /* TDA8060 */
.frequency_stepsize = 125, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
index 06c9480..04bbcc2 100644
--- a/drivers/media/dvb/frontends/tda826x.c
+++ b/drivers/media/dvb/frontends/tda826x.c
@@ -71,8 +71,9 @@ static int tda826x_sleep(struct dvb_frontend *fe)
return (ret == 1) ? 0 : ret;
}
-static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda826x_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct tda826x_priv *priv = fe->tuner_priv;
int ret;
u32 div;
@@ -83,11 +84,11 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
dprintk("%s:\n", __func__);
- div = (params->frequency + (1000-1)) / 1000;
+ div = (p->frequency + (1000-1)) / 1000;
/* BW = ((1 + RO) * SR/2 + 5) * 1.3 [SR in MSPS, BW in MHz] */
/* with R0 = 0.35 and some transformations: */
- ksyms = params->u.qpsk.symbol_rate / 1000;
+ ksyms = p->symbol_rate / 1000;
bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
if (bandwidth < 5)
bandwidth = 5;
diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h
index 51f1706..1775098 100644
--- a/drivers/media/dvb/frontends/tdhd1.h
+++ b/drivers/media/dvb/frontends/tdhd1.h
@@ -40,24 +40,25 @@ static struct tda1004x_config alps_tdhd1_204a_config = {
.request_firmware = alps_tdhd1_204_request_firmware
};
-static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct i2c_adapter *i2c = fe->tuner_priv;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
u32 div;
- div = (params->frequency + 36166666) / 166666;
+ div = (p->frequency + 36166666) / 166666;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85;
- if (params->frequency >= 174000000 && params->frequency <= 230000000)
+ if (p->frequency >= 174000000 && p->frequency <= 230000000)
data[3] = 0x02;
- else if (params->frequency >= 470000000 && params->frequency <= 823000000)
+ else if (p->frequency >= 470000000 && p->frequency <= 823000000)
data[3] = 0x0C;
- else if (params->frequency > 823000000 && params->frequency <= 862000000)
+ else if (p->frequency > 823000000 && p->frequency <= 862000000)
data[3] = 0x8C;
else
return -EINVAL;
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
index bcb95c2..029384d 100644
--- a/drivers/media/dvb/frontends/tua6100.c
+++ b/drivers/media/dvb/frontends/tua6100.c
@@ -67,9 +67,9 @@ static int tua6100_sleep(struct dvb_frontend *fe)
return (ret == 1) ? 0 : ret;
}
-static int tua6100_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int tua6100_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct tua6100_priv *priv = fe->tuner_priv;
u32 div;
u32 prediv;
@@ -85,36 +85,37 @@ static int tua6100_set_params(struct dvb_frontend *fe,
#define _ri 4000000
// setup register 0
- if (params->frequency < 2000000) {
+ if (c->frequency < 2000000)
reg0[1] = 0x03;
- } else {
+ else
reg0[1] = 0x07;
- }
// setup register 1
- if (params->frequency < 1630000) {
+ if (c->frequency < 1630000)
reg1[1] = 0x2c;
- } else {
+ else
reg1[1] = 0x0c;
- }
+
if (_P == 64)
reg1[1] |= 0x40;
- if (params->frequency >= 1525000)
+ if (c->frequency >= 1525000)
reg1[1] |= 0x80;
// register 2
reg2[1] = (_R >> 8) & 0x03;
reg2[2] = _R;
- if (params->frequency < 1455000) {
+ if (c->frequency < 1455000)
reg2[1] |= 0x1c;
- } else if (params->frequency < 1630000) {
+ else if (c->frequency < 1630000)
reg2[1] |= 0x0c;
- } else {
+ else
reg2[1] |= 0x1c;
- }
- // The N divisor ratio (note: params->frequency is in kHz, but we need it in Hz)
- prediv = (params->frequency * _R) / (_ri / 1000);
+ /*
+ * The N divisor ratio (note: c->frequency is in kHz, but we
+ * need it in Hz)
+ */
+ prediv = (c->frequency * _R) / (_ri / 1000);
div = prediv / _P;
reg1[1] |= (div >> 9) & 0x03;
reg1[2] = div >> 1;
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 550a07a..bb42b56 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -205,25 +205,26 @@ static int ves1820_init(struct dvb_frontend* fe)
return 0;
}
-static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1820_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ves1820_state* state = fe->demodulator_priv;
static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
- int real_qam = p->u.qam.modulation - QAM_16;
+ int real_qam = p->modulation - QAM_16;
if (real_qam < 0 || real_qam > 4)
return -EINVAL;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
+ ves1820_set_symbolrate(state, p->symbol_rate);
ves1820_writereg(state, 0x34, state->pwm);
ves1820_writereg(state, 0x01, reg0x01[real_qam]);
@@ -309,8 +310,9 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1820_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ves1820_state* state = fe->demodulator_priv;
int sync;
s8 afc = 0;
@@ -320,7 +322,7 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if (verbose) {
/* AFC only valid when carrier has been recovered */
printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
- "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10);
+ "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->symbol_rate * afc) >> 10);
}
if (!state->config->invert) {
@@ -329,13 +331,13 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
}
- p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+ p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
- p->u.qam.fec_inner = FEC_NONE;
+ p->fec_inner = FEC_NONE;
p->frequency = ((p->frequency + 31250) / 62500) * 62500;
if (sync & 2)
- p->frequency -= ((s32) p->u.qam.symbol_rate * afc) >> 10;
+ p->frequency -= ((s32) p->symbol_rate * afc) >> 10;
return 0;
}
@@ -405,10 +407,9 @@ error:
}
static struct dvb_frontend_ops ves1820_ops = {
-
+ .delsys = { SYS_DVBC_ANNEX_A },
.info = {
.name = "VLSI VES1820 DVB-C",
- .type = FE_QAM,
.frequency_stepsize = 62500,
.frequency_min = 47000000,
.frequency_max = 862000000,
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
index 8d7854c..9c17eac 100644
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ b/drivers/media/dvb/frontends/ves1x93.c
@@ -46,6 +46,7 @@ struct ves1x93_state {
u8 *init_1x93_wtab;
u8 tab_size;
u8 demod_type;
+ u32 frequency;
};
static int debug;
@@ -384,31 +385,34 @@ static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
-static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1x93_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ves1x93_state* state = fe->demodulator_priv;
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, p);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
ves1x93_set_inversion (state, p->inversion);
- ves1x93_set_fec (state, p->u.qpsk.fec_inner);
- ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
+ ves1x93_set_fec(state, p->fec_inner);
+ ves1x93_set_symbolrate(state, p->symbol_rate);
state->inversion = p->inversion;
+ state->frequency = p->frequency;
return 0;
}
-static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ves1x93_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ves1x93_state* state = fe->demodulator_priv;
int afc;
afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
- afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
+ afc = (afc * (int)(p->symbol_rate/1000/8))/16;
- p->frequency -= afc;
+ p->frequency = state->frequency - afc;
/*
* inversion indicator is only valid
@@ -417,7 +421,7 @@ static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if (state->inversion == INVERSION_AUTO)
p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ?
INVERSION_OFF : INVERSION_ON;
- p->u.qpsk.fec_inner = ves1x93_get_fec (state);
+ p->fec_inner = ves1x93_get_fec(state);
/* XXX FIXME: timing offset !! */
return 0;
@@ -506,10 +510,9 @@ error:
}
static struct dvb_frontend_ops ves1x93_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "VLSI VES1x93 DVB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125, /* kHz for QPSK frontends */
diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c
index 81aa984..0903d46 100644
--- a/drivers/media/dvb/frontends/zl10036.c
+++ b/drivers/media/dvb/frontends/zl10036.c
@@ -305,12 +305,12 @@ static int zl10036_set_gain_params(struct zl10036_state *state,
return zl10036_write(state, buf, sizeof(buf));
}
-static int zl10036_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int zl10036_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct zl10036_state *state = fe->tuner_priv;
int ret = 0;
- u32 frequency = params->frequency;
+ u32 frequency = p->frequency;
u32 fbw;
int i;
u8 c;
@@ -326,7 +326,7 @@ static int zl10036_set_params(struct dvb_frontend *fe,
* fBW = (alpha*symbolrate)/(2*0.8)
* 1.35 / (2*0.8) = 27 / 32
*/
- fbw = (27 * params->u.qpsk.symbol_rate) / 32;
+ fbw = (27 * p->symbol_rate) / 32;
/* scale to kHz */
fbw /= 1000;
@@ -353,7 +353,7 @@ static int zl10036_set_params(struct dvb_frontend *fe,
if (ret < 0)
goto error;
- ret = zl10036_set_frequency(state, params->frequency);
+ ret = zl10036_set_frequency(state, p->frequency);
if (ret < 0)
goto error;
diff --git a/drivers/media/dvb/frontends/zl10039.c b/drivers/media/dvb/frontends/zl10039.c
index c085e58..eff9c5f 100644
--- a/drivers/media/dvb/frontends/zl10039.c
+++ b/drivers/media/dvb/frontends/zl10039.c
@@ -176,9 +176,9 @@ static int zl10039_sleep(struct dvb_frontend *fe)
return 0;
}
-static int zl10039_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int zl10039_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct zl10039_state *state = fe->tuner_priv;
u8 buf[6];
u8 bf;
@@ -188,12 +188,12 @@ static int zl10039_set_params(struct dvb_frontend *fe,
dprintk("%s\n", __func__);
dprintk("Set frequency = %d, symbol rate = %d\n",
- params->frequency, params->u.qpsk.symbol_rate);
+ c->frequency, c->symbol_rate);
/* Assumed 10.111 MHz crystal oscillator */
/* Cancelled num/den 80 to prevent overflow */
- div = (params->frequency * 1000) / 126387;
- fbw = (params->u.qpsk.symbol_rate * 27) / 32000;
+ div = (c->frequency * 1000) / 126387;
+ fbw = (c->symbol_rate * 27) / 32000;
/* Cancelled num/den 10 to prevent overflow */
bf = ((fbw * 5088) / 1011100) - 1;
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index adbbf6d..ac72378 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -37,9 +37,9 @@ struct zl10353_state {
struct zl10353_config config;
- enum fe_bandwidth bandwidth;
- u32 ucblocks;
- u32 frequency;
+ u32 bandwidth;
+ u32 ucblocks;
+ u32 frequency;
};
static int debug;
@@ -122,30 +122,17 @@ static void zl10353_dump_regs(struct dvb_frontend *fe)
}
static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
- enum fe_bandwidth bandwidth,
+ u32 bandwidth,
u16 *nominal_rate)
{
struct zl10353_state *state = fe->demodulator_priv;
u32 adc_clock = 450560; /* 45.056 MHz */
u64 value;
- u8 bw;
+ u8 bw = bandwidth / 1000000;
if (state->config.adc_clock)
adc_clock = state->config.adc_clock;
- switch (bandwidth) {
- case BANDWIDTH_6_MHZ:
- bw = 6;
- break;
- case BANDWIDTH_7_MHZ:
- bw = 7;
- break;
- case BANDWIDTH_8_MHZ:
- default:
- bw = 8;
- break;
- }
-
value = (u64)10 * (1 << 23) / 7 * 125;
value = (bw * value) + adc_clock / 2;
do_div(value, adc_clock);
@@ -192,16 +179,15 @@ static int zl10353_sleep(struct dvb_frontend *fe)
return 0;
}
-static int zl10353_set_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int zl10353_set_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct zl10353_state *state = fe->demodulator_priv;
u16 nominal_rate, input_freq;
u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
u16 tps = 0;
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
- state->frequency = param->frequency;
+ state->frequency = c->frequency;
zl10353_single_write(fe, RESET, 0x80);
udelay(200);
@@ -211,42 +197,44 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
zl10353_single_write(fe, AGC_TARGET, 0x28);
- if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
+ if (c->transmission_mode != TRANSMISSION_MODE_AUTO)
acq_ctl |= (1 << 0);
- if (op->guard_interval != GUARD_INTERVAL_AUTO)
+ if (c->guard_interval != GUARD_INTERVAL_AUTO)
acq_ctl |= (1 << 1);
zl10353_single_write(fe, ACQ_CTL, acq_ctl);
- switch (op->bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
/* These are extrapolated from the 7 and 8MHz values */
zl10353_single_write(fe, MCLK_RATIO, 0x97);
zl10353_single_write(fe, 0x64, 0x34);
zl10353_single_write(fe, 0xcc, 0xdd);
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
zl10353_single_write(fe, MCLK_RATIO, 0x86);
zl10353_single_write(fe, 0x64, 0x35);
zl10353_single_write(fe, 0xcc, 0x73);
break;
- case BANDWIDTH_8_MHZ:
default:
+ c->bandwidth_hz = 8000000;
+ /* fall though */
+ case 8000000:
zl10353_single_write(fe, MCLK_RATIO, 0x75);
zl10353_single_write(fe, 0x64, 0x36);
zl10353_single_write(fe, 0xcc, 0x73);
}
- zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
+ zl10353_calc_nominal_rate(fe, c->bandwidth_hz, &nominal_rate);
zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
- state->bandwidth = op->bandwidth;
+ state->bandwidth = c->bandwidth_hz;
zl10353_calc_input_freq(fe, &input_freq);
zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
/* Hint at TPS settings */
- switch (op->code_rate_HP) {
+ switch (c->code_rate_HP) {
case FEC_2_3:
tps |= (1 << 7);
break;
@@ -266,7 +254,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
return -EINVAL;
}
- switch (op->code_rate_LP) {
+ switch (c->code_rate_LP) {
case FEC_2_3:
tps |= (1 << 4);
break;
@@ -283,14 +271,14 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
case FEC_AUTO:
break;
case FEC_NONE:
- if (op->hierarchy_information == HIERARCHY_AUTO ||
- op->hierarchy_information == HIERARCHY_NONE)
+ if (c->hierarchy == HIERARCHY_AUTO ||
+ c->hierarchy == HIERARCHY_NONE)
break;
default:
return -EINVAL;
}
- switch (op->constellation) {
+ switch (c->modulation) {
case QPSK:
break;
case QAM_AUTO:
@@ -304,7 +292,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
return -EINVAL;
}
- switch (op->transmission_mode) {
+ switch (c->transmission_mode) {
case TRANSMISSION_MODE_2K:
case TRANSMISSION_MODE_AUTO:
break;
@@ -315,7 +303,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
return -EINVAL;
}
- switch (op->guard_interval) {
+ switch (c->guard_interval) {
case GUARD_INTERVAL_1_32:
case GUARD_INTERVAL_AUTO:
break;
@@ -332,7 +320,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
return -EINVAL;
}
- switch (op->hierarchy_information) {
+ switch (c->hierarchy) {
case HIERARCHY_AUTO:
case HIERARCHY_NONE:
break;
@@ -362,12 +350,12 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
*/
if (state->config.no_tuner) {
if (fe->ops.tuner_ops.set_params) {
- fe->ops.tuner_ops.set_params(fe, param);
+ fe->ops.tuner_ops.set_params(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
} else if (fe->ops.tuner_ops.calc_regs) {
- fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5);
+ fe->ops.tuner_ops.calc_regs(fe, pllbuf + 1, 5);
pllbuf[1] <<= 1;
zl10353_write(fe, pllbuf, sizeof(pllbuf));
}
@@ -383,11 +371,10 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
return 0;
}
-static int zl10353_get_parameters(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int zl10353_get_parameters(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct zl10353_state *state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *op = &param->u.ofdm;
int s6, s9;
u16 tps;
static const u8 tps_fec_to_api[8] = {
@@ -411,66 +398,66 @@ static int zl10353_get_parameters(struct dvb_frontend *fe,
tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
zl10353_read_register(state, TPS_RECEIVED_0);
- op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
- op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
+ c->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
+ c->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
switch ((tps >> 13) & 3) {
case 0:
- op->constellation = QPSK;
+ c->modulation = QPSK;
break;
case 1:
- op->constellation = QAM_16;
+ c->modulation = QAM_16;
break;
case 2:
- op->constellation = QAM_64;
+ c->modulation = QAM_64;
break;
default:
- op->constellation = QAM_AUTO;
+ c->modulation = QAM_AUTO;
break;
}
- op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
+ c->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
TRANSMISSION_MODE_2K;
switch ((tps >> 2) & 3) {
case 0:
- op->guard_interval = GUARD_INTERVAL_1_32;
+ c->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
- op->guard_interval = GUARD_INTERVAL_1_16;
+ c->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
- op->guard_interval = GUARD_INTERVAL_1_8;
+ c->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- op->guard_interval = GUARD_INTERVAL_1_4;
+ c->guard_interval = GUARD_INTERVAL_1_4;
break;
default:
- op->guard_interval = GUARD_INTERVAL_AUTO;
+ c->guard_interval = GUARD_INTERVAL_AUTO;
break;
}
switch ((tps >> 10) & 7) {
case 0:
- op->hierarchy_information = HIERARCHY_NONE;
+ c->hierarchy = HIERARCHY_NONE;
break;
case 1:
- op->hierarchy_information = HIERARCHY_1;
+ c->hierarchy = HIERARCHY_1;
break;
case 2:
- op->hierarchy_information = HIERARCHY_2;
+ c->hierarchy = HIERARCHY_2;
break;
case 3:
- op->hierarchy_information = HIERARCHY_4;
+ c->hierarchy = HIERARCHY_4;
break;
default:
- op->hierarchy_information = HIERARCHY_AUTO;
+ c->hierarchy = HIERARCHY_AUTO;
break;
}
- param->frequency = state->frequency;
- op->bandwidth = state->bandwidth;
- param->inversion = INVERSION_AUTO;
+ c->frequency = state->frequency;
+ c->bandwidth_hz = state->bandwidth;
+ c->inversion = INVERSION_AUTO;
return 0;
}
@@ -651,10 +638,9 @@ error:
}
static struct dvb_frontend_ops zl10353_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "Zarlink ZL10353 DVB-T",
- .type = FE_OFDM,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 166667,
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c
index 2ae0afa..ad013e9 100644
--- a/drivers/media/dvb/mantis/mantis_vp1033.c
+++ b/drivers/media/dvb/mantis/mantis_vp1033.c
@@ -83,9 +83,9 @@ u8 lgtdqcs001f_inittab[] = {
#define MANTIS_MODEL_NAME "VP-1033"
#define MANTIS_DEV_TYPE "DVB-S/DSS"
-int lgtdqcs001f_tuner_set(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mantis_pci *mantis = fe->dvb->priv;
struct i2c_adapter *adapter = &mantis->adapter;
@@ -95,14 +95,14 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe,
struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
- div = params->frequency / 250;
+ div = p->frequency / 250;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x83;
buf[3] = 0xc0;
- if (params->frequency < 1531000)
+ if (p->frequency < 1531000)
buf[3] |= 0x04;
else
buf[3] &= ~0x04;
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c
index 06da0dd..1ca6837 100644
--- a/drivers/media/dvb/mantis/mantis_vp2033.c
+++ b/drivers/media/dvb/mantis/mantis_vp2033.c
@@ -65,8 +65,9 @@ static u8 read_pwm(struct mantis_pci *mantis)
return pwm;
}
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mantis_pci *mantis = fe->dvb->priv;
struct i2c_adapter *adapter = &mantis->adapter;
@@ -77,13 +78,13 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten
#define CU1216_IF 36125000
#define TUNER_MUL 62500
- u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+ u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0xce;
- buf[3] = (params->frequency < 150000000 ? 0x01 :
- params->frequency < 445000000 ? 0x02 : 0x04);
+ buf[3] = (p->frequency < 150000000 ? 0x01 :
+ p->frequency < 445000000 ? 0x02 : 0x04);
buf[4] = 0xde;
buf[5] = 0x20;
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c
index f72b137..d480741 100644
--- a/drivers/media/dvb/mantis/mantis_vp2040.c
+++ b/drivers/media/dvb/mantis/mantis_vp2040.c
@@ -47,8 +47,9 @@ struct tda10023_config vp2040_tda10023_cu1216_config = {
.invert = 1,
};
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mantis_pci *mantis = fe->dvb->priv;
struct i2c_adapter *adapter = &mantis->adapter;
@@ -59,13 +60,13 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten
#define CU1216_IF 36125000
#define TUNER_MUL 62500
- u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+ u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0xce;
- buf[3] = (params->frequency < 150000000 ? 0x01 :
- params->frequency < 445000000 ? 0x02 : 0x04);
+ buf[3] = (p->frequency < 150000000 ? 0x01 :
+ p->frequency < 445000000 ? 0x02 : 0x04);
buf[4] = 0xde;
buf[5] = 0x20;
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
index 0564192..8418c02 100644
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ b/drivers/media/dvb/ngene/ngene-cards.c
@@ -218,7 +218,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
memset(&config, 0, sizeof(config));
config.adr = 0x29 + (chan->number ^ 2);
- chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2);
+ chan->fe = dvb_attach(drxk_attach, &config, i2c);
if (!chan->fe) {
printk(KERN_ERR "No DRXK found!\n");
return -ENODEV;
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 80fb510..e1f20c2 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -445,9 +445,9 @@ static inline u32 divide(u32 numerator, u32 denominator)
}
/* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct pluto *pluto = frontend_to_pluto(fe);
struct i2c_msg msg;
int ret;
@@ -478,7 +478,7 @@ static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
else
buf[3] = 0x04;
- if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+ if (p->bandwidth_hz == 8000000)
buf[3] |= 0x08;
if (sizeof(buf) == 6) {
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c
index 451641c..d980dfb 100644
--- a/drivers/media/dvb/pt1/va1j5jf8007s.c
+++ b/drivers/media/dvb/pt1/va1j5jf8007s.c
@@ -385,7 +385,7 @@ va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
static int
va1j5jf8007s_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
+ bool re_tune,
unsigned int mode_flags, unsigned int *delay,
fe_status_t *status)
{
@@ -395,7 +395,7 @@ va1j5jf8007s_tune(struct dvb_frontend *fe,
state = fe->demodulator_priv;
- if (params != NULL)
+ if (re_tune)
state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
switch (state->tune_state) {
@@ -579,9 +579,9 @@ static void va1j5jf8007s_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops va1j5jf8007s_ops = {
+ .delsys = { SYS_ISDBS },
.info = {
.name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1000,
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c
index 0f085c3..2db15159 100644
--- a/drivers/media/dvb/pt1/va1j5jf8007t.c
+++ b/drivers/media/dvb/pt1/va1j5jf8007t.c
@@ -264,7 +264,7 @@ static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
static int
va1j5jf8007t_tune(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params,
+ bool re_tune,
unsigned int mode_flags, unsigned int *delay,
fe_status_t *status)
{
@@ -274,7 +274,7 @@ va1j5jf8007t_tune(struct dvb_frontend *fe,
state = fe->demodulator_priv;
- if (params != NULL)
+ if (re_tune)
state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
switch (state->tune_state) {
@@ -428,9 +428,9 @@ static void va1j5jf8007t_release(struct dvb_frontend *fe)
}
static struct dvb_frontend_ops va1j5jf8007t_ops = {
+ .delsys = { SYS_ISDBT },
.info = {
.name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
- .type = FE_OFDM,
.frequency_min = 90000000,
.frequency_max = 770000000,
.frequency_stepsize = 142857,
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 37c594f..654685c 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -50,7 +50,7 @@ struct smsdvb_client_t {
struct completion tune_done;
/* todo: save freq/band instead whole struct */
- struct dvb_frontend_parameters fe_params;
+ struct dtv_frontend_properties fe_params;
struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
int event_fe_state;
@@ -591,8 +591,7 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct smsdvb_client_t *client =
@@ -658,8 +657,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
&client->tune_done);
}
-static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct smsdvb_client_t *client =
@@ -723,8 +721,7 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
&client->tune_done);
}
-static int smsdvb_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int smsdvb_set_frontend(struct dvb_frontend *fe)
{
struct smsdvb_client_t *client =
container_of(fe, struct smsdvb_client_t, frontend);
@@ -733,18 +730,18 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
switch (smscore_get_device_mode(coredev)) {
case DEVICE_MODE_DVBT:
case DEVICE_MODE_DVBT_BDA:
- return smsdvb_dvbt_set_frontend(fe, fep);
+ return smsdvb_dvbt_set_frontend(fe);
case DEVICE_MODE_ISDBT:
case DEVICE_MODE_ISDBT_BDA:
- return smsdvb_isdbt_set_frontend(fe, fep);
+ return smsdvb_isdbt_set_frontend(fe);
default:
return -EINVAL;
}
}
-static int smsdvb_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int smsdvb_get_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct smsdvb_client_t *client =
container_of(fe, struct smsdvb_client_t, frontend);
@@ -752,7 +749,7 @@ static int smsdvb_get_frontend(struct dvb_frontend *fe,
/* todo: */
memcpy(fep, &client->fe_params,
- sizeof(struct dvb_frontend_parameters));
+ sizeof(struct dtv_frontend_properties));
return 0;
}
@@ -789,7 +786,6 @@ static void smsdvb_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops smsdvb_fe_ops = {
.info = {
.name = "Siano Mobile Digital MDTV Receiver",
- .type = FE_OFDM,
.frequency_min = 44250000,
.frequency_max = 867250000,
.frequency_stepsize = 250000,
@@ -873,6 +869,17 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
memcpy(&client->frontend.ops, &smsdvb_fe_ops,
sizeof(struct dvb_frontend_ops));
+ switch (smscore_get_device_mode(coredev)) {
+ case DEVICE_MODE_DVBT:
+ case DEVICE_MODE_DVBT_BDA:
+ smsdvb_fe_ops.delsys[0] = SYS_DVBT;
+ break;
+ case DEVICE_MODE_ISDBT:
+ case DEVICE_MODE_ISDBT_BDA:
+ smsdvb_fe_ops.delsys[0] = SYS_ISDBT;
+ break;
+ }
+
rc = dvb_register_frontend(&client->adapter, &client->frontend);
if (rc < 0) {
sms_err("frontend registration failed %d", rc);
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 3d20719..6ecbcf6 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -991,7 +991,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
if (feed->type == DMX_TYPE_TS) {
if ((feed->ts_type & TS_DECODER) &&
- (feed->pes_type < DMX_TS_PES_OTHER)) {
+ (feed->pes_type <= DMX_TS_PES_PCR)) {
switch (demux->dmx.frontend->source) {
case DMX_MEMORY_FE:
if (feed->ts_type & TS_DECODER)
@@ -1568,20 +1568,27 @@ static int get_firmware(struct av7110* av7110)
return ret;
}
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- u32 div = (params->frequency + 479500) / 125;
+ u32 div = (p->frequency + 479500) / 125;
- if (params->frequency > 2000000) pwr = 3;
- else if (params->frequency > 1800000) pwr = 2;
- else if (params->frequency > 1600000) pwr = 1;
- else if (params->frequency > 1200000) pwr = 0;
- else if (params->frequency >= 1100000) pwr = 1;
- else pwr = 2;
+ if (p->frequency > 2000000)
+ pwr = 3;
+ else if (p->frequency > 1800000)
+ pwr = 2;
+ else if (p->frequency > 1600000)
+ pwr = 1;
+ else if (p->frequency > 1200000)
+ pwr = 0;
+ else if (p->frequency >= 1100000)
+ pwr = 1;
+ else
+ pwr = 2;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
@@ -1604,19 +1611,20 @@ static struct ves1x93_config alps_bsrv2_config = {
.invert_pwm = 0,
};
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (params->frequency + 35937500 + 31250) / 62500;
+ div = (p->frequency + 35937500 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85 | ((div >> 10) & 0x60);
- data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1635,14 +1643,15 @@ static struct ves1820_config alps_tdbe2_config = {
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
- div = params->frequency / 125;
+ div = p->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
@@ -1661,11 +1670,12 @@ static struct tda8083_config grundig_29504_451_config = {
-static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div;
- u32 f = params->frequency;
+ u32 f = p->frequency;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -1692,16 +1702,17 @@ static struct ves1820_config philips_cd1516_config = {
-static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div, pwr;
u8 data[4];
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (params->frequency + 36200000) / 166666;
+ div = (p->frequency + 36200000) / 166666;
- if (params->frequency <= 782000000)
+ if (p->frequency <= 782000000)
pwr = 1;
else
pwr = 2;
@@ -1829,8 +1840,9 @@ static u8 nexusca_stv0297_inittab[] = {
0xff, 0xff,
};
-static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div;
u8 data[4];
@@ -1838,19 +1850,19 @@ static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_
struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
int i;
- div = (params->frequency + 36150000 + 31250) / 62500;
+ div = (p->frequency + 36150000 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0xce;
- if (params->frequency < 45000000)
+ if (p->frequency < 45000000)
return -EINVAL;
- else if (params->frequency < 137000000)
+ else if (p->frequency < 137000000)
data[3] = 0x01;
- else if (params->frequency < 403000000)
+ else if (p->frequency < 403000000)
data[3] = 0x02;
- else if (params->frequency < 860000000)
+ else if (p->frequency < 860000000)
data[3] = 0x04;
else
return -EINVAL;
@@ -1884,27 +1896,36 @@ static struct stv0297_config nexusca_stv0297_config = {
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct av7110* av7110 = fe->dvb->priv;
u32 div;
u8 cfg, cpump, band_select;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (36125000 + params->frequency) / 166666;
+ div = (36125000 + p->frequency) / 166666;
cfg = 0x88;
- if (params->frequency < 175000000) cpump = 2;
- else if (params->frequency < 390000000) cpump = 1;
- else if (params->frequency < 470000000) cpump = 2;
- else if (params->frequency < 750000000) cpump = 1;
- else cpump = 3;
+ if (p->frequency < 175000000)
+ cpump = 2;
+ else if (p->frequency < 390000000)
+ cpump = 1;
+ else if (p->frequency < 470000000)
+ cpump = 2;
+ else if (p->frequency < 750000000)
+ cpump = 1;
+ else
+ cpump = 3;
- if (params->frequency < 175000000) band_select = 0x0e;
- else if (params->frequency < 470000000) band_select = 0x05;
- else band_select = 0x03;
+ if (p->frequency < 175000000)
+ band_select = 0x0e;
+ else if (p->frequency < 470000000)
+ band_select = 0x05;
+ else
+ band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
@@ -1964,15 +1985,14 @@ static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
return ret;
}
-static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int av7110_fe_set_frontend(struct dvb_frontend *fe)
{
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret) {
- av7110->saved_fe_params = *params;
- ret = av7110->fe_set_frontend(fe, params);
- }
+ if (!ret)
+ ret = av7110->fe_set_frontend(fe);
+
return ret;
}
@@ -2081,7 +2101,7 @@ static void dvb_s_recover(struct av7110* av7110)
msleep(20);
av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
- av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
+ av7110_fe_set_frontend(av7110->fe);
}
static u8 read_pwm(struct av7110* av7110)
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index d85b851..88b3b2d 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -272,7 +272,6 @@ struct av7110 {
/* crash recovery */
void (*recover)(struct av7110* av7110);
- struct dvb_frontend_parameters saved_fe_params;
fe_sec_voltage_t saved_voltage;
fe_sec_tone_mode_t saved_tone;
struct dvb_diseqc_master_cmd saved_master_cmd;
@@ -286,7 +285,7 @@ struct av7110 {
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
- int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ int (*fe_set_frontend)(struct dvb_frontend *fe);
};
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 78d32f7..8b32e28 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -502,33 +502,33 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
return 0;
}
-static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 div;
u8 buf[4];
struct budget *budget = (struct budget *) fe->dvb->priv;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
- if ((params->frequency < 950000) || (params->frequency > 2150000))
+ if ((c->frequency < 950000) || (c->frequency > 2150000))
return -EINVAL;
- div = (params->frequency + (125 - 1)) / 125; // round correctly
+ div = (c->frequency + (125 - 1)) / 125; /* round correctly */
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0x20;
- if (params->u.qpsk.symbol_rate < 4000000)
+ if (c->symbol_rate < 4000000)
buf[3] |= 1;
- if (params->frequency < 1250000)
+ if (c->frequency < 1250000)
buf[3] |= 0;
- else if (params->frequency < 1550000)
+ else if (c->frequency < 1550000)
buf[3] |= 0x40;
- else if (params->frequency < 2050000)
+ else if (c->frequency < 2050000)
buf[3] |= 0x80;
- else if (params->frequency < 2150000)
+ else if (c->frequency < 2150000)
buf[3] |= 0xC0;
if (fe->ops.i2c_gate_ctrl)
@@ -617,8 +617,9 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
};
-static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 buf[6];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -627,13 +628,13 @@ static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
#define CU1216_IF 36125000
#define TUNER_MUL 62500
- u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+ u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0xce;
- buf[3] = (params->frequency < 150000000 ? 0x01 :
- params->frequency < 445000000 ? 0x02 : 0x04);
+ buf[3] = (c->frequency < 150000000 ? 0x01 :
+ c->frequency < 445000000 ? 0x02 : 0x04);
buf[4] = 0xde;
buf[5] = 0x20;
@@ -697,8 +698,9 @@ static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
return 0;
}
-static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 tuner_buf[4];
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
@@ -707,7 +709,7 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
u8 band, cp, filter;
// determine charge pump
- tuner_frequency = params->frequency + 36166000;
+ tuner_frequency = c->frequency + 36166000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
@@ -732,28 +734,28 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
return -EINVAL;
// determine band
- if (params->frequency < 49000000)
+ if (c->frequency < 49000000)
return -EINVAL;
- else if (params->frequency < 161000000)
+ else if (c->frequency < 161000000)
band = 1;
- else if (params->frequency < 444000000)
+ else if (c->frequency < 444000000)
band = 2;
- else if (params->frequency < 861000000)
+ else if (c->frequency < 861000000)
band = 4;
else
return -EINVAL;
// setup PLL filter
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
filter = 0;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
filter = 0;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
filter = 1;
break;
@@ -763,7 +765,7 @@ static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
// calculate divisor
// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
+ tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
// setup tuner buffer
tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index ca02e97..98e5241 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -193,7 +193,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
dev->input_phys = budget_ci->ir.phys;
dev->input_id.bustype = BUS_PCI;
dev->input_id.version = 1;
- dev->scanmask = 0xff;
if (saa->pci->subsystem_vendor) {
dev->input_id.vendor = saa->pci->subsystem_vendor;
dev->input_id.product = saa->pci->subsystem_device;
@@ -234,6 +233,8 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
dev->map_name = RC_MAP_BUDGET_CI_OLD;
break;
}
+ if (!budget_ci->ir.full_rc5)
+ dev->scanmask = 0xff;
error = rc_register_device(dev);
if (error) {
@@ -659,33 +660,33 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
return 0;
}
-static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
- if ((params->frequency < 950000) || (params->frequency > 2150000))
+ if ((p->frequency < 950000) || (p->frequency > 2150000))
return -EINVAL;
- div = (params->frequency + (500 - 1)) / 500; // round correctly
+ div = (p->frequency + (500 - 1)) / 500; /* round correctly */
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
buf[3] = 0x20;
- if (params->u.qpsk.symbol_rate < 4000000)
+ if (p->symbol_rate < 4000000)
buf[3] |= 1;
- if (params->frequency < 1250000)
+ if (p->frequency < 1250000)
buf[3] |= 0;
- else if (params->frequency < 1550000)
+ else if (p->frequency < 1550000)
buf[3] |= 0x40;
- else if (params->frequency < 2050000)
+ else if (p->frequency < 2050000)
buf[3] |= 0x80;
- else if (params->frequency < 2150000)
+ else if (p->frequency < 2150000)
buf[3] |= 0xC0;
if (fe->ops.i2c_gate_ctrl)
@@ -740,8 +741,9 @@ static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
return 0;
}
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 tuner_buf[4];
struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
@@ -749,7 +751,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
u8 band, cp, filter;
// determine charge pump
- tuner_frequency = params->frequency + 36130000;
+ tuner_frequency = p->frequency + 36130000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
@@ -774,30 +776,30 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
return -EINVAL;
// determine band
- if (params->frequency < 49000000)
+ if (p->frequency < 49000000)
return -EINVAL;
- else if (params->frequency < 159000000)
+ else if (p->frequency < 159000000)
band = 1;
- else if (params->frequency < 444000000)
+ else if (p->frequency < 444000000)
band = 2;
- else if (params->frequency < 861000000)
+ else if (p->frequency < 861000000)
band = 4;
else
return -EINVAL;
// setup PLL filter and TDA9889
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
tda1004x_writereg(fe, 0x0C, 0x14);
filter = 0;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
tda1004x_writereg(fe, 0x0C, 0x80);
filter = 0;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
tda1004x_writereg(fe, 0x0C, 0x14);
filter = 1;
break;
@@ -808,7 +810,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb
// calculate divisor
// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
+ tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
@@ -855,8 +857,9 @@ static struct tda1004x_config philips_tdm1316l_config_invert = {
.request_firmware = philips_tdm1316l_request_firmware,
};
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 tuner_buf[5];
struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
@@ -867,7 +870,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
u8 band, cp, filter;
// determine charge pump
- tuner_frequency = params->frequency + 36125000;
+ tuner_frequency = p->frequency + 36125000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000) {
@@ -904,7 +907,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
filter = 1;
// calculate divisor
- tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+ tuner_frequency = (p->frequency + 36125000 + (62500/2)) / 62500;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 3395d1a..2cb35c2 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -261,19 +261,25 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c
return 0;
}
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- u32 div = (params->frequency + 479500) / 125;
-
- if (params->frequency > 2000000) pwr = 3;
- else if (params->frequency > 1800000) pwr = 2;
- else if (params->frequency > 1600000) pwr = 1;
- else if (params->frequency > 1200000) pwr = 0;
- else if (params->frequency >= 1100000) pwr = 1;
+ u32 div = (p->frequency + 479500) / 125;
+
+ if (p->frequency > 2000000)
+ pwr = 3;
+ else if (p->frequency > 1800000)
+ pwr = 2;
+ else if (p->frequency > 1600000)
+ pwr = 1;
+ else if (p->frequency > 1200000)
+ pwr = 0;
+ else if (p->frequency >= 1100000)
+ pwr = 1;
else pwr = 2;
buf[0] = (div >> 8) & 0x7f;
@@ -297,14 +303,15 @@ static struct ves1x93_config alps_bsrv2_config = {
.invert_pwm = 0,
};
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
- div = params->frequency / 125;
+ div = p->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index d238fb9..b21bcce 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -200,19 +200,25 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
return 0;
}
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 pwr = 0;
u8 buf[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- u32 div = (params->frequency + 479500) / 125;
-
- if (params->frequency > 2000000) pwr = 3;
- else if (params->frequency > 1800000) pwr = 2;
- else if (params->frequency > 1600000) pwr = 1;
- else if (params->frequency > 1200000) pwr = 0;
- else if (params->frequency >= 1100000) pwr = 1;
+ u32 div = (c->frequency + 479500) / 125;
+
+ if (c->frequency > 2000000)
+ pwr = 3;
+ else if (c->frequency > 1800000)
+ pwr = 2;
+ else if (c->frequency > 1600000)
+ pwr = 1;
+ else if (c->frequency > 1200000)
+ pwr = 0;
+ else if (c->frequency >= 1100000)
+ pwr = 1;
else pwr = 2;
buf[0] = (div >> 8) & 0x7f;
@@ -236,19 +242,20 @@ static struct ves1x93_config alps_bsrv2_config =
.invert_pwm = 0,
};
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (params->frequency + 35937500 + 31250) / 62500;
+ div = (c->frequency + 35937500 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85 | ((div >> 10) & 0x60);
- data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -263,8 +270,9 @@ static struct ves1820_config alps_tdbe2_config = {
.selagc = VES1820_SELAGC_SIGNAMPERR,
};
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget *budget = fe->dvb->priv;
u8 *tuner_addr = fe->tuner_priv;
u32 div;
@@ -277,19 +285,27 @@ static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dv
else
msg.addr = 0x61;
- div = (36125000 + params->frequency) / 166666;
+ div = (36125000 + c->frequency) / 166666;
cfg = 0x88;
- if (params->frequency < 175000000) cpump = 2;
- else if (params->frequency < 390000000) cpump = 1;
- else if (params->frequency < 470000000) cpump = 2;
- else if (params->frequency < 750000000) cpump = 1;
- else cpump = 3;
+ if (c->frequency < 175000000)
+ cpump = 2;
+ else if (c->frequency < 390000000)
+ cpump = 1;
+ else if (c->frequency < 470000000)
+ cpump = 2;
+ else if (c->frequency < 750000000)
+ cpump = 1;
+ else
+ cpump = 3;
- if (params->frequency < 175000000) band_select = 0x0e;
- else if (params->frequency < 470000000) band_select = 0x05;
- else band_select = 0x03;
+ if (c->frequency < 175000000)
+ band_select = 0x0e;
+ else if (c->frequency < 470000000)
+ band_select = 0x05;
+ else
+ band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
@@ -312,14 +328,15 @@ static struct l64781_config grundig_29504_401_config_activy = {
static u8 tuner_address_grundig_29504_401_activy = 0x60;
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
- div = params->frequency / 125;
+ div = c->frequency / 125;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x8e;
@@ -335,14 +352,15 @@ static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
};
-static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
- div = params->frequency / 1000;
+ div = c->frequency / 1000;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0xc2;
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index e90192f..5b682cc 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1017,19 +1017,20 @@ static u32 functionality(struct i2c_adapter *adapter)
-static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdmb7_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 data[4];
struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };
u32 div;
- div = (params->frequency + 36166667) / 166667;
+ div = (p->frequency + 36166667) / 166667;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = ((div >> 10) & 0x60) | 0x85;
- data[3] = params->frequency < 592000000 ? 0x40 : 0x80;
+ data[3] = p->frequency < 592000000 ? 0x40 : 0x80;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1071,8 +1072,9 @@ static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
return 0;
}
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 tuner_buf[4];
struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
@@ -1080,7 +1082,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
u8 band, cp, filter;
// determine charge pump
- tuner_frequency = params->frequency + 36130000;
+ tuner_frequency = p->frequency + 36130000;
if (tuner_frequency < 87000000) return -EINVAL;
else if (tuner_frequency < 130000000) cp = 3;
else if (tuner_frequency < 160000000) cp = 5;
@@ -1094,25 +1096,29 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
else return -EINVAL;
// determine band
- if (params->frequency < 49000000) return -EINVAL;
- else if (params->frequency < 159000000) band = 1;
- else if (params->frequency < 444000000) band = 2;
- else if (params->frequency < 861000000) band = 4;
+ if (p->frequency < 49000000)
+ return -EINVAL;
+ else if (p->frequency < 159000000)
+ band = 1;
+ else if (p->frequency < 444000000)
+ band = 2;
+ else if (p->frequency < 861000000)
+ band = 4;
else return -EINVAL;
// setup PLL filter
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (p->bandwidth_hz) {
+ case 6000000:
tda1004x_writereg(fe, 0x0C, 0);
filter = 0;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
tda1004x_writereg(fe, 0x0C, 0);
filter = 0;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
tda1004x_writereg(fe, 0x0C, 0xFF);
filter = 1;
break;
@@ -1123,7 +1129,7 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb
// calculate divisor
// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
+ tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
@@ -1273,23 +1279,24 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
return 0;
}
-static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
- if ((params->frequency < 950000) || (params->frequency > 2150000))
+ if ((p->frequency < 950000) || (p->frequency > 2150000))
return -EINVAL;
- div = (params->frequency + (125 - 1)) / 125; // round correctly
+ div = (p->frequency + (125 - 1)) / 125; /* round correctly */
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
buf[3] = 0xC4;
- if (params->frequency > 1530000)
+ if (p->frequency > 1530000)
buf[3] = 0xC0;
/* BSBE1 wants XCE bit set */
@@ -1316,14 +1323,15 @@ static struct stv0299_config alps_stv0299_config = {
.set_symbol_rate = alps_stv0299_set_symbol_rate,
};
-static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
- div = params->frequency / 125;
+ div = p->frequency / 125;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
@@ -1343,19 +1351,20 @@ static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
.demod_address = 0x68,
};
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb* ttusb = fe->dvb->priv;
u32 div;
u8 data[4];
struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
- div = (params->frequency + 35937500 + 31250) / 62500;
+ div = (p->frequency + 35937500 + 31250) / 62500;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = 0x85 | ((div >> 10) & 0x60);
- data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -1387,8 +1396,9 @@ static u8 read_pwm(struct ttusb* ttusb)
}
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
u8 tuner_buf[5];
struct i2c_msg tuner_msg = {.addr = 0x60,
@@ -1399,7 +1409,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
u8 band, cp, filter;
// determine charge pump
- tuner_frequency = params->frequency;
+ tuner_frequency = p->frequency;
if (tuner_frequency < 87000000) {return -EINVAL;}
else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
@@ -1417,7 +1427,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
// calculate divisor
// (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
- tuner_frequency = ((params->frequency + 36125000) / 62500);
+ tuner_frequency = ((p->frequency + 36125000) / 62500);
// setup tuner buffer
tuner_buf[0] = tuner_frequency >> 8;
@@ -1694,10 +1704,8 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb->i2c_adap.dev.parent = &udev->dev;
result = i2c_add_adapter(&ttusb->i2c_adap);
- if (result) {
- dvb_unregister_adapter (&ttusb->adapter);
- return result;
- }
+ if (result)
+ goto err_unregister_adapter;
memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
@@ -1714,33 +1722,29 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
ttusb->dvb_demux.write_to_decoder = NULL;
- if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
+ result = dvb_dmx_init(&ttusb->dvb_demux);
+ if (result < 0) {
printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
- i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (&ttusb->adapter);
- return -ENODEV;
+ result = -ENODEV;
+ goto err_i2c_del_adapter;
}
//FIXME dmxdev (nur WAS?)
ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
ttusb->dmxdev.capabilities = 0;
- if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) {
+ result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter);
+ if (result < 0) {
printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
result);
- dvb_dmx_release(&ttusb->dvb_demux);
- i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (&ttusb->adapter);
- return -ENODEV;
+ result = -ENODEV;
+ goto err_release_dmx;
}
if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
printk("ttusb_dvb: dvb_net_init failed!\n");
- dvb_dmxdev_release(&ttusb->dmxdev);
- dvb_dmx_release(&ttusb->dvb_demux);
- i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (&ttusb->adapter);
- return -ENODEV;
+ result = -ENODEV;
+ goto err_release_dmxdev;
}
usb_set_intfdata(intf, (void *) ttusb);
@@ -1748,6 +1752,16 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
frontend_init(ttusb);
return 0;
+
+err_release_dmxdev:
+ dvb_dmxdev_release(&ttusb->dmxdev);
+err_release_dmx:
+ dvb_dmx_release(&ttusb->dvb_demux);
+err_i2c_del_adapter:
+ i2c_del_adapter(&ttusb->i2c_adap);
+err_unregister_adapter:
+ dvb_unregister_adapter (&ttusb->adapter);
+ return result;
}
static void ttusb_disconnect(struct usb_interface *intf)
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 21260aa..5c45c9d 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -87,8 +87,9 @@ static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
return 0;
}
-static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
u8 b[] = { 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
@@ -113,8 +114,9 @@ static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
return 0;
}
-static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
u8 b[] = { 0x00, 0x00, 0x00, 0x01,
@@ -135,7 +137,7 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron
freq = htonl(p->frequency +
(state->hi_band ? LOF_HI : LOF_LO));
memcpy(&b[4], &freq, sizeof(u32));
- sym_rate = htonl(p->u.qam.symbol_rate);
+ sym_rate = htonl(p->symbol_rate);
memcpy(&b[12], &sym_rate, sizeof(u32));
band = htonl(state->hi_band ? LOF_HI : LOF_LO);
memcpy(&b[24], &band, sizeof(u32));
@@ -241,10 +243,9 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
}
static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
-
+ .delsys = { SYS_DVBT },
.info = {
.name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
- .type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
@@ -265,10 +266,9 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
};
static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
-
+ .delsys = { SYS_DVBS },
.info = {
.name = "TechnoTrend/Hauppauge DEC3000-s Frontend",
- .type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 6edc9ba..6f9eb94 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -108,8 +108,7 @@ static long media_device_enum_entities(struct media_device *mdev,
u_ent.group_id = ent->group_id;
u_ent.pads = ent->num_pads;
u_ent.links = ent->num_links - ent->num_backlinks;
- u_ent.v4l.major = ent->v4l.major;
- u_ent.v4l.minor = ent->v4l.minor;
+ memcpy(&u_ent.raw, &ent->info, sizeof(ent->info));
if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
return -EFAULT;
return 0;
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index ccd5f0d..e954781 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -11,6 +11,162 @@ menuconfig RADIO_ADAPTERS
if RADIO_ADAPTERS && VIDEO_V4L2
+config RADIO_SI470X
+ bool "Silicon Labs Si470x FM Radio Receiver support"
+ depends on VIDEO_V4L2
+
+source "drivers/media/radio/si470x/Kconfig"
+
+config USB_MR800
+ tristate "AverMedia MR 800 USB FM radio support"
+ depends on USB && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-mr800.
+
+config USB_DSBR
+ tristate "D-Link/GemTek USB FM radio support"
+ depends on USB && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dsbr100.
+
+config RADIO_MAXIRADIO
+ tristate "Guillemot MAXI Radio FM 2000 radio"
+ depends on VIDEO_V4L2 && PCI
+ ---help---
+ Choose Y here if you have this radio card. This card may also be
+ found as Gemtek PCI FM.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux API. Information on
+ this API and pointers to "v4l" programs may be found at
+ <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-maxiradio.
+
+
+config I2C_SI4713
+ tristate "I2C driver for Silicon Labs Si4713 device"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ Say Y here if you want support to Si4713 I2C device.
+ This device driver supports only i2c bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called si4713.
+
+config RADIO_SI4713
+ tristate "Silicon Labs Si4713 FM Radio Transmitter support"
+ depends on I2C && VIDEO_V4L2
+ select I2C_SI4713
+ ---help---
+ Say Y here if you want support to Si4713 FM Radio Transmitter.
+ This device can transmit audio through FM. It can transmit
+ RDS and RBDS signals as well. This module is the v4l2 radio
+ interface for the i2c driver of this device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-si4713.
+
+config RADIO_TEA5764
+ tristate "TEA5764 I2C FM radio support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to use the TEA5764 FM chip found in
+ EZX phones. This FM chip is present in EZX phones from Motorola,
+ connected to internal pxa I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-tea5764.
+
+config RADIO_TEA5764_XTAL
+ bool "TEA5764 crystal reference"
+ depends on RADIO_TEA5764=y
+ default y
+ help
+ Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
+ here if TEA5764 reference frequency is connected in FREQIN.
+
+config RADIO_SAA7706H
+ tristate "SAA7706H Car Radio DSP"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to use the SAA7706H Car radio Digital
+ Signal Processor, found for instance on the Russellville development
+ board. On the russellville the device is connected to internal
+ timberdale I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called SAA7706H.
+
+config RADIO_TEF6862
+ tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to use the TEF6862 Car Radio Enhanced
+ Selectivity Tuner, found for instance on the Russellville development
+ board. On the russellville the device is connected to internal
+ timberdale I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called TEF6862.
+
+config RADIO_TIMBERDALE
+ tristate "Enable the Timberdale radio driver"
+ depends on MFD_TIMBERDALE && VIDEO_V4L2
+ depends on I2C # for RADIO_SAA7706H
+ select RADIO_TEF6862
+ select RADIO_SAA7706H
+ ---help---
+ This is a kind of umbrella driver for the Radio Tuner and DSP
+ found behind the Timberdale FPGA on the Russellville board.
+ Enabling this driver will automatically select the DSP and tuner.
+
+config RADIO_WL1273
+ tristate "Texas Instruments WL1273 I2C FM Radio"
+ depends on I2C && VIDEO_V4L2
+ select MFD_CORE
+ select MFD_WL1273_CORE
+ select FW_LOADER
+ ---help---
+ Choose Y here if you have this FM radio chip.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux 2 API. Information on
+ this API and pointers to "v4l2" programs may be found at
+ <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-wl1273.
+
+# TI's ST based wl128x FM radio
+source "drivers/media/radio/wl128x/Kconfig"
+
+#
+# ISA drivers configuration
+#
+
+menuconfig V4L_RADIO_ISA_DRIVERS
+ bool "ISA radio devices"
+ depends on ISA
+ default n
+ ---help---
+ Say Y here to enable support for these ISA drivers.
+
+if V4L_RADIO_ISA_DRIVERS
+
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
depends on ISA && VIDEO_V4L2
@@ -151,21 +307,6 @@ config RADIO_GEMTEK_PROBE
following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
0x28c.
-config RADIO_MAXIRADIO
- tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on VIDEO_V4L2 && PCI
- ---help---
- Choose Y here if you have this radio card. This card may also be
- found as Gemtek PCI FM.
-
- In order to control your radio card, you will need to use programs
- that are compatible with the Video For Linux API. Information on
- this API and pointers to "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-maxiradio.
-
config RADIO_MIROPCM20
tristate "miroSOUND PCM20 radio"
depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
@@ -316,130 +457,6 @@ config RADIO_ZOLTRIX_PORT
help
Enter the I/O port of your Zoltrix radio card.
-config I2C_SI4713
- tristate "I2C driver for Silicon Labs Si4713 device"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want support to Si4713 I2C device.
- This device driver supports only i2c bus.
-
- To compile this driver as a module, choose M here: the
- module will be called si4713.
-
-config RADIO_SI4713
- tristate "Silicon Labs Si4713 FM Radio Transmitter support"
- depends on I2C && VIDEO_V4L2
- select I2C_SI4713
- ---help---
- Say Y here if you want support to Si4713 FM Radio Transmitter.
- This device can transmit audio through FM. It can transmit
- RDS and RBDS signals as well. This module is the v4l2 radio
- interface for the i2c driver of this device.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-si4713.
-
-config USB_DSBR
- tristate "D-Link/GemTek USB FM radio support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- To compile this driver as a module, choose M here: the
- module will be called dsbr100.
-
-config RADIO_SI470X
- bool "Silicon Labs Si470x FM Radio Receiver support"
- depends on VIDEO_V4L2
-
-source "drivers/media/radio/si470x/Kconfig"
-
-config USB_MR800
- tristate "AverMedia MR 800 USB FM radio support"
- depends on USB && VIDEO_V4L2
- ---help---
- Say Y here if you want to connect this type of radio to your
- computer's USB port. Note that the audio is not digital, and
- you must connect the line out connector to a sound card or a
- set of speakers.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-mr800.
-
-config RADIO_TEA5764
- tristate "TEA5764 I2C FM radio support"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the TEA5764 FM chip found in
- EZX phones. This FM chip is present in EZX phones from Motorola,
- connected to internal pxa I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-tea5764.
-
-config RADIO_TEA5764_XTAL
- bool "TEA5764 crystal reference"
- depends on RADIO_TEA5764=y
- default y
- help
- Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
- here if TEA5764 reference frequency is connected in FREQIN.
-
-config RADIO_SAA7706H
- tristate "SAA7706H Car Radio DSP"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the SAA7706H Car radio Digital
- Signal Processor, found for instance on the Russellville development
- board. On the russellville the device is connected to internal
- timberdale I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called SAA7706H.
-
-config RADIO_TEF6862
- tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
- depends on I2C && VIDEO_V4L2
- ---help---
- Say Y here if you want to use the TEF6862 Car Radio Enhanced
- Selectivity Tuner, found for instance on the Russellville development
- board. On the russellville the device is connected to internal
- timberdale I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called TEF6862.
-
-config RADIO_TIMBERDALE
- tristate "Enable the Timberdale radio driver"
- depends on MFD_TIMBERDALE && VIDEO_V4L2
- depends on I2C # for RADIO_SAA7706H
- select RADIO_TEF6862
- select RADIO_SAA7706H
- ---help---
- This is a kind of umbrella driver for the Radio Tuner and DSP
- found behind the Timberdale FPGA on the Russellville board.
- Enabling this driver will automatically select the DSP and tuner.
-
-config RADIO_WL1273
- tristate "Texas Instruments WL1273 I2C FM Radio"
- depends on I2C && VIDEO_V4L2
- select MFD_WL1273_CORE
- select FW_LOADER
- ---help---
- Choose Y here if you have this FM radio chip.
-
- In order to control your radio card, you will need to use programs
- that are compatible with the Video For Linux 2 API. Information on
- this API and pointers to "v4l2" programs may be found at
- <file:Documentation/video4linux/API.html>.
-
- To compile this driver as a module, choose M here: the
- module will be called radio-wl1273.
-
-# TI's ST based wl128x FM radio
-source "drivers/media/radio/wl128x/Kconfig"
+endif # V4L_RADIO_ISA_DRIVERS
endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index edadc84..36ce061 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -47,11 +47,11 @@ MODULE_VERSION("0.0.4");
#endif
static int io = CONFIG_RADIO_GEMTEK_PORT;
-static int probe = CONFIG_RADIO_GEMTEK_PROBE;
-static int hardmute;
-static int shutdown = 1;
-static int keepmuted = 1;
-static int initmute = 1;
+static bool probe = CONFIG_RADIO_GEMTEK_PROBE;
+static bool hardmute;
+static bool shutdown = 1;
+static bool keepmuted = 1;
+static bool initmute = 1;
static int radio_nr = -1;
module_param(io, int, 0444);
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index 3fb76e3..87c1ee1 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -23,7 +23,7 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0);
MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX). Default: -1 (autodetect)");
-static int mono;
+static bool mono;
module_param(mono, bool, 0);
MODULE_PARM_DESC(mono, "Force tuner into mono mode.");
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
index d1fab58..c54210c 100644
--- a/drivers/media/radio/radio-si4713.c
+++ b/drivers/media/radio/radio-si4713.c
@@ -355,17 +355,4 @@ static struct platform_driver radio_si4713_pdriver = {
.remove = __exit_p(radio_si4713_pdriver_remove),
};
-/* Module Interface */
-static int __init radio_si4713_module_init(void)
-{
- return platform_driver_register(&radio_si4713_pdriver);
-}
-
-static void __exit radio_si4713_module_exit(void)
-{
- platform_driver_unregister(&radio_si4713_pdriver);
-}
-
-module_init(radio_si4713_module_init);
-module_exit(radio_si4713_module_exit);
-
+module_platform_driver(radio_si4713_pdriver);
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 3e9209f..5d9a90a 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -226,20 +226,7 @@ static struct platform_driver timbradio_platform_driver = {
.remove = timbradio_remove,
};
-/*--------------------------------------------------------------------------*/
-
-static int __init timbradio_init(void)
-{
- return platform_driver_register(&timbradio_platform_driver);
-}
-
-static void __exit timbradio_exit(void)
-{
- platform_driver_unregister(&timbradio_platform_driver);
-}
-
-module_init(timbradio_init);
-module_exit(timbradio_exit);
+module_platform_driver(timbradio_platform_driver);
MODULE_DESCRIPTION("Timberdale Radio driver");
MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index 8aa4968..f1b6070 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -2148,8 +2148,6 @@ pdata_err:
return r;
}
-MODULE_ALIAS("platform:wl1273_fm_radio");
-
static struct platform_driver wl1273_fm_radio_driver = {
.probe = wl1273_fm_radio_probe,
.remove = __devexit_p(wl1273_fm_radio_remove),
@@ -2159,20 +2157,9 @@ static struct platform_driver wl1273_fm_radio_driver = {
},
};
-static int __init wl1273_fm_module_init(void)
-{
- pr_info("%s\n", __func__);
- return platform_driver_register(&wl1273_fm_radio_driver);
-}
-module_init(wl1273_fm_module_init);
-
-static void __exit wl1273_fm_module_exit(void)
-{
- platform_driver_unregister(&wl1273_fm_radio_driver);
- pr_info(DRIVER_DESC ", Exiting.\n");
-}
-module_exit(wl1273_fm_module_exit);
+module_platform_driver(wl1273_fm_radio_driver);
MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wl1273_fm_radio");
diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c
index 0991e19..3408685 100644
--- a/drivers/media/radio/tef6862.c
+++ b/drivers/media/radio/tef6862.c
@@ -118,9 +118,11 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
i2cmsg[2] = pll & 0xff;
err = i2c_master_send(client, i2cmsg, sizeof(i2cmsg));
- if (!err)
- state->freq = f->frequency;
- return err;
+ if (err != sizeof(i2cmsg))
+ return err < 0 ? err : -EIO;
+
+ state->freq = f->frequency;
+ return 0;
}
static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
diff --git a/drivers/media/radio/wl128x/Kconfig b/drivers/media/radio/wl128x/Kconfig
index 749f67b..86b2857 100644
--- a/drivers/media/radio/wl128x/Kconfig
+++ b/drivers/media/radio/wl128x/Kconfig
@@ -5,7 +5,7 @@ menu "Texas Instruments WL128x FM driver (ST based)"
config RADIO_WL128X
tristate "Texas Instruments WL128x FM Radio"
depends on VIDEO_V4L2 && RFKILL
- select TI_ST
+ select TI_ST if NET && GPIOLIB
help
Choose Y here if you have this FM radio chip.
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index 5991ab6..bf867a6 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -387,7 +387,7 @@ static void send_tasklet(unsigned long arg)
* Queues FM Channel-8 packet to FM TX queue and schedules FM TX tasklet for
* transmission
*/
-static u32 fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
+static int fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
int payload_len, struct completion *wait_completion)
{
struct sk_buff *skb;
@@ -456,13 +456,13 @@ static u32 fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
}
/* Sends FM Channel-8 command to the chip and waits for the response */
-u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
+int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
unsigned int payload_len, void *response, int *response_len)
{
struct sk_buff *skb;
struct fm_event_msg_hdr *evt_hdr;
unsigned long flags;
- u32 ret;
+ int ret;
init_completion(&fmdev->maintask_comp);
ret = fm_send_cmd(fmdev, fm_op, type, payload, payload_len,
@@ -470,8 +470,8 @@ u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
if (ret)
return ret;
- ret = wait_for_completion_timeout(&fmdev->maintask_comp, FM_DRV_TX_TIMEOUT);
- if (!ret) {
+ if (!wait_for_completion_timeout(&fmdev->maintask_comp,
+ FM_DRV_TX_TIMEOUT)) {
fmerr("Timeout(%d sec),didn't get reg"
"completion signal from RX tasklet\n",
jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
@@ -508,7 +508,7 @@ u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
}
/* --- Helper functions used in FM interrupt handlers ---*/
-static inline u32 check_cmdresp_status(struct fmdev *fmdev,
+static inline int check_cmdresp_status(struct fmdev *fmdev,
struct sk_buff **skb)
{
struct fm_event_msg_hdr *fm_evt_hdr;
@@ -1058,7 +1058,7 @@ static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *fmdev)
}
/* Returns availability of RDS data in internel buffer */
-u32 fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
+int fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
struct poll_table_struct *pts)
{
poll_wait(file, &fmdev->rx.rds.read_queue, pts);
@@ -1069,7 +1069,7 @@ u32 fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
}
/* Copies RDS data from internal buffer to user buffer */
-u32 fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
+int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
u8 __user *buf, size_t count)
{
u32 block_count;
@@ -1113,7 +1113,7 @@ u32 fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
return ret;
}
-u32 fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+int fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
{
switch (fmdev->curr_fmmode) {
case FM_MODE_RX:
@@ -1127,7 +1127,7 @@ u32 fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
}
}
-u32 fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
+int fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
{
if (fmdev->rx.freq == FM_UNDEFINED_FREQ) {
fmerr("RX frequency is not set\n");
@@ -1153,7 +1153,7 @@ u32 fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
}
-u32 fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
+int fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
{
switch (fmdev->curr_fmmode) {
case FM_MODE_RX:
@@ -1167,7 +1167,7 @@ u32 fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
}
}
-u32 fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
{
switch (fmdev->curr_fmmode) {
case FM_MODE_RX:
@@ -1181,7 +1181,7 @@ u32 fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
}
}
-u32 fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
{
switch (fmdev->curr_fmmode) {
case FM_MODE_RX:
@@ -1195,7 +1195,7 @@ u32 fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
}
}
-u32 fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
{
switch (fmdev->curr_fmmode) {
case FM_MODE_RX:
@@ -1210,10 +1210,10 @@ u32 fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
}
/* Sends power off command to the chip */
-static u32 fm_power_down(struct fmdev *fmdev)
+static int fm_power_down(struct fmdev *fmdev)
{
u16 payload;
- u32 ret;
+ int ret;
if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
fmerr("FM core is not ready\n");
@@ -1234,7 +1234,7 @@ static u32 fm_power_down(struct fmdev *fmdev)
}
/* Reads init command from FM firmware file and loads to the chip */
-static u32 fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
+static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
{
const struct firmware *fw_entry;
struct bts_header *fw_header;
@@ -1299,7 +1299,7 @@ rel_fw:
}
/* Loads default RX configuration to the chip */
-static u32 load_default_rx_configuration(struct fmdev *fmdev)
+static int load_default_rx_configuration(struct fmdev *fmdev)
{
int ret;
@@ -1311,7 +1311,7 @@ static u32 load_default_rx_configuration(struct fmdev *fmdev)
}
/* Does FM power on sequence */
-static u32 fm_power_up(struct fmdev *fmdev, u8 mode)
+static int fm_power_up(struct fmdev *fmdev, u8 mode)
{
u16 payload, asic_id, asic_ver;
int resp_len, ret;
@@ -1374,7 +1374,7 @@ rel:
}
/* Set FM Modes(TX, RX, OFF) */
-u32 fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
+int fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
{
int ret = 0;
@@ -1427,7 +1427,7 @@ u32 fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
}
/* Returns current FM mode (TX, RX, OFF) */
-u32 fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
+int fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
{
if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
fmerr("FM core is not ready\n");
@@ -1483,10 +1483,10 @@ static void fm_st_reg_comp_cb(void *arg, char data)
* This function will be called from FM V4L2 open function.
* Register with ST driver and initialize driver data.
*/
-u32 fmc_prepare(struct fmdev *fmdev)
+int fmc_prepare(struct fmdev *fmdev)
{
static struct st_proto_s fm_st_proto;
- u32 ret;
+ int ret;
if (test_bit(FM_CORE_READY, &fmdev->flag)) {
fmdbg("FM Core is already up\n");
@@ -1512,10 +1512,8 @@ u32 fmc_prepare(struct fmdev *fmdev)
fmdev->streg_cbdata = -EINPROGRESS;
fmdbg("%s waiting for ST reg completion signal\n", __func__);
- ret = wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
- FM_ST_REG_TIMEOUT);
-
- if (!ret) {
+ if (!wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
+ FM_ST_REG_TIMEOUT)) {
fmerr("Timeout(%d sec), didn't get reg "
"completion signal from ST\n",
jiffies_to_msecs(FM_ST_REG_TIMEOUT) / 1000);
@@ -1589,10 +1587,10 @@ u32 fmc_prepare(struct fmdev *fmdev)
* This function will be called from FM V4L2 release function.
* Unregister from ST driver.
*/
-u32 fmc_release(struct fmdev *fmdev)
+int fmc_release(struct fmdev *fmdev)
{
static struct st_proto_s fm_st_proto;
- u32 ret;
+ int ret;
if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
fmdbg("FM Core is already down\n");
@@ -1631,7 +1629,7 @@ u32 fmc_release(struct fmdev *fmdev)
static int __init fm_drv_init(void)
{
struct fmdev *fmdev = NULL;
- u32 ret = -ENOMEM;
+ int ret = -ENOMEM;
fmdbg("FM driver version %s\n", FM_DRV_VERSION);
diff --git a/drivers/media/radio/wl128x/fmdrv_common.h b/drivers/media/radio/wl128x/fmdrv_common.h
index aee243b..d9b9c6c 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.h
+++ b/drivers/media/radio/wl128x/fmdrv_common.h
@@ -368,27 +368,27 @@ struct fm_event_msg_hdr {
#define FM_TX_ANT_IMP_500 2
/* Functions exported by FM common sub-module */
-u32 fmc_prepare(struct fmdev *);
-u32 fmc_release(struct fmdev *);
+int fmc_prepare(struct fmdev *);
+int fmc_release(struct fmdev *);
void fmc_update_region_info(struct fmdev *, u8);
-u32 fmc_send_cmd(struct fmdev *, u8, u16,
+int fmc_send_cmd(struct fmdev *, u8, u16,
void *, unsigned int, void *, int *);
-u32 fmc_is_rds_data_available(struct fmdev *, struct file *,
+int fmc_is_rds_data_available(struct fmdev *, struct file *,
struct poll_table_struct *);
-u32 fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
+int fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
u8 __user *, size_t);
-u32 fmc_set_freq(struct fmdev *, u32);
-u32 fmc_set_mode(struct fmdev *, u8);
-u32 fmc_set_region(struct fmdev *, u8);
-u32 fmc_set_mute_mode(struct fmdev *, u8);
-u32 fmc_set_stereo_mono(struct fmdev *, u16);
-u32 fmc_set_rds_mode(struct fmdev *, u8);
+int fmc_set_freq(struct fmdev *, u32);
+int fmc_set_mode(struct fmdev *, u8);
+int fmc_set_region(struct fmdev *, u8);
+int fmc_set_mute_mode(struct fmdev *, u8);
+int fmc_set_stereo_mono(struct fmdev *, u16);
+int fmc_set_rds_mode(struct fmdev *, u8);
-u32 fmc_get_freq(struct fmdev *, u32 *);
-u32 fmc_get_region(struct fmdev *, u8 *);
-u32 fmc_get_mode(struct fmdev *, u8 *);
+int fmc_get_freq(struct fmdev *, u32 *);
+int fmc_get_region(struct fmdev *, u8 *);
+int fmc_get_mode(struct fmdev *, u8 *);
/*
* channel spacing
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.c b/drivers/media/radio/wl128x/fmdrv_rx.c
index ec529b5..43fb722 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.c
+++ b/drivers/media/radio/wl128x/fmdrv_rx.c
@@ -43,12 +43,13 @@ void fm_rx_reset_station_info(struct fmdev *fmdev)
fmdev->rx.stat_info.af_list_max = 0;
}
-u32 fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
+int fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
{
unsigned long timeleft;
u16 payload, curr_frq, intr_flag;
u32 curr_frq_in_khz;
- u32 ret, resp_len;
+ u32 resp_len;
+ int ret;
if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) {
fmerr("Invalid frequency %d\n", freq);
@@ -141,10 +142,10 @@ exit:
return ret;
}
-static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
+static int fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
{
u16 payload;
- u32 ret;
+ int ret;
if (spacing > 0 && spacing <= 50000)
spacing = FM_CHANNEL_SPACING_50KHZ;
@@ -165,7 +166,7 @@ static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
return ret;
}
-u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
+int fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
u32 wrap_around, u32 spacing)
{
u32 resp_len;
@@ -173,7 +174,7 @@ u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
u16 payload, int_reason, intr_flag;
u16 offset, space_idx;
unsigned long timeleft;
- u32 ret;
+ int ret;
/* Set channel spacing */
ret = fm_rx_set_channel_spacing(fmdev, spacing);
@@ -296,10 +297,10 @@ again:
return ret;
}
-u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
+int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -322,7 +323,7 @@ u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
}
/* Get volume */
-u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
+int fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -338,7 +339,7 @@ u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
}
/* To get current band's bottom and top frequency */
-u32 fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
+int fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
{
if (bot_freq != NULL)
*bot_freq = fmdev->rx.region.bot_freq;
@@ -356,11 +357,11 @@ void fm_rx_get_region(struct fmdev *fmdev, u8 *region)
}
/* Sets band (0-Europe/US; 1-Japan) */
-u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
+int fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
{
u16 payload;
u32 new_frq = 0;
- u32 ret;
+ int ret;
if (region_to_set != FM_BAND_EUROPE_US &&
region_to_set != FM_BAND_JAPAN) {
@@ -399,7 +400,7 @@ u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
}
/* Reads current mute mode (Mute Off/On/Attenuate)*/
-u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
+int fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -414,10 +415,10 @@ u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
return 0;
}
-static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
+static int fm_config_rx_mute_reg(struct fmdev *fmdev)
{
u16 payload, muteval;
- u32 ret;
+ int ret;
muteval = 0;
switch (fmdev->rx.mute_mode) {
@@ -448,10 +449,10 @@ static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
}
/* Configures mute mode (Mute Off/On/Attenuate) */
-u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
{
u8 org_state;
- u32 ret;
+ int ret;
if (fmdev->rx.mute_mode == mute_mode_toset)
return 0;
@@ -469,7 +470,7 @@ u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
}
/* Gets RF dependent soft mute mode enable/disable status */
-u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
+int fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -485,10 +486,10 @@ u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
}
/* Sets RF dependent soft mute mode */
-u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
+int fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
{
u8 org_state;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -514,11 +515,11 @@ u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
}
/* Returns the signal strength level of current channel */
-u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
+int fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
{
u16 curr_rssi_lel;
u32 resp_len;
- u32 ret;
+ int ret;
if (rssilvl == NULL) {
fmerr("Invalid memory\n");
@@ -539,10 +540,10 @@ u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
* Sets the signal strength level that once reached
* will stop the auto search process
*/
-u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
+int fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
{
u16 payload;
- u32 ret;
+ int ret;
if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN ||
rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) {
@@ -561,7 +562,7 @@ u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
}
/* Returns current RX RSSI threshold value */
-u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
+int fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -577,10 +578,10 @@ u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
}
/* Sets RX stereo/mono modes */
-u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
{
u16 payload;
- u32 ret;
+ int ret;
if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) {
fmerr("Invalid mode\n");
@@ -605,10 +606,11 @@ u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
}
/* Gets current RX stereo/mono mode */
-u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
+int fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
{
u16 curr_mode;
- u32 ret, resp_len;
+ u32 resp_len;
+ int ret;
if (mode == NULL) {
fmerr("Invalid memory\n");
@@ -626,10 +628,10 @@ u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
}
/* Choose RX de-emphasis filter mode (50us/75us) */
-u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
+int fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -652,7 +654,7 @@ u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
}
/* Gets current RX de-emphasis filter mode */
-u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
+int fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -668,10 +670,10 @@ u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
}
/* Enable/Disable RX RDS */
-u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
{
u16 payload;
- u32 ret;
+ int ret;
if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) {
fmerr("Invalid rds option\n");
@@ -743,7 +745,7 @@ u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
}
/* Returns current RX RDS enable/disable status */
-u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
+int fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -759,10 +761,10 @@ u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
}
/* Sets RDS operation mode (RDS/RDBS) */
-u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
+int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -784,7 +786,7 @@ u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
}
/* Returns current RDS operation mode */
-u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
+int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -800,10 +802,10 @@ u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
}
/* Configures Alternate Frequency switch mode */
-u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
+int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
@@ -831,7 +833,7 @@ u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
}
/* Returns Alternate Frequency switch status */
-u32 fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
+int fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
{
if (fmdev->curr_fmmode != FM_MODE_RX)
return -EPERM;
diff --git a/drivers/media/radio/wl128x/fmdrv_rx.h b/drivers/media/radio/wl128x/fmdrv_rx.h
index 329e62f..32add81 100644
--- a/drivers/media/radio/wl128x/fmdrv_rx.h
+++ b/drivers/media/radio/wl128x/fmdrv_rx.h
@@ -22,38 +22,38 @@
#ifndef _FMDRV_RX_H
#define _FMDRV_RX_H
-u32 fm_rx_set_freq(struct fmdev *, u32);
-u32 fm_rx_set_mute_mode(struct fmdev *, u8);
-u32 fm_rx_set_stereo_mono(struct fmdev *, u16);
-u32 fm_rx_set_rds_mode(struct fmdev *, u8);
-u32 fm_rx_set_rds_system(struct fmdev *, u8);
-u32 fm_rx_set_volume(struct fmdev *, u16);
-u32 fm_rx_set_rssi_threshold(struct fmdev *, short);
-u32 fm_rx_set_region(struct fmdev *, u8);
-u32 fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
-u32 fm_rx_set_deemphasis_mode(struct fmdev *, u16);
-u32 fm_rx_set_af_switch(struct fmdev *, u8);
+int fm_rx_set_freq(struct fmdev *, u32);
+int fm_rx_set_mute_mode(struct fmdev *, u8);
+int fm_rx_set_stereo_mono(struct fmdev *, u16);
+int fm_rx_set_rds_mode(struct fmdev *, u8);
+int fm_rx_set_rds_system(struct fmdev *, u8);
+int fm_rx_set_volume(struct fmdev *, u16);
+int fm_rx_set_rssi_threshold(struct fmdev *, short);
+int fm_rx_set_region(struct fmdev *, u8);
+int fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
+int fm_rx_set_deemphasis_mode(struct fmdev *, u16);
+int fm_rx_set_af_switch(struct fmdev *, u8);
void fm_rx_reset_rds_cache(struct fmdev *);
void fm_rx_reset_station_info(struct fmdev *);
-u32 fm_rx_seek(struct fmdev *, u32, u32, u32);
+int fm_rx_seek(struct fmdev *, u32, u32, u32);
-u32 fm_rx_get_rds_mode(struct fmdev *, u8 *);
-u32 fm_rx_get_rds_system(struct fmdev *, u8 *);
-u32 fm_rx_get_mute_mode(struct fmdev *, u8 *);
-u32 fm_rx_get_volume(struct fmdev *, u16 *);
-u32 fm_rx_get_band_freq_range(struct fmdev *,
+int fm_rx_get_rds_mode(struct fmdev *, u8 *);
+int fm_rx_get_rds_system(struct fmdev *, u8 *);
+int fm_rx_get_mute_mode(struct fmdev *, u8 *);
+int fm_rx_get_volume(struct fmdev *, u16 *);
+int fm_rx_get_band_freq_range(struct fmdev *,
u32 *, u32 *);
-u32 fm_rx_get_stereo_mono(struct fmdev *, u16 *);
-u32 fm_rx_get_rssi_level(struct fmdev *, u16 *);
-u32 fm_rx_get_rssi_threshold(struct fmdev *, short *);
-u32 fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
-u32 fm_rx_get_deemph_mode(struct fmdev *, u16 *);
-u32 fm_rx_get_af_switch(struct fmdev *, u8 *);
+int fm_rx_get_stereo_mono(struct fmdev *, u16 *);
+int fm_rx_get_rssi_level(struct fmdev *, u16 *);
+int fm_rx_get_rssi_threshold(struct fmdev *, short *);
+int fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
+int fm_rx_get_deemph_mode(struct fmdev *, u16 *);
+int fm_rx_get_af_switch(struct fmdev *, u8 *);
void fm_rx_get_region(struct fmdev *, u8 *);
-u32 fm_rx_set_chanl_spacing(struct fmdev *, u8);
-u32 fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
+int fm_rx_set_chanl_spacing(struct fmdev *, u8);
+int fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
#endif
diff --git a/drivers/media/radio/wl128x/fmdrv_tx.c b/drivers/media/radio/wl128x/fmdrv_tx.c
index be54068..6ea33e0 100644
--- a/drivers/media/radio/wl128x/fmdrv_tx.c
+++ b/drivers/media/radio/wl128x/fmdrv_tx.c
@@ -24,10 +24,10 @@
#include "fmdrv_common.h"
#include "fmdrv_tx.h"
-u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+int fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->tx_data.aud_mode == mode)
return 0;
@@ -46,10 +46,10 @@ u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
return ret;
}
-static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text)
+static int set_rds_text(struct fmdev *fmdev, u8 *rds_text)
{
u16 payload;
- u32 ret;
+ int ret;
ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text,
strlen(rds_text), NULL, NULL);
@@ -66,10 +66,10 @@ static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text)
return 0;
}
-static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode)
+static int set_rds_data_mode(struct fmdev *fmdev, u8 mode)
{
u16 payload;
- u32 ret;
+ int ret;
/* Setting unique PI TODO: how unique? */
payload = (u16)0xcafe;
@@ -89,10 +89,10 @@ static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode)
return 0;
}
-static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
+static int set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
{
u16 payload;
- u32 ret;
+ int ret;
len |= type << 8;
payload = len;
@@ -105,10 +105,10 @@ static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
return 0;
}
-u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+int fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
{
u16 payload;
- u32 ret;
+ int ret;
u8 rds_text[] = "Zoom2\n";
fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis,
@@ -148,10 +148,10 @@ u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
return 0;
}
-u32 fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
+int fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_TX)
return -EPERM;
@@ -176,10 +176,10 @@ u32 fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
return 0;
}
-u32 fm_tx_set_af(struct fmdev *fmdev, u32 af)
+int fm_tx_set_af(struct fmdev *fmdev, u32 af)
{
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_TX)
return -EPERM;
@@ -196,10 +196,10 @@ u32 fm_tx_set_af(struct fmdev *fmdev, u32 af)
return 0;
}
-u32 fm_tx_set_region(struct fmdev *fmdev, u8 region)
+int fm_tx_set_region(struct fmdev *fmdev, u8 region)
{
u16 payload;
- u32 ret;
+ int ret;
if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) {
fmerr("Invalid band\n");
@@ -216,10 +216,10 @@ u32 fm_tx_set_region(struct fmdev *fmdev, u8 region)
return 0;
}
-u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+int fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
{
u16 payload;
- u32 ret;
+ int ret;
fmdbg("tx: mute mode %d\n", mute_mode_toset);
@@ -233,11 +233,11 @@ u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
}
/* Set TX Audio I/O */
-static u32 set_audio_io(struct fmdev *fmdev)
+static int set_audio_io(struct fmdev *fmdev)
{
struct fmtx_data *tx = &fmdev->tx_data;
u16 payload;
- u32 ret;
+ int ret;
/* Set Audio I/O Enable */
payload = tx->audio_io;
@@ -251,12 +251,12 @@ static u32 set_audio_io(struct fmdev *fmdev)
}
/* Start TX Transmission */
-static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
+static int enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
{
struct fmtx_data *tx = &fmdev->tx_data;
unsigned long timeleft;
u16 payload;
- u32 ret;
+ int ret;
/* Enable POWER_ENB interrupts */
payload = FM_POW_ENB_EVENT;
@@ -289,11 +289,11 @@ static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
}
/* Set TX power level */
-u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
+int fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
{
u16 payload;
struct fmtx_data *tx = &fmdev->tx_data;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_TX)
return -EPERM;
@@ -328,11 +328,11 @@ u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
* Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us)
* Convert V4L2 specified filter values to chip specific filter values.
*/
-u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
+int fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
{
struct fmtx_data *tx = &fmdev->tx_data;
u16 payload;
- u32 ret;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_TX)
return -EPERM;
@@ -360,10 +360,11 @@ u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
}
/* Get the TX tuning capacitor value.*/
-u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev)
+int fm_tx_get_tune_cap_val(struct fmdev *fmdev)
{
u16 curr_val;
- u32 ret, resp_len;
+ u32 resp_len;
+ int ret;
if (fmdev->curr_fmmode != FM_MODE_TX)
return -EPERM;
@@ -379,11 +380,11 @@ u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev)
}
/* Set TX Frequency */
-u32 fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+int fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
{
struct fmtx_data *tx = &fmdev->tx_data;
u16 payload, chanl_index;
- u32 ret;
+ int ret;
if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) {
enable_xmit(fmdev, 0);
diff --git a/drivers/media/radio/wl128x/fmdrv_tx.h b/drivers/media/radio/wl128x/fmdrv_tx.h
index e393a2b..11ae2e4 100644
--- a/drivers/media/radio/wl128x/fmdrv_tx.h
+++ b/drivers/media/radio/wl128x/fmdrv_tx.h
@@ -22,16 +22,16 @@
#ifndef _FMDRV_TX_H
#define _FMDRV_TX_H
-u32 fm_tx_set_freq(struct fmdev *, u32);
-u32 fm_tx_set_pwr_lvl(struct fmdev *, u8);
-u32 fm_tx_set_region(struct fmdev *, u8);
-u32 fm_tx_set_mute_mode(struct fmdev *, u8);
-u32 fm_tx_set_stereo_mono(struct fmdev *, u16);
-u32 fm_tx_set_rds_mode(struct fmdev *, u8);
-u32 fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
-u32 fm_tx_set_af(struct fmdev *, u32);
-u32 fm_tx_set_preemph_filter(struct fmdev *, u32);
-u32 fm_tx_get_tune_cap_val(struct fmdev *);
+int fm_tx_set_freq(struct fmdev *, u32);
+int fm_tx_set_pwr_lvl(struct fmdev *, u8);
+int fm_tx_set_region(struct fmdev *, u8);
+int fm_tx_set_mute_mode(struct fmdev *, u8);
+int fm_tx_set_stereo_mono(struct fmdev *, u16);
+int fm_tx_set_rds_mode(struct fmdev *, u8);
+int fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
+int fm_tx_set_af(struct fmdev *, u32);
+int fm_tx_set_preemph_filter(struct fmdev *, u32);
+int fm_tx_get_tune_cap_val(struct fmdev *);
#endif
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 4f5c43d..077d369 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -84,6 +84,7 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
struct fmdev *fmdev;
ret = copy_from_user(&rds, buf, sizeof(rds));
+ rds.text[sizeof(rds.text) - 1] = '\0';
fmdbg("(%d)type: %d, text %s, af %d\n",
ret, rds.text_type, rds.text, rds.af_freq);
if (ret)
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index aeb7f43..4df4aff 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -87,6 +87,16 @@ config IR_RC5_SZ_DECODER
uses an IR protocol that is almost standard RC-5, but not quite,
as it uses an additional bit).
+config IR_SANYO_DECODER
+ tristate "Enable IR raw decoder for the Sanyo protocol"
+ depends on RC_CORE
+ default y
+
+ ---help---
+ Enable this option if you have an infrared remote control which
+ uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes),
+ and you need software decoding support.
+
config IR_MCE_KBD_DECODER
tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol"
depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 2156e78..fb3dee2 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
+obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 17f8db0..3c9431a 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -194,8 +194,8 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
return 0;
}
- IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 2e5cd31..95e6309 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -357,6 +357,7 @@ static void init_decoders(struct work_struct *work)
load_rc6_decode();
load_jvc_decode();
load_sony_decode();
+ load_sanyo_decode();
load_mce_kbd_decode();
load_lirc_codec();
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 140fb67..4cfdd7f 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -18,24 +18,31 @@
/*
* This decoder currently supports:
* RC6-0-16 (standard toggle bit in header)
+ * RC6-6A-20 (no toggle bit)
* RC6-6A-24 (no toggle bit)
* RC6-6A-32 (MCE version with toggle bit in body)
*/
-#define RC6_UNIT 444444 /* us */
+#define RC6_UNIT 444444 /* nanosecs */
#define RC6_HEADER_NBITS 4 /* not including toggle bit */
#define RC6_0_NBITS 16
-#define RC6_6A_SMALL_NBITS 24
-#define RC6_6A_LARGE_NBITS 32
+#define RC6_6A_32_NBITS 32
+#define RC6_6A_NBITS 128 /* Variable 8..128 */
#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
#define RC6_BIT_START (1 * RC6_UNIT)
#define RC6_BIT_END (1 * RC6_UNIT)
#define RC6_TOGGLE_START (2 * RC6_UNIT)
#define RC6_TOGGLE_END (2 * RC6_UNIT)
+#define RC6_SUFFIX_SPACE (6 * RC6_UNIT)
#define RC6_MODE_MASK 0x07 /* for the header bits */
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
+#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */
+#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */
+#ifndef CHAR_BIT
+#define CHAR_BIT 8 /* Normally in <limits.h> */
+#endif
enum rc6_mode {
RC6_MODE_0,
@@ -125,6 +132,7 @@ again:
break;
data->state = STATE_HEADER_BIT_START;
+ data->header = 0;
return 0;
case STATE_HEADER_BIT_START:
@@ -171,20 +179,14 @@ again:
data->state = STATE_BODY_BIT_START;
decrease_duration(&ev, RC6_TOGGLE_END);
data->count = 0;
+ data->body = 0;
switch (rc6_mode(data)) {
case RC6_MODE_0:
data->wanted_bits = RC6_0_NBITS;
break;
case RC6_MODE_6A:
- /* This might look weird, but we basically
- check the value of the first body bit to
- determine the number of bits in mode 6A */
- if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
- geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
- data->wanted_bits = RC6_6A_LARGE_NBITS;
- else
- data->wanted_bits = RC6_6A_SMALL_NBITS;
+ data->wanted_bits = RC6_6A_NBITS;
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
@@ -193,15 +195,21 @@ again:
goto again;
case STATE_BODY_BIT_START:
- if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
- break;
-
- data->body <<= 1;
- if (ev.pulse)
- data->body |= 1;
- data->count++;
- data->state = STATE_BODY_BIT_END;
- return 0;
+ if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
+ /* Discard LSB's that won't fit in data->body */
+ if (data->count++ < CHAR_BIT * sizeof data->body) {
+ data->body <<= 1;
+ if (ev.pulse)
+ data->body |= 1;
+ }
+ data->state = STATE_BODY_BIT_END;
+ return 0;
+ } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
+ geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
+ data->state = STATE_FINISHED;
+ goto again;
+ }
+ break;
case STATE_BODY_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
@@ -221,20 +229,27 @@ again:
switch (rc6_mode(data)) {
case RC6_MODE_0:
- scancode = data->body & 0xffff;
+ scancode = data->body;
toggle = data->toggle;
IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
scancode, toggle);
break;
case RC6_MODE_6A:
- if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
- toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
- scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
+ if (data->count > CHAR_BIT * sizeof data->body) {
+ IR_dprintk(1, "RC6 too many (%u) data bits\n",
+ data->count);
+ goto out;
+ }
+
+ scancode = data->body;
+ if (data->count == RC6_6A_32_NBITS &&
+ (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+ /* MCE RC */
+ toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
+ scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
} else {
toggle = 0;
- scancode = data->body & 0xffffff;
}
-
IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
scancode, toggle);
break;
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
new file mode 100644
index 0000000..d38fbdd
--- /dev/null
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -0,0 +1,205 @@
+/* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol
+ *
+ * Copyright (C) 2011 by Mauro Carvalho Chehab <mchehab@redhat.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.
+ *
+ * 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.
+ *
+ * This protocol uses the NEC protocol timings. However, data is formatted as:
+ * 13 bits Custom Code
+ * 13 bits NOT(Custom Code)
+ * 8 bits Key data
+ * 8 bits NOT(Key data)
+ *
+ * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
+ * Information for this protocol is available at the Sanyo LC7461 datasheet.
+ */
+
+#include <linux/module.h>
+#include <linux/bitrev.h>
+#include "rc-core-priv.h"
+
+#define SANYO_NBITS (13+13+8+8)
+#define SANYO_UNIT 562500 /* ns */
+#define SANYO_HEADER_PULSE (16 * SANYO_UNIT)
+#define SANYO_HEADER_SPACE (8 * SANYO_UNIT)
+#define SANYO_BIT_PULSE (1 * SANYO_UNIT)
+#define SANYO_BIT_0_SPACE (1 * SANYO_UNIT)
+#define SANYO_BIT_1_SPACE (3 * SANYO_UNIT)
+#define SANYO_REPEAT_SPACE (150 * SANYO_UNIT)
+#define SANYO_TRAILER_PULSE (1 * SANYO_UNIT)
+#define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */
+
+enum sanyo_state {
+ STATE_INACTIVE,
+ STATE_HEADER_SPACE,
+ STATE_BIT_PULSE,
+ STATE_BIT_SPACE,
+ STATE_TRAILER_PULSE,
+ STATE_TRAILER_SPACE,
+};
+
+/**
+ * ir_sanyo_decode() - Decode one SANYO pulse or space
+ * @dev: the struct rc_dev descriptor of the device
+ * @duration: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+ struct sanyo_dec *data = &dev->raw->sanyo;
+ u32 scancode;
+ u8 address, not_address, command, not_command;
+
+ if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+ return 0;
+
+ if (!is_timing_event(ev)) {
+ if (ev.reset) {
+ IR_dprintk(1, "SANYO event reset received. reset to state 0\n");
+ data->state = STATE_INACTIVE;
+ }
+ return 0;
+ }
+
+ IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+ switch (data->state) {
+
+ case STATE_INACTIVE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) {
+ data->count = 0;
+ data->state = STATE_HEADER_SPACE;
+ return 0;
+ }
+ break;
+
+
+ case STATE_HEADER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) {
+ data->state = STATE_BIT_PULSE;
+ return 0;
+ }
+
+ break;
+
+ case STATE_BIT_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_SPACE;
+ return 0;
+
+ case STATE_BIT_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) {
+ if (!dev->keypressed) {
+ IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n");
+ } else {
+ rc_repeat(dev);
+ IR_dprintk(1, "SANYO repeat last key\n");
+ data->state = STATE_INACTIVE;
+ }
+ return 0;
+ }
+
+ data->bits <<= 1;
+ if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2))
+ data->bits |= 1;
+ else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2))
+ break;
+ data->count++;
+
+ if (data->count == SANYO_NBITS)
+ data->state = STATE_TRAILER_PULSE;
+ else
+ data->state = STATE_BIT_PULSE;
+
+ return 0;
+
+ case STATE_TRAILER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2))
+ break;
+
+ data->state = STATE_TRAILER_SPACE;
+ return 0;
+
+ case STATE_TRAILER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2))
+ break;
+
+ address = bitrev16((data->bits >> 29) & 0x1fff) >> 3;
+ not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3;
+ command = bitrev8((data->bits >> 8) & 0xff);
+ not_command = bitrev8((data->bits >> 0) & 0xff);
+
+ if ((command ^ not_command) != 0xff) {
+ IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n",
+ data->bits);
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ scancode = address << 8 | command;
+ IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
+ rc_keydown(dev, scancode, 0);
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static struct ir_raw_handler sanyo_handler = {
+ .protocols = RC_TYPE_SANYO,
+ .decode = ir_sanyo_decode,
+};
+
+static int __init ir_sanyo_decode_init(void)
+{
+ ir_raw_handler_register(&sanyo_handler);
+
+ printk(KERN_INFO "IR SANYO protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_sanyo_decode_exit(void)
+{
+ ir_raw_handler_unregister(&sanyo_handler);
+}
+
+module_init(ir_sanyo_decode_init);
+module_exit(ir_sanyo_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("SANYO IR protocol decoder");
diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c
index e51c616..929bbbc1 100644
--- a/drivers/media/rc/keymaps/rc-hauppauge.c
+++ b/drivers/media/rc/keymaps/rc-hauppauge.c
@@ -183,6 +183,57 @@ static struct rc_map_table rc5_hauppauge_new[] = {
{ 0x1d3f, KEY_HOME },
/*
+ * Keycodes for PT# R-005 remote bundled with Haupauge HVR-930C
+ * Keycodes start with address = 0x1c
+ */
+ { 0x1c3b, KEY_GOTO },
+ { 0x1c3d, KEY_POWER },
+
+ { 0x1c14, KEY_UP },
+ { 0x1c15, KEY_DOWN },
+ { 0x1c16, KEY_LEFT },
+ { 0x1c17, KEY_RIGHT },
+ { 0x1c25, KEY_OK },
+
+ { 0x1c00, KEY_0 },
+ { 0x1c01, KEY_1 },
+ { 0x1c02, KEY_2 },
+ { 0x1c03, KEY_3 },
+ { 0x1c04, KEY_4 },
+ { 0x1c05, KEY_5 },
+ { 0x1c06, KEY_6 },
+ { 0x1c07, KEY_7 },
+ { 0x1c08, KEY_8 },
+ { 0x1c09, KEY_9 },
+
+ { 0x1c1f, KEY_EXIT }, /* BACK */
+ { 0x1c0d, KEY_MENU },
+ { 0x1c1c, KEY_TV },
+
+ { 0x1c10, KEY_VOLUMEUP },
+ { 0x1c11, KEY_VOLUMEDOWN },
+
+ { 0x1c20, KEY_CHANNELUP },
+ { 0x1c21, KEY_CHANNELDOWN },
+
+ { 0x1c0f, KEY_MUTE },
+ { 0x1c12, KEY_PREVIOUS }, /* Prev */
+
+ { 0x1c36, KEY_STOP },
+ { 0x1c37, KEY_RECORD },
+
+ { 0x1c24, KEY_LAST }, /* <| */
+ { 0x1c1e, KEY_NEXT }, /* >| */
+
+ { 0x1c0a, KEY_TEXT },
+ { 0x1c0e, KEY_SUBTITLE }, /* CC */
+
+ { 0x1c32, KEY_REWIND },
+ { 0x1c30, KEY_PAUSE },
+ { 0x1c35, KEY_PLAY },
+ { 0x1c34, KEY_FASTFORWARD },
+
+ /*
* Keycodes for the old Black Remote Controller
* This one also uses RC-5 protocol
* Keycodes start with address = 0x00
diff --git a/drivers/media/rc/keymaps/rc-videomate-m1f.c b/drivers/media/rc/keymaps/rc-videomate-m1f.c
index 3bd1de1..23ee05e 100644
--- a/drivers/media/rc/keymaps/rc-videomate-m1f.c
+++ b/drivers/media/rc/keymaps/rc-videomate-m1f.c
@@ -1,4 +1,4 @@
-/* videomate-m1f.h - Keytable for videomate_m1f Remote Controller
+/* videomate-k100.h - Keytable for videomate_k100 Remote Controller
*
* keymap imported from ir-keymaps.c
*
@@ -13,7 +13,7 @@
#include <media/rc-map.h>
#include <linux/module.h>
-static struct rc_map_table videomate_m1f[] = {
+static struct rc_map_table videomate_k100[] = {
{ 0x01, KEY_POWER },
{ 0x31, KEY_TUNER },
{ 0x33, KEY_VIDEO },
@@ -67,27 +67,27 @@ static struct rc_map_table videomate_m1f[] = {
{ 0x18, KEY_TEXT },
};
-static struct rc_map_list videomate_m1f_map = {
+static struct rc_map_list videomate_k100_map = {
.map = {
- .scan = videomate_m1f,
- .size = ARRAY_SIZE(videomate_m1f),
+ .scan = videomate_k100,
+ .size = ARRAY_SIZE(videomate_k100),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
- .name = RC_MAP_VIDEOMATE_M1F,
+ .name = RC_MAP_VIDEOMATE_K100,
}
};
-static int __init init_rc_map_videomate_m1f(void)
+static int __init init_rc_map_videomate_k100(void)
{
- return rc_map_register(&videomate_m1f_map);
+ return rc_map_register(&videomate_k100_map);
}
-static void __exit exit_rc_map_videomate_m1f(void)
+static void __exit exit_rc_map_videomate_k100(void)
{
- rc_map_unregister(&videomate_m1f_map);
+ rc_map_unregister(&videomate_k100_map);
}
-module_init(init_rc_map_videomate_m1f)
-module_exit(exit_rc_map_videomate_m1f)
+module_init(init_rc_map_videomate_k100)
+module_exit(exit_rc_map_videomate_k100)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pavel Osnova <pvosnova@gmail.com>");
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 27997a9..ca12d32 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -38,7 +38,7 @@
#include <media/lirc.h>
#include <media/lirc_dev.h>
-static int debug;
+static bool debug;
#define IRCTL_DEV_NAME "BaseRemoteCtl"
#define NOPLUG -1
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 20bb12d..21105bf 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -156,9 +156,9 @@
/* module parameters */
#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
+static bool debug = 1;
#else
-static int debug;
+static bool debug;
#endif
#define mce_dbg(dev, fmt, ...) \
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index c6ca870..b72f858 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -84,6 +84,11 @@ struct ir_raw_event_ctrl {
unsigned count;
unsigned wanted_bits;
} rc5_sz;
+ struct sanyo_dec {
+ int state;
+ unsigned count;
+ u64 bits;
+ } sanyo;
struct mce_kbd_dec {
struct input_dev *idev;
struct timer_list rx_timeout;
@@ -193,6 +198,13 @@ static inline void load_jvc_decode(void) { }
static inline void load_sony_decode(void) { }
#endif
+/* from ir-sanyo-decoder.c */
+#ifdef CONFIG_IR_SANYO_DECODER_MODULE
+#define load_sanyo_decode() request_module("ir-sanyo-decoder")
+#else
+static inline void load_sanyo_decode(void) { }
+#endif
+
/* from ir-mce_kbd-decoder.c */
#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE
#define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder")
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index f5db8b9..f6a930b 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -736,6 +736,7 @@ static struct {
{ RC_TYPE_JVC, "jvc" },
{ RC_TYPE_SONY, "sony" },
{ RC_TYPE_RC5_SZ, "rc-5-sz" },
+ { RC_TYPE_SANYO, "sanyo" },
{ RC_TYPE_MCE_KBD, "mce_kbd" },
{ RC_TYPE_LIRC, "lirc" },
{ RC_TYPE_OTHER, "other" },
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 07322fb..ad95c67 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -286,12 +286,6 @@ static void redrat3_issue_async(struct redrat3_dev *rr3)
rr3_ftr(rr3->dev, "Entering %s\n", __func__);
- if (!rr3->det_enabled) {
- dev_warn(rr3->dev, "not issuing async read, "
- "detector not enabled\n");
- return;
- }
-
memset(rr3->bulk_in_buf, 0, rr3->ep_in->wMaxPacketSize);
res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
if (res)
@@ -827,6 +821,7 @@ out:
static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
{
struct redrat3_dev *rr3;
+ int ret;
if (!urb)
return;
@@ -840,15 +835,13 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
rr3_ftr(rr3->dev, "Entering %s\n", __func__);
- if (!rr3->det_enabled) {
- rr3_dbg(rr3->dev, "received a read callback but detector "
- "disabled - ignoring\n");
- return;
- }
-
switch (urb->status) {
case 0:
- redrat3_get_ir_data(rr3, urb->actual_length);
+ ret = redrat3_get_ir_data(rr3, urb->actual_length);
+ if (!ret) {
+ /* no error, prepare to read more */
+ redrat3_issue_async(rr3);
+ }
break;
case -ECONNRESET:
@@ -865,11 +858,6 @@ static void redrat3_handle_async(struct urb *urb, struct pt_regs *regs)
rr3->pkttype = 0;
break;
}
-
- if (!rr3->transmitting)
- redrat3_issue_async(rr3);
- else
- rr3_dbg(rr3->dev, "IR transmit in progress\n");
}
static void redrat3_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
@@ -896,21 +884,24 @@ static u16 mod_freq_to_val(unsigned int mod_freq)
return (u16)(65536 - (mult / mod_freq));
}
-static int redrat3_set_tx_carrier(struct rc_dev *dev, u32 carrier)
+static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
{
- struct redrat3_dev *rr3 = dev->priv;
+ struct redrat3_dev *rr3 = rcdev->priv;
+ struct device *dev = rr3->dev;
+ rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
rr3->carrier = carrier;
return carrier;
}
-static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
+ unsigned count)
{
struct redrat3_dev *rr3 = rcdev->priv;
struct device *dev = rr3->dev;
struct redrat3_signal_header header;
- int i, j, count, ret, ret_len, offset;
+ int i, j, ret, ret_len, offset;
int lencheck, cur_sample_len, pipe;
char *buffer = NULL, *sigdata = NULL;
int *sample_lens = NULL;
@@ -928,20 +919,13 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
return -EAGAIN;
}
- count = n / sizeof(int);
if (count > (RR3_DRIVER_MAXLENS * 2))
return -EINVAL;
+ /* rr3 will disable rc detector on transmit */
+ rr3->det_enabled = false;
rr3->transmitting = true;
- redrat3_disable_detector(rr3);
-
- if (rr3->det_enabled) {
- dev_err(dev, "%s: cannot tx while rx is enabled\n", __func__);
- ret = -EIO;
- goto out;
- }
-
sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
if (!sample_lens) {
ret = -ENOMEM;
@@ -1055,7 +1039,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
if (ret < 0)
dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
else
- ret = n;
+ ret = count;
out:
kfree(sample_lens);
@@ -1063,8 +1047,8 @@ out:
kfree(sigdata);
rr3->transmitting = false;
-
- redrat3_enable_detector(rr3);
+ /* rr3 re-enables rc detector because it was enabled before */
+ rr3->det_enabled = true;
return ret;
}
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index b1d29d0..d6f4bfe 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -43,9 +43,9 @@
#define DRIVER_DESC "Streamzap Remote Control driver"
#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
+static bool debug = 1;
#else
-static int debug;
+static bool debug;
#endif
#define USB_STREAMZAP_VENDOR_ID 0x0e9c
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index e7f7a57..b09c5fa 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -226,11 +226,11 @@ module_param(protocol, uint, 0444);
MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command "
"(0 = RC5, 1 = NEC, 2 = RC6A, default)");
-static int invert; /* default = 0 */
+static bool invert; /* default = 0 */
module_param(invert, bool, 0444);
MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
-static int txandrx; /* default = 0 */
+static bool txandrx; /* default = 0 */
module_param(txandrx, bool, 0444);
MODULE_PARM_DESC(invert, "Allow simultaneous TX and RX");
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index b303a3f..9adada0 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -533,6 +533,13 @@ config VIDEO_ADP1653
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
+ ---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
@@ -580,25 +587,6 @@ config VIDEO_M52790
endmenu # encoder / decoder chips
-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_VIVI
tristate "Virtual Video Driver"
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
@@ -613,66 +601,130 @@ config VIDEO_VIVI
Say Y here if you want to test video apps or debug V4L devices.
In doubt, say N.
-source "drivers/media/video/davinci/Kconfig"
+#
+# USB Multimedia device configuration
+#
-source "drivers/media/video/omap/Kconfig"
+menuconfig V4L_USB_DRIVERS
+ bool "V4L USB devices"
+ depends on USB
+ default y
-source "drivers/media/video/bt8xx/Kconfig"
+if V4L_USB_DRIVERS
-config VIDEO_PMS
- tristate "Mediavision Pro Movie Studio Video For Linux"
- depends on ISA && VIDEO_V4L2
- help
- Say Y if you have such a thing.
+source "drivers/media/video/uvc/Kconfig"
+
+source "drivers/media/video/gspca/Kconfig"
+
+source "drivers/media/video/pvrusb2/Kconfig"
+
+source "drivers/media/video/hdpvr/Kconfig"
+
+source "drivers/media/video/em28xx/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"
+
+source "drivers/media/video/et61x251/Kconfig"
+
+source "drivers/media/video/sn9c102/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 pms.
+ module will be called zr364xx.
-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.
+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 bw-qcam.
+ module will be called stkwebcam.
-config VIDEO_CQCAM
- tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
+config USB_S2255
+ tristate "USB Sensoray 2255 video capture device"
+ depends on VIDEO_V4L2
+ select VIDEOBUF_VMALLOC
+ default n
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.
+ Say Y here if you want support for the Sensoray 2255 USB device.
+ This driver can be compiled as a module, called s2255drv.
-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).
+endif # V4L_USB_DRIVERS
- Check out <file:Documentation/video4linux/w9966.txt> for more
- information.
+#
+# PCI drivers configuration
+#
-source "drivers/media/video/cpia2/Kconfig"
+menuconfig V4L_PCI_DRIVERS
+ bool "V4L PCI(e) devices"
+ depends on PCI
+ default y
+ ---help---
+ Say Y here to enable support for these PCI(e) drivers.
-config VIDEO_VINO
- tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
- depends on I2C && SGI_IP22 && EXPERIMENTAL && 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.
+if V4L_PCI_DRIVERS
-source "drivers/media/video/zoran/Kconfig"
+source "drivers/media/video/au0828/Kconfig"
+
+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"
@@ -688,8 +740,6 @@ config VIDEO_MEYE
To compile this driver as a module, choose M here: the
module will be called meye.
-source "drivers/media/video/saa7134/Kconfig"
-
config VIDEO_MXB
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
depends on PCI && VIDEO_V4L2 && I2C
@@ -706,28 +756,119 @@ config VIDEO_MXB
To compile this driver as a module, choose M here: the
module will be called mxb.
-config VIDEO_HEXIUM_ORION
- tristate "Hexium HV-PCI6 and Orion frame grabber"
- depends on PCI && VIDEO_V4L2 && I2C
- select VIDEO_SAA7146_VV
+source "drivers/media/video/saa7134/Kconfig"
+
+source "drivers/media/video/saa7164/Kconfig"
+
+source "drivers/media/video/zoran/Kconfig"
+
+endif # V4L_PCI_DRIVERS
+
+#
+# ISA & parallel port drivers configuration
+#
+
+menuconfig V4L_ISA_PARPORT_DRIVERS
+ bool "V4L ISA and parallel port devices"
+ depends on ISA || PARPORT
+ default n
---help---
- This is a video4linux driver for the Hexium HV-PCI6 and
- Orion frame grabber cards by Hexium.
+ 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 hexium_orion.
+ module will be called bw-qcam.
-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.
+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 hexium_gemini.
+ 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
+
+menuconfig V4L_PLATFORM_DRIVERS
+ bool "V4L platform devices"
+ 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"
+
+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"
@@ -739,21 +880,13 @@ config VIDEO_TIMBERDALE
---help---
Add support for the Video In peripherial of the timberdale FPGA.
-source "drivers/media/video/cx88/Kconfig"
-
-source "drivers/media/video/cx23885/Kconfig"
-
-source "drivers/media/video/cx25821/Kconfig"
-
-source "drivers/media/video/au0828/Kconfig"
-
-source "drivers/media/video/ivtv/Kconfig"
-
-source "drivers/media/video/cx18/Kconfig"
-
-source "drivers/media/video/saa7164/Kconfig"
-
-source "drivers/media/video/marvell-ccic/Kconfig"
+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"
@@ -774,16 +907,6 @@ config VIDEO_M32R_AR_M64278
To compile this driver as a module, choose M here: the
module will be called arv.
-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.
-
config VIDEO_OMAP3
tristate "OMAP 3 Camera support (EXPERIMENTAL)"
depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
@@ -1002,78 +1125,7 @@ config VIDEO_S5P_MIPI_CSIS
source "drivers/media/video/s5p-tv/Kconfig"
-#
-# USB Multimedia device configuration
-#
-
-menuconfig V4L_USB_DRIVERS
- bool "V4L USB devices"
- depends on USB
- default y
-
-if V4L_USB_DRIVERS && USB
-
-source "drivers/media/video/uvc/Kconfig"
-
-source "drivers/media/video/gspca/Kconfig"
-
-source "drivers/media/video/pvrusb2/Kconfig"
-
-source "drivers/media/video/hdpvr/Kconfig"
-
-source "drivers/media/video/em28xx/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"
-
-source "drivers/media/video/et61x251/Kconfig"
-
-source "drivers/media/video/sn9c102/Kconfig"
-
-source "drivers/media/video/pwc/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.
-
-endif # V4L_USB_DRIVERS
+endif # V4L_PLATFORM_DRIVERS
endif # VIDEO_CAPTURE_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
@@ -1098,6 +1150,23 @@ config VIDEO_MEM2MEM_TESTDEV
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"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 117f9c4..3541388 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o
+obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o
obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
@@ -177,9 +178,12 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.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_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 23ba5c3..879f1d8 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -64,6 +64,11 @@ static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd)
static char *inputs[] = { "pass_through", "play_back" };
+static enum v4l2_mbus_pixelcode adv7170_codes[] = {
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
/* ----------------------------------------------------------------------- */
static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value)
@@ -258,6 +263,60 @@ static int adv7170_s_routing(struct v4l2_subdev *sd,
return 0;
}
+static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ if (index >= ARRAY_SIZE(adv7170_codes))
+ return -EINVAL;
+
+ *code = adv7170_codes[index];
+ return 0;
+}
+
+static int adv7170_g_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ u8 val = adv7170_read(sd, 0x7);
+
+ if ((val & 0x40) == (1 << 6))
+ mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+ else
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ mf->width = 0;
+ mf->height = 0;
+ mf->field = V4L2_FIELD_ANY;
+
+ return 0;
+}
+
+static int adv7170_s_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ u8 val = adv7170_read(sd, 0x7);
+ int ret;
+
+ switch (mf->code) {
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ val &= ~0x40;
+ break;
+
+ case V4L2_MBUS_FMT_UYVY8_1X16:
+ val |= 0x40;
+ break;
+
+ default:
+ v4l2_dbg(1, debug, sd,
+ "illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+ return -EINVAL;
+ }
+
+ ret = adv7170_write(sd, 0x7, val);
+
+ return ret;
+}
+
static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -274,6 +333,9 @@ static const struct v4l2_subdev_core_ops adv7170_core_ops = {
static const struct v4l2_subdev_video_ops adv7170_video_ops = {
.s_std_output = adv7170_s_std_output,
.s_routing = adv7170_s_routing,
+ .s_mbus_fmt = adv7170_s_fmt,
+ .g_mbus_fmt = adv7170_g_fmt,
+ .enum_mbus_fmt = adv7170_enum_fmt,
};
static const struct v4l2_subdev_ops adv7170_ops = {
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c
new file mode 100644
index 0000000..ec859a5
--- /dev/null
+++ b/drivers/media/video/as3645a.c
@@ -0,0 +1,904 @@
+/*
+ * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver
+ *
+ * Copyright (C) 2008-2011 Nokia Corporation
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.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.
+ *
+ * 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 St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - Check hardware FSTROBE control when sensor driver add support for this
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <media/as3645a.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#define AS_TIMER_MS_TO_CODE(t) (((t) - 100) / 50)
+#define AS_TIMER_CODE_TO_MS(c) (50 * (c) + 100)
+
+/* Register definitions */
+
+/* Read-only Design info register: Reset state: xxxx 0001 */
+#define AS_DESIGN_INFO_REG 0x00
+#define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4))
+#define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f)
+
+/* Read-only Version control register: Reset state: 0000 0000
+ * for first engineering samples
+ */
+#define AS_VERSION_CONTROL_REG 0x01
+#define AS_VERSION_CONTROL_RFU(x) (((x) >> 4))
+#define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f)
+
+/* Read / Write (Indicator and timer register): Reset state: 0000 1111 */
+#define AS_INDICATOR_AND_TIMER_REG 0x02
+#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0
+#define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4
+#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
+
+/* Read / Write (Current set register): Reset state: 0110 1001 */
+#define AS_CURRENT_SET_REG 0x03
+#define AS_CURRENT_ASSIST_LIGHT_SHIFT 0
+#define AS_CURRENT_LED_DET_ON (1 << 3)
+#define AS_CURRENT_FLASH_CURRENT_SHIFT 4
+
+/* Read / Write (Control register): Reset state: 1011 0100 */
+#define AS_CONTROL_REG 0x04
+#define AS_CONTROL_MODE_SETTING_SHIFT 0
+#define AS_CONTROL_STROBE_ON (1 << 2)
+#define AS_CONTROL_OUT_ON (1 << 3)
+#define AS_CONTROL_EXT_TORCH_ON (1 << 4)
+#define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5)
+#define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5)
+#define AS_CONTROL_COIL_PEAK_SHIFT 6
+
+/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
+#define AS_FAULT_INFO_REG 0x05
+#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1)
+#define AS_FAULT_INFO_INDICATOR_LED (1 << 2)
+#define AS_FAULT_INFO_LED_AMOUNT (1 << 3)
+#define AS_FAULT_INFO_TIMEOUT (1 << 4)
+#define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5)
+#define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6)
+#define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7)
+
+/* Boost register */
+#define AS_BOOST_REG 0x0d
+#define AS_BOOST_CURRENT_DISABLE (0 << 0)
+#define AS_BOOST_CURRENT_ENABLE (1 << 0)
+
+/* Password register is used to unlock boost register writing */
+#define AS_PASSWORD_REG 0x0f
+#define AS_PASSWORD_UNLOCK_VALUE 0x55
+
+enum as_mode {
+ AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
+ AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
+ AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
+ AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
+};
+
+/*
+ * struct as3645a
+ *
+ * @subdev: V4L2 subdev
+ * @pdata: Flash platform data
+ * @power_lock: Protects power_count
+ * @power_count: Power reference count
+ * @led_mode: V4L2 flash LED mode
+ * @timeout: Flash timeout in microseconds
+ * @flash_current: Flash current (0=200mA ... 15=500mA). Maximum
+ * values are 400mA for two LEDs and 500mA for one LED.
+ * @assist_current: Torch/Assist light current (0=20mA, 1=40mA ... 7=160mA)
+ * @indicator_current: Indicator LED current (0=0mA, 1=2.5mA ... 4=10mA)
+ * @strobe_source: Flash strobe source (software or external)
+ */
+struct as3645a {
+ struct v4l2_subdev subdev;
+ const struct as3645a_platform_data *pdata;
+
+ struct mutex power_lock;
+ int power_count;
+
+ /* Controls */
+ struct v4l2_ctrl_handler ctrls;
+
+ enum v4l2_flash_led_mode led_mode;
+ unsigned int timeout;
+ u8 flash_current;
+ u8 assist_current;
+ u8 indicator_current;
+ enum v4l2_flash_strobe_source strobe_source;
+};
+
+#define to_as3645a(sd) container_of(sd, struct as3645a, subdev)
+
+/* Return negative errno else zero on success */
+static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int rval;
+
+ rval = i2c_smbus_write_byte_data(client, addr, val);
+
+ dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
+ rval < 0 ? "fail" : "ok");
+
+ return rval;
+}
+
+/* Return negative errno else a data byte received from the device. */
+static int as3645a_read(struct as3645a *flash, u8 addr)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int rval;
+
+ rval = i2c_smbus_read_byte_data(client, addr);
+
+ dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
+ rval < 0 ? "fail" : "ok");
+
+ return rval;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration and trigger
+ */
+
+/*
+ * as3645a_set_config - Set flash configuration registers
+ * @flash: The flash
+ *
+ * Configure the hardware with flash, assist and indicator currents, as well as
+ * flash timeout.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int as3645a_set_config(struct as3645a *flash)
+{
+ int ret;
+ u8 val;
+
+ val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
+ | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
+ | AS_CURRENT_LED_DET_ON;
+
+ ret = as3645a_write(flash, AS_CURRENT_SET_REG, val);
+ if (ret < 0)
+ return ret;
+
+ val = AS_TIMER_MS_TO_CODE(flash->timeout / 1000)
+ << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
+
+ val |= (flash->pdata->vref << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
+ | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
+ << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
+
+ return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
+}
+
+/*
+ * as3645a_set_control - Set flash control register
+ * @flash: The flash
+ * @mode: Desired output mode
+ * @on: Desired output state
+ *
+ * Configure the hardware with output mode and state.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int
+as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
+{
+ u8 reg;
+
+ /* Configure output parameters and operation mode. */
+ reg = (flash->pdata->peak << AS_CONTROL_COIL_PEAK_SHIFT)
+ | (on ? AS_CONTROL_OUT_ON : 0)
+ | mode;
+
+ if (flash->led_mode == V4L2_FLASH_LED_MODE_FLASH &&
+ flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL) {
+ reg |= AS_CONTROL_STROBE_TYPE_LEVEL
+ | AS_CONTROL_STROBE_ON;
+ }
+
+ return as3645a_write(flash, AS_CONTROL_REG, reg);
+}
+
+/*
+ * as3645a_set_output - Configure output and operation mode
+ * @flash: Flash controller
+ * @strobe: Strobe the flash (only valid in flash mode)
+ *
+ * Turn the LEDs output on/off and set the operation mode based on the current
+ * parameters.
+ *
+ * The AS3645A can't control the indicator LED independently of the flash/torch
+ * LED. If the flash controller is in V4L2_FLASH_LED_MODE_NONE mode, set the
+ * chip to indicator mode. Otherwise set it to assist light (torch) or flash
+ * mode.
+ *
+ * In indicator and assist modes, turn the output on/off based on the indicator
+ * and torch currents. In software strobe flash mode, turn the output on/off
+ * based on the strobe parameter.
+ */
+static int as3645a_set_output(struct as3645a *flash, bool strobe)
+{
+ enum as_mode mode;
+ bool on;
+
+ switch (flash->led_mode) {
+ case V4L2_FLASH_LED_MODE_NONE:
+ on = flash->indicator_current != 0;
+ mode = AS_MODE_INDICATOR;
+ break;
+ case V4L2_FLASH_LED_MODE_TORCH:
+ on = true;
+ mode = AS_MODE_ASSIST;
+ break;
+ case V4L2_FLASH_LED_MODE_FLASH:
+ on = strobe;
+ mode = AS_MODE_FLASH;
+ break;
+ default:
+ BUG();
+ }
+
+ /* Configure output parameters and operation mode. */
+ return as3645a_set_control(flash, mode, on);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int as3645a_is_active(struct as3645a *flash)
+{
+ int ret;
+
+ ret = as3645a_read(flash, AS_CONTROL_REG);
+ return ret < 0 ? ret : !!(ret & AS_CONTROL_OUT_ON);
+}
+
+static int as3645a_read_fault(struct as3645a *flash)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int rval;
+
+ /* NOTE: reading register clear fault status */
+ rval = as3645a_read(flash, AS_FAULT_INFO_REG);
+ if (rval < 0)
+ return rval;
+
+ if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+ dev_dbg(&client->dev, "Inductor Peak limit fault\n");
+
+ if (rval & AS_FAULT_INFO_INDICATOR_LED)
+ dev_dbg(&client->dev, "Indicator LED fault: "
+ "Short circuit or open loop\n");
+
+ dev_dbg(&client->dev, "%u connected LEDs\n",
+ rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
+
+ if (rval & AS_FAULT_INFO_TIMEOUT)
+ dev_dbg(&client->dev, "Timeout fault\n");
+
+ if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
+ dev_dbg(&client->dev, "Over temperature fault\n");
+
+ if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
+ dev_dbg(&client->dev, "Short circuit fault\n");
+
+ if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
+ dev_dbg(&client->dev, "Over voltage fault: "
+ "Indicates missing capacitor or open connection\n");
+
+ return rval;
+}
+
+static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct as3645a *flash =
+ container_of(ctrl->handler, struct as3645a, ctrls);
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int value;
+
+ switch (ctrl->id) {
+ case V4L2_CID_FLASH_FAULT:
+ value = as3645a_read_fault(flash);
+ if (value < 0)
+ return value;
+
+ ctrl->cur.val = 0;
+ if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+ if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+ if (value & AS_FAULT_INFO_TIMEOUT)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+ if (value & AS_FAULT_INFO_OVER_VOLTAGE)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+ if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
+ if (value & AS_FAULT_INFO_INDICATOR_LED)
+ ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
+ break;
+
+ case V4L2_CID_FLASH_STROBE_STATUS:
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
+ ctrl->cur.val = 0;
+ break;
+ }
+
+ value = as3645a_is_active(flash);
+ if (value < 0)
+ return value;
+
+ ctrl->cur.val = value;
+ break;
+ }
+
+ dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
+
+ return 0;
+}
+
+static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct as3645a *flash =
+ container_of(ctrl->handler, struct as3645a, ctrls);
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int ret;
+
+ dev_dbg(&client->dev, "S_CTRL %08x:%d\n", ctrl->id, ctrl->val);
+
+ /* If a control that doesn't apply to the current mode is modified,
+ * we store the value and return immediately. The setting will be
+ * applied when the LED mode is changed. Otherwise we apply the setting
+ * immediately.
+ */
+
+ switch (ctrl->id) {
+ case V4L2_CID_FLASH_LED_MODE:
+ if (flash->indicator_current)
+ return -EBUSY;
+
+ ret = as3645a_set_config(flash);
+ if (ret < 0)
+ return ret;
+
+ flash->led_mode = ctrl->val;
+ return as3645a_set_output(flash, false);
+
+ case V4L2_CID_FLASH_STROBE_SOURCE:
+ flash->strobe_source = ctrl->val;
+
+ /* Applies to flash mode only. */
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+ break;
+
+ return as3645a_set_output(flash, false);
+
+ case V4L2_CID_FLASH_STROBE:
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+ return -EBUSY;
+
+ return as3645a_set_output(flash, true);
+
+ case V4L2_CID_FLASH_STROBE_STOP:
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+ return -EBUSY;
+
+ return as3645a_set_output(flash, false);
+
+ case V4L2_CID_FLASH_TIMEOUT:
+ flash->timeout = ctrl->val;
+
+ /* Applies to flash mode only. */
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+ break;
+
+ return as3645a_set_config(flash);
+
+ case V4L2_CID_FLASH_INTENSITY:
+ flash->flash_current = (ctrl->val - AS3645A_FLASH_INTENSITY_MIN)
+ / AS3645A_FLASH_INTENSITY_STEP;
+
+ /* Applies to flash mode only. */
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+ break;
+
+ return as3645a_set_config(flash);
+
+ case V4L2_CID_FLASH_TORCH_INTENSITY:
+ flash->assist_current =
+ (ctrl->val - AS3645A_TORCH_INTENSITY_MIN)
+ / AS3645A_TORCH_INTENSITY_STEP;
+
+ /* Applies to torch mode only. */
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_TORCH)
+ break;
+
+ return as3645a_set_config(flash);
+
+ case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+ if (flash->led_mode != V4L2_FLASH_LED_MODE_NONE)
+ return -EBUSY;
+
+ flash->indicator_current =
+ (ctrl->val - AS3645A_INDICATOR_INTENSITY_MIN)
+ / AS3645A_INDICATOR_INTENSITY_STEP;
+
+ ret = as3645a_set_config(flash);
+ if (ret < 0)
+ return ret;
+
+ if ((ctrl->val == 0) == (ctrl->cur.val == 0))
+ break;
+
+ return as3645a_set_output(flash, false);
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops as3645a_ctrl_ops = {
+ .g_volatile_ctrl = as3645a_get_ctrl,
+ .s_ctrl = as3645a_set_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+/* Put device into know state. */
+static int as3645a_setup(struct as3645a *flash)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+ int ret;
+
+ /* clear errors */
+ ret = as3645a_read(flash, AS_FAULT_INFO_REG);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(&client->dev, "Fault info: %02x\n", ret);
+
+ ret = as3645a_set_config(flash);
+ if (ret < 0)
+ return ret;
+
+ ret = as3645a_set_output(flash, false);
+ if (ret < 0)
+ return ret;
+
+ /* read status */
+ ret = as3645a_read_fault(flash);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(&client->dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
+ as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
+ dev_dbg(&client->dev, "AS_CURRENT_SET_REG: %02x\n",
+ as3645a_read(flash, AS_CURRENT_SET_REG));
+ dev_dbg(&client->dev, "AS_CONTROL_REG: %02x\n",
+ as3645a_read(flash, AS_CONTROL_REG));
+
+ return ret & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
+}
+
+static int __as3645a_set_power(struct as3645a *flash, int on)
+{
+ int ret;
+
+ if (!on)
+ as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
+
+ if (flash->pdata->set_power) {
+ ret = flash->pdata->set_power(&flash->subdev, on);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (!on)
+ return 0;
+
+ ret = as3645a_setup(flash);
+ if (ret < 0) {
+ if (flash->pdata->set_power)
+ flash->pdata->set_power(&flash->subdev, 0);
+ }
+
+ return ret;
+}
+
+static int as3645a_set_power(struct v4l2_subdev *sd, int on)
+{
+ struct as3645a *flash = to_as3645a(sd);
+ int ret = 0;
+
+ mutex_lock(&flash->power_lock);
+
+ if (flash->power_count == !on) {
+ ret = __as3645a_set_power(flash, !!on);
+ if (ret < 0)
+ goto done;
+ }
+
+ flash->power_count += on ? 1 : -1;
+ WARN_ON(flash->power_count < 0);
+
+done:
+ mutex_unlock(&flash->power_lock);
+ return ret;
+}
+
+static int as3645a_registered(struct v4l2_subdev *sd)
+{
+ struct as3645a *flash = to_as3645a(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int rval, man, model, rfu, version;
+ const char *vendor;
+
+ /* Power up the flash driver and read manufacturer ID, model ID, RFU
+ * and version.
+ */
+ rval = as3645a_set_power(&flash->subdev, 1);
+ if (rval < 0)
+ return rval;
+
+ rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
+ if (rval < 0)
+ goto power_off;
+
+ man = AS_DESIGN_INFO_FACTORY(rval);
+ model = AS_DESIGN_INFO_MODEL(rval);
+
+ rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
+ if (rval < 0)
+ goto power_off;
+
+ rfu = AS_VERSION_CONTROL_RFU(rval);
+ version = AS_VERSION_CONTROL_VERSION(rval);
+
+ /* Verify the chip model and version. */
+ if (model != 0x01 || rfu != 0x00) {
+ dev_err(&client->dev, "AS3645A not detected "
+ "(model %d rfu %d)\n", model, rfu);
+ rval = -ENODEV;
+ goto power_off;
+ }
+
+ switch (man) {
+ case 1:
+ vendor = "AMS, Austria Micro Systems";
+ break;
+ case 2:
+ vendor = "ADI, Analog Devices Inc.";
+ break;
+ case 3:
+ vendor = "NSC, National Semiconductor";
+ break;
+ case 4:
+ vendor = "NXP";
+ break;
+ case 5:
+ vendor = "TI, Texas Instrument";
+ break;
+ default:
+ vendor = "Unknown";
+ }
+
+ dev_info(&client->dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
+ man, version);
+
+ rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
+ if (rval < 0)
+ goto power_off;
+
+ rval = as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
+ if (rval < 0)
+ goto power_off;
+
+ /* Setup default values. This makes sure that the chip is in a known
+ * state, in case the power rail can't be controlled.
+ */
+ rval = as3645a_setup(flash);
+
+power_off:
+ as3645a_set_power(&flash->subdev, 0);
+
+ return rval;
+}
+
+static int as3645a_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ return as3645a_set_power(sd, 1);
+}
+
+static int as3645a_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ return as3645a_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops as3645a_core_ops = {
+ .s_power = as3645a_set_power,
+};
+
+static const struct v4l2_subdev_ops as3645a_ops = {
+ .core = &as3645a_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops as3645a_internal_ops = {
+ .registered = as3645a_registered,
+ .open = as3645a_open,
+ .close = as3645a_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int as3645a_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct as3645a *flash = to_as3645a(subdev);
+ int rval;
+
+ if (flash->power_count == 0)
+ return 0;
+
+ rval = __as3645a_set_power(flash, 0);
+
+ dev_dbg(&client->dev, "Suspend %s\n", rval < 0 ? "failed" : "ok");
+
+ return rval;
+}
+
+static int as3645a_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct as3645a *flash = to_as3645a(subdev);
+ int rval;
+
+ if (flash->power_count == 0)
+ return 0;
+
+ rval = __as3645a_set_power(flash, 1);
+
+ dev_dbg(&client->dev, "Resume %s\n", rval < 0 ? "fail" : "ok");
+
+ return rval;
+}
+
+#else
+
+#define as3645a_suspend NULL
+#define as3645a_resume NULL
+
+#endif /* CONFIG_PM */
+
+/*
+ * as3645a_init_controls - Create controls
+ * @flash: The flash
+ *
+ * The number of LEDs reported in platform data is used to compute default
+ * limits. Parameters passed through platform data can override those limits.
+ */
+static int as3645a_init_controls(struct as3645a *flash)
+{
+ const struct as3645a_platform_data *pdata = flash->pdata;
+ struct v4l2_ctrl *ctrl;
+ int maximum;
+
+ v4l2_ctrl_handler_init(&flash->ctrls, 10);
+
+ /* V4L2_CID_FLASH_LED_MODE */
+ v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_LED_MODE, 2, ~7,
+ V4L2_FLASH_LED_MODE_NONE);
+
+ /* V4L2_CID_FLASH_STROBE_SOURCE */
+ v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_STROBE_SOURCE,
+ pdata->ext_strobe ? 1 : 0,
+ pdata->ext_strobe ? ~3 : ~1,
+ V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
+
+ flash->strobe_source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
+
+ /* V4L2_CID_FLASH_STROBE */
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+
+ /* V4L2_CID_FLASH_STROBE_STOP */
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+
+ /* V4L2_CID_FLASH_STROBE_STATUS */
+ ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_STROBE_STATUS, 0, 1, 1, 1);
+ if (ctrl != NULL)
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+ /* V4L2_CID_FLASH_TIMEOUT */
+ maximum = pdata->timeout_max;
+
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_TIMEOUT, AS3645A_FLASH_TIMEOUT_MIN,
+ maximum, AS3645A_FLASH_TIMEOUT_STEP, maximum);
+
+ flash->timeout = maximum;
+
+ /* V4L2_CID_FLASH_INTENSITY */
+ maximum = pdata->flash_max_current;
+
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_INTENSITY, AS3645A_FLASH_INTENSITY_MIN,
+ maximum, AS3645A_FLASH_INTENSITY_STEP, maximum);
+
+ flash->flash_current = (maximum - AS3645A_FLASH_INTENSITY_MIN)
+ / AS3645A_FLASH_INTENSITY_STEP;
+
+ /* V4L2_CID_FLASH_TORCH_INTENSITY */
+ maximum = pdata->torch_max_current;
+
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_TORCH_INTENSITY,
+ AS3645A_TORCH_INTENSITY_MIN, maximum,
+ AS3645A_TORCH_INTENSITY_STEP,
+ AS3645A_TORCH_INTENSITY_MIN);
+
+ flash->assist_current = 0;
+
+ /* V4L2_CID_FLASH_INDICATOR_INTENSITY */
+ v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_INDICATOR_INTENSITY,
+ AS3645A_INDICATOR_INTENSITY_MIN,
+ AS3645A_INDICATOR_INTENSITY_MAX,
+ AS3645A_INDICATOR_INTENSITY_STEP,
+ AS3645A_INDICATOR_INTENSITY_MIN);
+
+ flash->indicator_current = 0;
+
+ /* V4L2_CID_FLASH_FAULT */
+ ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+ V4L2_CID_FLASH_FAULT, 0,
+ V4L2_FLASH_FAULT_OVER_VOLTAGE |
+ V4L2_FLASH_FAULT_TIMEOUT |
+ V4L2_FLASH_FAULT_OVER_TEMPERATURE |
+ V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+ if (ctrl != NULL)
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+ flash->subdev.ctrl_handler = &flash->ctrls;
+
+ return flash->ctrls.error;
+}
+
+static int as3645a_probe(struct i2c_client *client,
+ const struct i2c_device_id *devid)
+{
+ struct as3645a *flash;
+ int ret;
+
+ if (client->dev.platform_data == NULL)
+ return -ENODEV;
+
+ flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+ if (flash == NULL)
+ return -ENOMEM;
+
+ flash->pdata = client->dev.platform_data;
+
+ v4l2_i2c_subdev_init(&flash->subdev, client, &as3645a_ops);
+ flash->subdev.internal_ops = &as3645a_internal_ops;
+ flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ ret = as3645a_init_controls(flash);
+ if (ret < 0)
+ goto done;
+
+ ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+ if (ret < 0)
+ goto done;
+
+ flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+ mutex_init(&flash->power_lock);
+
+ flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+
+done:
+ if (ret < 0) {
+ v4l2_ctrl_handler_free(&flash->ctrls);
+ kfree(flash);
+ }
+
+ return ret;
+}
+
+static int __exit as3645a_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct as3645a *flash = to_as3645a(subdev);
+
+ v4l2_device_unregister_subdev(subdev);
+ v4l2_ctrl_handler_free(&flash->ctrls);
+ media_entity_cleanup(&flash->subdev.entity);
+ mutex_destroy(&flash->power_lock);
+ kfree(flash);
+
+ return 0;
+}
+
+static const struct i2c_device_id as3645a_id_table[] = {
+ { AS3645A_NAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
+
+static const struct dev_pm_ops as3645a_pm_ops = {
+ .suspend = as3645a_suspend,
+ .resume = as3645a_resume,
+};
+
+static struct i2c_driver as3645a_i2c_driver = {
+ .driver = {
+ .name = AS3645A_NAME,
+ .pm = &as3645a_pm_ops,
+ },
+ .probe = as3645a_probe,
+ .remove = __exit_p(as3645a_remove),
+ .id_table = as3645a_id_table,
+};
+
+static int __init as3645a_init(void)
+{
+ int rval;
+
+ rval = i2c_add_driver(&as3645a_i2c_driver);
+ if (rval)
+ pr_err("%s: Failed to register the driver\n", AS3645A_NAME);
+
+ return rval;
+}
+
+static void __exit as3645a_exit(void)
+{
+ i2c_del_driver(&as3645a_i2c_driver);
+}
+
+module_init(as3645a_init);
+module_exit(as3645a_exit);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 8c775c5..9fe4519 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -90,7 +90,10 @@ struct atmel_isi {
struct isi_dma_desc dma_desc[MAX_BUFFER_NUM];
struct completion complete;
+ /* ISI peripherial clock */
struct clk *pclk;
+ /* ISI_MCK, feed to camera sensor to generate pixel clock */
+ struct clk *mck;
unsigned int irq;
struct isi_platform_data *pdata;
@@ -766,6 +769,12 @@ static int isi_camera_add_device(struct soc_camera_device *icd)
if (ret)
return ret;
+ ret = clk_enable(isi->mck);
+ if (ret) {
+ clk_disable(isi->pclk);
+ return ret;
+ }
+
isi->icd = icd;
dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n",
icd->devnum);
@@ -779,6 +788,7 @@ static void isi_camera_remove_device(struct soc_camera_device *icd)
BUG_ON(icd != isi->icd);
+ clk_disable(isi->mck);
clk_disable(isi->pclk);
isi->icd = NULL;
@@ -803,7 +813,7 @@ static int isi_camera_querycap(struct soc_camera_host *ici,
return 0;
}
-static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
+static int isi_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -874,7 +884,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt)
if (isi->pdata->has_emb_sync)
cfg1 |= ISI_CFG1_EMB_SYNC;
- if (isi->pdata->isi_full_mode)
+ if (isi->pdata->full_mode)
cfg1 |= ISI_CFG1_FULL_MODE;
isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
@@ -912,6 +922,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev)
isi->fb_descriptors_phys);
iounmap(isi->regs);
+ clk_put(isi->mck);
clk_put(isi->pclk);
kfree(isi);
@@ -930,7 +941,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
struct isi_platform_data *pdata;
pdata = dev->platform_data;
- if (!pdata || !pdata->data_width_flags) {
+ if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) {
dev_err(&pdev->dev,
"No config available for Atmel ISI\n");
return -EINVAL;
@@ -959,6 +970,19 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&isi->video_buffer_list);
INIT_LIST_HEAD(&isi->dma_desc_head);
+ /* Get ISI_MCK, provided by programmable clock or external clock */
+ isi->mck = clk_get(dev, "isi_mck");
+ if (IS_ERR(isi->mck)) {
+ dev_err(dev, "Failed to get isi_mck\n");
+ ret = PTR_ERR(isi->mck);
+ goto err_clk_get;
+ }
+
+ /* Set ISI_MCK's frequency, it should be faster than pixel clock */
+ ret = clk_set_rate(isi->mck, pdata->mck_hz);
+ if (ret < 0)
+ goto err_set_mck_rate;
+
isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
sizeof(struct fbd) * MAX_BUFFER_NUM,
&isi->fb_descriptors_phys,
@@ -1034,9 +1058,12 @@ err_alloc_ctx:
isi->p_fb_descriptors,
isi->fb_descriptors_phys);
err_alloc_descriptors:
+err_set_mck_rate:
+ clk_put(isi->mck);
+err_clk_get:
kfree(isi);
err_alloc_isi:
- clk_put(isi->pclk);
+ clk_put(pclk);
return ret;
}
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
index 0c3a5ba..81ba9d9 100644
--- a/drivers/media/video/au0828/Kconfig
+++ b/drivers/media/video/au0828/Kconfig
@@ -2,6 +2,7 @@
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
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
index cbdb65c..05c299f 100644
--- a/drivers/media/video/au0828/au0828-i2c.c
+++ b/drivers/media/video/au0828/au0828-i2c.c
@@ -348,7 +348,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
}
}
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int au0828_i2c_register(struct au0828_dev *dev)
{
dprintk(1, "%s()\n", __func__);
diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/video/bt8xx/bt848.h
index 0bcd953..c37e6ac 100644
--- a/drivers/media/video/bt8xx/bt848.h
+++ b/drivers/media/video/bt8xx/bt848.h
@@ -30,6 +30,10 @@
#ifndef PCI_DEVICE_ID_BT849
#define PCI_DEVICE_ID_BT849 0x351
#endif
+#ifndef PCI_DEVICE_ID_FUSION879
+#define PCI_DEVICE_ID_FUSION879 0x36c
+#endif
+
#ifndef PCI_DEVICE_ID_BT878
#define PCI_DEVICE_ID_BT878 0x36e
#endif
@@ -37,7 +41,6 @@
#define PCI_DEVICE_ID_BT879 0x36f
#endif
-
/* Brooktree 848 registers */
#define BT848_DSTATUS 0x000
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 5939021..ff2933a 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -80,6 +80,8 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input);
static void gv800s_muxsel(struct bttv *btv, unsigned int input);
static void gv800s_init(struct bttv *btv);
+static void td3116_muxsel(struct bttv *btv, unsigned int input);
+
static int terratec_active_radio_upgrade(struct bttv *btv);
static int tea5757_read(struct bttv *btv);
static int tea5757_write(struct bttv *btv, int value);
@@ -284,7 +286,8 @@ static struct CARD {
{ 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" },
{ 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" },
- { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" },
+ { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" },
+ { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" },
{ 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" },
{ 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" },
{ 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" },
@@ -341,6 +344,7 @@ static struct CARD {
{ 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" },
{ 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" },
{ 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" },
+ { 0x3116f200, BTTV_BOARD_TVT_TD3116, "Tongwei Video Technology TD-3116" },
{ 0, -1, NULL }
};
@@ -1526,10 +1530,10 @@ struct tvcard bttv_tvcards[] = {
GPIO20,22,23: R30,R29,R28
*/
},
- [BTTV_BOARD_SENSORAY311] = {
+ [BTTV_BOARD_SENSORAY311_611] = {
/* Clay Kunz <ckunz@mail.arc.nasa.gov> */
- /* you must jumper JP5 for the card to work */
- .name = "Sensoray 311",
+ /* you must jumper JP5 for the 311 card (PC/104+) to work */
+ .name = "Sensoray 311/611",
.video_inputs = 5,
/* .audio_inputs= 0, */
.svhs = 4,
@@ -2879,6 +2883,16 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_addr = ADDR_UNSET,
},
+ [BTTV_BOARD_TVT_TD3116] = {
+ .name = "Tongwei Video Technology TD-3116",
+ .video_inputs = 16,
+ .gpiomask = 0xc00ff,
+ .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+ .muxsel_hook = td3116_muxsel,
+ .svhs = NO_SVHS,
+ .pll = PLL_28,
+ .tuner_type = TUNER_ABSENT,
+ },
};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3228,6 +3242,42 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input)
gpio_bits(0xf, inmux);
}
+/*
+ * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878.
+ * The first 74HC4051 has the lower 8 inputs, the second one the higher 8.
+ * The muxes are controlled via a 74HC373 latch which is connected to
+ * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch.
+ * Q0 of the latch is connected to the Enable (~E) input of the first
+ * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051.
+ * Q4 - Q7 are connected to the second 74HC4051 in the same way.
+ */
+
+static void td3116_latch_value(struct bttv *btv, u32 value)
+{
+ gpio_bits((1<<18) | 0xff, value);
+ gpio_bits((1<<18) | 0xff, (1<<18) | value);
+ udelay(1);
+ gpio_bits((1<<18) | 0xff, value);
+}
+
+static void td3116_muxsel(struct bttv *btv, unsigned int input)
+{
+ u32 value;
+ u32 highbit;
+
+ highbit = (input & 0x8) >> 3 ;
+
+ /* Disable outputs and set value in the mux */
+ value = 0x11; /* Disable outputs */
+ value |= ((input & 0x7) << 1) << (4 * highbit);
+ td3116_latch_value(btv, value);
+
+ /* Enable the correct output */
+ value &= ~0x11;
+ value |= ((highbit ^ 0x1) << 4) | highbit;
+ td3116_latch_value(btv, value);
+}
+
/* ----------------------------------------------------------------------- */
static void bttv_reset_audio(struct bttv *btv)
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 3dd0660..76c301f 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -4572,6 +4572,7 @@ static struct pci_device_id bttv_pci_tbl[] = {
{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
+ {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
{0,}
};
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index e3952af..580c8e6 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -346,7 +346,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
}
}
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int __devinit init_bttv_i2c(struct bttv *btv)
{
strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index c633359..c517161 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -96,7 +96,7 @@
#define BTTV_BOARD_PV_BT878P_PLUS 0x46
#define BTTV_BOARD_FLYVIDEO98EZ 0x47
#define BTTV_BOARD_PV_BT878P_9B 0x48
-#define BTTV_BOARD_SENSORAY311 0x49
+#define BTTV_BOARD_SENSORAY311_611 0x49
#define BTTV_BOARD_RV605 0x4a
#define BTTV_BOARD_POWERCLR_MTV878 0x4b
#define BTTV_BOARD_WINDVR 0x4c
@@ -183,6 +183,7 @@
#define BTTV_BOARD_GEOVISION_GV800S 0x9d
#define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e
#define BTTV_BOARD_PV183 0x9f
+#define BTTV_BOARD_TVT_TD3116 0xa0
/* more card-specific defines */
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index cd8ff04..fda32f5 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -72,7 +72,7 @@ struct qcam {
static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
static int probe = 2;
-static int force_rgb;
+static bool force_rgb;
static int video_nr = -1;
/* FIXME: parport=auto would never have worked, surely? --RR */
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c
index 5909f25..1d64af9 100644
--- a/drivers/media/video/cs5345.c
+++ b/drivers/media/video/cs5345.c
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC");
MODULE_AUTHOR("Hans Verkuil");
MODULE_LICENSE("GPL");
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index d93e5ab..51c5b9a 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
MODULE_AUTHOR("Martin Vaughan");
MODULE_LICENSE("GPL");
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index c6ff32a..349bd9c 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -75,7 +75,7 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 };
static unsigned cardtype_c = 1;
static unsigned tuner_c = 1;
-static unsigned radio_c = 1;
+static bool radio_c = 1;
static char pal[] = "--";
static char secam[] = "--";
static char ntsc[] = "-";
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 040aaa8..51609d5 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -232,7 +232,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = {
.timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
};
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int init_cx18_i2c(struct cx18 *cx)
{
int i, err;
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
index bdfd192..1180fdc 100644
--- a/drivers/media/video/cx18/cx18-i2c.h
+++ b/drivers/media/video/cx18/cx18-i2c.h
@@ -24,6 +24,6 @@
int cx18_i2c_register(struct cx18 *cx, unsigned idx);
struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int init_cx18_i2c(struct cx18 *cx);
void exit_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig
index ae85a7a..446f692 100644
--- a/drivers/media/video/cx231xx/Kconfig
+++ b/drivers/media/video/cx231xx/Kconfig
@@ -40,10 +40,10 @@ config VIDEO_CX231XX_ALSA
config VIDEO_CX231XX_DVB
tristate "DVB/ATSC Support for Cx231xx based TV cards"
- depends on VIDEO_CX231XX && DVB_CORE
+ depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS
select VIDEOBUF_DVB
- select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE
- select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
select DVB_MB86A20S if !DVB_FE_CUSTOMISE
---help---
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c
index 30d13c1..a2c2b7d 100644
--- a/drivers/media/video/cx231xx/cx231xx-audio.c
+++ b/drivers/media/video/cx231xx/cx231xx-audio.c
@@ -111,6 +111,9 @@ static void cx231xx_audio_isocirq(struct urb *urb)
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
+ if (dev->state & DEV_DISCONNECTED)
+ return;
+
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
@@ -196,6 +199,9 @@ static void cx231xx_audio_bulkirq(struct urb *urb)
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
+ if (dev->state & DEV_DISCONNECTED)
+ return;
+
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
@@ -273,6 +279,9 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+
sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -298,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
urb->context = dev;
urb->pipe = usb_rcvisocpipe(dev->udev,
dev->adev.end_point_addr);
- urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->interval = 1;
urb->complete = cx231xx_audio_isocirq;
@@ -331,6 +340,9 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+
sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
@@ -356,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev)
urb->context = dev;
urb->pipe = usb_rcvbulkpipe(dev->udev,
dev->adev.end_point_addr);
- urb->transfer_flags = 0;
+ urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->complete = cx231xx_audio_bulkirq;
urb->transfer_buffer_length = sb_size;
@@ -432,6 +444,11 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
return -ENODEV;
}
+ if (dev->state & DEV_DISCONNECTED) {
+ cx231xx_errdev("Can't open. the device was removed.\n");
+ return -ENODEV;
+ }
+
/* Sets volume, mute, etc */
dev->mute = 0;
@@ -571,6 +588,9 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
struct cx231xx *dev = snd_pcm_substream_chip(substream);
int retval;
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+
spin_lock(&dev->adev.slock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 60b021e..919ed77 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -843,25 +843,34 @@ void cx231xx_release_resources(struct cx231xx *dev)
cx231xx_remove_from_devlist(dev);
+ cx231xx_ir_exit(dev);
+
/* Release I2C buses */
cx231xx_dev_uninit(dev);
- cx231xx_ir_exit(dev);
+ /* delete v4l2 device */
+ v4l2_device_unregister(&dev->v4l2_dev);
usb_put_dev(dev->udev);
/* Mark device as unused */
- cx231xx_devused &= ~(1 << dev->devno);
+ clear_bit(dev->devno, &cx231xx_devused);
+
+ kfree(dev->video_mode.alt_max_pkt_size);
+ kfree(dev->vbi_mode.alt_max_pkt_size);
+ kfree(dev->sliced_cc_mode.alt_max_pkt_size);
+ kfree(dev->ts1_mode.alt_max_pkt_size);
+ kfree(dev);
+ dev = NULL;
}
/*
* cx231xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device
*/
-static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
+static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
int minor)
{
- struct cx231xx *dev = *devhandle;
int retval = -ENOMEM;
int errCode;
unsigned int maxh, maxw;
@@ -1016,7 +1025,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
int i, isoc_pipe = 0;
char *speed;
char descr[255] = "";
- struct usb_interface *lif = NULL;
struct usb_interface_assoc_descriptor *assoc_desc;
udev = usb_get_dev(interface_to_usbdev(interface));
@@ -1030,21 +1038,21 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
return -ENODEV;
/* Check to see next free device and mark as used */
- nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
- cx231xx_devused |= 1 << nr;
-
- if (nr >= CX231XX_MAXBOARDS) {
- cx231xx_err(DRIVER_NAME
- ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS);
- cx231xx_devused &= ~(1 << nr);
- return -ENOMEM;
- }
+ do {
+ nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+ if (nr >= CX231XX_MAXBOARDS) {
+ /* No free device slots */
+ cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+ CX231XX_MAXBOARDS);
+ return -ENOMEM;
+ }
+ } while (test_and_set_bit(nr, &cx231xx_devused));
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
cx231xx_err(DRIVER_NAME ": out of memory!\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
return -ENOMEM;
}
@@ -1071,9 +1079,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
/* init CIR module TBD */
- /* store the current interface */
- lif = interface;
-
/*mode_tv: digital=1 or analog=0*/
dev->mode_tv = 0;
@@ -1113,9 +1118,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
le16_to_cpu(udev->descriptor.idProduct),
dev->max_iad_interface_count);
- /* store the interface 0 back */
- lif = udev->actconfig->interface[0];
-
/* increment interface count */
dev->interface_count++;
@@ -1126,7 +1128,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (assoc_desc->bFirstInterface != ifnum) {
cx231xx_err(DRIVER_NAME ": Not found "
"matching IAD interface\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
kfree(dev);
dev = NULL;
return -ENODEV;
@@ -1135,7 +1137,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_info("registering interface %d\n", ifnum);
/* save our data pointer in this interface device */
- usb_set_intfdata(lif, dev);
+ usb_set_intfdata(interface, dev);
/*
* AV device initialization - only done at the last interface
@@ -1145,19 +1147,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
if (retval) {
cx231xx_errdev("v4l2_device_register failed\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
kfree(dev);
dev = NULL;
return -EIO;
}
/* allocate device struct */
- retval = cx231xx_init_dev(&dev, udev, nr);
+ retval = cx231xx_init_dev(dev, udev, nr);
if (retval) {
- cx231xx_devused &= ~(1 << dev->devno);
+ clear_bit(dev->devno, &cx231xx_devused);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
dev = NULL;
- usb_set_intfdata(lif, NULL);
+ usb_set_intfdata(interface, NULL);
return retval;
}
@@ -1178,7 +1180,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (dev->video_mode.alt_max_pkt_size == NULL) {
cx231xx_errdev("out of memory!\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
dev = NULL;
@@ -1212,7 +1214,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (dev->vbi_mode.alt_max_pkt_size == NULL) {
cx231xx_errdev("out of memory!\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
dev = NULL;
@@ -1247,7 +1249,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
cx231xx_errdev("out of memory!\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
dev = NULL;
@@ -1283,7 +1285,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
if (dev->ts1_mode.alt_max_pkt_size == NULL) {
cx231xx_errdev("out of memory!\n");
- cx231xx_devused &= ~(1 << nr);
+ clear_bit(dev->devno, &cx231xx_devused);
v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev);
dev = NULL;
@@ -1334,10 +1336,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
if (!dev->udev)
return;
- flush_request_modules(dev);
+ dev->state |= DEV_DISCONNECTED;
- /* delete v4l2 device */
- v4l2_device_unregister(&dev->v4l2_dev);
+ flush_request_modules(dev);
/* wait until all current v4l2 io is finished then deallocate
resources */
@@ -1351,31 +1352,24 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
"deallocation are deferred on close.\n",
video_device_node_name(dev->vdev));
- dev->state |= DEV_MISCONFIGURED;
+ /* Even having users, it is safe to remove the RC i2c driver */
+ cx231xx_ir_exit(dev);
+
if (dev->USE_ISO)
cx231xx_uninit_isoc(dev);
else
cx231xx_uninit_bulk(dev);
- dev->state |= DEV_DISCONNECTED;
wake_up_interruptible(&dev->wait_frame);
wake_up_interruptible(&dev->wait_stream);
} else {
- dev->state |= DEV_DISCONNECTED;
- cx231xx_release_resources(dev);
}
cx231xx_close_extension(dev);
mutex_unlock(&dev->lock);
- if (!dev->users) {
- kfree(dev->video_mode.alt_max_pkt_size);
- kfree(dev->vbi_mode.alt_max_pkt_size);
- kfree(dev->sliced_cc_mode.alt_max_pkt_size);
- kfree(dev->ts1_mode.alt_max_pkt_size);
- kfree(dev);
- dev = NULL;
- }
+ if (!dev->users)
+ cx231xx_release_resources(dev);
}
static struct usb_driver cx231xx_usb_driver = {
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
index d4457f9..08dd930 100644
--- a/drivers/media/video/cx231xx/cx231xx-core.c
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -166,6 +166,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
u8 _i2c_nostop = 0;
u8 _i2c_reserve = 0;
+ if (dev->state & DEV_DISCONNECTED)
+ return -ENODEV;
+
/* Get the I2C period, nostop and reserve parameters */
_i2c_period = i2c_bus->i2c_period;
_i2c_nostop = i2c_bus->i2c_nostop;
@@ -1071,7 +1074,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
sb_size, cx231xx_isoc_irq_callback, dma_q, 1);
urb->number_of_packets = max_packets;
- urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
k = 0;
for (j = 0; j < max_packets; j++) {
@@ -1182,7 +1185,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
return -ENOMEM;
}
dev->video_mode.bulk_ctl.urb[i] = urb;
- urb->transfer_flags = 0;
+ urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
dev->video_mode.bulk_ctl.transfer_buffer[i] =
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c
index da9a4a0..7c4e360 100644
--- a/drivers/media/video/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/video/cx231xx/cx231xx-dvb.c
@@ -196,7 +196,7 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
if (!dev)
return 0;
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ if (dev->state & DEV_DISCONNECTED)
return 0;
if (urb->status < 0) {
@@ -228,7 +228,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
if (!dev)
return 0;
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ if (dev->state & DEV_DISCONNECTED)
return 0;
if (urb->status < 0) {
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
index 45e14cac..96176e9 100644
--- a/drivers/media/video/cx231xx/cx231xx-input.c
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -27,12 +27,16 @@
static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw)
{
+ int rc;
u8 cmd, scancode;
dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
/* poll IR chip */
- if (1 != i2c_master_recv(ir->c, &cmd, 1))
+ rc = i2c_master_recv(ir->c, &cmd, 1);
+ if (rc < 0)
+ return rc;
+ if (rc != 1)
return -EIO;
/* it seems that 0xFE indicates that a button is still hold
@@ -102,11 +106,14 @@ int cx231xx_ir_init(struct cx231xx *dev)
ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
ir_i2c_bus, info.addr);
- i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
+ dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
return 0;
}
void cx231xx_ir_exit(struct cx231xx *dev)
{
+ if (dev->ir_i2c_client)
+ i2c_unregister_device(dev->ir_i2c_client);
+ dev->ir_i2c_client = NULL;
}
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
index 1c7a4da..8cdee5f 100644
--- a/drivers/media/video/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.c
@@ -93,7 +93,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
if (!dev)
return 0;
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ if (dev->state & DEV_DISCONNECTED)
return 0;
if (urb->status < 0) {
@@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
return -ENOMEM;
}
dev->vbi_mode.bulk_ctl.urb[i] = urb;
- urb->transfer_flags = 0;
+ urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
kzalloc(sb_size, GFP_KERNEL);
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index 6e81f97..829a41b 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -337,7 +337,7 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
if (!dev)
return 0;
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ if (dev->state & DEV_DISCONNECTED)
return 0;
if (urb->status < 0) {
@@ -440,7 +440,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
if (!dev)
return 0;
- if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+ if (dev->state & DEV_DISCONNECTED)
return 0;
if (urb->status < 0) {
@@ -1000,12 +1000,6 @@ static int check_dev(struct cx231xx *dev)
cx231xx_errdev("v4l2 ioctl: device not present\n");
return -ENODEV;
}
-
- if (dev->state & DEV_MISCONFIGURED) {
- cx231xx_errdev("v4l2 ioctl: device is misconfigured; "
- "close and open it again\n");
- return -EIO;
- }
return 0;
}
@@ -2347,7 +2341,8 @@ static int cx231xx_v4l2_close(struct file *filp)
return 0;
}
- if (dev->users == 1) {
+ dev->users--;
+ if (!dev->users) {
videobuf_stop(&fh->vb_vidq);
videobuf_mmap_free(&fh->vb_vidq);
@@ -2374,7 +2369,6 @@ static int cx231xx_v4l2_close(struct file *filp)
cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
}
kfree(fh);
- dev->users--;
wake_up_interruptible_nr(&dev->open, 1);
return 0;
}
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index 2000bc6..e174475 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -377,7 +377,6 @@ struct cx231xx_board {
enum cx231xx_dev_state {
DEV_INITIALIZED = 0x01,
DEV_DISCONNECTED = 0x02,
- DEV_MISCONFIGURED = 0x04,
};
enum AFE_MODE {
@@ -621,6 +620,7 @@ struct cx231xx {
/* For I2C IR support */
struct IR_i2c_init_data init_data;
+ struct i2c_client *ir_i2c_client;
unsigned int stream_on:1; /* Locks streams */
unsigned int vbi_stream_on:1; /* Locks streams for VBI */
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 67c4a59..f5c79e5 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -900,6 +900,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
int i, retval = 0;
u32 value = 0;
u32 gpio_output = 0;
+ u32 gpio_value;
u32 checksum = 0;
u32 *dataptr;
@@ -907,7 +908,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
/* Save GPIO settings before reset of APU */
retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
- retval |= mc417_memory_read(dev, 0x900C, &value);
+ retval |= mc417_memory_read(dev, 0x900C, &gpio_value);
retval = mc417_register_write(dev,
IVTV_REG_VPU, 0xFFFFFFED);
@@ -991,11 +992,18 @@ static int cx23885_load_firmware(struct cx23885_dev *dev)
/* F/W power up disturbs the GPIOs, restore state */
retval |= mc417_register_write(dev, 0x9020, gpio_output);
- retval |= mc417_register_write(dev, 0x900C, value);
+ retval |= mc417_register_write(dev, 0x900C, gpio_value);
retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+ /* Hardcoded GPIO's here */
+ retval |= mc417_register_write(dev, 0x9020, 0x4000);
+ retval |= mc417_register_write(dev, 0x900C, 0x4000);
+
+ mc417_register_read(dev, 0x9020, &gpio_output);
+ mc417_register_read(dev, 0x900C, &gpio_value);
+
if (retval < 0)
printk(KERN_ERR "%s: Error with mc417_register_write\n",
__func__);
@@ -1015,6 +1023,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev)
{
dprintk(1, "%s()\n", __func__);
+ /* Dynamically change the height based on video standard */
+ if (dev->encodernorm.id & V4L2_STD_525_60)
+ dev->ts1.height = 480;
+ else
+ dev->ts1.height = 576;
+
/* assign frame size */
cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
dev->ts1.height, dev->ts1.width);
@@ -1030,7 +1044,7 @@ static void cx23885_codec_settings(struct cx23885_dev *dev)
cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
}
-static int cx23885_initialize_codec(struct cx23885_dev *dev)
+static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
{
int version;
int retval;
@@ -1112,9 +1126,11 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev)
mc417_memory_write(dev, 2120, 0x00000080);
/* start capturing to the host interface */
- cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
- CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
- msleep(10);
+ if (startencoder) {
+ cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+ CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+ msleep(10);
+ }
return 0;
}
@@ -1196,6 +1212,16 @@ static int cx23885_querymenu(struct cx23885_dev *dev,
cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
}
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct cx23885_fh *fh = file->private_data;
+ struct cx23885_dev *dev = fh->dev;
+
+ call_all(dev, core, g_std, id);
+
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct cx23885_fh *fh = file->private_data;
@@ -1208,55 +1234,31 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
if (i == ARRAY_SIZE(cx23885_tvnorms))
return -EINVAL;
dev->encodernorm = cx23885_tvnorms[i];
+
+ /* Have the drier core notify the subdevices */
+ mutex_lock(&dev->lock);
+ cx23885_set_tvnorm(dev, *id);
+ mutex_unlock(&dev->lock);
+
return 0;
}
static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+ struct v4l2_input *i)
{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_dev *dev = fh->dev;
- struct cx23885_input *input;
- int n;
-
- if (i->index >= 4)
- return -EINVAL;
-
- input = &cx23885_boards[dev->board].input[i->index];
-
- if (input->type == 0)
- return -EINVAL;
-
- /* FIXME
- * strcpy(i->name, input->name); */
- strcpy(i->name, "unset");
-
- if (input->type == CX23885_VMUX_TELEVISION ||
- input->type == CX23885_VMUX_CABLE)
- i->type = V4L2_INPUT_TYPE_TUNER;
- else
- i->type = V4L2_INPUT_TYPE_CAMERA;
-
- for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
- i->std |= cx23885_tvnorms[n].id;
- return 0;
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ dprintk(1, "%s()\n", __func__);
+ return cx23885_enum_input(dev, i);
}
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_dev *dev = fh->dev;
-
- *i = dev->input;
- return 0;
+ return cx23885_get_input(file, priv, i);
}
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
- if (i >= 4)
- return -EINVAL;
-
- return 0;
+ return cx23885_set_input(file, priv, i);
}
static int vidioc_g_tuner(struct file *file, void *priv,
@@ -1309,43 +1311,25 @@ static int vidioc_g_frequency(struct file *file, void *priv,
}
static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+ struct v4l2_frequency *f)
{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_dev *dev = fh->dev;
-
- cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
- CX23885_END_NOW, CX23885_MPEG_CAPTURE,
- CX23885_RAW_BITS_NONE);
-
- dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
- dev->tuner_type);
- dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
- f->tuner, f->type);
- if (UNSET == dev->tuner_type)
- return -EINVAL;
- if (f->tuner != 0)
- return -EINVAL;
- if (f->type != V4L2_TUNER_ANALOG_TV)
- return -EINVAL;
- dev->freq = f->frequency;
-
- call_all(dev, tuner, s_frequency, f);
+ return cx23885_set_frequency(file, priv, f);
+}
- cx23885_initialize_codec(dev);
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctl)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- return 0;
+ return cx23885_get_control(dev, ctl);
}
static int vidioc_s_ctrl(struct file *file, void *priv,
- struct v4l2_control *ctl)
+ struct v4l2_control *ctl)
{
- struct cx23885_fh *fh = file->private_data;
- struct cx23885_dev *dev = fh->dev;
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
- /* Update the A/V core */
- call_all(dev, core, s_ctrl, ctl);
- return 0;
+ return cx23885_set_control(dev, ctl);
}
static int vidioc_querycap(struct file *file, void *priv,
@@ -1636,7 +1620,7 @@ static ssize_t mpeg_read(struct file *file, char __user *data,
/* Start mpeg encoder on first read. */
if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
- if (cx23885_initialize_codec(dev) < 0)
+ if (cx23885_initialize_codec(dev, 1) < 0)
return -EINVAL;
}
}
@@ -1677,6 +1661,8 @@ static struct v4l2_file_operations mpeg_fops = {
};
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+ .vidioc_querystd = vidioc_g_std,
+ .vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
@@ -1686,6 +1672,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
@@ -1746,8 +1733,8 @@ static struct video_device *cx23885_video_dev_alloc(
if (NULL == vfd)
return NULL;
*vfd = *template;
- snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
- type, cx23885_boards[tsport->dev->board].name);
+ snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+ cx23885_boards[tsport->dev->board].name, type);
vfd->parent = &pci->dev;
vfd->release = video_device_release;
return vfd;
@@ -1791,5 +1778,11 @@ int cx23885_417_register(struct cx23885_dev *dev)
printk(KERN_INFO "%s: registered device %s [mpeg]\n",
dev->name, video_device_node_name(dev->v4l_device));
+ /* ST: Configure the encoder paramaters, but don't begin
+ * encoding, this resolves an issue where the first time the
+ * encoder is started video can be choppy.
+ */
+ cx23885_initialize_codec(dev, 0);
+
return 0;
}
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index c3cf089..3c01be9 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -335,8 +335,33 @@ struct cx23885_board cx23885_boards[] = {
},
[CX23885_BOARD_HAUPPAUGE_HVR1850] = {
.name = "Hauppauge WinTV-HVR1850",
+ .porta = CX23885_ANALOG_VIDEO,
.portb = CX23885_MPEG_ENCODER,
.portc = CX23885_MPEG_DVB,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_addr = 0x42, /* 0x84 >> 1 */
+ .force_bff = 1,
+ .input = {{
+ .type = CX23885_VMUX_TELEVISION,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN5_CH2 |
+ CX25840_VIN2_CH1 |
+ CX25840_DIF_ON,
+ .amux = CX25840_AUDIO8,
+ }, {
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN6_CH1,
+ .amux = CX25840_AUDIO7,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN8_CH1 |
+ CX25840_SVIDEO_ON,
+ .amux = CX25840_AUDIO7,
+ } },
},
[CX23885_BOARD_COMPRO_VIDEOMATE_E800] = {
.name = "Compro VideoMate E800",
@@ -438,6 +463,41 @@ struct cx23885_board cx23885_boards[] = {
.gpio0 = 0,
} },
},
+ [CX23885_BOARD_MYGICA_X8507] = {
+ .name = "Mygica X8507",
+ .tuner_type = TUNER_XC5000,
+ .tuner_addr = 0x61,
+ .tuner_bus = 1,
+ .porta = CX23885_ANALOG_VIDEO,
+ .input = {
+ {
+ .type = CX23885_VMUX_TELEVISION,
+ .vmux = CX25840_COMPOSITE2,
+ .amux = CX25840_AUDIO8,
+ },
+ {
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_COMPOSITE8,
+ },
+ {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_SVIDEO_LUMA3 |
+ CX25840_SVIDEO_CHROMA4,
+ },
+ {
+ .type = CX23885_VMUX_COMPONENT,
+ .vmux = CX25840_COMPONENT_ON |
+ CX25840_VIN1_CH1 |
+ CX25840_VIN6_CH2 |
+ CX25840_VIN7_CH3,
+ },
+ },
+ },
+ [CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = {
+ .name = "TerraTec Cinergy T PCIe Dual",
+ .portb = CX23885_MPEG_DVB,
+ .portc = CX23885_MPEG_DVB,
+ }
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -637,6 +697,14 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x1b55,
.subdevice = 0xe2e4,
.card = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
+ }, {
+ .subvendor = 0x14f1,
+ .subdevice = 0x8502,
+ .card = CX23885_BOARD_MYGICA_X8507,
+ }, {
+ .subvendor = 0x153b,
+ .subdevice = 0x117e,
+ .card = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1068,6 +1136,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_MYGICA_X8506:
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+ case CX23885_BOARD_MYGICA_X8507:
/* GPIO-0 (0)Analog / (1)Digital TV */
/* GPIO-1 reset XC5000 */
/* GPIO-2 reset LGS8GL5 / LGS8G75 */
@@ -1367,6 +1436,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
+ case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
/* Defaults for VID B - Analog encoder */
/* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
@@ -1377,6 +1447,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
/* APB_TSVALERR_POL (active low)*/
ts1->vld_misc_val = 0x2000;
ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+ cx_write(0x130184, 0xc);
/* Defaults for VID C */
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
@@ -1396,6 +1467,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+ case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1431,7 +1503,6 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1275:
case CX23885_BOARD_HAUPPAUGE_HVR1255:
case CX23885_BOARD_HAUPPAUGE_HVR1210:
- case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
@@ -1468,6 +1539,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_MPX885:
+ case CX23885_BOARD_MYGICA_X8507:
+ case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[2].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 40e68b2..6ad2270 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -206,12 +206,12 @@ static struct sram_channel cx23887_sram_channels[] = {
.cnt2_reg = DMA1_CNT2,
},
[SRAM_CH02] = {
- .name = "ch2",
- .cmds_start = 0x0,
- .ctrl_start = 0x0,
- .cdt = 0x0,
- .fifo_start = 0x0,
- .fifo_size = 0x0,
+ .name = "VID A (VBI)",
+ .cmds_start = 0x10050,
+ .ctrl_start = 0x105F0,
+ .cdt = 0x10810,
+ .fifo_start = 0x3000,
+ .fifo_size = 0x1000,
.ptr1_reg = DMA2_PTR1,
.ptr2_reg = DMA2_PTR2,
.cnt1_reg = DMA2_CNT1,
@@ -266,12 +266,12 @@ static struct sram_channel cx23887_sram_channels[] = {
.cnt2_reg = DMA5_CNT2,
},
[SRAM_CH07] = {
- .name = "ch7",
- .cmds_start = 0x0,
- .ctrl_start = 0x0,
- .cdt = 0x0,
- .fifo_start = 0x0,
- .fifo_size = 0x0,
+ .name = "TV Audio",
+ .cmds_start = 0x10190,
+ .ctrl_start = 0x106B0,
+ .cdt = 0x10930,
+ .fifo_start = 0x7000,
+ .fifo_size = 0x1000,
.ptr1_reg = DMA6_PTR1,
.ptr2_reg = DMA6_PTR2,
.cnt1_reg = DMA6_CNT1,
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index bcb45be..af8a225 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -61,6 +61,8 @@
#include "cx23885-f300.h"
#include "altera-ci.h"
#include "stv0367.h"
+#include "drxk.h"
+#include "mt2063.h"
static unsigned int debug;
@@ -111,6 +113,8 @@ static void dvb_buf_release(struct videobuf_queue *q,
cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
}
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
+
static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open)
{
struct videobuf_dvb_frontends *f;
@@ -125,6 +129,12 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open)
if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+
+ /*
+ * FIXME: Improve this path to avoid calling the
+ * cx23885_dvb_set_frontend() every time it passes here.
+ */
+ cx23885_dvb_set_frontend(fe->dvb.frontend);
}
static struct videobuf_queue_ops dvb_qops = {
@@ -479,15 +489,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
.if_khz = 5380,
};
-static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *param)
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx23885_tsport *port = fe->dvb->priv;
struct cx23885_dev *dev = port->dev;
switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1275:
- switch (param->u.vsb.modulation) {
+ switch (p->modulation) {
case VSB_8:
cx23885_gpio_clear(dev, GPIO_5);
break;
@@ -507,31 +517,6 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
return 0;
}
-static int cx23885_dvb_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_SET_FRONTEND:
- err = cx23885_dvb_set_frontend(fe,
- (struct dvb_frontend_parameters *) parg);
- break;
- }
- break;
-
- case DVB_FE_IOCTL_POST:
- /* no post-ioctl handling required */
- break;
- }
- return err;
-};
-
-
static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
.prod = LGS8GXX_PROD_LGS8G75,
.demod_address = 0x19,
@@ -617,6 +602,24 @@ static struct xc5000_config netup_xc5000_config[] = {
},
};
+static struct drxk_config terratec_drxk_config[] = {
+ {
+ .adr = 0x29,
+ .no_i2c_bridge = 1,
+ }, {
+ .adr = 0x2a,
+ .no_i2c_bridge = 1,
+ },
+};
+
+static struct mt2063_config terratec_mt2063_config[] = {
+ {
+ .tuner_address = 0x60,
+ }, {
+ .tuner_address = 0x67,
+ },
+};
+
int netup_altera_fpga_rw(void *device, int flag, int data, int read)
{
struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1043,6 +1046,20 @@ static int dvb_register(struct cx23885_tsport *port)
}
break;
case CX23885_BOARD_HAUPPAUGE_HVR1850:
+ i2c_bus = &dev->i2c_bus[0];
+ fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+ &hcw_s5h1411_config,
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[0].i2c_adap,
+ &hauppauge_tda18271_config);
+
+ tda18271_attach(&dev->ts1.analog_fe,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_tda18271_config);
+
+ break;
case CX23885_BOARD_HAUPPAUGE_HVR1290:
i2c_bus = &dev->i2c_bus[0];
fe0->dvb.frontend = dvb_attach(s5h1411_attach,
@@ -1118,6 +1135,39 @@ static int dvb_register(struct cx23885_tsport *port)
goto frontend_detach;
}
break;
+ case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+ i2c_bus = &dev->i2c_bus[0];
+ i2c_bus2 = &dev->i2c_bus[1];
+
+ switch (port->nr) {
+ /* port b */
+ case 1:
+ fe0->dvb.frontend = dvb_attach(drxk_attach,
+ &terratec_drxk_config[0],
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(mt2063_attach,
+ fe0->dvb.frontend,
+ &terratec_mt2063_config[0],
+ &i2c_bus2->i2c_adap))
+ goto frontend_detach;
+ }
+ break;
+ /* port c */
+ case 2:
+ fe0->dvb.frontend = dvb_attach(drxk_attach,
+ &terratec_drxk_config[1],
+ &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(mt2063_attach,
+ fe0->dvb.frontend,
+ &terratec_mt2063_config[1],
+ &i2c_bus2->i2c_adap))
+ goto frontend_detach;
+ }
+ break;
+ }
+ break;
default:
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
" isn't supported yet\n",
@@ -1151,7 +1201,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,
- cx23885_dvb_fe_ioctl_override);
+ NULL);
if (ret)
goto frontend_detach;
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 0ff7a9e..be1e21d 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -309,7 +309,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
}
}
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int cx23885_i2c_register(struct cx23885_i2c *bus)
{
struct cx23885_dev *dev = bus->dev;
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index e730b92..4bbf9bb 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -253,9 +253,9 @@ static struct cx23885_ctrl cx23885_ctls[] = {
.id = V4L2_CID_AUDIO_VOLUME,
.name = "Volume",
.minimum = 0,
- .maximum = 0x3f,
- .step = 1,
- .default_value = 0x3f,
+ .maximum = 65535,
+ .step = 65535 / 100,
+ .default_value = 65535,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.reg = PATH1_VOL_CTL,
@@ -316,7 +316,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
__func__, bc);
}
-static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
{
dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
__func__,
@@ -344,8 +344,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
*vfd = *template;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release;
- snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
- dev->name, type, cx23885_boards[dev->board].name);
+ snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+ cx23885_boards[dev->board].name, type);
video_set_drvdata(vfd, dev);
return vfd;
}
@@ -492,7 +492,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
dev->input = input;
if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
- dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) {
+ dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 ||
+ dev->board == CX23885_BOARD_MYGICA_X8507) {
/* Select Analog TV */
if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
cx23885_gpio_clear(dev, GPIO_0);
@@ -503,7 +504,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
INPUT(input)->vmux, 0, 0);
if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
- (dev->board == CX23885_BOARD_MPX885)) {
+ (dev->board == CX23885_BOARD_MPX885) ||
+ (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
/* Configure audio routing */
v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
INPUT(input)->amux, 0, 0);
@@ -649,6 +651,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
int rc, init_buffer = 0;
u32 line0_offset, line1_offset;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+ int field_tff;
BUG_ON(NULL == fh->fmt);
if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) ||
@@ -690,15 +693,25 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
buf->bpl, 0, buf->vb.height);
break;
case V4L2_FIELD_INTERLACED:
- if (dev->tvnorm & V4L2_STD_NTSC) {
+ if (dev->tvnorm & V4L2_STD_NTSC)
+ /* NTSC or */
+ field_tff = 1;
+ else
+ field_tff = 0;
+
+ if (cx23885_boards[dev->board].force_bff)
+ /* PAL / SECAM OR 888 in NTSC MODE */
+ field_tff = 0;
+
+ if (field_tff) {
/* cx25840 transmits NTSC bottom field first */
- dprintk(1, "%s() Creating NTSC risc\n",
+ dprintk(1, "%s() Creating TFF/NTSC risc\n",
__func__);
line0_offset = buf->bpl;
line1_offset = 0;
} else {
/* All other formats are top field first */
- dprintk(1, "%s() Creating PAL/SECAM risc\n",
+ dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n",
__func__);
line0_offset = 0;
line1_offset = buf->bpl;
@@ -981,6 +994,8 @@ static int video_release(struct file *file)
}
videobuf_mmap_free(&fh->vidq);
+ videobuf_mmap_free(&fh->vbiq);
+
file->private_data = NULL;
kfree(fh);
@@ -1002,7 +1017,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS */
-static int cx23885_get_control(struct cx23885_dev *dev,
+int cx23885_get_control(struct cx23885_dev *dev,
struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
@@ -1010,7 +1025,7 @@ static int cx23885_get_control(struct cx23885_dev *dev,
return 0;
}
-static int cx23885_set_control(struct cx23885_dev *dev,
+int cx23885_set_control(struct cx23885_dev *dev,
struct v4l2_control *ctl)
{
dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
@@ -1229,6 +1244,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return 0;
}
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+ dprintk(1, "%s()\n", __func__);
+
+ call_all(dev, core, g_std, id);
+
+ return 0;
+}
+
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -1241,7 +1266,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
return 0;
}
-static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
{
static const char *iname[] = {
[CX23885_VMUX_COMPOSITE1] = "Composite1",
@@ -1278,6 +1303,15 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
i->audioset = 0x3;
+ if (dev->input == n) {
+ /* enum'd input matches our configured input.
+ * Ask the video decoder to process the call
+ * and give it an oppertunity to update the
+ * status field.
+ */
+ call_all(dev, video, g_input_status, &i->status);
+ }
+
return 0;
}
@@ -1289,7 +1323,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
return cx23885_enum_input(dev, i);
}
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -1298,7 +1332,12 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
return 0;
}
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ return cx23885_get_input(file, priv, i);
+}
+
+int cx23885_set_input(struct file *file, void *priv, unsigned int i)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -1322,6 +1361,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ return cx23885_set_input(file, priv, i);
+}
+
static int vidioc_log_status(struct file *file, void *priv)
{
struct cx23885_fh *fh = priv;
@@ -1329,11 +1373,11 @@ static int vidioc_log_status(struct file *file, void *priv)
printk(KERN_INFO
"%s/0: ============ START LOG STATUS ============\n",
- dev->name);
+ dev->name);
call_all(dev, core, log_status);
printk(KERN_INFO
"%s/0: ============= END LOG STATUS =============\n",
- dev->name);
+ dev->name);
return 0;
}
@@ -1471,6 +1515,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
{
+ struct v4l2_control ctrl;
+
if (unlikely(UNSET == dev->tuner_type))
return -EINVAL;
if (unlikely(f->tuner != 0))
@@ -1479,29 +1525,102 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
mutex_lock(&dev->lock);
dev->freq = f->frequency;
+ /* I need to mute audio here */
+ ctrl.id = V4L2_CID_AUDIO_MUTE;
+ ctrl.value = 1;
+ cx23885_set_control(dev, &ctrl);
+
call_all(dev, tuner, s_frequency, f);
/* When changing channels it is required to reset TVAUDIO */
- msleep(10);
+ msleep(100);
+
+ /* I need to unmute audio here */
+ ctrl.value = 0;
+ cx23885_set_control(dev, &ctrl);
mutex_unlock(&dev->lock);
return 0;
}
-static int vidioc_s_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
+ struct v4l2_frequency *f)
+{
+ struct v4l2_control ctrl;
+ struct videobuf_dvb_frontend *vfe;
+ struct dvb_frontend *fe;
+ int err = 0;
+
+ struct analog_parameters params = {
+ .mode = V4L2_TUNER_ANALOG_TV,
+ .audmode = V4L2_TUNER_MODE_STEREO,
+ .std = dev->tvnorm,
+ .frequency = f->frequency
+ };
+
+ mutex_lock(&dev->lock);
+ dev->freq = f->frequency;
+
+ /* I need to mute audio here */
+ ctrl.id = V4L2_CID_AUDIO_MUTE;
+ ctrl.value = 1;
+ cx23885_set_control(dev, &ctrl);
+
+ /* If HVR1850 */
+ dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__,
+ params.frequency, f->tuner, params.std);
+
+ vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
+ if (!vfe)
+ err = -EINVAL;
+
+ fe = vfe->dvb.frontend;
+
+ if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)
+ fe = &dev->ts1.analog_fe;
+
+ if (fe && fe->ops.tuner_ops.set_analog_params) {
+ call_all(dev, core, s_std, dev->tvnorm);
+ fe->ops.tuner_ops.set_analog_params(fe, &params);
+ }
+ else
+ printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+ /* When changing channels it is required to reset TVAUDIO */
+ msleep(100);
+
+ /* I need to unmute audio here */
+ ctrl.value = 0;
+ cx23885_set_control(dev, &ctrl);
+
+ mutex_unlock(&dev->lock);
+
+ return 0;
+}
+
+int cx23885_set_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
{
struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = fh->dev;
+ int ret;
- if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
- return -EINVAL;
- if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
- return -EINVAL;
+ switch (dev->board) {
+ case CX23885_BOARD_HAUPPAUGE_HVR1850:
+ ret = cx23885_set_freq_via_ops(dev, f);
+ break;
+ default:
+ ret = cx23885_set_freq(dev, f);
+ }
- return
- cx23885_set_freq(dev, f);
+ return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ return cx23885_set_frequency(file, priv, f);
}
/* ----------------------------------------------------------- */
@@ -1613,6 +1732,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_s_std = vidioc_s_std,
+ .vidioc_g_std = vidioc_g_std,
+ .vidioc_querystd = vidioc_g_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index b49036f..f020f05 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -87,6 +87,8 @@
#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
#define CX23885_BOARD_MPX885 32
+#define CX23885_BOARD_MYGICA_X8507 33
+#define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
@@ -226,6 +228,8 @@ struct cx23885_board {
u32 clk_freq;
struct cx23885_input input[MAX_CX23885_INPUT];
int ci_type; /* for NetUP */
+ /* Force bottom field first during DMA (888 workaround) */
+ u32 force_bff;
};
struct cx23885_subid {
@@ -310,6 +314,9 @@ struct cx23885_tsport {
u32 num_frontends;
void (*gate_ctrl)(struct cx23885_tsport *port, int open);
void *port_priv;
+
+ /* Workaround for a temp dvb_frontend that the tuner can attached to */
+ struct dvb_frontend analog_fe;
};
struct cx23885_kernel_ir {
@@ -574,6 +581,13 @@ extern void cx23885_video_unregister(struct cx23885_dev *dev);
extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
extern void cx23885_video_wakeup(struct cx23885_dev *dev,
struct cx23885_dmaqueue *q, u32 count);
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
+int cx23885_set_input(struct file *file, void *priv, unsigned int i);
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
+int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
/* ----------------------------------------------------------- */
/* cx23885-vbi.c */
diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c
index 09e99de..03cfac4 100644
--- a/drivers/media/video/cx25821/cx25821-alsa.c
+++ b/drivers/media/video/cx25821/cx25821-alsa.c
@@ -102,7 +102,7 @@ struct cx25821_audio_dev {
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
@@ -176,8 +176,7 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
/* Set the input mode to 16-bit */
tmp = cx_read(AUD_A_CFG);
- cx_write(AUD_A_CFG,
- tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+ cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
FLD_AUD_CLK_ENABLE);
/*
@@ -188,9 +187,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
*/
/* Enables corresponding bits at AUD_INT_STAT */
- cx_write(AUD_A_INT_MSK,
- FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC |
- FLD_AUD_DST_OPC_ERR);
+ cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF |
+ FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR);
/* Clean any pending interrupt bits already set */
cx_write(AUD_A_INT_STAT, ~0);
@@ -200,8 +198,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
/* Turn on audio downstream fifo and risc enable 0x101 */
tmp = cx_read(AUD_INT_DMA_CTL);
- cx_set(AUD_INT_DMA_CTL,
- tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+ cx_set(AUD_INT_DMA_CTL, tmp |
+ (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
mdelay(100);
return 0;
@@ -220,9 +218,8 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
/* disable irqs */
cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
- cx_clear(AUD_A_INT_MSK,
- AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 |
- AUD_INT_DN_RISCI1);
+ cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+ AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
return 0;
}
@@ -234,15 +231,15 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
*/
static char *cx25821_aud_irqs[32] = {
"dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
- NULL, /* reserved */
+ NULL, /* reserved */
"dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
- NULL, /* reserved */
- "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
- NULL, /* reserved */
- "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
- NULL, /* reserved */
- "opc_err", "par_err", "rip_err", /* 16-18 */
- "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
+ NULL, /* reserved */
+ "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
+ NULL, /* reserved */
+ "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
+ NULL, /* reserved */
+ "opc_err", "par_err", "rip_err", /* 16-18 */
+ "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
};
/*
@@ -258,10 +255,8 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
cx_write(AUD_A_INT_STAT, status);
if (debug > 1 || (status & mask & ~0xff))
- cx25821_print_irqbits(dev->name, "irq aud",
- cx25821_aud_irqs,
- ARRAY_SIZE(cx25821_aud_irqs), status,
- mask);
+ cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs,
+ ARRAY_SIZE(cx25821_aud_irqs), status, mask);
/* risc op code error */
if (status & AUD_INT_OPC_ERR) {
@@ -270,8 +265,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
cx_clear(AUD_INT_DMA_CTL,
FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
cx25821_sram_channel_dump_audio(dev,
- &cx25821_sram_channels
- [AUDIO_SRAM_CHANNEL]);
+ &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
}
if (status & AUD_INT_DN_SYNC) {
pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
@@ -317,8 +311,9 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id)
cx25821_aud_irq(chip, audint_status,
audint_mask);
break;
- } else
+ } else {
goto out;
+ }
}
handled = 1;
@@ -361,9 +356,8 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip)
*/
#define DEFAULT_FIFO_SIZE 384
static struct snd_pcm_hardware snd_cx25821_digital_hw = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
@@ -396,8 +390,8 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
return -ENODEV;
}
- err =
- snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+ err = snd_pcm_hw_constraint_pow2(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIODS);
if (err < 0)
goto _error;
@@ -468,8 +462,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
dma = &buf->dma;
videobuf_dma_init(dma);
ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
- (PAGE_ALIGN(chip->dma_size) >>
- PAGE_SHIFT));
+ (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
if (ret < 0)
goto error;
@@ -477,10 +470,8 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
goto error;
- ret =
- cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
- chip->period_size, chip->num_periods,
- 1);
+ ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+ chip->period_size, chip->num_periods, 1);
if (ret < 0) {
pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
goto error;
@@ -686,7 +677,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
}
err = snd_card_create(index[devno], id[devno], THIS_MODULE,
- sizeof(struct cx25821_audio_dev), &card);
+ sizeof(struct cx25821_audio_dev), &card);
if (err < 0) {
pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
__func__);
@@ -711,8 +702,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
IRQF_SHARED, chip->dev->name, chip);
if (err < 0) {
- pr_err("ERROR %s: can't get IRQ %d for ALSA\n",
- chip->dev->name, dev->pci->irq);
+ pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
+ dev->pci->irq);
goto error;
}
@@ -730,8 +721,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
chip->iobase, chip->irq);
strcpy(card->mixername, "CX25821");
- pr_info("%s/%i: ALSA support for cx25821 boards\n",
- card->driver, devno);
+ pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
+ devno);
err = snd_card_register(card);
if (err < 0) {
diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c
index c20d6de..20c7ca3 100644
--- a/drivers/media/video/cx25821/cx25821-audio-upstream.c
+++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c
@@ -107,7 +107,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
{
unsigned int line;
struct sram_channel *sram_ch =
- dev->channels[dev->_audio_upstream_channel].sram_channels;
+ dev->channels[dev->_audio_upstream_channel].sram_channels;
int offset = 0;
/* scan lines */
@@ -175,10 +175,8 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
}
rp = cx25821_risc_field_upstream_audio(dev, rp,
- dev->
- _audiodata_buf_phys_addr
- + databuf_offset, bpl,
- fifo_enable);
+ dev->_audiodata_buf_phys_addr + databuf_offset,
+ bpl, fifo_enable);
if (USE_RISC_NOOP_AUDIO) {
for (i = 0; i < NUM_NO_OPS; i++)
@@ -193,7 +191,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
/* Recalculate virtual address based on frame index */
rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
- (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+ (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
}
return 0;
@@ -218,7 +216,7 @@ void cx25821_free_memory_audio(struct cx25821_dev *dev)
void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
{
struct sram_channel *sram_ch =
- dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+ dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
u32 tmp = 0;
if (!dev->_audio_is_running) {
@@ -286,14 +284,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
} else {
if (!(myfile->f_op)) {
pr_err("%s(): File has no file operations registered!\n",
- __func__);
+ __func__);
filp_close(myfile, NULL);
return -EIO;
}
if (!myfile->f_op->read) {
pr_err("%s(): File has no READ operations registered!\n",
- __func__);
+ __func__);
filp_close(myfile, NULL);
return -EIO;
}
@@ -305,14 +303,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
for (i = 0; i < dev->_audio_lines_count; i++) {
pos = file_offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+ &pos);
if (vfs_read_retval > 0 && vfs_read_retval == line_size
&& dev->_audiodata_buf_virt_addr != NULL) {
memcpy((void *)(dev->_audiodata_buf_virt_addr +
frame_offset / 4), mybuf,
- vfs_read_retval);
+ vfs_read_retval);
}
file_offset += vfs_read_retval;
@@ -328,8 +326,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
if (i > 0)
dev->_audioframe_count++;
- dev->_audiofile_status =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_audiofile_status = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
filp_close(myfile, NULL);
@@ -340,12 +338,12 @@ int cx25821_get_audio_data(struct cx25821_dev *dev,
static void cx25821_audioups_handler(struct work_struct *work)
{
- struct cx25821_dev *dev =
- container_of(work, struct cx25821_dev, _audio_work_entry);
+ struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+ _audio_work_entry);
if (!dev) {
pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
- __func__);
+ __func__);
return;
}
@@ -370,19 +368,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
if (IS_ERR(myfile)) {
const int open_errno = -PTR_ERR(myfile);
pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
- __func__, dev->_audiofilename, open_errno);
+ __func__, dev->_audiofilename, open_errno);
return PTR_ERR(myfile);
} else {
if (!(myfile->f_op)) {
pr_err("%s(): File has no file operations registered!\n",
- __func__);
+ __func__);
filp_close(myfile, NULL);
return -EIO;
}
if (!myfile->f_op->read) {
pr_err("%s(): File has no READ operations registered!\n",
- __func__);
+ __func__);
filp_close(myfile, NULL);
return -EIO;
}
@@ -395,12 +393,12 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
for (i = 0; i < dev->_audio_lines_count; i++) {
pos = offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf,
+ line_size, &pos);
- if (vfs_read_retval > 0
- && vfs_read_retval == line_size
- && dev->_audiodata_buf_virt_addr != NULL) {
+ if (vfs_read_retval > 0 &&
+ vfs_read_retval == line_size &&
+ dev->_audiodata_buf_virt_addr != NULL) {
memcpy((void *)(dev->
_audiodata_buf_virt_addr
+ offset / 4), mybuf,
@@ -423,8 +421,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev,
break;
}
- dev->_audiofile_status =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_audiofile_status = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
myfile->f_pos = 0;
@@ -444,9 +442,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
cx25821_free_memory_audio(dev);
- dev->_risc_virt_addr =
- pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size,
- &dma_addr);
+ dev->_risc_virt_addr = pci_alloc_consistent(dev->pci,
+ dev->audio_upstream_riscbuf_size, &dma_addr);
dev->_risc_virt_start_addr = dev->_risc_virt_addr;
dev->_risc_phys_start_addr = dma_addr;
dev->_risc_phys_addr = dma_addr;
@@ -454,22 +451,21 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
if (!dev->_risc_virt_addr) {
printk(KERN_DEBUG
- pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+ pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
return -ENOMEM;
}
/* Clear out memory at address */
memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
/* For Audio Data buffer allocation */
- dev->_audiodata_buf_virt_addr =
- pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size,
- &data_dma_addr);
+ dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci,
+ dev->audio_upstream_databuf_size, &data_dma_addr);
dev->_audiodata_buf_phys_addr = data_dma_addr;
dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
if (!dev->_audiodata_buf_virt_addr) {
printk(KERN_DEBUG
- pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+ pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
return -ENOMEM;
}
/* Clear out memory at address */
@@ -480,12 +476,11 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
return ret;
/* Creating RISC programs */
- ret =
- cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
- dev->_audio_lines_count);
+ ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+ dev->_audio_lines_count);
if (ret < 0) {
printk(KERN_DEBUG
- pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+ pr_fmt("ERROR creating audio upstream RISC programs!\n"));
goto error;
}
@@ -533,9 +528,9 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
if (dev->_risc_virt_start_addr != NULL) {
risc_phys_jump_addr =
- dev->_risc_phys_start_addr +
- RISC_SYNC_INSTRUCTION_SIZE +
- AUDIO_RISC_DMA_BUF_SIZE;
+ dev->_risc_phys_start_addr +
+ RISC_SYNC_INSTRUCTION_SIZE +
+ AUDIO_RISC_DMA_BUF_SIZE;
rp = cx25821_risc_field_upstream_audio(dev,
dev->_risc_virt_start_addr + 1,
@@ -632,7 +627,7 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
/* 10 millisecond timeout */
if (count++ > 1000) {
pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
- __func__);
+ __func__);
return;
}
@@ -661,9 +656,9 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
/* Set the input mode to 16-bit */
tmp = cx_read(sram_ch->aud_cfg);
- tmp |=
- FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
- FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;
+ tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+ FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D |
+ FLD_AUD_SONY_MODE;
cx_write(sram_ch->aud_cfg, tmp);
/* Read and write back the interrupt status register to clear it */
@@ -678,12 +673,11 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
tmp = cx_read(sram_ch->int_msk);
cx_write(sram_ch->int_msk, tmp |= _intr_msk);
- err =
- request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+ err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
- pr_err("%s: can't get upstream IRQ %d\n",
- dev->name, dev->pci->irq);
+ pr_err("%s: can't get upstream IRQ %d\n", dev->name,
+ dev->pci->irq);
goto fail_irq;
}
@@ -726,7 +720,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
if (!dev->_irq_audio_queues) {
printk(KERN_DEBUG
- pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+ pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
return -ENOMEM;
}
@@ -739,33 +733,30 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
if (dev->input_audiofilename) {
str_length = strlen(dev->input_audiofilename);
- dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_audiofilename = kmemdup(dev->input_audiofilename,
+ str_length + 1, GFP_KERNEL);
if (!dev->_audiofilename)
goto error;
- memcpy(dev->_audiofilename, dev->input_audiofilename,
- str_length + 1);
-
/* Default if filename is empty string */
if (strcmp(dev->input_audiofilename, "") == 0)
dev->_audiofilename = "/root/audioGOOD.wav";
} else {
str_length = strlen(_defaultAudioName);
- dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_audiofilename = kmemdup(_defaultAudioName,
+ str_length + 1, GFP_KERNEL);
if (!dev->_audiofilename)
goto error;
-
- memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);
}
retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
_line_size, 0);
dev->audio_upstream_riscbuf_size =
- AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
- RISC_SYNC_INSTRUCTION_SIZE;
+ AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+ RISC_SYNC_INSTRUCTION_SIZE;
dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
/* Allocating buffers and prepare RISC program */
@@ -773,7 +764,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
_line_size);
if (retval < 0) {
pr_err("%s: Failed to set up Audio upstream buffers!\n",
- dev->name);
+ dev->name);
goto error;
}
/* Start RISC engine */
diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/video/cx25821/cx25821-audio.h
index 8eb55b7..1fc2d24 100644
--- a/drivers/media/video/cx25821/cx25821-audio.h
+++ b/drivers/media/video/cx25821/cx25821-audio.h
@@ -23,39 +23,40 @@
#ifndef __CX25821_AUDIO_H__
#define __CX25821_AUDIO_H__
-#define USE_RISC_NOOP 1
-#define LINES_PER_BUFFER 15
-#define AUDIO_LINE_SIZE 128
+#define USE_RISC_NOOP 1
+#define LINES_PER_BUFFER 15
+#define AUDIO_LINE_SIZE 128
/* Number of buffer programs to use at once. */
-#define NUMBER_OF_PROGRAMS 8
+#define NUMBER_OF_PROGRAMS 8
/*
* Max size of the RISC program for a buffer. - worst case is 2 writes per line
* Space is also added for the 4 no-op instructions added on the end.
*/
#ifndef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE \
- (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
- RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE * 4)
#endif
/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
#ifdef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE \
- (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
- RISC_NOOP_INSTRUCTION_SIZE * 4)
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+ RISC_NOOP_INSTRUCTION_SIZE * 4)
#endif
/* Sizes of various instructions in bytes. Used when adding instructions. */
-#define RISC_WRITE_INSTRUCTION_SIZE 12
-#define RISC_JUMP_INSTRUCTION_SIZE 12
-#define RISC_SKIP_INSTRUCTION_SIZE 4
-#define RISC_SYNC_INSTRUCTION_SIZE 4
-#define RISC_WRITECR_INSTRUCTION_SIZE 16
-#define RISC_NOOP_INSTRUCTION_SIZE 4
-
-#define MAX_AUDIO_DMA_BUFFER_SIZE \
-(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)
+#define RISC_WRITE_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE 12
+#define RISC_SKIP_INSTRUCTION_SIZE 4
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_NOOP_INSTRUCTION_SIZE 4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE \
+ (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + \
+ RISC_SYNC_INSTRUCTION_SIZE)
#endif
diff --git a/drivers/media/video/cx25821/cx25821-cards.c b/drivers/media/video/cx25821/cx25821-cards.c
index 6ace603..99988c9 100644
--- a/drivers/media/video/cx25821/cx25821-cards.c
+++ b/drivers/media/video/cx25821/cx25821-cards.c
@@ -67,6 +67,6 @@ void cx25821_card_setup(struct cx25821_dev *dev)
if (dev->i2c_bus[0].i2c_rc == 0) {
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
- sizeof(eeprom));
+ sizeof(eeprom));
}
}
diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c
index a7fa38f..f617474 100644
--- a/drivers/media/video/cx25821/cx25821-core.c
+++ b/drivers/media/video/cx25821/cx25821-core.c
@@ -804,8 +804,8 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
u32 format)
{
if (channel_select <= 7 && channel_select >= 0) {
- cx_write(dev->channels[channel_select].
- sram_channels->pix_frmt, format);
+ cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
+ format);
dev->channels[channel_select].pixel_formats = format;
}
}
@@ -855,21 +855,19 @@ static void cx25821_initialize(struct cx25821_dev *dev)
}
cx25821_sram_channel_setup_audio(dev,
- dev->channels[SRAM_CH08].sram_channels,
- 128, 0);
+ dev->channels[SRAM_CH08].sram_channels, 128, 0);
cx25821_gpio_init(dev);
}
static int cx25821_get_resources(struct cx25821_dev *dev)
{
- if (request_mem_region
- (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0),
- dev->name))
+ if (request_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0), dev->name))
return 0;
pr_err("%s: can't get MMIO memory @ 0x%llx\n",
- dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+ dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
return -EBUSY;
}
@@ -972,8 +970,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
if (!dev->lmmio) {
- CX25821_ERR
- ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+ CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
cx25821_iounmap(dev);
return -ENOMEM;
}
@@ -994,7 +991,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
* cx25821_i2c_register(&dev->i2c_bus[2]); */
CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
- dev->i2c_bus[0].i2c_rc);
+ dev->i2c_bus[0].i2c_rc);
cx25821_card_setup(dev);
@@ -1004,9 +1001,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
cx25821_video_register(dev);
/* register IOCTL device */
- dev->ioctl_dev =
- cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template,
- "video");
+ dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci,
+ &cx25821_videoioctl_template, "video");
if (video_register_device
(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
@@ -1103,16 +1099,15 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
}
if (bpl <= sg_dma_len(sg) - offset) {
/* fits into current chunk */
- *(rp++) =
- cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL |
+ bpl);
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += bpl;
} else {
/* scanline needs to be split */
todo = bpl;
- *(rp++) =
- cpu_to_le32(RISC_WRITE | RISC_SOL |
+ *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL |
(sg_dma_len(sg) - offset));
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
@@ -1120,8 +1115,8 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
offset = 0;
sg++;
while (todo > sg_dma_len(sg)) {
- *(rp++) =
- cpu_to_le32(RISC_WRITE | sg_dma_len(sg));
+ *(rp++) = cpu_to_le32(RISC_WRITE |
+ sg_dma_len(sg));
*(rp++) = cpu_to_le32(sg_dma_address(sg));
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
@@ -1160,8 +1155,8 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
can cause next bpl to start close to a page border. First DMA
region may be smaller than PAGE_SIZE */
/* write and jump need and extra dword */
- instructions =
- fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+ instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
+ lines);
instructions += 2;
rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
@@ -1215,8 +1210,8 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
if (bpl <= sg_dma_len(sg) - offset) {
/* fits into current chunk */
- *(rp++) =
- cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl);
+ *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL |
+ bpl);
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
offset += bpl;
@@ -1224,7 +1219,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
/* scanline needs to be split */
todo = bpl;
*(rp++) = cpu_to_le32(RISC_WRITE | sol |
- (sg_dma_len(sg) - offset));
+ (sg_dma_len(sg) - offset));
*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg) - offset);
@@ -1232,7 +1227,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
sg++;
while (todo > sg_dma_len(sg)) {
*(rp++) = cpu_to_le32(RISC_WRITE |
- sg_dma_len(sg));
+ sg_dma_len(sg));
*(rp++) = cpu_to_le32(sg_dma_address(sg));
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
@@ -1339,8 +1334,8 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id)
sram_channels->int_stat);
if (vid_status)
- handled +=
- cx25821_video_irq(dev, i, vid_status);
+ handled += cx25821_video_irq(dev, i,
+ vid_status);
cx_write(PCI_INT_STAT, mask[i]);
}
@@ -1427,9 +1422,8 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
goto fail_irq;
}
- err =
- request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED,
- dev->name, dev);
+ err = request_irq(pci_dev->irq, cx25821_irq,
+ IRQF_SHARED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
@@ -1512,6 +1506,5 @@ static void __exit cx25821_fini(void)
pci_unregister_driver(&cx25821_pci_driver);
}
-
module_init(cx25821_init);
module_exit(cx25821_fini);
diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c
index 4d3d0ce..12d7300 100644
--- a/drivers/media/video/cx25821/cx25821-i2c.c
+++ b/drivers/media/video/cx25821/cx25821-i2c.c
@@ -252,8 +252,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
msgs[i].addr == msgs[i + 1].addr) {
/* write then read from same address */
- retval =
- i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
+ retval = i2c_sendbytes(i2c_adap, &msgs[i],
+ msgs[i + 1].len);
if (retval < 0)
goto err;
@@ -276,10 +276,8 @@ err:
static u32 cx25821_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL |
- I2C_FUNC_I2C |
- I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
}
static struct i2c_algorithm cx25821_i2c_algo_template = {
@@ -300,7 +298,7 @@ static struct i2c_client cx25821_i2c_client_template = {
.name = "cx25821 internal",
};
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int cx25821_i2c_register(struct cx25821_i2c *bus)
{
struct cx25821_dev *dev = bus->dev;
diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/video/cx25821/cx25821-medusa-defines.h
index 60d197f..7a9e647 100644
--- a/drivers/media/video/cx25821/cx25821-medusa-defines.h
+++ b/drivers/media/video/cx25821/cx25821-medusa-defines.h
@@ -23,7 +23,7 @@
#ifndef _MEDUSA_DEF_H_
#define _MEDUSA_DEF_H_
-/* Video deocder that we supported */
+/* Video decoder that we supported */
#define VDEC_A 0
#define VDEC_B 1
#define VDEC_C 2
@@ -34,9 +34,9 @@
#define VDEC_H 7
/* end of display sequence */
-#define END_OF_SEQ 0xF;
+#define END_OF_SEQ 0xF;
/* registry string size */
-#define MAX_REGISTRY_SZ 40;
+#define MAX_REGISTRY_SZ 40;
#endif
diff --git a/drivers/media/video/cx25821/cx25821-medusa-reg.h b/drivers/media/video/cx25821/cx25821-medusa-reg.h
index 1c1c228..c98ac94 100644
--- a/drivers/media/video/cx25821/cx25821-medusa-reg.h
+++ b/drivers/media/video/cx25821/cx25821-medusa-reg.h
@@ -28,22 +28,22 @@
#define HOST_REGISTER2 0x0001
/* Chip Configuration Registers */
-#define CHIP_CTRL 0x0100
-#define AFE_AB_CTRL 0x0104
-#define AFE_CD_CTRL 0x0108
-#define AFE_EF_CTRL 0x010C
-#define AFE_GH_CTRL 0x0110
+#define CHIP_CTRL 0x0100
+#define AFE_AB_CTRL 0x0104
+#define AFE_CD_CTRL 0x0108
+#define AFE_EF_CTRL 0x010C
+#define AFE_GH_CTRL 0x0110
#define DENC_AB_CTRL 0x0114
-#define BYP_AB_CTRL 0x0118
-#define MON_A_CTRL 0x011C
-#define DISP_SEQ_A 0x0120
-#define DISP_SEQ_B 0x0124
-#define DISP_AB_CNT 0x0128
-#define DISP_CD_CNT 0x012C
-#define DISP_EF_CNT 0x0130
-#define DISP_GH_CNT 0x0134
-#define DISP_IJ_CNT 0x0138
-#define PIN_OE_CTRL 0x013C
+#define BYP_AB_CTRL 0x0118
+#define MON_A_CTRL 0x011C
+#define DISP_SEQ_A 0x0120
+#define DISP_SEQ_B 0x0124
+#define DISP_AB_CNT 0x0128
+#define DISP_CD_CNT 0x012C
+#define DISP_EF_CNT 0x0130
+#define DISP_GH_CNT 0x0134
+#define DISP_IJ_CNT 0x0138
+#define PIN_OE_CTRL 0x013C
#define PIN_SPD_CTRL 0x0140
#define PIN_SPD_CTRL2 0x0144
#define IRQ_STAT_CTRL 0x0148
@@ -51,8 +51,8 @@
#define POWER_CTRL_CD 0x0150
#define POWER_CTRL_EF 0x0154
#define POWER_CTRL_GH 0x0158
-#define TUNE_CTRL 0x015C
-#define BIAS_CTRL 0x0160
+#define TUNE_CTRL 0x015C
+#define BIAS_CTRL 0x0160
#define AFE_AB_DIAG_CTRL 0x0164
#define AFE_CD_DIAG_CTRL 0x0168
#define AFE_EF_DIAG_CTRL 0x016C
@@ -61,17 +61,17 @@
#define PLL_CD_DIAG_CTRL 0x0178
#define PLL_EF_DIAG_CTRL 0x017C
#define PLL_GH_DIAG_CTRL 0x0180
-#define TEST_CTRL 0x0184
-#define BIST_STAT 0x0188
-#define BIST_STAT2 0x018C
-#define BIST_VID_PLL_AB_STAT 0x0190
-#define BIST_VID_PLL_CD_STAT 0x0194
-#define BIST_VID_PLL_EF_STAT 0x0198
-#define BIST_VID_PLL_GH_STAT 0x019C
+#define TEST_CTRL 0x0184
+#define BIST_STAT 0x0188
+#define BIST_STAT2 0x018C
+#define BIST_VID_PLL_AB_STAT 0x0190
+#define BIST_VID_PLL_CD_STAT 0x0194
+#define BIST_VID_PLL_EF_STAT 0x0198
+#define BIST_VID_PLL_GH_STAT 0x019C
#define DLL_DIAG_CTRL 0x01A0
#define DEV_CH_ID_CTRL 0x01A4
#define ABIST_CTRL_STATUS 0x01A8
-#define ABIST_FREQ 0x01AC
+#define ABIST_FREQ 0x01AC
#define ABIST_GOERT_SHIFT 0x01B0
#define ABIST_COEF12 0x01B4
#define ABIST_COEF34 0x01B8
@@ -92,357 +92,357 @@
#define ABIST_CLAMP_E 0x01F4
#define ABIST_CLAMP_F 0x01F8
-/* Digital Video Encoder A Registers */
-#define DENC_A_REG_1 0x0200
-#define DENC_A_REG_2 0x0204
-#define DENC_A_REG_3 0x0208
-#define DENC_A_REG_4 0x020C
-#define DENC_A_REG_5 0x0210
-#define DENC_A_REG_6 0x0214
-#define DENC_A_REG_7 0x0218
-#define DENC_A_REG_8 0x021C
+/* Digital Video Encoder A Registers */
+#define DENC_A_REG_1 0x0200
+#define DENC_A_REG_2 0x0204
+#define DENC_A_REG_3 0x0208
+#define DENC_A_REG_4 0x020C
+#define DENC_A_REG_5 0x0210
+#define DENC_A_REG_6 0x0214
+#define DENC_A_REG_7 0x0218
+#define DENC_A_REG_8 0x021C
-/* Digital Video Encoder B Registers */
-#define DENC_B_REG_1 0x0300
-#define DENC_B_REG_2 0x0304
-#define DENC_B_REG_3 0x0308
-#define DENC_B_REG_4 0x030C
-#define DENC_B_REG_5 0x0310
-#define DENC_B_REG_6 0x0314
-#define DENC_B_REG_7 0x0318
-#define DENC_B_REG_8 0x031C
+/* Digital Video Encoder B Registers */
+#define DENC_B_REG_1 0x0300
+#define DENC_B_REG_2 0x0304
+#define DENC_B_REG_3 0x0308
+#define DENC_B_REG_4 0x030C
+#define DENC_B_REG_5 0x0310
+#define DENC_B_REG_6 0x0314
+#define DENC_B_REG_7 0x0318
+#define DENC_B_REG_8 0x031C
-/* Video Decoder A Registers */
-#define MODE_CTRL 0x1000
-#define OUT_CTRL1 0x1004
-#define OUT_CTRL_NS 0x1008
-#define GEN_STAT 0x100C
-#define INT_STAT_MASK 0x1010
-#define LUMA_CTRL 0x1014
-#define CHROMA_CTRL 0x1018
-#define CRUSH_CTRL 0x101C
-#define HORIZ_TIM_CTRL 0x1020
-#define VERT_TIM_CTRL 0x1024
-#define MISC_TIM_CTRL 0x1028
-#define FIELD_COUNT 0x102C
-#define HSCALE_CTRL 0x1030
-#define VSCALE_CTRL 0x1034
-#define MAN_VGA_CTRL 0x1038
-#define MAN_AGC_CTRL 0x103C
-#define DFE_CTRL1 0x1040
-#define DFE_CTRL2 0x1044
-#define DFE_CTRL3 0x1048
-#define PLL_CTRL 0x104C
-#define PLL_CTRL_FAST 0x1050
-#define HTL_CTRL 0x1054
-#define SRC_CFG 0x1058
-#define SC_STEP_SIZE 0x105C
-#define SC_CONVERGE_CTRL 0x1060
-#define SC_LOOP_CTRL 0x1064
-#define COMB_2D_HFS_CFG 0x1068
-#define COMB_2D_HFD_CFG 0x106C
-#define COMB_2D_LF_CFG 0x1070
-#define COMB_2D_BLEND 0x1074
-#define COMB_MISC_CTRL 0x1078
+/* Video Decoder A Registers */
+#define MODE_CTRL 0x1000
+#define OUT_CTRL1 0x1004
+#define OUT_CTRL_NS 0x1008
+#define GEN_STAT 0x100C
+#define INT_STAT_MASK 0x1010
+#define LUMA_CTRL 0x1014
+#define CHROMA_CTRL 0x1018
+#define CRUSH_CTRL 0x101C
+#define HORIZ_TIM_CTRL 0x1020
+#define VERT_TIM_CTRL 0x1024
+#define MISC_TIM_CTRL 0x1028
+#define FIELD_COUNT 0x102C
+#define HSCALE_CTRL 0x1030
+#define VSCALE_CTRL 0x1034
+#define MAN_VGA_CTRL 0x1038
+#define MAN_AGC_CTRL 0x103C
+#define DFE_CTRL1 0x1040
+#define DFE_CTRL2 0x1044
+#define DFE_CTRL3 0x1048
+#define PLL_CTRL 0x104C
+#define PLL_CTRL_FAST 0x1050
+#define HTL_CTRL 0x1054
+#define SRC_CFG 0x1058
+#define SC_STEP_SIZE 0x105C
+#define SC_CONVERGE_CTRL 0x1060
+#define SC_LOOP_CTRL 0x1064
+#define COMB_2D_HFS_CFG 0x1068
+#define COMB_2D_HFD_CFG 0x106C
+#define COMB_2D_LF_CFG 0x1070
+#define COMB_2D_BLEND 0x1074
+#define COMB_MISC_CTRL 0x1078
#define COMB_FLAT_THRESH_CTRL 0x107C
-#define COMB_TEST 0x1080
-#define BP_MISC_CTRL 0x1084
-#define VCR_DET_CTRL 0x1088
-#define NOISE_DET_CTRL 0x108C
+#define COMB_TEST 0x1080
+#define BP_MISC_CTRL 0x1084
+#define VCR_DET_CTRL 0x1088
+#define NOISE_DET_CTRL 0x108C
#define COMB_FLAT_NOISE_CTRL 0x1090
-#define VERSION 0x11F8
-#define SOFT_RST_CTRL 0x11FC
+#define VERSION 0x11F8
+#define SOFT_RST_CTRL 0x11FC
-/* Video Decoder B Registers */
-#define VDEC_B_MODE_CTRL 0x1200
-#define VDEC_B_OUT_CTRL1 0x1204
-#define VDEC_B_OUT_CTRL_NS 0x1208
-#define VDEC_B_GEN_STAT 0x120C
+/* Video Decoder B Registers */
+#define VDEC_B_MODE_CTRL 0x1200
+#define VDEC_B_OUT_CTRL1 0x1204
+#define VDEC_B_OUT_CTRL_NS 0x1208
+#define VDEC_B_GEN_STAT 0x120C
#define VDEC_B_INT_STAT_MASK 0x1210
-#define VDEC_B_LUMA_CTRL 0x1214
-#define VDEC_B_CHROMA_CTRL 0x1218
-#define VDEC_B_CRUSH_CTRL 0x121C
+#define VDEC_B_LUMA_CTRL 0x1214
+#define VDEC_B_CHROMA_CTRL 0x1218
+#define VDEC_B_CRUSH_CTRL 0x121C
#define VDEC_B_HORIZ_TIM_CTRL 0x1220
#define VDEC_B_VERT_TIM_CTRL 0x1224
#define VDEC_B_MISC_TIM_CTRL 0x1228
-#define VDEC_B_FIELD_COUNT 0x122C
-#define VDEC_B_HSCALE_CTRL 0x1230
-#define VDEC_B_VSCALE_CTRL 0x1234
-#define VDEC_B_MAN_VGA_CTRL 0x1238
-#define VDEC_B_MAN_AGC_CTRL 0x123C
-#define VDEC_B_DFE_CTRL1 0x1240
-#define VDEC_B_DFE_CTRL2 0x1244
-#define VDEC_B_DFE_CTRL3 0x1248
-#define VDEC_B_PLL_CTRL 0x124C
+#define VDEC_B_FIELD_COUNT 0x122C
+#define VDEC_B_HSCALE_CTRL 0x1230
+#define VDEC_B_VSCALE_CTRL 0x1234
+#define VDEC_B_MAN_VGA_CTRL 0x1238
+#define VDEC_B_MAN_AGC_CTRL 0x123C
+#define VDEC_B_DFE_CTRL1 0x1240
+#define VDEC_B_DFE_CTRL2 0x1244
+#define VDEC_B_DFE_CTRL3 0x1248
+#define VDEC_B_PLL_CTRL 0x124C
#define VDEC_B_PLL_CTRL_FAST 0x1250
-#define VDEC_B_HTL_CTRL 0x1254
-#define VDEC_B_SRC_CFG 0x1258
-#define VDEC_B_SC_STEP_SIZE 0x125C
+#define VDEC_B_HTL_CTRL 0x1254
+#define VDEC_B_SRC_CFG 0x1258
+#define VDEC_B_SC_STEP_SIZE 0x125C
#define VDEC_B_SC_CONVERGE_CTRL 0x1260
-#define VDEC_B_SC_LOOP_CTRL 0x1264
+#define VDEC_B_SC_LOOP_CTRL 0x1264
#define VDEC_B_COMB_2D_HFS_CFG 0x1268
#define VDEC_B_COMB_2D_HFD_CFG 0x126C
#define VDEC_B_COMB_2D_LF_CFG 0x1270
#define VDEC_B_COMB_2D_BLEND 0x1274
#define VDEC_B_COMB_MISC_CTRL 0x1278
-#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C
-#define VDEC_B_COMB_TEST 0x1280
-#define VDEC_B_BP_MISC_CTRL 0x1284
-#define VDEC_B_VCR_DET_CTRL 0x1288
+#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C
+#define VDEC_B_COMB_TEST 0x1280
+#define VDEC_B_BP_MISC_CTRL 0x1284
+#define VDEC_B_VCR_DET_CTRL 0x1288
#define VDEC_B_NOISE_DET_CTRL 0x128C
#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290
-#define VDEC_B_VERSION 0x13F8
+#define VDEC_B_VERSION 0x13F8
#define VDEC_B_SOFT_RST_CTRL 0x13FC
/* Video Decoder C Registers */
-#define VDEC_C_MODE_CTRL 0x1400
-#define VDEC_C_OUT_CTRL1 0x1404
-#define VDEC_C_OUT_CTRL_NS 0x1408
-#define VDEC_C_GEN_STAT 0x140C
+#define VDEC_C_MODE_CTRL 0x1400
+#define VDEC_C_OUT_CTRL1 0x1404
+#define VDEC_C_OUT_CTRL_NS 0x1408
+#define VDEC_C_GEN_STAT 0x140C
#define VDEC_C_INT_STAT_MASK 0x1410
-#define VDEC_C_LUMA_CTRL 0x1414
-#define VDEC_C_CHROMA_CTRL 0x1418
-#define VDEC_C_CRUSH_CTRL 0x141C
+#define VDEC_C_LUMA_CTRL 0x1414
+#define VDEC_C_CHROMA_CTRL 0x1418
+#define VDEC_C_CRUSH_CTRL 0x141C
#define VDEC_C_HORIZ_TIM_CTRL 0x1420
#define VDEC_C_VERT_TIM_CTRL 0x1424
#define VDEC_C_MISC_TIM_CTRL 0x1428
-#define VDEC_C_FIELD_COUNT 0x142C
-#define VDEC_C_HSCALE_CTRL 0x1430
-#define VDEC_C_VSCALE_CTRL 0x1434
-#define VDEC_C_MAN_VGA_CTRL 0x1438
-#define VDEC_C_MAN_AGC_CTRL 0x143C
-#define VDEC_C_DFE_CTRL1 0x1440
-#define VDEC_C_DFE_CTRL2 0x1444
-#define VDEC_C_DFE_CTRL3 0x1448
-#define VDEC_C_PLL_CTRL 0x144C
+#define VDEC_C_FIELD_COUNT 0x142C
+#define VDEC_C_HSCALE_CTRL 0x1430
+#define VDEC_C_VSCALE_CTRL 0x1434
+#define VDEC_C_MAN_VGA_CTRL 0x1438
+#define VDEC_C_MAN_AGC_CTRL 0x143C
+#define VDEC_C_DFE_CTRL1 0x1440
+#define VDEC_C_DFE_CTRL2 0x1444
+#define VDEC_C_DFE_CTRL3 0x1448
+#define VDEC_C_PLL_CTRL 0x144C
#define VDEC_C_PLL_CTRL_FAST 0x1450
-#define VDEC_C_HTL_CTRL 0x1454
-#define VDEC_C_SRC_CFG 0x1458
-#define VDEC_C_SC_STEP_SIZE 0x145C
+#define VDEC_C_HTL_CTRL 0x1454
+#define VDEC_C_SRC_CFG 0x1458
+#define VDEC_C_SC_STEP_SIZE 0x145C
#define VDEC_C_SC_CONVERGE_CTRL 0x1460
-#define VDEC_C_SC_LOOP_CTRL 0x1464
+#define VDEC_C_SC_LOOP_CTRL 0x1464
#define VDEC_C_COMB_2D_HFS_CFG 0x1468
#define VDEC_C_COMB_2D_HFD_CFG 0x146C
#define VDEC_C_COMB_2D_LF_CFG 0x1470
#define VDEC_C_COMB_2D_BLEND 0x1474
#define VDEC_C_COMB_MISC_CTRL 0x1478
-#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C
-#define VDEC_C_COMB_TEST 0x1480
-#define VDEC_C_BP_MISC_CTRL 0x1484
-#define VDEC_C_VCR_DET_CTRL 0x1488
+#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C
+#define VDEC_C_COMB_TEST 0x1480
+#define VDEC_C_BP_MISC_CTRL 0x1484
+#define VDEC_C_VCR_DET_CTRL 0x1488
#define VDEC_C_NOISE_DET_CTRL 0x148C
#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490
-#define VDEC_C_VERSION 0x15F8
+#define VDEC_C_VERSION 0x15F8
#define VDEC_C_SOFT_RST_CTRL 0x15FC
/* Video Decoder D Registers */
-#define VDEC_D_MODE_CTRL 0x1600
-#define VDEC_D_OUT_CTRL1 0x1604
-#define VDEC_D_OUT_CTRL_NS 0x1608
-#define VDEC_D_GEN_STAT 0x160C
+#define VDEC_D_MODE_CTRL 0x1600
+#define VDEC_D_OUT_CTRL1 0x1604
+#define VDEC_D_OUT_CTRL_NS 0x1608
+#define VDEC_D_GEN_STAT 0x160C
#define VDEC_D_INT_STAT_MASK 0x1610
-#define VDEC_D_LUMA_CTRL 0x1614
-#define VDEC_D_CHROMA_CTRL 0x1618
-#define VDEC_D_CRUSH_CTRL 0x161C
+#define VDEC_D_LUMA_CTRL 0x1614
+#define VDEC_D_CHROMA_CTRL 0x1618
+#define VDEC_D_CRUSH_CTRL 0x161C
#define VDEC_D_HORIZ_TIM_CTRL 0x1620
#define VDEC_D_VERT_TIM_CTRL 0x1624
#define VDEC_D_MISC_TIM_CTRL 0x1628
-#define VDEC_D_FIELD_COUNT 0x162C
-#define VDEC_D_HSCALE_CTRL 0x1630
-#define VDEC_D_VSCALE_CTRL 0x1634
-#define VDEC_D_MAN_VGA_CTRL 0x1638
-#define VDEC_D_MAN_AGC_CTRL 0x163C
-#define VDEC_D_DFE_CTRL1 0x1640
-#define VDEC_D_DFE_CTRL2 0x1644
-#define VDEC_D_DFE_CTRL3 0x1648
-#define VDEC_D_PLL_CTRL 0x164C
+#define VDEC_D_FIELD_COUNT 0x162C
+#define VDEC_D_HSCALE_CTRL 0x1630
+#define VDEC_D_VSCALE_CTRL 0x1634
+#define VDEC_D_MAN_VGA_CTRL 0x1638
+#define VDEC_D_MAN_AGC_CTRL 0x163C
+#define VDEC_D_DFE_CTRL1 0x1640
+#define VDEC_D_DFE_CTRL2 0x1644
+#define VDEC_D_DFE_CTRL3 0x1648
+#define VDEC_D_PLL_CTRL 0x164C
#define VDEC_D_PLL_CTRL_FAST 0x1650
-#define VDEC_D_HTL_CTRL 0x1654
-#define VDEC_D_SRC_CFG 0x1658
-#define VDEC_D_SC_STEP_SIZE 0x165C
+#define VDEC_D_HTL_CTRL 0x1654
+#define VDEC_D_SRC_CFG 0x1658
+#define VDEC_D_SC_STEP_SIZE 0x165C
#define VDEC_D_SC_CONVERGE_CTRL 0x1660
-#define VDEC_D_SC_LOOP_CTRL 0x1664
+#define VDEC_D_SC_LOOP_CTRL 0x1664
#define VDEC_D_COMB_2D_HFS_CFG 0x1668
#define VDEC_D_COMB_2D_HFD_CFG 0x166C
#define VDEC_D_COMB_2D_LF_CFG 0x1670
#define VDEC_D_COMB_2D_BLEND 0x1674
#define VDEC_D_COMB_MISC_CTRL 0x1678
-#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C
-#define VDEC_D_COMB_TEST 0x1680
-#define VDEC_D_BP_MISC_CTRL 0x1684
-#define VDEC_D_VCR_DET_CTRL 0x1688
+#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C
+#define VDEC_D_COMB_TEST 0x1680
+#define VDEC_D_BP_MISC_CTRL 0x1684
+#define VDEC_D_VCR_DET_CTRL 0x1688
#define VDEC_D_NOISE_DET_CTRL 0x168C
#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690
-#define VDEC_D_VERSION 0x17F8
+#define VDEC_D_VERSION 0x17F8
#define VDEC_D_SOFT_RST_CTRL 0x17FC
/* Video Decoder E Registers */
-#define VDEC_E_MODE_CTRL 0x1800
-#define VDEC_E_OUT_CTRL1 0x1804
-#define VDEC_E_OUT_CTRL_NS 0x1808
-#define VDEC_E_GEN_STAT 0x180C
+#define VDEC_E_MODE_CTRL 0x1800
+#define VDEC_E_OUT_CTRL1 0x1804
+#define VDEC_E_OUT_CTRL_NS 0x1808
+#define VDEC_E_GEN_STAT 0x180C
#define VDEC_E_INT_STAT_MASK 0x1810
-#define VDEC_E_LUMA_CTRL 0x1814
-#define VDEC_E_CHROMA_CTRL 0x1818
-#define VDEC_E_CRUSH_CTRL 0x181C
+#define VDEC_E_LUMA_CTRL 0x1814
+#define VDEC_E_CHROMA_CTRL 0x1818
+#define VDEC_E_CRUSH_CTRL 0x181C
#define VDEC_E_HORIZ_TIM_CTRL 0x1820
#define VDEC_E_VERT_TIM_CTRL 0x1824
#define VDEC_E_MISC_TIM_CTRL 0x1828
-#define VDEC_E_FIELD_COUNT 0x182C
-#define VDEC_E_HSCALE_CTRL 0x1830
-#define VDEC_E_VSCALE_CTRL 0x1834
-#define VDEC_E_MAN_VGA_CTRL 0x1838
-#define VDEC_E_MAN_AGC_CTRL 0x183C
-#define VDEC_E_DFE_CTRL1 0x1840
-#define VDEC_E_DFE_CTRL2 0x1844
-#define VDEC_E_DFE_CTRL3 0x1848
-#define VDEC_E_PLL_CTRL 0x184C
+#define VDEC_E_FIELD_COUNT 0x182C
+#define VDEC_E_HSCALE_CTRL 0x1830
+#define VDEC_E_VSCALE_CTRL 0x1834
+#define VDEC_E_MAN_VGA_CTRL 0x1838
+#define VDEC_E_MAN_AGC_CTRL 0x183C
+#define VDEC_E_DFE_CTRL1 0x1840
+#define VDEC_E_DFE_CTRL2 0x1844
+#define VDEC_E_DFE_CTRL3 0x1848
+#define VDEC_E_PLL_CTRL 0x184C
#define VDEC_E_PLL_CTRL_FAST 0x1850
-#define VDEC_E_HTL_CTRL 0x1854
-#define VDEC_E_SRC_CFG 0x1858
-#define VDEC_E_SC_STEP_SIZE 0x185C
+#define VDEC_E_HTL_CTRL 0x1854
+#define VDEC_E_SRC_CFG 0x1858
+#define VDEC_E_SC_STEP_SIZE 0x185C
#define VDEC_E_SC_CONVERGE_CTRL 0x1860
-#define VDEC_E_SC_LOOP_CTRL 0x1864
+#define VDEC_E_SC_LOOP_CTRL 0x1864
#define VDEC_E_COMB_2D_HFS_CFG 0x1868
#define VDEC_E_COMB_2D_HFD_CFG 0x186C
#define VDEC_E_COMB_2D_LF_CFG 0x1870
#define VDEC_E_COMB_2D_BLEND 0x1874
#define VDEC_E_COMB_MISC_CTRL 0x1878
-#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C
-#define VDEC_E_COMB_TEST 0x1880
-#define VDEC_E_BP_MISC_CTRL 0x1884
-#define VDEC_E_VCR_DET_CTRL 0x1888
+#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C
+#define VDEC_E_COMB_TEST 0x1880
+#define VDEC_E_BP_MISC_CTRL 0x1884
+#define VDEC_E_VCR_DET_CTRL 0x1888
#define VDEC_E_NOISE_DET_CTRL 0x188C
#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890
-#define VDEC_E_VERSION 0x19F8
+#define VDEC_E_VERSION 0x19F8
#define VDEC_E_SOFT_RST_CTRL 0x19FC
/* Video Decoder F Registers */
-#define VDEC_F_MODE_CTRL 0x1A00
-#define VDEC_F_OUT_CTRL1 0x1A04
-#define VDEC_F_OUT_CTRL_NS 0x1A08
-#define VDEC_F_GEN_STAT 0x1A0C
+#define VDEC_F_MODE_CTRL 0x1A00
+#define VDEC_F_OUT_CTRL1 0x1A04
+#define VDEC_F_OUT_CTRL_NS 0x1A08
+#define VDEC_F_GEN_STAT 0x1A0C
#define VDEC_F_INT_STAT_MASK 0x1A10
-#define VDEC_F_LUMA_CTRL 0x1A14
-#define VDEC_F_CHROMA_CTRL 0x1A18
-#define VDEC_F_CRUSH_CTRL 0x1A1C
+#define VDEC_F_LUMA_CTRL 0x1A14
+#define VDEC_F_CHROMA_CTRL 0x1A18
+#define VDEC_F_CRUSH_CTRL 0x1A1C
#define VDEC_F_HORIZ_TIM_CTRL 0x1A20
#define VDEC_F_VERT_TIM_CTRL 0x1A24
#define VDEC_F_MISC_TIM_CTRL 0x1A28
-#define VDEC_F_FIELD_COUNT 0x1A2C
-#define VDEC_F_HSCALE_CTRL 0x1A30
-#define VDEC_F_VSCALE_CTRL 0x1A34
-#define VDEC_F_MAN_VGA_CTRL 0x1A38
-#define VDEC_F_MAN_AGC_CTRL 0x1A3C
-#define VDEC_F_DFE_CTRL1 0x1A40
-#define VDEC_F_DFE_CTRL2 0x1A44
-#define VDEC_F_DFE_CTRL3 0x1A48
-#define VDEC_F_PLL_CTRL 0x1A4C
+#define VDEC_F_FIELD_COUNT 0x1A2C
+#define VDEC_F_HSCALE_CTRL 0x1A30
+#define VDEC_F_VSCALE_CTRL 0x1A34
+#define VDEC_F_MAN_VGA_CTRL 0x1A38
+#define VDEC_F_MAN_AGC_CTRL 0x1A3C
+#define VDEC_F_DFE_CTRL1 0x1A40
+#define VDEC_F_DFE_CTRL2 0x1A44
+#define VDEC_F_DFE_CTRL3 0x1A48
+#define VDEC_F_PLL_CTRL 0x1A4C
#define VDEC_F_PLL_CTRL_FAST 0x1A50
-#define VDEC_F_HTL_CTRL 0x1A54
-#define VDEC_F_SRC_CFG 0x1A58
-#define VDEC_F_SC_STEP_SIZE 0x1A5C
+#define VDEC_F_HTL_CTRL 0x1A54
+#define VDEC_F_SRC_CFG 0x1A58
+#define VDEC_F_SC_STEP_SIZE 0x1A5C
#define VDEC_F_SC_CONVERGE_CTRL 0x1A60
-#define VDEC_F_SC_LOOP_CTRL 0x1A64
+#define VDEC_F_SC_LOOP_CTRL 0x1A64
#define VDEC_F_COMB_2D_HFS_CFG 0x1A68
#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C
#define VDEC_F_COMB_2D_LF_CFG 0x1A70
#define VDEC_F_COMB_2D_BLEND 0x1A74
#define VDEC_F_COMB_MISC_CTRL 0x1A78
-#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C
-#define VDEC_F_COMB_TEST 0x1A80
-#define VDEC_F_BP_MISC_CTRL 0x1A84
-#define VDEC_F_VCR_DET_CTRL 0x1A88
+#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C
+#define VDEC_F_COMB_TEST 0x1A80
+#define VDEC_F_BP_MISC_CTRL 0x1A84
+#define VDEC_F_VCR_DET_CTRL 0x1A88
#define VDEC_F_NOISE_DET_CTRL 0x1A8C
#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90
-#define VDEC_F_VERSION 0x1BF8
+#define VDEC_F_VERSION 0x1BF8
#define VDEC_F_SOFT_RST_CTRL 0x1BFC
/* Video Decoder G Registers */
-#define VDEC_G_MODE_CTRL 0x1C00
-#define VDEC_G_OUT_CTRL1 0x1C04
-#define VDEC_G_OUT_CTRL_NS 0x1C08
-#define VDEC_G_GEN_STAT 0x1C0C
+#define VDEC_G_MODE_CTRL 0x1C00
+#define VDEC_G_OUT_CTRL1 0x1C04
+#define VDEC_G_OUT_CTRL_NS 0x1C08
+#define VDEC_G_GEN_STAT 0x1C0C
#define VDEC_G_INT_STAT_MASK 0x1C10
-#define VDEC_G_LUMA_CTRL 0x1C14
-#define VDEC_G_CHROMA_CTRL 0x1C18
-#define VDEC_G_CRUSH_CTRL 0x1C1C
+#define VDEC_G_LUMA_CTRL 0x1C14
+#define VDEC_G_CHROMA_CTRL 0x1C18
+#define VDEC_G_CRUSH_CTRL 0x1C1C
#define VDEC_G_HORIZ_TIM_CTRL 0x1C20
#define VDEC_G_VERT_TIM_CTRL 0x1C24
#define VDEC_G_MISC_TIM_CTRL 0x1C28
-#define VDEC_G_FIELD_COUNT 0x1C2C
-#define VDEC_G_HSCALE_CTRL 0x1C30
-#define VDEC_G_VSCALE_CTRL 0x1C34
-#define VDEC_G_MAN_VGA_CTRL 0x1C38
-#define VDEC_G_MAN_AGC_CTRL 0x1C3C
-#define VDEC_G_DFE_CTRL1 0x1C40
-#define VDEC_G_DFE_CTRL2 0x1C44
-#define VDEC_G_DFE_CTRL3 0x1C48
-#define VDEC_G_PLL_CTRL 0x1C4C
+#define VDEC_G_FIELD_COUNT 0x1C2C
+#define VDEC_G_HSCALE_CTRL 0x1C30
+#define VDEC_G_VSCALE_CTRL 0x1C34
+#define VDEC_G_MAN_VGA_CTRL 0x1C38
+#define VDEC_G_MAN_AGC_CTRL 0x1C3C
+#define VDEC_G_DFE_CTRL1 0x1C40
+#define VDEC_G_DFE_CTRL2 0x1C44
+#define VDEC_G_DFE_CTRL3 0x1C48
+#define VDEC_G_PLL_CTRL 0x1C4C
#define VDEC_G_PLL_CTRL_FAST 0x1C50
-#define VDEC_G_HTL_CTRL 0x1C54
-#define VDEC_G_SRC_CFG 0x1C58
-#define VDEC_G_SC_STEP_SIZE 0x1C5C
+#define VDEC_G_HTL_CTRL 0x1C54
+#define VDEC_G_SRC_CFG 0x1C58
+#define VDEC_G_SC_STEP_SIZE 0x1C5C
#define VDEC_G_SC_CONVERGE_CTRL 0x1C60
-#define VDEC_G_SC_LOOP_CTRL 0x1C64
+#define VDEC_G_SC_LOOP_CTRL 0x1C64
#define VDEC_G_COMB_2D_HFS_CFG 0x1C68
#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C
#define VDEC_G_COMB_2D_LF_CFG 0x1C70
#define VDEC_G_COMB_2D_BLEND 0x1C74
#define VDEC_G_COMB_MISC_CTRL 0x1C78
-#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C
-#define VDEC_G_COMB_TEST 0x1C80
-#define VDEC_G_BP_MISC_CTRL 0x1C84
-#define VDEC_G_VCR_DET_CTRL 0x1C88
+#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C
+#define VDEC_G_COMB_TEST 0x1C80
+#define VDEC_G_BP_MISC_CTRL 0x1C84
+#define VDEC_G_VCR_DET_CTRL 0x1C88
#define VDEC_G_NOISE_DET_CTRL 0x1C8C
#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90
-#define VDEC_G_VERSION 0x1DF8
+#define VDEC_G_VERSION 0x1DF8
#define VDEC_G_SOFT_RST_CTRL 0x1DFC
-/* Video Decoder H Registers */
-#define VDEC_H_MODE_CTRL 0x1E00
-#define VDEC_H_OUT_CTRL1 0x1E04
-#define VDEC_H_OUT_CTRL_NS 0x1E08
-#define VDEC_H_GEN_STAT 0x1E0C
+/* Video Decoder H Registers */
+#define VDEC_H_MODE_CTRL 0x1E00
+#define VDEC_H_OUT_CTRL1 0x1E04
+#define VDEC_H_OUT_CTRL_NS 0x1E08
+#define VDEC_H_GEN_STAT 0x1E0C
#define VDEC_H_INT_STAT_MASK 0x1E1E
-#define VDEC_H_LUMA_CTRL 0x1E14
-#define VDEC_H_CHROMA_CTRL 0x1E18
-#define VDEC_H_CRUSH_CTRL 0x1E1C
+#define VDEC_H_LUMA_CTRL 0x1E14
+#define VDEC_H_CHROMA_CTRL 0x1E18
+#define VDEC_H_CRUSH_CTRL 0x1E1C
#define VDEC_H_HORIZ_TIM_CTRL 0x1E20
#define VDEC_H_VERT_TIM_CTRL 0x1E24
#define VDEC_H_MISC_TIM_CTRL 0x1E28
-#define VDEC_H_FIELD_COUNT 0x1E2C
-#define VDEC_H_HSCALE_CTRL 0x1E30
-#define VDEC_H_VSCALE_CTRL 0x1E34
-#define VDEC_H_MAN_VGA_CTRL 0x1E38
-#define VDEC_H_MAN_AGC_CTRL 0x1E3C
-#define VDEC_H_DFE_CTRL1 0x1E40
-#define VDEC_H_DFE_CTRL2 0x1E44
-#define VDEC_H_DFE_CTRL3 0x1E48
-#define VDEC_H_PLL_CTRL 0x1E4C
+#define VDEC_H_FIELD_COUNT 0x1E2C
+#define VDEC_H_HSCALE_CTRL 0x1E30
+#define VDEC_H_VSCALE_CTRL 0x1E34
+#define VDEC_H_MAN_VGA_CTRL 0x1E38
+#define VDEC_H_MAN_AGC_CTRL 0x1E3C
+#define VDEC_H_DFE_CTRL1 0x1E40
+#define VDEC_H_DFE_CTRL2 0x1E44
+#define VDEC_H_DFE_CTRL3 0x1E48
+#define VDEC_H_PLL_CTRL 0x1E4C
#define VDEC_H_PLL_CTRL_FAST 0x1E50
-#define VDEC_H_HTL_CTRL 0x1E54
-#define VDEC_H_SRC_CFG 0x1E58
-#define VDEC_H_SC_STEP_SIZE 0x1E5C
+#define VDEC_H_HTL_CTRL 0x1E54
+#define VDEC_H_SRC_CFG 0x1E58
+#define VDEC_H_SC_STEP_SIZE 0x1E5C
#define VDEC_H_SC_CONVERGE_CTRL 0x1E60
-#define VDEC_H_SC_LOOP_CTRL 0x1E64
+#define VDEC_H_SC_LOOP_CTRL 0x1E64
#define VDEC_H_COMB_2D_HFS_CFG 0x1E68
#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C
#define VDEC_H_COMB_2D_LF_CFG 0x1E70
#define VDEC_H_COMB_2D_BLEND 0x1E74
#define VDEC_H_COMB_MISC_CTRL 0x1E78
-#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C
-#define VDEC_H_COMB_TEST 0x1E80
-#define VDEC_H_BP_MISC_CTRL 0x1E84
-#define VDEC_H_VCR_DET_CTRL 0x1E88
+#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C
+#define VDEC_H_COMB_TEST 0x1E80
+#define VDEC_H_BP_MISC_CTRL 0x1E84
+#define VDEC_H_VCR_DET_CTRL 0x1E88
#define VDEC_H_NOISE_DET_CTRL 0x1E8C
#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90
-#define VDEC_H_VERSION 0x1FF8
+#define VDEC_H_VERSION 0x1FF8
#define VDEC_H_SOFT_RST_CTRL 0x1FFC
/*****************************************************************************/
/* LUMA_CTRL register fields */
-#define VDEC_A_BRITE_CTRL 0x1014
+#define VDEC_A_BRITE_CTRL 0x1014
#define VDEC_A_CNTRST_CTRL 0x1015
#define VDEC_A_PEAK_SEL 0x1016
diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c
index fc780d0..298a68d 100644
--- a/drivers/media/video/cx25821/cx25821-medusa-video.c
+++ b/drivers/media/video/cx25821/cx25821-medusa-video.c
@@ -99,82 +99,67 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev)
for (i = 0; i < MAX_DECODERS; i++) {
/* set video format NTSC-M */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ MODE_CTRL + (0x200 * i), &tmp);
value &= 0xFFFFFFF0;
/* enable the fast locking mode bit[16] */
value |= 0x10001;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ MODE_CTRL + (0x200 * i), value);
/* resolution NTSC 720x480 */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x612D0074;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- HORIZ_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), value);
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VERT_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- VERT_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), value);
/* chroma subcarrier step size */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ SC_STEP_SIZE + (0x200 * i), 0x43E00000);
/* enable VIP optional active */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- OUT_CTRL_NS + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- OUT_CTRL_NS + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), value);
/* enable VIP optional active (VIP_OPT_AL) for direct output. */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL1 + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL1 + (0x200 * i), value);
/*
* clear VPRES_VERT_EN bit, fixes the chroma run away problem
* when the input switching rate < 16 fields
*/
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- MISC_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), &tmp);
/* disable special play detection */
value = setBitAtPos(value, 14);
value = clearBitAtPos(value, 15);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- MISC_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), value);
/* set vbi_gate_en to 0 */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DFE_CTRL1 + (0x200 * i), &tmp);
value = clearBitAtPos(value, 29);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DFE_CTRL1 + (0x200 * i), value);
/* Enable the generation of blue field output if no video */
medusa_enable_bluefield_output(dev, i, 1);
@@ -182,61 +167,49 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev)
for (i = 0; i < MAX_ENCODERS; i++) {
/* NTSC hclock */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_1 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), &tmp);
value &= 0xF000FC00;
value |= 0x06B402D0;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_1 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), value);
/* burst begin and burst end */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_2 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), &tmp);
value &= 0xFF000000;
value |= 0x007E9054;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_2 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), value);
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_3 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), &tmp);
value &= 0xFC00FE00;
value |= 0x00EC00F0;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_3 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), value);
/* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_4 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), &tmp);
value &= 0x00FCFFFF;
value |= 0x13020000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_4 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), value);
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_5 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), &tmp);
value &= 0xFFFF0000;
value |= 0x0000E575;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_5 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), value);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
/* Subcarrier Increment */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
}
/* set picture resolutions */
@@ -261,34 +234,27 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
u32 value = 0, tmp = 0;
/* Setup for 2D threshold */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec),
- 0x20002861);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec),
- 0x20002861);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec),
- 0x200A1023);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
/* Setup flat chroma and luma thresholds */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
value &= 0x06230000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
/* set comb 2D blend */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec),
- 0x210F0F0F);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
/* COMB MISC CONTROL */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec),
- 0x41120A7F);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
return ret_val;
}
@@ -304,83 +270,68 @@ static int medusa_initialize_pal(struct cx25821_dev *dev)
for (i = 0; i < MAX_DECODERS; i++) {
/* set video format PAL-BDGHI */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ MODE_CTRL + (0x200 * i), &tmp);
value &= 0xFFFFFFF0;
/* enable the fast locking mode bit[16] */
value |= 0x10004;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ MODE_CTRL + (0x200 * i), value);
/* resolution PAL 720x576 */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x632D007D;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- HORIZ_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ HORIZ_TIM_CTRL + (0x200 * i), value);
/* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VERT_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), &tmp);
value &= 0x00C00C00;
value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- VERT_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ VERT_TIM_CTRL + (0x200 * i), value);
/* chroma subcarrier step size */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
/* enable VIP optional active */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- OUT_CTRL_NS + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- OUT_CTRL_NS + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL_NS + (0x200 * i), value);
/* enable VIP optional active (VIP_OPT_AL) for direct output. */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ OUT_CTRL1 + (0x200 * i), &tmp);
value &= 0xFFFBFFFF;
value |= 0x00040000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ OUT_CTRL1 + (0x200 * i), value);
/*
* clear VPRES_VERT_EN bit, fixes the chroma run away problem
* when the input switching rate < 16 fields
*/
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- MISC_TIM_CTRL + (0x200 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), &tmp);
/* disable special play detection */
value = setBitAtPos(value, 14);
value = clearBitAtPos(value, 15);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- MISC_TIM_CTRL + (0x200 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ MISC_TIM_CTRL + (0x200 * i), value);
/* set vbi_gate_en to 0 */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
- &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DFE_CTRL1 + (0x200 * i), &tmp);
value = clearBitAtPos(value, 29);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i),
- value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DFE_CTRL1 + (0x200 * i), value);
medusa_PALCombInit(dev, i);
@@ -390,62 +341,50 @@ static int medusa_initialize_pal(struct cx25821_dev *dev)
for (i = 0; i < MAX_ENCODERS; i++) {
/* PAL hclock */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_1 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), &tmp);
value &= 0xF000FC00;
value |= 0x06C002D0;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_1 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_1 + (0x100 * i), value);
/* burst begin and burst end */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_2 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), &tmp);
value &= 0xFF000000;
value |= 0x007E9754;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_2 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_2 + (0x100 * i), value);
/* hblank and vactive */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_3 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), &tmp);
value &= 0xFC00FE00;
value |= 0x00FC0120;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_3 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_3 + (0x100 * i), value);
/* set PAL vblank, phase alternation, 0 IRE pedestal */
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_4 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), &tmp);
value &= 0x00FCFFFF;
value |= 0x14010000;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_4 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_4 + (0x100 * i), value);
- value =
- cx25821_i2c_read(&dev->i2c_bus[0],
- DENC_A_REG_5 + (0x100 * i), &tmp);
+ value = cx25821_i2c_read(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), &tmp);
value &= 0xFFFF0000;
value |= 0x0000F078;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_5 + (0x100 * i), value);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_5 + (0x100 * i), value);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
/* Subcarrier Increment */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
}
/* set picture resolutions */
@@ -499,7 +438,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width,
mutex_lock(&dev->lock);
- /* validate the width - cannot be negative */
+ /* validate the width */
if (width > MAX_WIDTH) {
pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
__func__, width, MAX_WIDTH);
@@ -543,12 +482,10 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width,
for (; decoder < decoder_count; decoder++) {
/* write scaling values for each decoder */
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- HSCALE_CTRL + (0x200 * decoder), hscale);
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0],
- VSCALE_CTRL + (0x200 * decoder), vscale);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ HSCALE_CTRL + (0x200 * decoder), hscale);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+ VSCALE_CTRL + (0x200 * decoder), vscale);
}
mutex_unlock(&dev->lock);
@@ -606,8 +543,8 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
}
/* Map to Medusa register setting */
-static int mapM(int srcMin,
- int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal)
+static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
+ int *dstVal)
{
int numerator;
int denominator;
@@ -654,23 +591,19 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
u32 val = 0, tmp = 0;
mutex_lock(&dev->lock);
- if ((brightness > VIDEO_PROCAMP_MAX)
- || (brightness < VIDEO_PROCAMP_MIN)) {
+ if ((brightness > VIDEO_PROCAMP_MAX) ||
+ (brightness < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
- ret_val =
- mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
- SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+ ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+ SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
value = convert_to_twos(value, 8);
- val =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+ val = cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
- ret_val |=
- cx25821_i2c_write(&dev->i2c_bus[0],
- VDEC_A_BRITE_CTRL + (0x200 * decoder),
- val | value);
+ ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
mutex_unlock(&dev->lock);
return ret_val;
}
@@ -688,17 +621,13 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
return -1;
}
- ret_val =
- mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
- UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
- val =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+ ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+ UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+ val = cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
- ret_val |=
- cx25821_i2c_write(&dev->i2c_bus[0],
- VDEC_A_CNTRST_CTRL + (0x200 * decoder),
- val | value);
+ ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
mutex_unlock(&dev->lock);
return ret_val;
@@ -717,19 +646,16 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
return -1;
}
- ret_val =
- mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN,
- SIGNED_BYTE_MAX, &value);
+ ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
+ SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
value = convert_to_twos(value, 8);
- val =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+ val = cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
- ret_val |=
- cx25821_i2c_write(&dev->i2c_bus[0],
- VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+ ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
mutex_unlock(&dev->lock);
return ret_val;
@@ -743,33 +669,26 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
mutex_lock(&dev->lock);
- if ((saturation > VIDEO_PROCAMP_MAX)
- || (saturation < VIDEO_PROCAMP_MIN)) {
+ if ((saturation > VIDEO_PROCAMP_MAX) ||
+ (saturation < VIDEO_PROCAMP_MIN)) {
mutex_unlock(&dev->lock);
return -1;
}
- ret_val =
- mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
- UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+ ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+ UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
- val =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+ val = cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
- ret_val |=
- cx25821_i2c_write(&dev->i2c_bus[0],
- VDEC_A_USAT_CTRL + (0x200 * decoder),
- val | value);
-
- val =
- cx25821_i2c_read(&dev->i2c_bus[0],
- VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+ ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
+
+ val = cx25821_i2c_read(&dev->i2c_bus[0],
+ VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
val &= 0xFFFFFF00;
- ret_val |=
- cx25821_i2c_write(&dev->i2c_bus[0],
- VDEC_A_VSAT_CTRL + (0x200 * decoder),
- val | value);
+ ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+ VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
mutex_unlock(&dev->lock);
return ret_val;
@@ -830,9 +749,8 @@ int medusa_video_init(struct cx25821_dev *dev)
/* select AFE clock to output mode */
value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
value &= 0x83FFFFFF;
- ret_val =
- cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
- value | 0x10000000);
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+ value | 0x10000000);
if (ret_val < 0)
goto error;
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
index 2a724dd..5a157cf 100644
--- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
+++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
@@ -65,9 +65,8 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
- if ((lines <= NTSC_FIELD_HEIGHT)
- || (line < (NTSC_FIELD_HEIGHT - 1))
- || !(dev->_isNTSC_ch2)) {
+ if ((lines <= NTSC_FIELD_HEIGHT) ||
+ (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
offset += dist_betwn_starts;
}
}
@@ -85,7 +84,7 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
{
unsigned int line, i;
struct sram_channel *sram_ch =
- dev->channels[dev->_channel2_upstream_select].sram_channels;
+ dev->channels[dev->_channel2_upstream_select].sram_channels;
int dist_betwn_starts = bpl * 2;
/* sync instruction */
@@ -103,9 +102,8 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
- if ((lines <= NTSC_FIELD_HEIGHT)
- || (line < (NTSC_FIELD_HEIGHT - 1))
- || !(dev->_isNTSC_ch2)) {
+ if ((lines <= NTSC_FIELD_HEIGHT) ||
+ (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
offset += dist_betwn_starts;
}
@@ -173,7 +171,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
fifo_enable = FIFO_DISABLE;
- /* Even field */
+ /* Even field */
rp = cx25821_risc_field_upstream_ch2(dev, rp,
dev->_data_buf_phys_addr_ch2 + databuf_offset,
bottom_offset, 0x200, bpl, singlefield_lines,
@@ -189,9 +187,9 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
}
/*
- Loop to 2ndFrameRISC or to Start of
- Risc program & generate IRQ
- */
+ * Loop to 2ndFrameRISC or to Start of
+ * Risc program & generate IRQ
+ */
*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
*(rp++) = cpu_to_le32(risc_phys_jump_addr);
*(rp++) = cpu_to_le32(0);
@@ -203,7 +201,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
{
struct sram_channel *sram_ch =
- dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+ dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
u32 tmp = 0;
if (!dev->_is_running_ch2) {
@@ -262,9 +260,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
struct file *myfile;
int frame_index_temp = dev->_frame_index_ch2;
int i = 0;
- int line_size =
- (dev->_pixel_format_ch2 ==
- PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+ Y411_LINE_SZ : Y422_LINE_SZ;
int frame_size = 0;
int frame_offset = 0;
ssize_t vfs_read_retval = 0;
@@ -277,14 +274,11 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
return 0;
if (dev->_isNTSC_ch2) {
- frame_size =
- (line_size ==
- Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
- FRAME_SIZE_NTSC_Y422;
+ frame_size = (line_size == Y411_LINE_SZ) ?
+ FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
} else {
- frame_size =
- (line_size ==
- Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ frame_size = (line_size == Y411_LINE_SZ) ?
+ FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
}
frame_offset = (frame_index_temp > 0) ? frame_size : 0;
@@ -318,14 +312,14 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
for (i = 0; i < dev->_lines_count_ch2; i++) {
pos = file_offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+ &pos);
if (vfs_read_retval > 0 && vfs_read_retval == line_size
&& dev->_data_buf_virt_addr_ch2 != NULL) {
memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
frame_offset / 4), mybuf,
- vfs_read_retval);
+ vfs_read_retval);
}
file_offset += vfs_read_retval;
@@ -341,8 +335,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
if (i > 0)
dev->_frame_count_ch2++;
- dev->_file_status_ch2 =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
filp_close(myfile, NULL);
@@ -353,8 +347,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
static void cx25821_vidups_handler_ch2(struct work_struct *work)
{
- struct cx25821_dev *dev =
- container_of(work, struct cx25821_dev, _irq_work_entry_ch2);
+ struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+ _irq_work_entry_ch2);
if (!dev) {
pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
@@ -362,18 +356,16 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work)
return;
}
- cx25821_get_frame_ch2(dev,
- dev->channels[dev->
- _channel2_upstream_select].sram_channels);
+ cx25821_get_frame_ch2(dev, dev->channels[dev->
+ _channel2_upstream_select].sram_channels);
}
int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
{
struct file *myfile;
int i = 0, j = 0;
- int line_size =
- (dev->_pixel_format_ch2 ==
- PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+ Y411_LINE_SZ : Y422_LINE_SZ;
ssize_t vfs_read_retval = 0;
char mybuf[line_size];
loff_t pos;
@@ -410,16 +402,16 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
for (i = 0; i < dev->_lines_count_ch2; i++) {
pos = offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf,
+ line_size, &pos);
- if (vfs_read_retval > 0
- && vfs_read_retval == line_size
- && dev->_data_buf_virt_addr_ch2 != NULL) {
+ if (vfs_read_retval > 0 &&
+ vfs_read_retval == line_size &&
+ dev->_data_buf_virt_addr_ch2 != NULL) {
memcpy((void *)(dev->
_data_buf_virt_addr_ch2
+ offset / 4), mybuf,
- vfs_read_retval);
+ vfs_read_retval);
}
offset += vfs_read_retval;
@@ -438,8 +430,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
break;
}
- dev->_file_status_ch2 =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
myfile->f_pos = 0;
@@ -463,9 +455,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
dev->_dma_phys_addr_ch2);
}
- dev->_dma_virt_addr_ch2 =
- pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
- &dma_addr);
+ dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+ dev->upstream_riscbuf_size_ch2, &dma_addr);
dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
dev->_dma_phys_start_addr_ch2 = dma_addr;
dev->_dma_phys_addr_ch2 = dma_addr;
@@ -485,9 +476,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
dev->_data_buf_phys_addr_ch2);
}
/* For Video Data buffer allocation */
- dev->_data_buf_virt_addr_ch2 =
- pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2,
- &data_dma_addr);
+ dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+ dev->upstream_databuf_size_ch2, &data_dma_addr);
dev->_data_buf_phys_addr_ch2 = data_dma_addr;
dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
@@ -563,8 +553,8 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
else
line_size_in_bytes = Y422_LINE_SZ;
risc_phys_jump_addr =
- dev->_dma_phys_start_addr_ch2 +
- odd_risc_prog_size;
+ dev->_dma_phys_start_addr_ch2 +
+ odd_risc_prog_size;
rp = cx25821_update_riscprogram_ch2(dev,
dev->_dma_virt_start_addr_ch2,
@@ -612,11 +602,9 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
vid_status = cx_read(sram_ch->int_stat);
/* Only deal with our interrupt */
- if (vid_status) {
- handled =
- cx25821_video_upstream_irq_ch2(dev, channel_num,
- vid_status);
- }
+ if (vid_status)
+ handled = cx25821_video_upstream_irq_ch2(dev, channel_num,
+ vid_status);
if (handled < 0)
cx25821_stop_upstream_video_ch2(dev);
@@ -691,8 +679,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
tmp = cx_read(sram_ch->int_msk);
cx_write(sram_ch->int_msk, tmp |= _intr_msk);
- err =
- request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+ err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get upstream IRQ %d\n",
@@ -752,45 +739,38 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
dev->_file_status_ch2 = RESET_STATUS;
dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
dev->_pixel_format_ch2 = pixel_format;
- dev->_line_size_ch2 =
- (dev->_pixel_format_ch2 ==
- PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+ dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ?
+ (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
- risc_buffer_size =
- dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+ risc_buffer_size = dev->_isNTSC_ch2 ?
+ NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
if (dev->input_filename_ch2) {
str_length = strlen(dev->input_filename_ch2);
- dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
+ str_length + 1, GFP_KERNEL);
if (!dev->_filename_ch2)
goto error;
-
- memcpy(dev->_filename_ch2, dev->input_filename_ch2,
- str_length + 1);
} else {
str_length = strlen(dev->_defaultname_ch2);
- dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
+ str_length + 1, GFP_KERNEL);
if (!dev->_filename_ch2)
goto error;
-
- memcpy(dev->_filename_ch2, dev->_defaultname_ch2,
- str_length + 1);
}
/* Default if filename is empty string */
if (strcmp(dev->input_filename_ch2, "") == 0) {
if (dev->_isNTSC_ch2) {
- dev->_filename_ch2 =
- (dev->_pixel_format_ch2 ==
- PIXEL_FRMT_411) ? "/root/vid411.yuv" :
- "/root/vidtest.yuv";
+ dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+ "/root/vidtest.yuv";
} else {
- dev->_filename_ch2 =
- (dev->_pixel_format_ch2 ==
- PIXEL_FRMT_411) ? "/root/pal411.yuv" :
- "/root/pal422.yuv";
+ dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+ PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+ "/root/pal422.yuv";
}
}
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c
index c0b8006..21e7d65 100644
--- a/drivers/media/video/cx25821/cx25821-video-upstream.c
+++ b/drivers/media/video/cx25821/cx25821-video-upstream.c
@@ -136,7 +136,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
{
unsigned int line, i;
struct sram_channel *sram_ch =
- dev->channels[dev->_channel_upstream_select].sram_channels;
+ dev->channels[dev->_channel_upstream_select].sram_channels;
int dist_betwn_starts = bpl * 2;
/* sync instruction */
@@ -194,15 +194,12 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
if (dev->_isNTSC) {
odd_num_lines = singlefield_lines + 1;
risc_program_size = FRAME1_VID_PROG_SIZE;
- frame_size =
- (bpl ==
- Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
- FRAME_SIZE_NTSC_Y422;
+ frame_size = (bpl == Y411_LINE_SZ) ?
+ FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
} else {
risc_program_size = PAL_VID_PROG_SIZE;
- frame_size =
- (bpl ==
- Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+ frame_size = (bpl == Y411_LINE_SZ) ?
+ FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
}
/* Virtual address of Risc buffer program */
@@ -214,13 +211,9 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
if (UNSET != top_offset) {
fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
rp = cx25821_risc_field_upstream(dev, rp,
- dev->
- _data_buf_phys_addr +
- databuf_offset,
- top_offset, 0, bpl,
- odd_num_lines,
- fifo_enable,
- ODD_FIELD);
+ dev->_data_buf_phys_addr +
+ databuf_offset, top_offset, 0, bpl,
+ odd_num_lines, fifo_enable, ODD_FIELD);
}
fifo_enable = FIFO_DISABLE;
@@ -234,8 +227,8 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
if (frame == 0) {
risc_flag = RISC_CNT_RESET;
- risc_phys_jump_addr =
- dev->_dma_phys_start_addr + risc_program_size;
+ risc_phys_jump_addr = dev->_dma_phys_start_addr +
+ risc_program_size;
} else {
risc_phys_jump_addr = dev->_dma_phys_start_addr;
risc_flag = RISC_CNT_INC;
@@ -255,7 +248,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
{
struct sram_channel *sram_ch =
- dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+ dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
u32 tmp = 0;
if (!dev->_is_running) {
@@ -312,9 +305,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
struct file *myfile;
int frame_index_temp = dev->_frame_index;
int i = 0;
- int line_size =
- (dev->_pixel_format ==
- PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+ Y411_LINE_SZ : Y422_LINE_SZ;
int frame_size = 0;
int frame_offset = 0;
ssize_t vfs_read_retval = 0;
@@ -326,16 +318,12 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
if (dev->_file_status == END_OF_FILE)
return 0;
- if (dev->_isNTSC) {
- frame_size =
- (line_size ==
- Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 :
- FRAME_SIZE_NTSC_Y422;
- } else {
- frame_size =
- (line_size ==
- Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
- }
+ if (dev->_isNTSC)
+ frame_size = (line_size == Y411_LINE_SZ) ?
+ FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+ else
+ frame_size = (line_size == Y411_LINE_SZ) ?
+ FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
frame_offset = (frame_index_temp > 0) ? frame_size : 0;
file_offset = dev->_frame_count * frame_size;
@@ -369,8 +357,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
for (i = 0; i < dev->_lines_count; i++) {
pos = file_offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+ &pos);
if (vfs_read_retval > 0 && vfs_read_retval == line_size
&& dev->_data_buf_virt_addr != NULL) {
@@ -392,8 +380,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
if (i > 0)
dev->_frame_count++;
- dev->_file_status =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_file_status = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
filp_close(myfile, NULL);
@@ -404,8 +392,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
static void cx25821_vidups_handler(struct work_struct *work)
{
- struct cx25821_dev *dev =
- container_of(work, struct cx25821_dev, _irq_work_entry);
+ struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+ _irq_work_entry);
if (!dev) {
pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
@@ -413,18 +401,16 @@ static void cx25821_vidups_handler(struct work_struct *work)
return;
}
- cx25821_get_frame(dev,
- dev->channels[dev->_channel_upstream_select].
- sram_channels);
+ cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
+ sram_channels);
}
int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
{
struct file *myfile;
int i = 0, j = 0;
- int line_size =
- (dev->_pixel_format ==
- PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;
+ int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+ Y411_LINE_SZ : Y422_LINE_SZ;
ssize_t vfs_read_retval = 0;
char mybuf[line_size];
loff_t pos;
@@ -461,8 +447,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
for (i = 0; i < dev->_lines_count; i++) {
pos = offset;
- vfs_read_retval =
- vfs_read(myfile, mybuf, line_size, &pos);
+ vfs_read_retval = vfs_read(myfile, mybuf,
+ line_size, &pos);
if (vfs_read_retval > 0
&& vfs_read_retval == line_size
@@ -489,8 +475,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
break;
}
- dev->_file_status =
- (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;
+ dev->_file_status = (vfs_read_retval == line_size) ?
+ IN_PROGRESS : END_OF_FILE;
set_fs(old_fs);
myfile->f_pos = 0;
@@ -507,14 +493,12 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
dma_addr_t dma_addr;
dma_addr_t data_dma_addr;
- if (dev->_dma_virt_addr != NULL) {
+ if (dev->_dma_virt_addr != NULL)
pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
- dev->_dma_virt_addr, dev->_dma_phys_addr);
- }
+ dev->_dma_virt_addr, dev->_dma_phys_addr);
- dev->_dma_virt_addr =
- pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size,
- &dma_addr);
+ dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
+ dev->upstream_riscbuf_size, &dma_addr);
dev->_dma_virt_start_addr = dev->_dma_virt_addr;
dev->_dma_phys_start_addr = dma_addr;
dev->_dma_phys_addr = dma_addr;
@@ -528,15 +512,13 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
/* Clear memory at address */
memset(dev->_dma_virt_addr, 0, dev->_risc_size);
- if (dev->_data_buf_virt_addr != NULL) {
+ if (dev->_data_buf_virt_addr != NULL)
pci_free_consistent(dev->pci, dev->upstream_databuf_size,
- dev->_data_buf_virt_addr,
- dev->_data_buf_phys_addr);
- }
+ dev->_data_buf_virt_addr,
+ dev->_data_buf_phys_addr);
/* For Video Data buffer allocation */
- dev->_data_buf_virt_addr =
- pci_alloc_consistent(dev->pci, dev->upstream_databuf_size,
- &data_dma_addr);
+ dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
+ dev->upstream_databuf_size, &data_dma_addr);
dev->_data_buf_phys_addr = data_dma_addr;
dev->_data_buf_size = dev->upstream_databuf_size;
@@ -553,9 +535,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
return ret;
/* Create RISC programs */
- ret =
- cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
- dev->_lines_count);
+ ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+ dev->_lines_count);
if (ret < 0) {
pr_info("Failed creating Video Upstream Risc programs!\n");
goto error;
@@ -672,10 +653,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
vid_status = cx_read(sram_ch->int_stat);
/* Only deal with our interrupt */
- if (vid_status) {
- handled =
- cx25821_video_upstream_irq(dev, channel_num, vid_status);
- }
+ if (vid_status)
+ handled = cx25821_video_upstream_irq(dev, channel_num,
+ vid_status);
if (handled < 0)
cx25821_stop_upstream_video_ch1(dev);
@@ -747,8 +727,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
tmp = cx_read(sram_ch->int_msk);
cx_write(sram_ch->int_msk, tmp |= _intr_msk);
- err =
- request_irq(dev->pci->irq, cx25821_upstream_irq,
+ err = request_irq(dev->pci->irq, cx25821_upstream_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get upstream IRQ %d\n",
@@ -807,43 +786,38 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
dev->_file_status = RESET_STATUS;
dev->_lines_count = dev->_isNTSC ? 480 : 576;
dev->_pixel_format = pixel_format;
- dev->_line_size =
- (dev->_pixel_format ==
- PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+ dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+ (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
- risc_buffer_size =
- dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+ risc_buffer_size = dev->_isNTSC ?
+ NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
if (dev->input_filename) {
str_length = strlen(dev->input_filename);
- dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_filename = kmemdup(dev->input_filename, str_length + 1,
+ GFP_KERNEL);
if (!dev->_filename)
goto error;
-
- memcpy(dev->_filename, dev->input_filename, str_length + 1);
} else {
str_length = strlen(dev->_defaultname);
- dev->_filename = kmalloc(str_length + 1, GFP_KERNEL);
+ dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
+ GFP_KERNEL);
if (!dev->_filename)
goto error;
-
- memcpy(dev->_filename, dev->_defaultname, str_length + 1);
}
/* Default if filename is empty string */
if (strcmp(dev->input_filename, "") == 0) {
if (dev->_isNTSC) {
dev->_filename =
- (dev->_pixel_format ==
- PIXEL_FRMT_411) ? "/root/vid411.yuv" :
- "/root/vidtest.yuv";
+ (dev->_pixel_format == PIXEL_FRMT_411) ?
+ "/root/vid411.yuv" : "/root/vidtest.yuv";
} else {
dev->_filename =
- (dev->_pixel_format ==
- PIXEL_FRMT_411) ? "/root/pal411.yuv" :
- "/root/pal422.yuv";
+ (dev->_pixel_format == PIXEL_FRMT_411) ?
+ "/root/pal411.yuv" : "/root/pal422.yuv";
}
}
@@ -852,13 +826,11 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
dev->_file_status = RESET_STATUS;
dev->_lines_count = dev->_isNTSC ? 480 : 576;
dev->_pixel_format = pixel_format;
- dev->_line_size =
- (dev->_pixel_format ==
- PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+ dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+ (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
- retval =
- cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size,
- 0);
+ retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+ dev->_line_size, 0);
/* setup fifo + format */
cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c
index 4d6907c..ffd8bc7 100644
--- a/drivers/media/video/cx25821/cx25821-video.c
+++ b/drivers/media/video/cx25821/cx25821-video.c
@@ -118,12 +118,12 @@ void cx25821_dump_video_queue(struct cx25821_dev *dev,
if (!list_empty(&q->active)) {
list_for_each(item, &q->active)
- buf = list_entry(item, struct cx25821_buffer, vb.queue);
+ buf = list_entry(item, struct cx25821_buffer, vb.queue);
}
if (!list_empty(&q->queued)) {
list_for_each(item, &q->queued)
- buf = list_entry(item, struct cx25821_buffer, vb.queue);
+ buf = list_entry(item, struct cx25821_buffer, vb.queue);
}
}
@@ -140,8 +140,8 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
break;
}
- buf =
- list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx25821_buffer,
+ vb.queue);
/* count comes from the hw and it is 16bit wide --
* this trick handles wrap-arounds correctly for
@@ -318,8 +318,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
struct list_head *item;
if (!list_empty(&q->active)) {
- buf =
- list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx25821_buffer,
+ vb.queue);
cx25821_start_video_dma(dev, q, buf, channel);
@@ -337,8 +337,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev,
if (list_empty(&q->queued))
return 0;
- buf =
- list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+ buf = list_entry(q->queued.next, struct cx25821_buffer,
+ vb.queue);
if (NULL == prev) {
list_move_tail(&buf->vb.queue, &q->active);
@@ -375,8 +375,8 @@ void cx25821_vid_timeout(unsigned long data)
spin_lock_irqsave(&dev->slock, flags);
while (!list_empty(&q->active)) {
- buf =
- list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx25821_buffer,
+ vb.queue);
list_del(&buf->vb.queue);
buf->vb.state = VIDEOBUF_ERROR;
@@ -484,8 +484,7 @@ int cx25821_video_register(struct cx25821_dev *dev)
cx25821_init_controls(dev, i);
cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
- dev->channels[i].sram_channels->dma_ctl,
- 0x11, 0);
+ dev->channels[i].sram_channels->dma_ctl, 0x11, 0);
dev->channels[i].sram_channels = &cx25821_sram_channels[i];
dev->channels[i].video_dev = NULL;
@@ -499,15 +498,14 @@ int cx25821_video_register(struct cx25821_dev *dev)
dev->channels[i].timeout_data.dev = dev;
dev->channels[i].timeout_data.channel =
&cx25821_sram_channels[i];
- dev->channels[i].vidq.timeout.function =
- cx25821_vid_timeout;
+ dev->channels[i].vidq.timeout.function = cx25821_vid_timeout;
dev->channels[i].vidq.timeout.data =
(unsigned long)&dev->channels[i].timeout_data;
init_timer(&dev->channels[i].vidq.timeout);
/* register v4l devices */
- dev->channels[i].video_dev = cx25821_vdev_init(dev,
- dev->pci, &cx25821_video_device, "video");
+ dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci,
+ &cx25821_video_device, "video");
err = video_register_device(dev->channels[i].video_dev,
VFL_TYPE_GRABBER, video_nr[dev->nr]);
@@ -528,7 +526,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
#endif
mutex_unlock(&dev->lock);
-
return 0;
fail_unreg:
@@ -558,7 +555,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct cx25821_fh *fh = q->priv_data;
struct cx25821_dev *dev = fh->dev;
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vb, struct cx25821_buffer, vb);
int rc, init_buffer = 0;
u32 line0_offset, line1_offset;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
@@ -617,14 +614,13 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (channel_opened >= 0 && channel_opened <= 7) {
if (dev->channels[channel_opened]
.use_cif_resolution) {
- if (dev->tvnorm & V4L2_STD_PAL_BG
- || dev->tvnorm & V4L2_STD_PAL_DK)
+ if (dev->tvnorm & V4L2_STD_PAL_BG ||
+ dev->tvnorm & V4L2_STD_PAL_DK)
bpl_local = 352 << 1;
else
- bpl_local =
- dev->channels[channel_opened].
- cif_width <<
- 1;
+ bpl_local = dev->channels[
+ channel_opened].
+ cif_width << 1;
}
}
}
@@ -685,7 +681,7 @@ void cx25821_buffer_release(struct videobuf_queue *q,
struct videobuf_buffer *vb)
{
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vb, struct cx25821_buffer, vb);
cx25821_free_buffer(q, buf);
}
@@ -723,7 +719,7 @@ int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
struct cx25821_buffer *buf =
- container_of(vb, struct cx25821_buffer, vb);
+ container_of(vb, struct cx25821_buffer, vb);
struct cx25821_buffer *prev;
struct cx25821_fh *fh = vq->priv_data;
struct cx25821_dev *dev = fh->dev;
@@ -814,7 +810,7 @@ static int video_open(struct file *file)
for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
if (h->channels[i].video_dev &&
- h->channels[i].video_dev->minor == minor) {
+ h->channels[i].video_dev->minor == minor) {
dev = h;
ch_id = i;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -848,11 +844,10 @@ static int video_open(struct file *file)
v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
- videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct cx25821_buffer), fh, NULL);
+ videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev,
+ &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
+ fh, NULL);
dprintk(1, "post videobuf_queue_init()\n");
mutex_unlock(&cx25821_devlist_mutex);
@@ -1168,8 +1163,8 @@ int cx25821_vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->version = CX25821_VERSION_CODE;
- cap->capabilities =
- V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING;
if (UNSET != dev->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
@@ -1454,38 +1449,38 @@ static const struct v4l2_queryctrl no_ctl = {
static struct v4l2_queryctrl cx25821_ctls[] = {
/* --- video --- */
{
- .id = V4L2_CID_BRIGHTNESS,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 10000,
- .step = 1,
- .default_value = 6200,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }, {
- .id = V4L2_CID_CONTRAST,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 10000,
- .step = 1,
- .default_value = 5000,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }, {
- .id = V4L2_CID_SATURATION,
- .name = "Saturation",
- .minimum = 0,
- .maximum = 10000,
- .step = 1,
- .default_value = 5000,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }, {
- .id = V4L2_CID_HUE,
- .name = "Hue",
- .minimum = 0,
- .maximum = 10000,
- .step = 1,
- .default_value = 5000,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }
+ .id = V4L2_CID_BRIGHTNESS,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 6200,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }, {
+ .id = V4L2_CID_HUE,
+ .name = "Hue",
+ .minimum = 0,
+ .maximum = 10000,
+ .step = 1,
+ .default_value = 5000,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ }
};
static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
@@ -1623,7 +1618,8 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv,
if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
cropcap->bounds.width = 720;
cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
cropcap->pixelaspect.numerator =
@@ -1829,8 +1825,11 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
struct downstream_user_struct *data_from_user;
int command;
int width = 720;
- int selected_channel = 0, pix_format = 0, i = 0;
- int cif_enable = 0, cif_width = 0;
+ int selected_channel = 0;
+ int pix_format = 0;
+ int i = 0;
+ int cif_enable = 0;
+ int cif_width = 0;
u32 value = 0;
data_from_user = (struct downstream_user_struct *)arg;
@@ -1895,8 +1894,8 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
}
if (selected_channel <= 7 && selected_channel >= 0) {
- dev->channels[selected_channel].
- use_cif_resolution = cif_enable;
+ dev->channels[selected_channel].use_cif_resolution =
+ cif_enable;
dev->channels[selected_channel].cif_width = width;
} else {
for (i = 0; i < VID_CHANNEL_NUM; i++) {
@@ -1932,9 +1931,9 @@ static long video_ioctl_set(struct file *file, unsigned int cmd,
static long cx25821_video_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
- int ret = 0;
+ int ret = 0;
- struct cx25821_fh *fh = file->private_data;
+ struct cx25821_fh *fh = file->private_data;
/* check to see if it's the video upstream */
if (fh->channel_id == SRAM_CH09) {
diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h
index 2d2d009..b9aa801 100644
--- a/drivers/media/video/cx25821/cx25821.h
+++ b/drivers/media/video/cx25821/cx25821.h
@@ -67,7 +67,7 @@
#define MAX_CAMERAS 16
/* Max number of inputs by card */
-#define MAX_CX25821_INPUT 8
+#define MAX_CX25821_INPUT 8
#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
#define RESOURCE_VIDEO0 1
#define RESOURCE_VIDEO1 2
@@ -85,7 +85,7 @@
#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */
-#define UNKNOWN_BOARD 0
+#define UNKNOWN_BOARD 0
#define CX25821_BOARD 1
/* Currently supported by the driver */
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 005f110..34b96c7 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -480,7 +480,6 @@ void cx25840_audio_set_path(struct i2c_client *client)
static void set_volume(struct i2c_client *client, int volume)
{
- struct cx25840_state *state = to_state(i2c_get_clientdata(client));
int vol;
/* Convert the volume to msp3400 values (0-127) */
@@ -496,14 +495,7 @@ static void set_volume(struct i2c_client *client, int volume)
}
/* PATH1_VOLUME */
- if (is_cx2388x(state)) {
- /* for cx23885 volume doesn't work,
- * the calculation always results in
- * e4 regardless.
- */
- cx25840_write(client, 0x8d4, volume);
- } else
- cx25840_write(client, 0x8d4, 228 - (vol * 2));
+ cx25840_write(client, 0x8d4, 228 - (vol * 2));
}
static void set_balance(struct i2c_client *client, int balance)
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index cd99764..05247d4 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -18,6 +18,9 @@
* CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
* Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
*
+ * CX23888 DIF support for the HVR1850
+ * Copyright (C) 2011 Steven Toth <stoth@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
@@ -40,6 +43,7 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/math64.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/cx25840.h>
@@ -80,6 +84,7 @@ MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
/* ----------------------------------------------------------------------- */
+static void cx23885_std_setup(struct i2c_client *client);
int cx25840_write(struct i2c_client *client, u16 addr, u8 value)
{
@@ -498,8 +503,13 @@ static void cx23885_initialize(struct i2c_client *client)
* 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz
* 572.73 MHz before post divide
*/
- cx25840_write4(client, 0x11c, 0x00e8ba26);
- cx25840_write4(client, 0x118, 0x0000040b);
+ /* HVR1850 or 50MHz xtal */
+ cx25840_write(client, 0x2, 0x71);
+ cx25840_write4(client, 0x11c, 0x01d1744c);
+ cx25840_write4(client, 0x118, 0x00000416);
+ cx25840_write4(client, 0x404, 0x0010253e);
+ cx25840_write4(client, 0x42c, 0x42600000);
+ cx25840_write4(client, 0x44c, 0x161f1000);
break;
case V4L2_IDENT_CX23887_AV:
/*
@@ -533,8 +543,18 @@ static void cx23885_initialize(struct i2c_client *client)
* 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz
* 432.0 MHz before post divide
*/
- cx25840_write4(client, 0x10c, 0x002be2c9);
- cx25840_write4(client, 0x108, 0x0000040f);
+
+ /* HVR1850 */
+ switch (state->id) {
+ case V4L2_IDENT_CX23888_AV:
+ /* 888/HVR1250 specific */
+ cx25840_write4(client, 0x10c, 0x13333333);
+ cx25840_write4(client, 0x108, 0x00000515);
+ break;
+ default:
+ cx25840_write4(client, 0x10c, 0x002be2c9);
+ cx25840_write4(client, 0x108, 0x0000040f);
+ }
/* Luma */
cx25840_write4(client, 0x414, 0x00107d12);
@@ -556,8 +576,9 @@ static void cx23885_initialize(struct i2c_client *client)
* 368.64 MHz before post divide
* 122.88 MHz / 0xa = 12.288 MHz
*/
- cx25840_write4(client, 0x114, 0x00bedfa4);
- cx25840_write4(client, 0x110, 0x000a0307);
+ /* HVR1850 or 50MHz xtal */
+ cx25840_write4(client, 0x114, 0x017dbf48);
+ cx25840_write4(client, 0x110, 0x000a030e);
break;
case V4L2_IDENT_CX23887_AV:
/*
@@ -617,7 +638,10 @@ static void cx23885_initialize(struct i2c_client *client)
finish_wait(&state->fw_wait, &wait);
destroy_workqueue(q);
- cx25840_std_setup(client);
+ /* Call the cx23885 specific std setup func, we no longer rely on
+ * the generic cx24840 func.
+ */
+ cx23885_std_setup(client);
/* (re)set input */
set_input(client, state->vid_input, state->aud_input);
@@ -631,6 +655,37 @@ static void cx23885_initialize(struct i2c_client *client)
/* Disable and clear audio interrupts - we don't use them */
cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
+
+ /* CC raw enable */
+ /* - VIP 1.1 control codes - 10bit, blue field enable.
+ * - enable raw data during vertical blanking.
+ * - enable ancillary Data insertion for 656 or VIP.
+ */
+ cx25840_write4(client, 0x404, 0x0010253e);
+
+ /* CC on - Undocumented Register */
+ cx25840_write(client, 0x42f, 0x66);
+
+ /* HVR-1250 / HVR1850 DIF related */
+ /* Power everything up */
+ cx25840_write4(client, 0x130, 0x0);
+
+ /* Undocumented */
+ cx25840_write4(client, 0x478, 0x6628021F);
+
+ /* AFE_CLK_OUT_CTRL - Select the clock output source as output */
+ cx25840_write4(client, 0x144, 0x5);
+
+ /* I2C_OUT_CTL - I2S output configuration as
+ * Master, Sony, Left justified, left sample on WS=1
+ */
+ cx25840_write4(client, 0x918, 0x1a0);
+
+ /* AFE_DIAG_CTRL1 */
+ cx25840_write4(client, 0x134, 0x000a1800);
+
+ /* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */
+ cx25840_write4(client, 0x13c, 0x00310000);
}
/* ----------------------------------------------------------------------- */
@@ -945,9 +1000,14 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
vid_input <= CX25840_COMPOSITE8);
u8 is_component = (vid_input & CX25840_COMPONENT_ON) ==
CX25840_COMPONENT_ON;
+ u8 is_dif = (vid_input & CX25840_DIF_ON) ==
+ CX25840_DIF_ON;
+ u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) ==
+ CX25840_SVIDEO_ON;
int luma = vid_input & 0xf0;
int chroma = vid_input & 0xf00;
u8 reg;
+ u32 val;
v4l_dbg(1, cx25840_debug, client,
"decoder set video input %d, audio input %d\n",
@@ -1012,6 +1072,66 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
else
cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
+ if (is_cx2388x(state)) {
+
+ /* Enable or disable the DIF for tuner use */
+ if (is_dif) {
+ cx25840_and_or(client, 0x102, ~0x80, 0x80);
+
+ /* Set of defaults for NTSC and PAL */
+ cx25840_write4(client, 0x31c, 0xc2262600);
+ cx25840_write4(client, 0x320, 0xc2262600);
+
+ /* 18271 IF - Nobody else yet uses a different
+ * tuner with the DIF, so these are reasonable
+ * assumptions (HVR1250 and HVR1850 specific).
+ */
+ cx25840_write4(client, 0x318, 0xda262600);
+ cx25840_write4(client, 0x33c, 0x2a24c800);
+ cx25840_write4(client, 0x104, 0x0704dd00);
+ } else {
+ cx25840_write4(client, 0x300, 0x015c28f5);
+
+ cx25840_and_or(client, 0x102, ~0x80, 0);
+ cx25840_write4(client, 0x340, 0xdf7df83);
+ cx25840_write4(client, 0x104, 0x0704dd80);
+ cx25840_write4(client, 0x314, 0x22400600);
+ cx25840_write4(client, 0x318, 0x40002600);
+ cx25840_write4(client, 0x324, 0x40002600);
+ cx25840_write4(client, 0x32c, 0x0250e620);
+ cx25840_write4(client, 0x39c, 0x01FF0B00);
+
+ cx25840_write4(client, 0x410, 0xffff0dbf);
+ cx25840_write4(client, 0x414, 0x00137d03);
+ cx25840_write4(client, 0x418, 0x01008080);
+ cx25840_write4(client, 0x41c, 0x00000000);
+ cx25840_write4(client, 0x420, 0x001c3e0f);
+ cx25840_write4(client, 0x42c, 0x42600000);
+ cx25840_write4(client, 0x430, 0x0000039b);
+ cx25840_write4(client, 0x438, 0x00000000);
+
+ cx25840_write4(client, 0x440, 0xF8E3E824);
+ cx25840_write4(client, 0x444, 0x401040dc);
+ cx25840_write4(client, 0x448, 0xcd3f02a0);
+ cx25840_write4(client, 0x44c, 0x161f1000);
+ cx25840_write4(client, 0x450, 0x00000802);
+
+ cx25840_write4(client, 0x91c, 0x01000000);
+ cx25840_write4(client, 0x8e0, 0x03063870);
+ cx25840_write4(client, 0x8d4, 0x7FFF0024);
+ cx25840_write4(client, 0x8d0, 0x00063073);
+
+ cx25840_write4(client, 0x8c8, 0x00010000);
+ cx25840_write4(client, 0x8cc, 0x00080023);
+
+ /* DIF BYPASS */
+ cx25840_write4(client, 0x33c, 0x2a04c800);
+ }
+
+ /* Reset the DIF */
+ cx25840_write4(client, 0x398, 0);
+ }
+
if (!is_cx2388x(state) && !is_cx231xx(state)) {
/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
@@ -1036,6 +1156,33 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
cx25840_and_or(client, 0x102, ~0x2, 0);
}
}
+
+ /* cx23885 / SVIDEO */
+ if (is_cx2388x(state) && is_svideo) {
+#define AFE_CTRL (0x104)
+#define MODE_CTRL (0x400)
+ cx25840_and_or(client, 0x102, ~0x2, 0x2);
+
+ val = cx25840_read4(client, MODE_CTRL);
+ val &= 0xFFFFF9FF;
+
+ /* YC */
+ val |= 0x00000200;
+ val &= ~0x2000;
+ cx25840_write4(client, MODE_CTRL, val);
+
+ val = cx25840_read4(client, AFE_CTRL);
+
+ /* Chroma in select */
+ val |= 0x00001000;
+ val &= 0xfffffe7f;
+ /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8).
+ * This sets them to use video rather than audio.
+ * Only one of the two will be in use.
+ */
+ cx25840_write4(client, AFE_CTRL, val);
+ } else
+ cx25840_and_or(client, 0x102, ~0x2, 0);
}
state->vid_input = vid_input;
@@ -1086,6 +1233,23 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
cx25840_write4(client, 0x8d0, 0x1f063870);
}
+ if (is_cx2388x(state)) {
+ /* HVR1850 */
+ /* AUD_IO_CTRL - I2S Input, Parallel1*/
+ /* - Channel 1 src - Parallel1 (Merlin out) */
+ /* - Channel 2 src - Parallel2 (Merlin out) */
+ /* - Channel 3 src - Parallel3 (Merlin AC97 out) */
+ /* - I2S source and dir - Merlin, output */
+ cx25840_write4(client, 0x124, 0x100);
+
+ if (!is_dif) {
+ /* Stop microcontroller if we don't need it
+ * to avoid audio popping on svideo/composite use.
+ */
+ cx25840_and_or(client, 0x803, ~0x10, 0x00);
+ }
+ }
+
return 0;
}
@@ -1134,7 +1298,10 @@ static int set_v4lstd(struct i2c_client *client)
}
cx25840_and_or(client, 0x400, ~0xf, fmt);
cx25840_and_or(client, 0x403, ~0x3, pal_m);
- cx25840_std_setup(client);
+ if (is_cx2388x(state))
+ cx23885_std_setup(client);
+ else
+ cx25840_std_setup(client);
if (!is_cx2583x(state))
input_change(client);
return 0;
@@ -1539,6 +1706,56 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
return 0;
}
+/* Query the current detected video format */
+static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ v4l2_std_id stds[] = {
+ /* 0000 */ V4L2_STD_UNKNOWN,
+
+ /* 0001 */ V4L2_STD_NTSC_M,
+ /* 0010 */ V4L2_STD_NTSC_M_JP,
+ /* 0011 */ V4L2_STD_NTSC_443,
+ /* 0100 */ V4L2_STD_PAL,
+ /* 0101 */ V4L2_STD_PAL_M,
+ /* 0110 */ V4L2_STD_PAL_N,
+ /* 0111 */ V4L2_STD_PAL_Nc,
+ /* 1000 */ V4L2_STD_PAL_60,
+
+ /* 1001 */ V4L2_STD_UNKNOWN,
+ /* 1010 */ V4L2_STD_UNKNOWN,
+ /* 1001 */ V4L2_STD_UNKNOWN,
+ /* 1010 */ V4L2_STD_UNKNOWN,
+ /* 1011 */ V4L2_STD_UNKNOWN,
+ /* 1110 */ V4L2_STD_UNKNOWN,
+ /* 1111 */ V4L2_STD_UNKNOWN
+ };
+
+ u32 fmt = (cx25840_read4(client, 0x40c) >> 8) & 0xf;
+ *std = stds[ fmt ];
+
+ v4l_dbg(1, cx25840_debug, client, "g_std fmt = %x, v4l2_std_id = 0x%x\n",
+ fmt, (unsigned int)stds[ fmt ]);
+
+ return 0;
+}
+
+static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ /* A limited function that checks for signal status and returns
+ * the state.
+ */
+
+ /* Check for status of Horizontal lock (SRC lock isn't reliable) */
+ if ((cx25840_read4(client, 0x40c) & 0x00010000) == 0)
+ *status |= V4L2_IN_ST_NO_SIGNAL;
+
+ return 0;
+}
+
static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct cx25840_state *state = to_state(sd);
@@ -1565,6 +1782,9 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd,
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ if (is_cx2388x(state))
+ cx23885_std_setup(client);
+
return set_input(client, input, state->aud_input);
}
@@ -1574,6 +1794,8 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ if (is_cx2388x(state))
+ cx23885_std_setup(client);
return set_input(client, state->vid_input, input);
}
@@ -1786,6 +2008,3007 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
/* ----------------------------------------------------------------------- */
+#define DIF_PLL_FREQ_WORD (0x300)
+#define DIF_BPF_COEFF01 (0x348)
+#define DIF_BPF_COEFF23 (0x34c)
+#define DIF_BPF_COEFF45 (0x350)
+#define DIF_BPF_COEFF67 (0x354)
+#define DIF_BPF_COEFF89 (0x358)
+#define DIF_BPF_COEFF1011 (0x35c)
+#define DIF_BPF_COEFF1213 (0x360)
+#define DIF_BPF_COEFF1415 (0x364)
+#define DIF_BPF_COEFF1617 (0x368)
+#define DIF_BPF_COEFF1819 (0x36c)
+#define DIF_BPF_COEFF2021 (0x370)
+#define DIF_BPF_COEFF2223 (0x374)
+#define DIF_BPF_COEFF2425 (0x378)
+#define DIF_BPF_COEFF2627 (0x37c)
+#define DIF_BPF_COEFF2829 (0x380)
+#define DIF_BPF_COEFF3031 (0x384)
+#define DIF_BPF_COEFF3233 (0x388)
+#define DIF_BPF_COEFF3435 (0x38c)
+#define DIF_BPF_COEFF36 (0x390)
+
+void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
+{
+ u64 pll_freq;
+ u32 pll_freq_word;
+
+ v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz);
+
+ /* Assuming TV */
+ /* Calculate the PLL frequency word based on the adjusted ifHz */
+ pll_freq = div_u64((u64)ifHz * 268435456, 50000000);
+ pll_freq_word = (u32)pll_freq;
+
+ cx25840_write4(client, DIF_PLL_FREQ_WORD, pll_freq_word);
+
+ /* Round down to the nearest 100KHz */
+ ifHz = (ifHz / 100000) * 100000;
+
+ if (ifHz < 3000000)
+ ifHz = 3000000;
+
+ if (ifHz > 16000000)
+ ifHz = 16000000;
+
+ v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz);
+
+ switch (ifHz) {
+ case 3000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00220032);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00370026);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff91);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0efe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fdcc);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe0afedb);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440224);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0434060c);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738074e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x06090361);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99fb39);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef3b6);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21af2a5);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf573fa33);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034067d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bfb0fb9);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000e);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00200038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x004c004f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x002fffdf);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff5cfeb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dfd92);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7ffe03);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36010a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x03410575);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x072607d2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x071804d5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134fcb7);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff451);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223f22e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4a7f94b);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xff6405e8);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bae0fa4);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00000008);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0036);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0056006d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00670030);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffbdff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46fd8d);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd25fd4f);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35ffe0);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0224049f);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9080e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x07ef0627);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9fe45);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f513);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250f1d2);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3ecf869);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930552);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b5f0f8f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0001);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000f002c);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0054007d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0093007c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0024ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6fdbb);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd03fcca);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51feb9);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x00eb0392);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270802);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08880750);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x044dffdb);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf5f8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0f193);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf342f78f);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc404b9);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b0e0f78);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff9);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0002001b);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0046007d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad00ba);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00870000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe1a);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1bfc7e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fda4);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xffa5025c);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x054507ad);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08dd0847);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80172);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef6ff);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313f170);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2abf6bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6041f);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0abc0f61);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff3);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff50006);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x002f006c);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b200e3);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00dc007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9fea0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd6bfc71);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fcb1);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe65010b);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x042d0713);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ec0906);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020302);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff823);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7f16a);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf228f5f5);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2a0384);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a670f4a);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7ffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9fff1);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0010004d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a100f2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x011a00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053ff44);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdedfca2);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fbef);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd39ffae);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x02ea0638);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08b50987);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230483);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f960);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45bf180);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1b8f537);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb6102e7);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a110f32);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffdd);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00024);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x007c00e5);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013a014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e6fff8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe98fd0f);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fb67);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc32fe54);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x01880525);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x083909c7);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x091505ee);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7fab3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52df1b4);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf15df484);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9b0249);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x09ba0f19);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 3900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff0);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffcf);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1fff6);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x004800be);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01390184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x016300ac);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff5efdb1);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb23);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb5cfd0d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x001703e4);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x077b09c4);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d2073c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251fc18);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61cf203);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf118f3dc);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d801aa);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x09600eff);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffefff4);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffca);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x000b0082);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01170198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10152);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0030fe7b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb24);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfac3fbe9);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5027f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0683097f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a560867);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2fd89);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723f26f);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0e8f341);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919010a);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x09060ee5);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fffb);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8ffca);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffa4);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffcd0036);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d70184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f601dc);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ffff60);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb6d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6efaf5);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd410103);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x055708f9);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e0969);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543ff02);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842f2f5);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cef2b2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85e006b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x08aa0ecb);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00050003);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff3ffd3);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaff8b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ffe5);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0080014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe023f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ba0050);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fbf8);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa62fa3b);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9ff7e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x04010836);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa90a3d);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f007f);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf975f395);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cbf231);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ffcb);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x084c0eaf);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000a);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0000ffe4);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff81);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff96);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x001c00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70271);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0254013b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fcbd);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa9ff9c5);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbfdfe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x028c073b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a750adf);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e101fa);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab8f44e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0ddf1be);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ff2b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x07ed0e94);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000efff8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff87);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff54);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffb5007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01860270);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c00210);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fdb2);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb22f997);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2fc90);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0102060f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a050b4c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902036e);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0af51e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf106f15a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64efe8b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x078d0e77);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0019000e);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff9e);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff25);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff560000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112023b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f702c0);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfec8);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbe5f9b3);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947fb41);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xff7004b9);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a0b81);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a0004d8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd65f603);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf144f104);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aafdec);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x072b0e5a);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00060012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00200022);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ffc1);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff09ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x008601d7);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f50340);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fff0);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcddfa19);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa1e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfde30343);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x08790b7f);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50631);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec7f6fc);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf198f0bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50dfd4e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x06c90e3d);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00220030);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffed);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff87ff15);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed6ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffed014c);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b90386);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110119);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfdfefac4);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6f92f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc6701b7);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x07670b44);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0776);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x002df807);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf200f086);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477fcb1);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x06650e1e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0009);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003f001b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffbcff36);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec2feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff5600a5);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0248038d);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00232);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xff39fbab);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4f87f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb060020);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x062a0ad2);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf908a3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0192f922);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf27df05e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8fc14);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x06000e00);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 4900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0002);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00160037);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00510046);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xfff9ff6d);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed0fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefff0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01aa0356);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413032b);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x007ffcc5);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cf812);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9cefe87);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c90a2c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4309b4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f3fa4a);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf30ef046);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361fb7a);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x059b0de0);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000a002d);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00570067);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0037ffb5);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfefffe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62ff3d);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ec02e3);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x043503f6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x01befe05);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa27f7ee);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8c6fcf8);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x034c0954);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0aa4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x044cfb7e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3b1f03f);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2fae1);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x05340dc0);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff4);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffd001e);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0051007b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x006e0006);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff48fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfe9a);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x001d023e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130488);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x02e6ff5b);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1ef812);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7f7fb7f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bc084e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430b72);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x059afcba);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf467f046);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cfa4a);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x04cd0da0);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff00009);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003f007f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00980056);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffa5feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe15);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff4b0170);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b004d7);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x03e800b9);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc48f87f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf768fa23);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022071f);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90c1b);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x06dafdfd);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf52df05e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef9b5);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x04640d7f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6fff3);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00250072);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00af009c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x000cff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13fdb8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe870089);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104e1);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04b8020f);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd98f92f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf71df8f0);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe8805ce);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0c9c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0808ff44);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf603f086);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af922);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x03fb0d5e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe0);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00050056);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b000d1);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0071ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53fd8c);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfddfff99);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104a3);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x054a034d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xff01fa1e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf717f7ed);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf50461);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50cf4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0921008d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf6e7f0bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff891);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x03920d3b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffffff3);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffd1);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5002f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x009c00ed);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00cb0000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfebafd94);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd61feb0);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d0422);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05970464);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0074fb41);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf759f721);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb7502de);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000d21);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a2201d4);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7d9f104);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf804);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x03280d19);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fffa);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3ffc9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc90002);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x007500ef);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x010e007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3dfdcf);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd16fddd);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440365);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x059b0548);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3fc90);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7dff691);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0f014d);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020d23);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0318);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8d7f15a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f779);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x02bd0cf6);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00060001);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffecffc9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffd4);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x004000d5);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013600f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd3fe39);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd04fd31);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff360277);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x055605ef);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x033efdfe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8a5f642);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbffb6);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10cfb);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50456);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9dff1be);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f6f2);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x02520cd2);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080009);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff8ffd2);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffac);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x000200a3);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013c014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x006dfec9);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2bfcb7);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe350165);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04cb0651);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477ff7e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9a5f635);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1fe20);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0ca8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c81058b);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfaf0f231);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f66d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x01e60cae);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 5900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000e);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0005ffe1);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffacff90);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5005f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01210184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fcff72);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd8afc77);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51003f);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04020669);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830103);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfad7f66b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8fc93);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430c2b);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d06b5);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfc08f2b2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af5ec);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x017b0c89);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0012fff5);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaff82);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff8e000f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e80198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750028);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe18fc75);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99ff15);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x03050636);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0656027f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc32f6e2);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614fb17);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20b87);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d7707d2);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfd26f341);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf56f);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x010f0c64);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00050012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001c000b);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff84);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ffbe);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00960184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd00da);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeccfcb2);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fdf9);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x01e005bc);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e703e4);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfdabf798);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f9b3);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510abd);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf08df);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfe48f3dc);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f4f6);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x00a20c3e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0002000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0021001f);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff97);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff74);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0034014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa0179);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff97fd2a);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fcfa);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x00a304fe);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310525);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xff37f886);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf86e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c709d0);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de209db);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xff6df484);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf481);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0x00360c18);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe000a);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0021002f);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ffb8);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff3b);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffcc00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa01fa);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0069fdd4);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fc26);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xff5d0407);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310638);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x00c9f9a8);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf74e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xff3908c3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de20ac3);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0093f537);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf410);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xffca0bf2);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb0003);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001c0037);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x002fffe2);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ff17);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff6a007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd0251);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0134fea5);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb8b);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe2002e0);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e70713);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0255faf5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f658);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0799);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf0b96);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x01b8f5f5);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f3a3);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xff5e0bca);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00120037);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00460010);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff8eff0f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff180000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750276);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01e8ff8d);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb31);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcfb0198);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x065607ad);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x03cefc64);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614f592);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0656);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d770c52);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x02daf6bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf33b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfef10ba3);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff5);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0005002f);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0054003c);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5ff22);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedfff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fc0267);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0276007e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb1c);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbfe003e);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830802);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0529fdec);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8f4fe);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd04ff);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d0cf6);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x03f8f78f);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af2d7);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe850b7b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff80020);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00560060);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0002ff4e);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec4ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x006d0225);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02d50166);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb4e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb35fee1);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477080e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x065bff82);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1f4a0);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610397);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c810d80);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0510f869);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f278);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe1a0b52);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffaffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffec000c);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0078);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0040ff8e);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecafeb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd301b6);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fc0235);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fbc5);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaaafd90);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x033e07d2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x075b011b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbf47a);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f0224);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50def);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0621f94b);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f21e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfdae0b29);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 6900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3fff6);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0037007f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0075ffdc);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef2fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3d0122);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02ea02dd);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fc79);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa65fc5d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3074e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x082102ad);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0ff48c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe00a9);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0e43);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0729fa33);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f1c9);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfd430b00);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0001fff3);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe2);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x001b0076);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x009c002d);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff35fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfeba0076);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x029f0352);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfd60);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa69fb53);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x00740688);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08a7042d);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb75f4d6);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600ff2d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a220e7a);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0827fb22);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf17a);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfcd80ad6);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff9);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffd2);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb005e);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b0007a);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8ffe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53ffc1);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0221038c);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fe6e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfab6fa80);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xff010587);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e90590);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf5f556);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfdb3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x09210e95);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0919fc15);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff12f);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc6e0aab);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00070000);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6ffc9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0039);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00af00b8);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfff4feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01790388);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311ff92);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb48f9ed);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd980453);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e306cd);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe88f60a);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fc40);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x08080e93);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x09fdfd0c);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af0ea);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc050a81);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080008);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff0ffc9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1000d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x009800e2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x005bff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe74);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00b50345);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000bc);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc18f9a1);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc4802f9);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x089807dc);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022f6f0);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fada);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x06da0e74);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ad3fe06);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef0ab);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb9c0a55);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000e);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffdffd0);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffdf);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x006e00f2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00b8ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfdf8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xffe302c8);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x041301dc);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd1af99e);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1e0183);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x080908b5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bcf801);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf985);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x059a0e38);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b99ff03);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cf071);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb330a2a);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00070011);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000affdf);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffa9ffb5);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x003700e6);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01010000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62fda8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff140219);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x043502e1);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe42f9e6);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa270000);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x073a0953);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x034cf939);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a4f845);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x044c0de1);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c4f0000);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2f03c);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfacc09fe);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00040012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0016fff3);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffafff95);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xfff900c0);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0130007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefd89);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe560146);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x041303bc);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xff81fa76);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cfe7d);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x063209b1);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c9fa93);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf71e);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f30d6e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cf200fd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361f00e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa6509d1);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00010010);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0008);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ff84);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffbc0084);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013e00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff56fd9f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdb8005c);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00460);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x00c7fb45);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4fd07);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x04fa09ce);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x062afc07);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407f614);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x01920ce0);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d8301fa);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8efe5);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa0009a4);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd000b);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001d);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff82);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff870039);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x012a014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffedfde7);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd47ff6b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104c6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0202fc4c);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6fbad);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x039909a7);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0767fd8e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482f52b);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x002d0c39);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e0002f4);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477efc2);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf99b0977);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 7900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa0004);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0020002d);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff91);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ffe8);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f70184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0086fe5c);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0bfe85);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104e5);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0323fd7d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa79);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x021d093f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0879ff22);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bf465);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec70b79);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e6803eb);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50defa5);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf937094a);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffd);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00190036);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x001bffaf);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff99);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00aa0198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112fef3);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd09fdb9);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04be);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x041bfecc);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947f978);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x00900897);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a00b9);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f3c5);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd650aa3);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ebc04de);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aaef8e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf8d5091c);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff6);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000e0038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ffd7);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff56);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x004b0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0186ffa1);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd40fd16);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440452);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04de0029);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2f8b2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfefe07b5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a05024d);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef34d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0a09b8);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0efa05cd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64eef7d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf87308ed);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00000031);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0005);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff27);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffe4014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70057);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdacfca6);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3603a7);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05610184);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbf82e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd74069f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a7503d6);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff2ff);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab808b9);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f2306b5);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ef72);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf81308bf);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff30022);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00560032);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8000f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe0106);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe46fc71);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3502c7);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x059e02ce);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9f7f2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfbff055b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa9054c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f2db);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf97507aa);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f350797);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ef6d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7b40890);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8000f);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00540058);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffcdff14);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff29007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f6019e);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff01fc7c);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5101bf);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x059203f6);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd41f7fe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfaa903f3);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e06a9);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf2e2);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842068b);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f320871);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85eef6e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7560860);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fff2);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1fff9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00460073);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x000bff34);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee90000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10215);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xffd0fcc5);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99009d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x053d04f1);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5f853);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf97d0270);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a5607e4);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef314);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723055f);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f180943);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919ef75);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6fa0830);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff8);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe4);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x002f007f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0048ff6b);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec7ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0163025f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00a2fd47);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff73);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04a405b2);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0017f8ed);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf88500dc);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d208f9);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff370);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61c0429);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ee80a0b);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d8ef82);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6a00800);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0007ffff);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffd4);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0010007a);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x007cffb2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec6ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e60277);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0168fdf9);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fe50);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x03ce0631);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0188f9c8);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7c7ff43);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x091509e3);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f3f6);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52d02ea);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ea30ac9);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9bef95);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf64607d0);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00090007);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9ffca);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00065);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a10003);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee6feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053025b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0213fed0);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fd46);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x02c70668);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x02eafadb);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf74bfdae);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230a9c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f4a3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45b01a6);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e480b7c);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb61efae);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf5ef079f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 8900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000d);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff5ffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10043);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b20053);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff24fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9020c);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0295ffbb);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fc64);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x019b0654);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x042dfc1c);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf714fc2a);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020b21);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f575);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7005e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0dd80c24);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2aefcd);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf599076e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00060011);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0002ffcf);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffba0018);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad009a);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff79fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff260192);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e500ab);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fbb6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x005b05f7);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545fd81);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf723fabf);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80b70);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f669);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313ff15);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d550cbf);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6eff2);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544073d);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00030012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000fffdd);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffea);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x009300cf);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdcfe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea600f7);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fd0190);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb46);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xff150554);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0627fefd);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf778f978);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x044d0b87);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f77d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0fdcf);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbe0d4e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc4f01d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2070b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00000010);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001afff0);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffbf);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x006700ed);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe460047);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02db0258);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb1b);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddc0473);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c90082);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf811f85e);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c90b66);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff8ad);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250fc8d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c140dcf);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe93f04d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a106d9);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc000c);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00200006);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff9c);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x002f00ef);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a4ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dff92);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x028102f7);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb37);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbf035e);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07260202);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e8f778);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x01340b0d);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f9f4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223fb51);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b590e42);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xff64f083);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf45206a7);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90005);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001a);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff86);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xfff000d7);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fee5);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f60362);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb99);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbcc0222);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07380370);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f7f6cc);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xff990a7e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902fb50);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21afa1f);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8d0ea6);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034f0bf);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4050675);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffe);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001e002b);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff81);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffb400a5);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe50);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01460390);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfc3a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb1000ce);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x070104bf);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb37f65f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe0009bc);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00fcbb);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f8f8);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b20efc);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105f101);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3ba0642);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff7);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00150036);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff8c);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff810061);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013d007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe71fddf);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x007c0380);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fd13);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa94ff70);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x068005e2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9bf633);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc7308ca);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5fe30);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf274f7e0);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c90f43);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d4f147);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371060f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fff1);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00090038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffa7);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff5e0012);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013200f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee3fd9b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaa0331);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fe15);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa60fe18);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bd06d1);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1bf64a);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafa07ae);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7effab);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d5f6d7);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d30f7a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a3f194);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf32905dc);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffb0032);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003fffcd);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effc1);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6efd8a);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfedd02aa);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0ff34);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa74fcd7);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bf0781);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaaf6a3);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99e066b);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90128);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf359f5e1);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d20fa2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0370f1e5);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e405a8);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 9900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffef0024);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0051fffa);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff54ff77);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00be0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0006fdad);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe2701f3);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413005e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad1fbba);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x039007ee);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x013bf73d);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868050a);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4302a1);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fdf4fe);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c70fba);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x043bf23c);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a10575);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fff1);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe50011);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00570027);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff70ff3c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00620198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x009efe01);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95011a);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350183);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb71fad0);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x023c0812);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c3f811);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75e0390);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0411);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c1f432);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b30fc1);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0503f297);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2610541);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0006fff7);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdffffc);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00510050);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff9dff18);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffc0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0128fe80);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32002e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130292);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4dfa21);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d107ee);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0435f91c);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6850205);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430573);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a1f37d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x03990fba);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c7f2f8);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222050d);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffe);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdfffe7);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003f006e);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffd6ff0f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0197ff1f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd05ff3e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0037c);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd59f9b7);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5d0781);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0585fa56);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4006f);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf906c4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69df2e0);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x02790fa2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0688f35d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e604d8);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00090005);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4ffd6);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0025007e);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0014ff20);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3c00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e1ffd0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd12fe5c);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110433);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88f996);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf106d1);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aafbb7);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57efed8);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e07ff);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b0f25e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x01560f7a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0745f3c7);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1ac04a4);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000c);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffedffcb);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0005007d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0050ff4c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ff0086);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd58fd97);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104ad);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xffcaf9c0);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc9905e2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x079afd35);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf555fd46);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50920);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d9f1f6);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x00310f43);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fdf435);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174046f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00050011);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffaffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5006b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0082ff8c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f00130);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd2fcfc);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04e3);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x010efa32);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb6404bf);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x084efec5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569fbc2);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000a23);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa15f1ab);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0b0efc);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b0f4a7);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13f043a);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00020012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0007ffcd);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9004c);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a4ffd9);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b401c1);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe76fc97);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404d2);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0245fae8);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5f0370);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1005f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bcfa52);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020b04);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb60f17b);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde70ea6);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x095df51e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10c0405);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0011);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0014ffdb);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40023);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2002a);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedbff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150022d);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff38fc6f);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36047b);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x035efbda);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9940202);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ee01f5);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf649f8fe);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10bc2);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb6f169);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc60e42);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a04f599);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0db03d0);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb000d);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001dffed);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaafff5);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00aa0077);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00ce026b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x000afc85);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3503e3);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x044cfcfb);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90c0082);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5037f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf710f7cc);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0c59);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe16f173);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaa0dcf);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa5f617);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0ad039b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 10900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90006);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00210003);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffc8);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x008e00b6);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff63fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x003a0275);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00dafcda);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd510313);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0501fe40);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cbfefd);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x087604f0);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80af6c2);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430cc8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7af19a);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa940d4e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3ff699);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0810365);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffff);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00210018);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffa3);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x006000e1);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc4fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0024b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x019afd66);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc990216);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0575ff99);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4fd81);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d40640);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf932f5e6);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20d0d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x00dff1de);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9860cbf);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd1f71e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058032f);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff8);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001b0029);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff8a);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x002600f2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x002cfe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0f01f0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x023bfe20);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc1700fa);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a200f7);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf927fc1c);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f40765);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa82f53b);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510d27);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0243f23d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8810c24);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5cf7a7);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf03102fa);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00110035);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff81);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffe700e7);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x008ffeb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94016d);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b0fefb);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3ffd1);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05850249);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c1fadb);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x05de0858);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf2f4c4);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c70d17);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a0f2b8);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7870b7c);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdff833);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00d02c4);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00040038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ff88);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffac00c2);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e2ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe3900cb);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f1ffe9);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3feaa);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05210381);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9cf9c8);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x04990912);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7af484);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xff390cdb);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f4f34d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69a0ac9);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5af8c1);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefec028e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0000ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff60033);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x002fff9f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff7b0087);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x011eff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe080018);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f900d8);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fd96);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x04790490);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbadf8ed);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x032f098e);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xff10f47d);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0c75);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x063cf3fc);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5ba0a0b);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dccf952);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcd0258);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff1);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffea0026);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0046ffc3);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff5a003c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04ff63);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c801b8);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fca6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397056a);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcecf853);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x01ad09c9);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x00acf4ad);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0be7);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0773f4c2);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e90943);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35f9e6);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb10221);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff6);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe20014);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0054ffee);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effeb);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2efebb);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260027a);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fbe6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x02870605);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4af7fe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x001d09c1);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0243f515);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd0b32);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0897f59e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4280871);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e95fa7c);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef9701eb);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffd);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffff);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0056001d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff57ff9c);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x011300f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe82fe2e);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ca0310);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb62);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155065a);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xffbaf7f2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8c0977);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x03cef5b2);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610a58);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a5f68f);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3790797);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eebfb14);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef8001b5);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080004);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0047);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff75ff58);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef9fdc8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111036f);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb21);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x00120665);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x012df82e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd0708ec);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542f682);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f095c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9af792);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2db06b5);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f38fbad);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6c017e);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 11900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000b);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe7ffd8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00370068);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffa4ff28);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00790184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87fd91);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00430392);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb26);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfece0626);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294f8b2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb990825);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0698f77f);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe0842);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b73f8a7);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf25105cd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7bfc48);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5a0148);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00050010);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff2ffcc);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x001b007b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffdfff10);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00140198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0020fd8e);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff710375);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb73);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9a059f);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e0f978);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4e0726);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c8f8a7);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600070c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2ff9c9);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1db04de);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4fce5);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4b0111);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00010012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffffffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb007e);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x001dff14);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffad0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b7fdbe);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9031b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fc01);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc8504d6);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0504fa79);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf93005f6);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x08caf9f2);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52b05c0);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccbfaf9);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf17903eb);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3fd83);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3f00db);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe0011);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000cffcc);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0071);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0058ff32);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4f014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x013cfe1f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfb028a);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fcc9);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9d03d6);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f4fbad);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848049d);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0999fb5b);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf4820461);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d46fc32);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12d02f4);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x1007fe21);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3600a4);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0017ffd9);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc10055);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0088ff68);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0400f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a6fea7);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7501cc);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fdc0);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaef02a8);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a7fd07);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79d0326);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a31fcda);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf40702f3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9ffd72);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f601fa);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x1021fec0);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2f006d);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80007);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001fffeb);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaf002d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a8ffb0);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e9ff4c);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2000ee);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fed8);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82015c);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0715fe7d);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7340198);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8dfe69);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bd017c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd5feb8);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d500fd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x1031ff60);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2b0037);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff70000);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00220000);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffa90000);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b30000);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec20000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x02000000);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd030000);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350000);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa5e0000);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x073b0000);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7110000);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aac0000);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a40000);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de70000);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0c90000);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x10360000);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef290000);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff9);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001f0015);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffd3);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a80050);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e900b4);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd20ff12);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130128);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82fea4);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x07150183);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf734fe68);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8d0197);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdfe84);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd50148);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d5ff03);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x103100a0);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2bffc9);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00170027);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ffab);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00880098);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff04ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a60159);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd75fe34);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00240);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaeffd58);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a702f9);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79dfcda);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a310326);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fd0d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9f028e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f6fe06);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x10210140);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2fff93);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000c0034);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff8f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x005800ce);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4ffeb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x013c01e1);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfbfd76);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110337);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9dfc2a);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f40453);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848fb63);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x099904a5);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fb9f);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d4603ce);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12dfd0c);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x100701df);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef36ff5c);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 12900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0001ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffff0038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff82);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x001d00ec);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffadfe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b70242);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9fce5);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x024103ff);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc85fb2a);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05040587);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf930fa0a);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x08ca060e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfa40);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccb0507);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf179fc15);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3027d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3fff25);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff0);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff20034);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x001bff85);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffdf00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0014fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00200272);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff71fc8b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d048d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9afa61);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e00688);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4ef8da);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c80759);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f8f4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2f0637);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1dbfb22);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4031b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4bfeef);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff5);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe70028);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ff98);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffa400d8);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0079fe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87026f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0043fc6e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404da);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfecef9da);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294074e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb99f7db);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x06980881);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef7be);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b730759);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf251fa33);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7b03b8);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5afeb8);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffc);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe00017);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x004cffb9);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff7500a8);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef90238);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111fc91);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604df);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0012f99b);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x012d07d2);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd07f714);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542097e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff6a4);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9a086e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2dbf94b);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f380453);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6cfe82);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080003);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffde0001);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0056ffe3);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff570064);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0113ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe8201d2);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01cafcf0);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35049e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155f9a6);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xffba080e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8cf689);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x03ce0a4e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f5a8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a50971);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf379f869);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eeb04ec);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef80fe4b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000a);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe2ffec);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00540012);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e0015);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2e0145);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260fd86);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51041a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0287f9fb);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4a0802);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x001df63f);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x02430aeb);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf4ce);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x08970a62);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf428f78f);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e950584);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xef97fe15);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffeaffda);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0046003d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff5affc4);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04009d);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c8fe48);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99035a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397fa96);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcec07ad);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x01adf637);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x00ac0b53);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef419);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x07730b3e);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e9f6bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35061a);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb1fddf);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00000012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfff6ffcd);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x002f0061);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff7bff79);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x011e007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe08ffe8);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f9ff28);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17026a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0479fb70);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbad0713);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x032ff672);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xff100b83);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff38b);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x063c0c04);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5baf5f5);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dcc06ae);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcdfda8);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0004ffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00100078);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffacff3e);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e200f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe39ff35);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f10017);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd30156);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0521fc7f);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9c0638);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0499f6ee);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7a0b7c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f325);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f40cb3);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69af537);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5a073f);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xefecfd72);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0011ffcb);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0007f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffe7ff19);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x008f014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94fe93);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b00105);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3002f);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x0585fdb7);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c10525);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x05def7a8);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf20b3c);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f2e9);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a00d48);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf787f484);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdf07cd);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00dfd3c);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 13900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80008);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001bffd7);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10076);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0026ff0e);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x002c0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0ffe10);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x023b01e0);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff06);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a2ff09);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf92703e4);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f4f89b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa820ac5);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f2d9);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x02430dc3);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf881f3dc);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5c0859);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf031fd06);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80001);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0021ffe8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffba005d);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0060ff1f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc40198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0fdb5);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x019a029a);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fdea);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x05750067);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4027f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d4f9c0);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf9320a1a);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f2f3);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0x00df0e22);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xf986f341);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd108e2);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058fcd1);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0021fffd);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0038);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x008eff4a);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff630184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x003afd8b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x00da0326);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fced);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x050101c0);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cb0103);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x0876fb10);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80a093e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f338);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7a0e66);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa94f2b2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3f0967);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf081fc9b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff3);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001d0013);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa000b);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00aaff89);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00cefd95);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x000a037b);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fc1d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x044c0305);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90cff7e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5fc81);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7100834);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff3a7);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe160e8d);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaaf231);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa509e9);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0adfc65);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00140025);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffdd);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2ffd6);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedb00f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150fdd3);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xff380391);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb85);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x035e0426);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xf994fdfe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08eefe0b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6490702);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f43e);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb60e97);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc6f1be);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a040a67);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0dbfc30);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0002ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00070033);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ffb4);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00a40027);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b4fe3f);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe760369);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb2e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x02450518);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5ffc90);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1ffa1);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bc05ae);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902f4fc);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb600e85);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde7f15a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x095d0ae2);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10cfbfb);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0005ffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffa0038);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff95);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00820074);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f0fed0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd20304);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb1d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x010e05ce);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb64fb41);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x084e013b);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569043e);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00f5dd);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa150e55);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0bf104);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b00b59);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13ffbc6);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fff4);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffed0035);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff83);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x005000b4);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6ff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ffff7a);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd580269);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fb53);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xffca0640);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc99fa1e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x079a02cb);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55502ba);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5f6e0);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d90e0a);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0031f0bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fd0bcb);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174fb91);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0009fffb);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4002a);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ff82);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x001400e0);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3cff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e10030);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1201a4);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fbcd);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88066a);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf1f92f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aa0449);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57e0128);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7ef801);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b00da2);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0156f086);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x07450c39);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1acfb5c);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00080002);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0019);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003fff92);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffd600f1);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x019700e1);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0500c2);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fc84);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd590649);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5df87f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x058505aa);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4ff91);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9f93c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69d0d20);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0279f05e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x06880ca3);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e6fb28);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 14900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x00060009);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0004);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0051ffb0);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff9d00e8);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffcfe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x01280180);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32ffd2);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fd6e);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4d05df);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d1f812);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x043506e4);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf685fdfb);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fa8d);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a10c83);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0399f046);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c70d08);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222faf3);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffe5ffef);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x0057ffd9);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff7000c4);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0062fe68);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x009e01ff);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95fee6);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0435fe7d);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb710530);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x023cf7ee);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c307ef);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75efc70);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5cfbef);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c10bce);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b3f03f);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x05030d69);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf261fabf);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15100000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xffefffdc);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00510006);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff540089);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00befe7c);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0x00060253);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe27fe0d);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413ffa2);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad10446);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0390f812);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0x013b08c3);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868faf6);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fd5f);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fd0b02);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c7f046);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x043b0dc4);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a1fa8b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15200000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0012);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0xfffbffce);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x003f0033);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e003f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106feb6);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6e0276);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeddfd56);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000cc);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa740329);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bff87f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaa095d);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99ef995);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9fed8);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3590a1f);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d2f05e);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x03700e1b);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e4fa58);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15300000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9000f);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0009ffc8);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00250059);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff5effee);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0132ff10);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee30265);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaafccf);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x031101eb);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6001e8);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bdf92f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1b09b6);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafaf852);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0055);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d50929);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d3f086);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a30e6c);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf329fa24);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15400000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80009);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0015ffca);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0x00050074);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xff81ff9f);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x013dff82);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe710221);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x007cfc80);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x024102ed);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa940090);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0680fa1e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9b09cd);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc73f736);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad501d0);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2740820);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c9f0bd);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d40eb9);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371f9f1);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15500000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80002);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001effd5);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5007f);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff5b);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2401b0);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0146fc70);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d03c6);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb10ff32);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0701fb41);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb3709a1);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f644);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000345);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2350708);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b2f104);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x01050eff);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3baf9be);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15600000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0022ffe6);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9007a);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff29);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2007e);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01011b);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f6fc9e);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440467);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbccfdde);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738fc90);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f70934);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99f582);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x090204b0);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21a05e1);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8df15a);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0x00340f41);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf405f98b);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15700000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcfff4);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x0020fffa);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40064);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x002fff11);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a400f0);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0d006e);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x0281fd09);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604c9);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbffca2);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0726fdfe);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e80888);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134f4f3);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1060c);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf22304af);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b59f1be);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xff640f7d);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf452f959);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15800000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0000fff0);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0010);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa0041);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0067ff13);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043014a);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46ffb9);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02dbfda8);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3504e5);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddcfb8d);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9ff7e);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf81107a2);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9f49a);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0753);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2500373);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c14f231);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930fb3);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a1f927);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 15900000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0003ffee);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x000f0023);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0016);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x0093ff31);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdc0184);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6ff09);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fdfe70);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5104ba);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0xff15faac);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270103);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7780688);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x044df479);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430883);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a00231);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbef2b2);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc40fe3);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2f8f5);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+
+ case 16000000:
+ cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+ cx25840_write4(client, DIF_BPF_COEFF23, 0x0006ffef);
+ cx25840_write4(client, DIF_BPF_COEFF45, 0x00020031);
+ cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffe8);
+ cx25840_write4(client, DIF_BPF_COEFF89, 0x00adff66);
+ cx25840_write4(client, DIF_BPF_COEFF1011, 0xff790198);
+ cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe6e);
+ cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e5ff55);
+ cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99044a);
+ cx25840_write4(client, DIF_BPF_COEFF1819, 0x005bfa09);
+ cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545027f);
+ cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7230541);
+ cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b8f490);
+ cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20997);
+ cx25840_write4(client, DIF_BPF_COEFF2829, 0xf31300eb);
+ cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d55f341);
+ cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6100e);
+ cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544f8c3);
+ cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+ break;
+ }
+}
+
+static void cx23885_std_setup(struct i2c_client *client)
+{
+ struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+ v4l2_std_id std = state->std;
+ u32 ifHz;
+
+ cx25840_write4(client, 0x478, 0x6628021F);
+ cx25840_write4(client, 0x400, 0x0);
+ cx25840_write4(client, 0x4b4, 0x20524030);
+ cx25840_write4(client, 0x47c, 0x010a8263);
+
+ if (std & V4L2_STD_NTSC) {
+ v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC",
+ __func__);
+
+ /* Horiz / vert timing */
+ cx25840_write4(client, 0x428, 0x1e1e601a);
+ cx25840_write4(client, 0x424, 0x5b2d007a);
+
+ /* DIF NTSC */
+ cx25840_write4(client, 0x304, 0x6503bc0c);
+ cx25840_write4(client, 0x308, 0xbd038c85);
+ cx25840_write4(client, 0x30c, 0x1db4640a);
+ cx25840_write4(client, 0x310, 0x00008800);
+ cx25840_write4(client, 0x314, 0x44400400);
+ cx25840_write4(client, 0x32c, 0x0c800800);
+ cx25840_write4(client, 0x330, 0x27000100);
+ cx25840_write4(client, 0x334, 0x1f296e1f);
+ cx25840_write4(client, 0x338, 0x009f50c1);
+ cx25840_write4(client, 0x340, 0x1befbf06);
+ cx25840_write4(client, 0x344, 0x000035e8);
+
+ /* DIF I/F */
+ ifHz = 5400000;
+
+ } else {
+ v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG",
+ __func__);
+
+ /* Horiz / vert timing */
+ cx25840_write4(client, 0x428, 0x28244024);
+ cx25840_write4(client, 0x424, 0x5d2d0084);
+
+ /* DIF */
+ cx25840_write4(client, 0x304, 0x6503bc0c);
+ cx25840_write4(client, 0x308, 0xbd038c85);
+ cx25840_write4(client, 0x30c, 0x1db4640a);
+ cx25840_write4(client, 0x310, 0x00008800);
+ cx25840_write4(client, 0x314, 0x44400600);
+ cx25840_write4(client, 0x32c, 0x0c800800);
+ cx25840_write4(client, 0x330, 0x27000100);
+ cx25840_write4(client, 0x334, 0x213530ec);
+ cx25840_write4(client, 0x338, 0x00a65ba8);
+ cx25840_write4(client, 0x340, 0x1befbf06);
+ cx25840_write4(client, 0x344, 0x000035e8);
+
+ /* DIF I/F */
+ ifHz = 6000000;
+ }
+
+ cx23885_dif_setup(client, ifHz);
+
+ /* Explicitly ensure the inputs are reconfigured after
+ * a standard change.
+ */
+ set_input(client, state->vid_input, state->aud_input);
+}
+
+/* ----------------------------------------------------------------------- */
+
static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
.s_ctrl = cx25840_s_ctrl,
};
@@ -1801,6 +5024,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = {
.queryctrl = v4l2_subdev_queryctrl,
.querymenu = v4l2_subdev_querymenu,
.s_std = cx25840_s_std,
+ .g_std = cx25840_g_std,
.reset = cx25840_reset,
.load_fw = cx25840_load_fw,
.s_io_pin_config = common_s_io_pin_config,
@@ -1828,6 +5052,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_routing = cx25840_s_video_routing,
.s_mbus_fmt = cx25840_s_mbus_fmt,
.s_stream = cx25840_s_stream,
+ .g_input_status = cx25840_g_input_status,
};
static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 5c42abd..3598dc0 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -70,11 +70,6 @@ config VIDEO_CX88_DVB
To compile this driver as a module, choose M here: the
module will be called cx88-dvb.
-config VIDEO_CX88_MPEG
- tristate
- depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
- default y
-
config VIDEO_CX88_VP3054
tristate "VP-3054 Secondary I2C Bus Support"
default m
@@ -84,3 +79,8 @@ config VIDEO_CX88_VP3054
Conexant 2388x chip and the MT352 demodulator,
which also require support for the VP-3054
Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
+config VIDEO_CX88_MPEG
+ tristate
+ depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
+ default y
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 68d1240..04bf662 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -96,7 +96,7 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 0d719fa..62c7ad0 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1306,7 +1306,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_WINFAST_DTV2000H_J] = {
.name = "WinFast DTV2000 H rev. J",
- .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .tuner_type = TUNER_PHILIPS_FMD1216MEX_MK3,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1643,6 +1643,78 @@ static const struct cx88_board cx88_boards[] = {
.gpio3 = 0x0000,
},
},
+ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = {
+ .name = "Leadtek TV2000 XP Global (SC4100)",
+ .tuner_type = TUNER_XC4000,
+ .tuner_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = { {
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */
+ .gpio3 = 0x0000,
+ } },
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x0000,
+ .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */
+ .gpio3 = 0x0000,
+ },
+ },
+ [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
+ .name = "Leadtek TV2000 XP Global (XC4100)",
+ .tuner_type = TUNER_XC4000,
+ .tuner_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = { {
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6040, /* pin 14 = 1, pin 13 = 0 */
+ .gpio2 = 0x0000,
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */
+ .gpio2 = 0x0000,
+ .gpio3 = 0x0000,
+ }, {
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */
+ .gpio2 = 0x0000,
+ .gpio3 = 0x0000,
+ } },
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0400, /* pin 2 = 0 */
+ .gpio1 = 0x6000, /* pin 14 = 1, pin 13 = 0 */
+ .gpio2 = 0x0000,
+ .gpio3 = 0x0000,
+ },
+ },
[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
.name = "PowerColor RA330", /* Long names may confuse LIRC. */
.tuner_type = TUNER_XC2028,
@@ -2719,6 +2791,21 @@ static const struct cx88_subid cx88_subids[] = {
.subdevice = 0x6618,
.card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
}, {
+ /* TV2000 XP Global [107d:6618] */
+ .subvendor = 0x107d,
+ .subdevice = 0x6619,
+ .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+ }, {
+ /* WinFast TV2000 XP Global with XC4000 tuner */
+ .subvendor = 0x107d,
+ .subdevice = 0x6f36,
+ .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
+ }, {
+ /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
+ .subvendor = 0x107d,
+ .subdevice = 0x6f43,
+ .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
+ }, {
.subvendor = 0xb034,
.subdevice = 0x3034,
.card = CX88_BOARD_PROF_7301,
@@ -3075,6 +3162,8 @@ static int cx88_xc4000_tuner_callback(struct cx88_core *core,
switch (core->boardnr) {
case CX88_BOARD_WINFAST_DTV1800H_XC4000:
case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
return cx88_xc4000_winfast2000h_plus_callback(core,
command, arg);
}
@@ -3232,6 +3321,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
cx_set(MO_GP0_IO, 0x00001010);
break;
+ case CX88_BOARD_WINFAST_DTV2000H_J:
case CX88_BOARD_HAUPPAUGE_HVR3000:
case CX88_BOARD_HAUPPAUGE_HVR4000:
/* Init GPIO */
@@ -3250,6 +3340,8 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
case CX88_BOARD_WINFAST_DTV1800H_XC4000:
case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
cx88_xc4000_winfast2000h_plus_callback(core,
XC4000_TUNER_RESET, 0);
break;
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index cf3d33a..003937c 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -815,9 +815,9 @@ static const u8 samsung_smt_7020_inittab[] = {
};
-static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx8802_dev *dev = fe->dvb->priv;
u8 buf[4];
u32 div;
@@ -827,14 +827,14 @@ static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe,
.buf = buf,
.len = sizeof(buf) };
- div = params->frequency / 125;
+ div = c->frequency / 125;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x84; /* 0xC4 */
buf[3] = 0x00;
- if (params->frequency < 1500000)
+ if (c->frequency < 1500000)
buf[3] |= 0x10;
if (fe->ops.i2c_gate_ctrl)
@@ -954,6 +954,7 @@ static int dvb_register(struct cx8802_dev *dev)
struct cx88_core *core = dev->core;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
int mfe_shared = 0; /* bus not shared by default */
+ int res = -EINVAL;
if (0 != core->i2c_rc) {
printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
@@ -999,7 +1000,6 @@ static int dvb_register(struct cx8802_dev *dev)
}
break;
case CX88_BOARD_WINFAST_DTV2000H:
- case CX88_BOARD_WINFAST_DTV2000H_J:
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -1013,6 +1013,17 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
}
break;
+ case CX88_BOARD_WINFAST_DTV2000H_J:
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &core->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+ &core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216MEX_MK3))
+ goto frontend_detach;
+ }
+ break;
case CX88_BOARD_HAUPPAUGE_HVR3000:
/* MFE frontend 1 */
mfe_shared = 1;
@@ -1566,13 +1577,16 @@ static int dvb_register(struct cx8802_dev *dev)
call_all(core, core, s_power, 0);
/* register everything */
- return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
- &dev->pci->dev, adapter_nr, mfe_shared, NULL);
+ res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ &dev->pci->dev, adapter_nr, mfe_shared, NULL);
+ if (res)
+ goto frontend_detach;
+ return res;
frontend_detach:
core->gate_ctrl = NULL;
videobuf_dvb_dealloc_frontends(&dev->frontends);
- return -EINVAL;
+ return res;
}
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index a1fe0ab..de0f1af 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -132,7 +132,7 @@ static void do_i2c_scan(const char *name, struct i2c_client *c)
}
}
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
{
/* Prevents usage of invalid delay values */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index e614201..ebf448c 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -103,6 +103,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
case CX88_BOARD_WINFAST_DTV1800H_XC4000:
case CX88_BOARD_WINFAST_DTV2000H_PLUS:
case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
auxgpio = gpio;
break;
@@ -302,6 +304,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_WINFAST2000XP_EXPERT:
case CX88_BOARD_WINFAST_DTV1000:
case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+ case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
ir_codes = RC_MAP_WINFAST;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0x8f8;
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index fa8d307..c9659de 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -244,6 +244,8 @@ extern const struct sram_channel const cx88_sram_channels[];
#define CX88_BOARD_TEVII_S464 86
#define CX88_BOARD_WINFAST_DTV2000H_PLUS 87
#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c
index bd443ee..f83baf3 100644
--- a/drivers/media/video/davinci/dm355_ccdc.c
+++ b/drivers/media/video/davinci/dm355_ccdc.c
@@ -1069,15 +1069,4 @@ static struct platform_driver dm355_ccdc_driver = {
.probe = dm355_ccdc_probe,
};
-static int __init dm355_ccdc_init(void)
-{
- return platform_driver_register(&dm355_ccdc_driver);
-}
-
-static void __exit dm355_ccdc_exit(void)
-{
- platform_driver_unregister(&dm355_ccdc_driver);
-}
-
-module_init(dm355_ccdc_init);
-module_exit(dm355_ccdc_exit);
+module_platform_driver(dm355_ccdc_driver);
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c
index 8051c29..9303fe5 100644
--- a/drivers/media/video/davinci/dm644x_ccdc.c
+++ b/drivers/media/video/davinci/dm644x_ccdc.c
@@ -1078,15 +1078,4 @@ static struct platform_driver dm644x_ccdc_driver = {
.probe = dm644x_ccdc_probe,
};
-static int __init dm644x_ccdc_init(void)
-{
- return platform_driver_register(&dm644x_ccdc_driver);
-}
-
-static void __exit dm644x_ccdc_exit(void)
-{
- platform_driver_unregister(&dm644x_ccdc_driver);
-}
-
-module_init(dm644x_ccdc_init);
-module_exit(dm644x_ccdc_exit);
+module_platform_driver(dm644x_ccdc_driver);
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c
index 29c29c6..1e63852 100644
--- a/drivers/media/video/davinci/isif.c
+++ b/drivers/media/video/davinci/isif.c
@@ -1156,17 +1156,6 @@ static struct platform_driver isif_driver = {
.probe = isif_probe,
};
-static int __init isif_init(void)
-{
- return platform_driver_register(&isif_driver);
-}
-
-static void isif_exit(void)
-{
- platform_driver_unregister(&isif_driver);
-}
-
-module_init(isif_init);
-module_exit(isif_exit);
+module_platform_driver(isif_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/video/davinci/vpbe.c
index d773d30..c4a82a1 100644
--- a/drivers/media/video/davinci/vpbe.c
+++ b/drivers/media/video/davinci/vpbe.c
@@ -141,11 +141,12 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
return 0;
}
-static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode)
+static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode,
+ int output_index)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
struct vpbe_enc_mode_info var;
- int curr_output = vpbe_dev->current_out_index;
+ int curr_output = output_index;
int i;
if (NULL == mode)
@@ -245,6 +246,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
struct encoder_config_info *curr_enc_info =
vpbe_current_encoder_info(vpbe_dev);
struct vpbe_config *cfg = vpbe_dev->cfg;
+ struct venc_platform_data *venc_device = vpbe_dev->venc_device;
+ enum v4l2_mbus_pixelcode if_params;
int enc_out_index;
int sd_index;
int ret = 0;
@@ -274,6 +277,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
goto out;
}
+ if_params = cfg->outputs[index].if_params;
+ venc_device->setup_if_config(if_params);
if (ret)
goto out;
}
@@ -293,7 +298,7 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
* encoder.
*/
ret = vpbe_get_mode_info(vpbe_dev,
- cfg->outputs[index].default_mode);
+ cfg->outputs[index].default_mode, index);
if (!ret) {
struct osd_state *osd_device = vpbe_dev->osd_device;
@@ -367,6 +372,11 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
s_dv_preset, dv_preset);
+ if (!ret && (vpbe_dev->amp != NULL)) {
+ /* Call amplifier subdevice */
+ ret = v4l2_subdev_call(vpbe_dev->amp, video,
+ s_dv_preset, dv_preset);
+ }
/* set the lcd controller output for the given mode */
if (!ret) {
struct osd_state *osd_device = vpbe_dev->osd_device;
@@ -566,6 +576,8 @@ static int platform_device_get(struct device *dev, void *data)
if (strcmp("vpbe-osd", pdev->name) == 0)
vpbe_dev->osd_device = platform_get_drvdata(pdev);
+ if (strcmp("vpbe-venc", pdev->name) == 0)
+ vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
return 0;
}
@@ -584,6 +596,7 @@ static int platform_device_get(struct device *dev, void *data)
static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
{
struct encoder_config_info *enc_info;
+ struct amp_config_info *amp_info;
struct v4l2_subdev **enc_subdev;
struct osd_state *osd_device;
struct i2c_adapter *i2c_adap;
@@ -704,6 +717,32 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
" currently not supported");
}
+ /* Add amplifier subdevice for dm365 */
+ if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
+ vpbe_dev->cfg->amp != NULL) {
+ amp_info = vpbe_dev->cfg->amp;
+ if (amp_info->is_i2c) {
+ vpbe_dev->amp = v4l2_i2c_new_subdev_board(
+ &vpbe_dev->v4l2_dev, i2c_adap,
+ &amp_info->board_info, NULL);
+ if (!vpbe_dev->amp) {
+ v4l2_err(&vpbe_dev->v4l2_dev,
+ "amplifier %s failed to register",
+ amp_info->module_name);
+ ret = -ENODEV;
+ goto vpbe_fail_amp_register;
+ }
+ v4l2_info(&vpbe_dev->v4l2_dev,
+ "v4l2 sub device %s registered\n",
+ amp_info->module_name);
+ } else {
+ vpbe_dev->amp = NULL;
+ v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
+ " currently not supported");
+ }
+ } else {
+ vpbe_dev->amp = NULL;
+ }
/* set the current encoder and output to that of venc by default */
vpbe_dev->current_sd_index = 0;
@@ -731,6 +770,8 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
/* TBD handling of bootargs for default output and mode */
return 0;
+vpbe_fail_amp_register:
+ kfree(vpbe_dev->amp);
vpbe_fail_sd_register:
kfree(vpbe_dev->encoders);
vpbe_fail_v4l2_device:
@@ -757,6 +798,7 @@ static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
clk_put(vpbe_dev->dac_clk);
+ kfree(vpbe_dev->amp);
kfree(vpbe_dev->encoders);
vpbe_dev->initialized = 0;
/* disable vpss clocks */
@@ -811,8 +853,10 @@ static __devinit int vpbe_probe(struct platform_device *pdev)
if (cfg->outputs->num_modes > 0)
vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
- else
+ else {
+ kfree(vpbe_dev);
return -ENODEV;
+ }
/* set the driver data in platform device */
platform_set_drvdata(pdev, vpbe_dev);
@@ -839,26 +883,4 @@ static struct platform_driver vpbe_driver = {
.remove = vpbe_remove,
};
-/**
- * vpbe_init: initialize the vpbe driver
- *
- * This function registers device and driver to the kernel
- */
-static __init int vpbe_init(void)
-{
- return platform_driver_register(&vpbe_driver);
-}
-
-/**
- * vpbe_cleanup : cleanup function for vpbe driver
- *
- * This will un-registers the device and driver to the kernel
- */
-static void vpbe_cleanup(void)
-{
- platform_driver_unregister(&vpbe_driver);
-}
-
-/* Function for module initialization and cleanup */
-module_init(vpbe_init);
-module_exit(vpbe_cleanup);
+module_platform_driver(vpbe_driver);
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
index 8588a86..1f3b1c7 100644
--- a/drivers/media/video/davinci/vpbe_display.c
+++ b/drivers/media/video/davinci/vpbe_display.c
@@ -1746,15 +1746,16 @@ static __devinit int vpbe_display_probe(struct platform_device *pdev)
for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
err = -ENODEV;
- goto probe_out;
+ goto probe_out_irq;
}
}
printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
return 0;
-probe_out:
+probe_out_irq:
free_irq(res->start, disp_dev);
+probe_out:
for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
/* Get the pointer to the layer object */
vpbe_display_layer = disp_dev->dev[k];
@@ -1816,43 +1817,7 @@ static struct platform_driver vpbe_display_driver = {
.remove = __devexit_p(vpbe_display_remove),
};
-/*
- * vpbe_display_init()
- * This function registers device and driver to the kernel, requests irq
- * handler and allocates memory for layer objects
- */
-static __devinit int vpbe_display_init(void)
-{
- int err;
-
- printk(KERN_DEBUG "vpbe_display_init\n");
-
- /* Register driver to the kernel */
- err = platform_driver_register(&vpbe_display_driver);
- if (0 != err)
- return err;
-
- printk(KERN_DEBUG "vpbe_display_init:"
- "VPBE V4L2 Display Driver V1.0 loaded\n");
- return 0;
-}
-
-/*
- * vpbe_display_cleanup()
- * This function un-registers device and driver to the kernel, frees requested
- * irq handler and de-allocates memory allocated for layer objects.
- */
-static void vpbe_display_cleanup(void)
-{
- printk(KERN_DEBUG "vpbe_display_cleanup\n");
-
- /* platform driver unregister */
- platform_driver_unregister(&vpbe_display_driver);
-}
-
-/* Function for module initialization and cleanup */
-module_init(vpbe_display_init);
-module_exit(vpbe_display_cleanup);
+module_platform_driver(vpbe_display_driver);
MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/video/davinci/vpbe_osd.c
index ceccf43..d6488b7 100644
--- a/drivers/media/video/davinci/vpbe_osd.c
+++ b/drivers/media/video/davinci/vpbe_osd.c
@@ -248,11 +248,29 @@ static void _osd_set_rec601_attenuation(struct osd_state *sd,
osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
enable ? OSD_OSDWIN0MD_ATN0E : 0,
OSD_OSDWIN0MD);
+ if (sd->vpbe_type == VPBE_VERSION_1)
+ osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
+ enable ? OSD_OSDWIN0MD_ATN0E : 0,
+ OSD_OSDWIN0MD);
+ else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+ (sd->vpbe_type == VPBE_VERSION_2))
+ osd_modify(sd, OSD_EXTMODE_ATNOSD0EN,
+ enable ? OSD_EXTMODE_ATNOSD0EN : 0,
+ OSD_EXTMODE);
break;
case OSDWIN_OSD1:
osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
enable ? OSD_OSDWIN1MD_ATN1E : 0,
OSD_OSDWIN1MD);
+ if (sd->vpbe_type == VPBE_VERSION_1)
+ osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
+ enable ? OSD_OSDWIN1MD_ATN1E : 0,
+ OSD_OSDWIN1MD);
+ else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+ (sd->vpbe_type == VPBE_VERSION_2))
+ osd_modify(sd, OSD_EXTMODE_ATNOSD1EN,
+ enable ? OSD_EXTMODE_ATNOSD1EN : 0,
+ OSD_EXTMODE);
break;
}
}
@@ -273,15 +291,71 @@ static void _osd_set_blending_factor(struct osd_state *sd,
}
}
+static void _osd_enable_rgb888_pixblend(struct osd_state *sd,
+ enum osd_win_layer osdwin)
+{
+
+ osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL);
+ switch (osdwin) {
+ case OSDWIN_OSD0:
+ osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR,
+ OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE);
+ break;
+ case OSDWIN_OSD1:
+ osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR,
+ OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE);
+ break;
+ }
+}
+
static void _osd_enable_color_key(struct osd_state *sd,
enum osd_win_layer osdwin,
unsigned colorkey,
enum osd_pix_format pixfmt)
{
switch (pixfmt) {
+ case PIXFMT_1BPP:
+ case PIXFMT_2BPP:
+ case PIXFMT_4BPP:
+ case PIXFMT_8BPP:
+ if (sd->vpbe_type == VPBE_VERSION_3) {
+ switch (osdwin) {
+ case OSDWIN_OSD0:
+ osd_modify(sd, OSD_TRANSPBMPIDX_BMP0,
+ colorkey <<
+ OSD_TRANSPBMPIDX_BMP0_SHIFT,
+ OSD_TRANSPBMPIDX);
+ break;
+ case OSDWIN_OSD1:
+ osd_modify(sd, OSD_TRANSPBMPIDX_BMP1,
+ colorkey <<
+ OSD_TRANSPBMPIDX_BMP1_SHIFT,
+ OSD_TRANSPBMPIDX);
+ break;
+ }
+ }
+ break;
case PIXFMT_RGB565:
- osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
- OSD_TRANSPVAL);
+ if (sd->vpbe_type == VPBE_VERSION_1)
+ osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
+ OSD_TRANSPVAL);
+ else if (sd->vpbe_type == VPBE_VERSION_3)
+ osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
+ OSD_TRANSPVALL);
+ break;
+ case PIXFMT_YCbCrI:
+ case PIXFMT_YCrCbI:
+ if (sd->vpbe_type == VPBE_VERSION_3)
+ osd_modify(sd, OSD_TRANSPVALU_Y, colorkey,
+ OSD_TRANSPVALU);
+ break;
+ case PIXFMT_RGB888:
+ if (sd->vpbe_type == VPBE_VERSION_3) {
+ osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL,
+ OSD_TRANSPVALL);
+ osd_modify(sd, OSD_TRANSPVALU_RGBU, colorkey >> 16,
+ OSD_TRANSPVALU);
+ }
break;
default:
break;
@@ -470,23 +544,188 @@ static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
return 0;
}
+#define OSD_SRC_ADDR_HIGH4 0x7800000
+#define OSD_SRC_ADDR_HIGH7 0x7F0000
+#define OSD_SRCADD_OFSET_SFT 23
+#define OSD_SRCADD_ADD_SFT 16
+#define OSD_WINADL_MASK 0xFFFF
+#define OSD_WINOFST_MASK 0x1000
+#define VPBE_REG_BASE 0x80000000
+
static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
unsigned long fb_base_phys,
unsigned long cbcr_ofst)
{
- switch (layer) {
- case WIN_OSD0:
- osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
- break;
- case WIN_VID0:
- osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
- break;
- case WIN_OSD1:
- osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
- break;
- case WIN_VID1:
- osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
- break;
+
+ if (sd->vpbe_type == VPBE_VERSION_1) {
+ switch (layer) {
+ case WIN_OSD0:
+ osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
+ break;
+ case WIN_VID0:
+ osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
+ break;
+ case WIN_OSD1:
+ osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
+ break;
+ case WIN_VID1:
+ osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
+ break;
+ }
+ } else if (sd->vpbe_type == VPBE_VERSION_3) {
+ unsigned long fb_offset_32 =
+ (fb_base_phys - VPBE_REG_BASE) >> 5;
+
+ switch (layer) {
+ case WIN_OSD0:
+ osd_modify(sd, OSD_OSDWINADH_O0AH,
+ fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+ OSD_OSDWINADH_O0AH_SHIFT),
+ OSD_OSDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_OSDWIN0ADL_O0AL,
+ OSD_OSDWIN0ADL);
+ break;
+ case WIN_VID0:
+ osd_modify(sd, OSD_VIDWINADH_V0AH,
+ fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V0AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_VIDWIN0ADL_V0AL,
+ OSD_VIDWIN0ADL);
+ break;
+ case WIN_OSD1:
+ osd_modify(sd, OSD_OSDWINADH_O1AH,
+ fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+ OSD_OSDWINADH_O1AH_SHIFT),
+ OSD_OSDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_OSDWIN1ADL_O1AL,
+ OSD_OSDWIN1ADL);
+ break;
+ case WIN_VID1:
+ osd_modify(sd, OSD_VIDWINADH_V1AH,
+ fb_offset_32 >> (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V1AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_VIDWIN1ADL_V1AL,
+ OSD_VIDWIN1ADL);
+ break;
+ }
+ } else if (sd->vpbe_type == VPBE_VERSION_2) {
+ struct osd_window_state *win = &sd->win[layer];
+ unsigned long fb_offset_32, cbcr_offset_32;
+
+ fb_offset_32 = fb_base_phys - VPBE_REG_BASE;
+ if (cbcr_ofst)
+ cbcr_offset_32 = cbcr_ofst;
+ else
+ cbcr_offset_32 = win->lconfig.line_length *
+ win->lconfig.ysize;
+ cbcr_offset_32 += fb_offset_32;
+ fb_offset_32 = fb_offset_32 >> 5;
+ cbcr_offset_32 = cbcr_offset_32 >> 5;
+ /*
+ * DM365: start address is 27-bit long address b26 - b23 are
+ * in offset register b12 - b9, and * bit 26 has to be '1'
+ */
+ if (win->lconfig.pixfmt == PIXFMT_NV12) {
+ switch (layer) {
+ case WIN_VID0:
+ case WIN_VID1:
+ /* Y is in VID0 */
+ osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
+ ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) |
+ OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
+ osd_modify(sd, OSD_VIDWINADH_V0AH,
+ (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V0AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+ OSD_VIDWIN0ADL);
+ /* CbCr is in VID1 */
+ osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
+ ((cbcr_offset_32 &
+ OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) |
+ OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
+ osd_modify(sd, OSD_VIDWINADH_V1AH,
+ (cbcr_offset_32 &
+ OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V1AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, cbcr_offset_32 & OSD_WINADL_MASK,
+ OSD_VIDWIN1ADL);
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (layer) {
+ case WIN_OSD0:
+ osd_modify(sd, OSD_OSDWIN0OFST_O0AH,
+ ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
+ OSD_OSDWIN0OFST);
+ osd_modify(sd, OSD_OSDWINADH_O0AH,
+ (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_OSDWINADH_O0AH_SHIFT), OSD_OSDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+ OSD_OSDWIN0ADL);
+ break;
+ case WIN_VID0:
+ if (win->lconfig.pixfmt != PIXFMT_NV12) {
+ osd_modify(sd, OSD_VIDWIN0OFST_V0AH,
+ ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) |
+ OSD_WINOFST_MASK, OSD_VIDWIN0OFST);
+ osd_modify(sd, OSD_VIDWINADH_V0AH,
+ (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V0AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+ OSD_VIDWIN0ADL);
+ }
+ break;
+ case WIN_OSD1:
+ osd_modify(sd, OSD_OSDWIN1OFST_O1AH,
+ ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK,
+ OSD_OSDWIN1OFST);
+ osd_modify(sd, OSD_OSDWINADH_O1AH,
+ (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_OSDWINADH_O1AH_SHIFT),
+ OSD_OSDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+ OSD_OSDWIN1ADL);
+ break;
+ case WIN_VID1:
+ if (win->lconfig.pixfmt != PIXFMT_NV12) {
+ osd_modify(sd, OSD_VIDWIN1OFST_V1AH,
+ ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >>
+ (OSD_SRCADD_OFSET_SFT -
+ OSD_WINOFST_AH_SHIFT)) |
+ OSD_WINOFST_MASK, OSD_VIDWIN1OFST);
+ osd_modify(sd, OSD_VIDWINADH_V1AH,
+ (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >>
+ (OSD_SRCADD_ADD_SFT -
+ OSD_VIDWINADH_V1AH_SHIFT),
+ OSD_VIDWINADH);
+ osd_write(sd, fb_offset_32 & OSD_WINADL_MASK,
+ OSD_VIDWIN1ADL);
+ }
+ break;
+ }
}
}
@@ -545,7 +784,7 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
{
struct osd_state *osd = sd;
struct osd_window_state *win = &osd->win[layer];
- int bad_config;
+ int bad_config = 0;
/* verify that the pixel format is compatible with the layer */
switch (lconfig->pixfmt) {
@@ -554,17 +793,25 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
case PIXFMT_4BPP:
case PIXFMT_8BPP:
case PIXFMT_RGB565:
- bad_config = !is_osd_win(layer);
+ if (osd->vpbe_type == VPBE_VERSION_1)
+ bad_config = !is_vid_win(layer);
break;
case PIXFMT_YCbCrI:
case PIXFMT_YCrCbI:
bad_config = !is_vid_win(layer);
break;
case PIXFMT_RGB888:
- bad_config = !is_vid_win(layer);
+ if (osd->vpbe_type == VPBE_VERSION_1)
+ bad_config = !is_vid_win(layer);
+ else if ((osd->vpbe_type == VPBE_VERSION_3) ||
+ (osd->vpbe_type == VPBE_VERSION_2))
+ bad_config = !is_osd_win(layer);
break;
case PIXFMT_NV12:
- bad_config = 1;
+ if (osd->vpbe_type != VPBE_VERSION_2)
+ bad_config = 1;
+ else
+ bad_config = is_osd_win(layer);
break;
case PIXFMT_OSD_ATTR:
bad_config = (layer != WIN_OSD1);
@@ -584,7 +831,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
/* DM6446: */
/* only one OSD window at a time can use RGB pixel formats */
- if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
+ if ((osd->vpbe_type == VPBE_VERSION_1) &&
+ is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
enum osd_pix_format pixfmt;
if (layer == WIN_OSD0)
pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
@@ -602,7 +850,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
}
/* DM6446: only one video window at a time can use RGB888 */
- if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) {
+ if ((osd->vpbe_type == VPBE_VERSION_1) && is_vid_win(layer) &&
+ lconfig->pixfmt == PIXFMT_RGB888) {
enum osd_pix_format pixfmt;
if (layer == WIN_VID0)
@@ -652,7 +901,8 @@ static void _osd_disable_vid_rgb888(struct osd_state *sd)
* The caller must ensure that neither video window is currently
* configured for RGB888 pixel format.
*/
- osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+ if (sd->vpbe_type == VPBE_VERSION_1)
+ osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
}
static void _osd_enable_vid_rgb888(struct osd_state *sd,
@@ -665,13 +915,14 @@ static void _osd_enable_vid_rgb888(struct osd_state *sd,
* currently configured for RGB888 pixel format, as this routine will
* disable RGB888 pixel format for the other window.
*/
- if (layer == WIN_VID0) {
- osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
- OSD_MISCCTL_RGBEN, OSD_MISCCTL);
- } else if (layer == WIN_VID1) {
- osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
- OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
- OSD_MISCCTL);
+ if (sd->vpbe_type == VPBE_VERSION_1) {
+ if (layer == WIN_VID0)
+ osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+ OSD_MISCCTL_RGBEN, OSD_MISCCTL);
+ else if (layer == WIN_VID1)
+ osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+ OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
+ OSD_MISCCTL);
}
}
@@ -697,9 +948,30 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
switch (layer) {
case WIN_OSD0:
- winmd_mask |= OSD_OSDWIN0MD_RGB0E;
- if (lconfig->pixfmt == PIXFMT_RGB565)
- winmd |= OSD_OSDWIN0MD_RGB0E;
+ if (sd->vpbe_type == VPBE_VERSION_1) {
+ winmd_mask |= OSD_OSDWIN0MD_RGB0E;
+ if (lconfig->pixfmt == PIXFMT_RGB565)
+ winmd |= OSD_OSDWIN0MD_RGB0E;
+ } else if ((sd->vpbe_type == VPBE_VERSION_3) ||
+ (sd->vpbe_type == VPBE_VERSION_2)) {
+ winmd_mask |= OSD_OSDWIN0MD_BMP0MD;
+ switch (lconfig->pixfmt) {
+ case PIXFMT_RGB565:
+ winmd |= (1 <<
+ OSD_OSDWIN0MD_BMP0MD_SHIFT);
+ break;
+ case PIXFMT_RGB888:
+ winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
+ _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0);
+ break;
+ case PIXFMT_YCbCrI:
+ case PIXFMT_YCrCbI:
+ winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT);
+ break;
+ default:
+ break;
+ }
+ }
winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
@@ -749,12 +1021,59 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
* For YUV420P format the register contents are
* duplicated in both VID registers
*/
+ if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ (lconfig->pixfmt == PIXFMT_NV12)) {
+ /* other window also */
+ if (lconfig->interlaced) {
+ winmd_mask |= OSD_VIDWINMD_VFF1;
+ winmd |= OSD_VIDWINMD_VFF1;
+ osd_modify(sd, winmd_mask, winmd,
+ OSD_VIDWINMD);
+ }
+
+ osd_modify(sd, OSD_MISCCTL_S420D,
+ OSD_MISCCTL_S420D, OSD_MISCCTL);
+ osd_write(sd, lconfig->line_length >> 5,
+ OSD_VIDWIN1OFST);
+ osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
+ osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
+ /*
+ * if NV21 pixfmt and line length not 32B
+ * aligned (e.g. NTSC), Need to set window
+ * X pixel size to be 32B aligned as well
+ */
+ if (lconfig->xsize % 32) {
+ osd_write(sd,
+ ((lconfig->xsize + 31) & ~31),
+ OSD_VIDWIN1XL);
+ osd_write(sd,
+ ((lconfig->xsize + 31) & ~31),
+ OSD_VIDWIN0XL);
+ }
+ } else if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ (lconfig->pixfmt != PIXFMT_NV12)) {
+ osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
+ OSD_MISCCTL);
+ }
+
if (lconfig->interlaced) {
osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
+ if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ lconfig->pixfmt == PIXFMT_NV12) {
+ osd_write(sd, lconfig->ypos >> 1,
+ OSD_VIDWIN1YP);
+ osd_write(sd, lconfig->ysize >> 1,
+ OSD_VIDWIN1YL);
+ }
} else {
osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
+ if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ lconfig->pixfmt == PIXFMT_NV12) {
+ osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
+ osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
+ }
}
break;
case WIN_OSD1:
@@ -764,14 +1083,43 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
* attribute mode to a normal mode.
*/
if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
- winmd_mask |=
- OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E |
- OSD_OSDWIN1MD_CLUTS1 |
- OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
+ if (sd->vpbe_type == VPBE_VERSION_1) {
+ winmd_mask |= OSD_OSDWIN1MD_ATN1E |
+ OSD_OSDWIN1MD_RGB1E | OSD_OSDWIN1MD_CLUTS1 |
+ OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
+ } else {
+ winmd_mask |= OSD_OSDWIN1MD_BMP1MD |
+ OSD_OSDWIN1MD_CLUTS1 | OSD_OSDWIN1MD_BLND1 |
+ OSD_OSDWIN1MD_TE1;
+ }
} else {
- winmd_mask |= OSD_OSDWIN1MD_RGB1E;
- if (lconfig->pixfmt == PIXFMT_RGB565)
- winmd |= OSD_OSDWIN1MD_RGB1E;
+ if (sd->vpbe_type == VPBE_VERSION_1) {
+ winmd_mask |= OSD_OSDWIN1MD_RGB1E;
+ if (lconfig->pixfmt == PIXFMT_RGB565)
+ winmd |= OSD_OSDWIN1MD_RGB1E;
+ } else if ((sd->vpbe_type == VPBE_VERSION_3)
+ || (sd->vpbe_type == VPBE_VERSION_2)) {
+ winmd_mask |= OSD_OSDWIN1MD_BMP1MD;
+ switch (lconfig->pixfmt) {
+ case PIXFMT_RGB565:
+ winmd |=
+ (1 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+ break;
+ case PIXFMT_RGB888:
+ winmd |=
+ (2 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+ _osd_enable_rgb888_pixblend(sd,
+ OSDWIN_OSD1);
+ break;
+ case PIXFMT_YCbCrI:
+ case PIXFMT_YCrCbI:
+ winmd |=
+ (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT);
+ break;
+ default:
+ break;
+ }
+ }
winmd_mask |= OSD_OSDWIN1MD_BMW1;
switch (lconfig->pixfmt) {
@@ -822,15 +1170,45 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
* For YUV420P format the register contents are
* duplicated in both VID registers
*/
- osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
- OSD_MISCCTL);
+ if (sd->vpbe_type == VPBE_VERSION_2) {
+ if (lconfig->pixfmt == PIXFMT_NV12) {
+ /* other window also */
+ if (lconfig->interlaced) {
+ winmd_mask |= OSD_VIDWINMD_VFF0;
+ winmd |= OSD_VIDWINMD_VFF0;
+ osd_modify(sd, winmd_mask, winmd,
+ OSD_VIDWINMD);
+ }
+ osd_modify(sd, OSD_MISCCTL_S420D,
+ OSD_MISCCTL_S420D, OSD_MISCCTL);
+ osd_write(sd, lconfig->line_length >> 5,
+ OSD_VIDWIN0OFST);
+ osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
+ osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
+ } else {
+ osd_modify(sd, OSD_MISCCTL_S420D,
+ ~OSD_MISCCTL_S420D, OSD_MISCCTL);
+ }
+ }
if (lconfig->interlaced) {
osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
+ if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ lconfig->pixfmt == PIXFMT_NV12) {
+ osd_write(sd, lconfig->ypos >> 1,
+ OSD_VIDWIN0YP);
+ osd_write(sd, lconfig->ysize >> 1,
+ OSD_VIDWIN0YL);
+ }
} else {
osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
+ if ((sd->vpbe_type == VPBE_VERSION_2) &&
+ lconfig->pixfmt == PIXFMT_NV12) {
+ osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
+ osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
+ }
}
break;
}
@@ -1089,6 +1467,11 @@ static void _osd_init(struct osd_state *sd)
osd_write(sd, 0, OSD_OSDWIN1MD);
osd_write(sd, 0, OSD_RECTCUR);
osd_write(sd, 0, OSD_MISCCTL);
+ if (sd->vpbe_type == VPBE_VERSION_3) {
+ osd_write(sd, 0, OSD_VBNDRY);
+ osd_write(sd, 0, OSD_EXTMODE);
+ osd_write(sd, OSD_MISCCTL_DMANG, OSD_MISCCTL);
+ }
}
static void osd_set_left_margin(struct osd_state *sd, u32 val)
@@ -1110,6 +1493,14 @@ static int osd_initialize(struct osd_state *osd)
/* set default Cb/Cr order */
osd->yc_pixfmt = PIXFMT_YCbCrI;
+ if (osd->vpbe_type == VPBE_VERSION_3) {
+ /*
+ * ROM CLUT1 on the DM355 is similar (identical?) to ROM CLUT0
+ * on the DM6446, so make ROM_CLUT1 the default on the DM355.
+ */
+ osd->rom_clut = ROM_CLUT1;
+ }
+
_osd_set_field_inversion(osd, osd->field_inversion);
_osd_set_rom_clut(osd, osd->rom_clut);
@@ -1208,23 +1599,7 @@ static struct platform_driver osd_driver = {
},
};
-static int osd_init(void)
-{
- if (platform_driver_register(&osd_driver)) {
- printk(KERN_ERR "Unable to register davinci osd driver\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void osd_exit(void)
-{
- platform_driver_unregister(&osd_driver);
-}
-
-module_init(osd_init);
-module_exit(osd_exit);
+module_platform_driver(osd_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/video/davinci/vpbe_venc.c
index 03a3e5c..00e80f5 100644
--- a/drivers/media/video/davinci/vpbe_venc.c
+++ b/drivers/media/video/davinci/vpbe_venc.c
@@ -99,6 +99,8 @@ static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
return val;
}
+#define VDAC_COMPONENT 0x543
+#define VDAC_S_VIDEO 0x210
/* This function sets the dac of the VPBE for various outputs
*/
static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
@@ -109,11 +111,12 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
venc_write(sd, VENC_DACSEL, 0);
break;
case 1:
- v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n");
- venc_write(sd, VENC_DACSEL, 0x210);
+ v4l2_dbg(debug, 1, sd, "Setting output to Component\n");
+ venc_write(sd, VENC_DACSEL, VDAC_COMPONENT);
break;
- case 2:
- venc_write(sd, VENC_DACSEL, 0x543);
+ case 2:
+ v4l2_dbg(debug, 1, sd, "Setting output to S-video\n");
+ venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO);
break;
default:
return -EINVAL;
@@ -124,6 +127,8 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
{
+ struct venc_state *venc = to_state(sd);
+ struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
if (benable) {
@@ -155,7 +160,8 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
/* Disable LCD output control (accepting default polarity) */
venc_write(sd, VENC_LCDOUT, 0);
- venc_write(sd, VENC_CMPNT, 0x100);
+ if (pdata->venc_type != VPBE_VERSION_3)
+ venc_write(sd, VENC_CMPNT, 0x100);
venc_write(sd, VENC_HSPLS, 0);
venc_write(sd, VENC_HINT, 0);
venc_write(sd, VENC_HSTART, 0);
@@ -178,11 +184,14 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
}
}
+#define VDAC_CONFIG_SD_V3 0x0E21A6B6
+#define VDAC_CONFIG_SD_V2 0x081141CF
/*
* setting NTSC mode
*/
static int venc_set_ntsc(struct v4l2_subdev *sd)
{
+ u32 val;
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
@@ -195,12 +204,22 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
venc_enabledigitaloutput(sd, 0);
- /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
- venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
- /* Set REC656 Mode */
- venc_write(sd, VENC_YCCCTL, 0x1);
- venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
- venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
+ if (pdata->venc_type == VPBE_VERSION_3) {
+ venc_write(sd, VENC_CLKCTL, 0x01);
+ venc_write(sd, VENC_VIDCTL, 0);
+ val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
+ } else if (pdata->venc_type == VPBE_VERSION_2) {
+ venc_write(sd, VENC_CLKCTL, 0x01);
+ venc_write(sd, VENC_VIDCTL, 0);
+ vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
+ } else {
+ /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+ venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+ /* Set REC656 Mode */
+ venc_write(sd, VENC_YCCCTL, 0x1);
+ venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
+ venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
+ }
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
@@ -220,6 +239,7 @@ static int venc_set_ntsc(struct v4l2_subdev *sd)
static int venc_set_pal(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
+ struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
@@ -230,10 +250,20 @@ static int venc_set_pal(struct v4l2_subdev *sd)
venc_enabledigitaloutput(sd, 0);
- /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
- venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
- /* Set REC656 Mode */
- venc_write(sd, VENC_YCCCTL, 0x1);
+ if (pdata->venc_type == VPBE_VERSION_3) {
+ venc_write(sd, VENC_CLKCTL, 0x1);
+ venc_write(sd, VENC_VIDCTL, 0);
+ vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
+ } else if (pdata->venc_type == VPBE_VERSION_2) {
+ venc_write(sd, VENC_CLKCTL, 0x1);
+ venc_write(sd, VENC_VIDCTL, 0);
+ vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
+ } else {
+ /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
+ venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
+ /* Set REC656 Mode */
+ venc_write(sd, VENC_YCCCTL, 0x1);
+ }
venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
VENC_SYNCCTL_OVD);
@@ -252,6 +282,7 @@ static int venc_set_pal(struct v4l2_subdev *sd)
return 0;
}
+#define VDAC_CONFIG_HD_V2 0x081141EF
/*
* venc_set_480p59_94
*
@@ -263,6 +294,9 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
+ if ((pdata->venc_type != VPBE_VERSION_1) &&
+ (pdata->venc_type != VPBE_VERSION_2))
+ return -EINVAL;
/* Setup clock at VPSS & VENC for SD */
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
@@ -270,12 +304,18 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
venc_enabledigitaloutput(sd, 0);
+ if (pdata->venc_type == VPBE_VERSION_2)
+ vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
- venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
- VENC_VDPRO_DAFRQ);
- venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
- VENC_VDPRO_DAUPS);
+
+ if (pdata->venc_type == VPBE_VERSION_1) {
+ venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+ VENC_VDPRO_DAFRQ);
+ venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+ VENC_VDPRO_DAUPS);
+ }
+
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
@@ -302,19 +342,27 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
+ if ((pdata->venc_type != VPBE_VERSION_1) &&
+ (pdata->venc_type != VPBE_VERSION_2))
+ return -EINVAL;
/* Setup clock at VPSS & VENC for SD */
if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
return -EINVAL;
venc_enabledigitaloutput(sd, 0);
+ if (pdata->venc_type == VPBE_VERSION_2)
+ vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
- venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
- VENC_VDPRO_DAFRQ);
- venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
- VENC_VDPRO_DAUPS);
+ if (pdata->venc_type == VPBE_VERSION_1) {
+ venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
+ VENC_VDPRO_DAFRQ);
+ venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
+ VENC_VDPRO_DAUPS);
+ }
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
@@ -330,6 +378,63 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
return 0;
}
+/*
+ * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
+ */
+static int venc_set_720p60_internal(struct v4l2_subdev *sd)
+{
+ struct venc_state *venc = to_state(sd);
+ struct venc_platform_data *pdata = venc->pdata;
+
+ if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
+ return -EINVAL;
+
+ venc_enabledigitaloutput(sd, 0);
+
+ venc_write(sd, VENC_OSDCLK0, 0);
+ venc_write(sd, VENC_OSDCLK1, 1);
+
+ venc_write(sd, VENC_VMOD, 0);
+ /* DM365 component HD mode */
+ venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+ VENC_VMOD_VIE);
+ venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+ venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
+ VENC_VMOD_TVTYP);
+ venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+ venc_write(sd, VENC_XHINTVL, 0);
+ return 0;
+}
+
+/*
+ * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
+ */
+static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
+{
+ struct venc_state *venc = to_state(sd);
+ struct venc_platform_data *pdata = venc->pdata;
+
+ if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
+ return -EINVAL;
+
+ venc_enabledigitaloutput(sd, 0);
+
+ venc_write(sd, VENC_OSDCLK0, 0);
+ venc_write(sd, VENC_OSDCLK1, 1);
+
+
+ venc_write(sd, VENC_VMOD, 0);
+ /* DM365 component HD mode */
+ venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
+ VENC_VMOD_VIE);
+ venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
+ venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
+ VENC_VMOD_TVTYP);
+ venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
+ venc_write(sd, VENC_XHINTVL, 0);
+ return 0;
+}
+
static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
{
v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
@@ -345,13 +450,30 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
static int venc_s_dv_preset(struct v4l2_subdev *sd,
struct v4l2_dv_preset *dv_preset)
{
+ struct venc_state *venc = to_state(sd);
+ int ret;
+
v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
if (dv_preset->preset == V4L2_DV_576P50)
return venc_set_576p50(sd);
else if (dv_preset->preset == V4L2_DV_480P59_94)
return venc_set_480p59_94(sd);
-
+ else if ((dv_preset->preset == V4L2_DV_720P60) &&
+ (venc->pdata->venc_type == VPBE_VERSION_2)) {
+ /* TBD setup internal 720p mode here */
+ ret = venc_set_720p60_internal(sd);
+ /* for DM365 VPBE, there is DAC inside */
+ vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+ return ret;
+ } else if ((dv_preset->preset == V4L2_DV_1080I30) &&
+ (venc->pdata->venc_type == VPBE_VERSION_2)) {
+ /* TBD setup internal 1080i mode here */
+ ret = venc_set_1080i30_internal(sd);
+ /* for DM365 VPBE, there is DAC inside */
+ vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
+ return ret;
+ }
return -EINVAL;
}
@@ -508,11 +630,41 @@ static int venc_probe(struct platform_device *pdev)
goto release_venc_mem_region;
}
+ if (venc->pdata->venc_type != VPBE_VERSION_1) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(venc->pdev,
+ "Unable to get VDAC_CONFIG address map\n");
+ ret = -ENODEV;
+ goto unmap_venc_io;
+ }
+
+ if (!request_mem_region(res->start,
+ resource_size(res), "venc")) {
+ dev_err(venc->pdev,
+ "Unable to reserve VDAC_CONFIG MMIO region\n");
+ ret = -ENODEV;
+ goto unmap_venc_io;
+ }
+
+ venc->vdaccfg_reg = ioremap_nocache(res->start,
+ resource_size(res));
+ if (!venc->vdaccfg_reg) {
+ dev_err(venc->pdev,
+ "Unable to map VDAC_CONFIG IO space\n");
+ ret = -ENODEV;
+ goto release_vdaccfg_mem_region;
+ }
+ }
spin_lock_init(&venc->lock);
platform_set_drvdata(pdev, venc);
dev_notice(venc->pdev, "VENC sub device probe success\n");
return 0;
+release_vdaccfg_mem_region:
+ release_mem_region(res->start, resource_size(res));
+unmap_venc_io:
+ iounmap(venc->venc_base);
release_venc_mem_region:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
@@ -529,6 +681,11 @@ static int venc_remove(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap((void *)venc->venc_base);
release_mem_region(res->start, resource_size(res));
+ if (venc->pdata->venc_type != VPBE_VERSION_1) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ iounmap((void *)venc->vdaccfg_reg);
+ release_mem_region(res->start, resource_size(res));
+ }
kfree(venc);
return 0;
@@ -543,23 +700,7 @@ static struct platform_driver venc_driver = {
},
};
-static int venc_init(void)
-{
- if (platform_driver_register(&venc_driver)) {
- printk(KERN_ERR "Unable to register venc driver\n");
- return -ENODEV;
- }
- return 0;
-}
-
-static void venc_exit(void)
-{
- platform_driver_unregister(&venc_driver);
- return;
-}
-
-module_init(venc_init);
-module_exit(venc_exit);
+module_platform_driver(venc_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VPBE VENC Driver");
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
index 5b38fc9..20cf271 100644
--- a/drivers/media/video/davinci/vpfe_capture.c
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -2076,20 +2076,4 @@ static struct platform_driver vpfe_driver = {
.remove = __devexit_p(vpfe_remove),
};
-static __init int vpfe_init(void)
-{
- printk(KERN_NOTICE "vpfe_init\n");
- /* Register driver to the kernel */
- return platform_driver_register(&vpfe_driver);
-}
-
-/*
- * vpfe_cleanup : This function un-registers device driver
- */
-static void vpfe_cleanup(void)
-{
- platform_driver_unregister(&vpfe_driver);
-}
-
-module_init(vpfe_init);
-module_exit(vpfe_cleanup);
+module_platform_driver(vpfe_driver);
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
index 49e4deb..6504e40 100644
--- a/drivers/media/video/davinci/vpif_capture.c
+++ b/drivers/media/video/davinci/vpif_capture.c
@@ -2177,6 +2177,12 @@ static __init int vpif_probe(struct platform_device *pdev)
return err;
}
+ err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
+ if (err) {
+ v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
+ return err;
+ }
+
k = 0;
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
for (i = res->start; i <= res->end; i++) {
@@ -2246,12 +2252,6 @@ static __init int vpif_probe(struct platform_device *pdev)
goto probe_out;
}
- err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
- if (err) {
- v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
- goto probe_subdev_out;
- }
-
for (i = 0; i < subdev_count; i++) {
subdevdata = &config->subdev_info[i];
vpif_obj.sd[i] =
@@ -2281,7 +2281,6 @@ probe_subdev_out:
j = VPIF_CAPTURE_MAX_DEVICES;
probe_out:
- v4l2_device_unregister(&vpif_obj.v4l2_dev);
for (k = 0; k < j; k++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[k];
@@ -2303,6 +2302,7 @@ vpif_int_err:
if (res)
i = res->end;
}
+ v4l2_device_unregister(&vpif_obj.v4l2_dev);
return err;
}
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index cff0768..e2a7b77 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
urb->dev = dev->udev;
urb->context = dev;
- urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
+ urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
urb->transfer_flags = URB_ISO_ASAP;
urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->interval = 1;
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 93807dc..4561cd8 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -336,6 +336,23 @@ static struct em28xx_reg_seq pctv_460e[] = {
{ -1, -1, -1, -1},
};
+#if 0
+static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
+ {EM2874_R80_GPIO, 0x6f, 0xff, 10},
+ {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */
+ {EM2874_R80_GPIO, 0x6f, 0xff, 10},
+ {EM2874_R80_GPIO, 0x4f, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
+static struct em28xx_reg_seq hauppauge_930c_digital[] = {
+ {EM2874_R80_GPIO, 0xf6, 0xff, 10},
+ {EM2874_R80_GPIO, 0xe6, 0xff, 100},
+ {EM2874_R80_GPIO, 0xa6, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+#endif
+
/*
* Board definitions
*/
@@ -839,6 +856,10 @@ struct em28xx_board em28xx_boards[] = {
[EM2870_BOARD_KWORLD_355U] = {
.name = "Kworld 355 U DVB-T",
.valid = EM28XX_BOARD_NOT_VALIDATED,
+ .tuner_type = TUNER_ABSENT,
+ .tuner_gpio = default_tuner_gpio,
+ .has_dvb = 1,
+ .dvb_gpio = default_digital,
},
[EM2870_BOARD_PINNACLE_PCTV_DVB] = {
.name = "Pinnacle PCTV DVB-T",
@@ -887,6 +908,37 @@ struct em28xx_board em28xx_boards[] = {
.tuner_addr = 0x41,
.dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
.tuner_gpio = terratec_h5_gpio,
+#else
+ .tuner_type = TUNER_ABSENT,
+#endif
+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
+ EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
+ },
+ [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = {
+ .name = "Hauppauge WinTV HVR 930C",
+ .has_dvb = 1,
+#if 0 /* FIXME: Add analog support */
+ .tuner_type = TUNER_XC5000,
+ .tuner_addr = 0x41,
+ .dvb_gpio = hauppauge_930c_digital,
+ .tuner_gpio = hauppauge_930c_gpio,
+#else
+ .tuner_type = TUNER_ABSENT,
+#endif
+ .ir_codes = RC_MAP_HAUPPAUGE,
+ .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
+ EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
+ },
+ [EM2884_BOARD_CINERGY_HTC_STICK] = {
+ .name = "Terratec Cinergy HTC Stick",
+ .has_dvb = 1,
+#if 0
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .tuner_addr = 0x41,
+ .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
+ .tuner_gpio = terratec_h5_gpio,
#endif
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
EM28XX_I2C_CLK_WAIT_ENABLE |
@@ -1127,7 +1179,7 @@ struct em28xx_board em28xx_boards[] = {
.name = "Terratec Cinergy 200 USB",
.is_em2800 = 1,
.has_ir_i2c = 1,
- .tuner_type = TUNER_LG_PAL_NEW_TAPC,
+ .tuner_type = TUNER_LG_TALN,
.tda9887_conf = TDA9887_PRESENT,
.decoder = EM28XX_SAA711X,
.input = { {
@@ -1218,7 +1270,7 @@ struct em28xx_board em28xx_boards[] = {
},
[EM2820_BOARD_PINNACLE_DVC_90] = {
.name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker "
- "/ Kworld DVD Maker 2",
+ "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
.tuner_type = TUNER_ABSENT, /* capture only board */
.decoder = EM28XX_SAA711X,
.input = { {
@@ -1840,6 +1892,22 @@ struct em28xx_board em28xx_boards[] = {
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
+ /* eb1a:5006 Honestech VIDBOX NW03
+ * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */
+ [EM2860_BOARD_HT_VIDBOX_NW03] = {
+ .name = "Honestech Vidbox NW03",
+ .tuner_type = TUNER_ABSENT,
+ .decoder = EM28XX_SAA711X,
+ .input = { {
+ .type = EM28XX_VMUX_COMPOSITE1,
+ .vmux = SAA7115_COMPOSITE0,
+ .amux = EM28XX_AMUX_LINE_IN,
+ }, {
+ .type = EM28XX_VMUX_SVIDEO,
+ .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */
+ .amux = EM28XX_AMUX_LINE_IN,
+ } },
+ },
};
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
@@ -1899,6 +1967,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
{ USB_DEVICE(0xeb1a, 0xe357),
.driver_info = EM2870_BOARD_KWORLD_355U },
+ { USB_DEVICE(0xeb1a, 0xe359),
+ .driver_info = EM2870_BOARD_KWORLD_355U },
{ USB_DEVICE(0x1b80, 0xe302),
.driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
{ USB_DEVICE(0x1b80, 0xe304),
@@ -1914,17 +1984,23 @@ struct usb_device_id em28xx_id_table[] = {
{ USB_DEVICE(0x0ccd, 0x0042),
.driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
{ USB_DEVICE(0x0ccd, 0x0043),
+ .driver_info = EM2870_BOARD_TERRATEC_XS },
+ { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
+ { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
+ { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */
.driver_info = EM2884_BOARD_TERRATEC_H5 },
- { USB_DEVICE(0x0ccd, 0x10a2), /* Rev. 1 */
+ { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */
.driver_info = EM2884_BOARD_TERRATEC_H5 },
- { USB_DEVICE(0x0ccd, 0x10ad), /* Rev. 2 */
- .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS },
{ USB_DEVICE(0x0ccd, 0x0084),
.driver_info = EM2860_BOARD_TERRATEC_AV350 },
{ USB_DEVICE(0x0ccd, 0x0096),
.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
{ USB_DEVICE(0x0ccd, 0x10AF),
.driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+ { USB_DEVICE(0x0ccd, 0x00b2),
+ .driver_info = EM2884_BOARD_CINERGY_HTC_STICK },
{ USB_DEVICE(0x0fd9, 0x0033),
.driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
{ USB_DEVICE(0x185b, 0x2870),
@@ -1963,6 +2039,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
{ USB_DEVICE(0x0413, 0x6023),
.driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
+ { USB_DEVICE(0x093b, 0xa003),
+ .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
{ USB_DEVICE(0x093b, 0xa005),
.driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
{ USB_DEVICE(0x04bb, 0x0515),
@@ -1975,6 +2053,12 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM28174_BOARD_PCTV_290E },
{ USB_DEVICE(0x2013, 0x024c),
.driver_info = EM28174_BOARD_PCTV_460E },
+ { USB_DEVICE(0x2040, 0x1605),
+ .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C },
+ { USB_DEVICE(0xeb1a, 0x5006),
+ .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 },
+ { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */
+ .driver_info = EM2860_BOARD_EASYCAP },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2028,10 +2112,10 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
int rc = 0;
struct em28xx *dev = ptr;
- if (dev->tuner_type != TUNER_XC2028)
+ if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000)
return 0;
- if (command != XC2028_TUNER_RESET)
+ if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET)
return 0;
rc = em28xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2203,7 +2287,8 @@ void em28xx_pre_card_setup(struct em28xx *dev)
/* Set the initial XCLK and I2C clock values based on the board
definition */
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
- em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+ if (!dev->board.is_em2800)
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
msleep(50);
/* request some modules */
@@ -2832,11 +2917,10 @@ void em28xx_release_resources(struct em28xx *dev)
* em28xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device
*/
-static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
struct usb_interface *interface,
int minor)
{
- struct em28xx *dev = *devhandle;
int retval;
dev->udev = udev;
@@ -2931,7 +3015,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
if (!dev->board.is_em2800) {
/* Resets I2C speed */
- em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+ retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
if (retval < 0) {
em28xx_errdev("%s: em28xx_write_reg failed!"
" retval [%d]\n",
@@ -3031,12 +3115,11 @@ unregister_dev:
static int em28xx_usb_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
- const struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev;
struct em28xx *dev = NULL;
int retval;
- bool is_audio_only = false, has_audio = false;
- int i, nr, isoc_pipe;
+ bool has_audio = false, has_video = false, has_dvb = false;
+ int i, nr;
const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
char *speed;
char descr[255] = "";
@@ -3068,54 +3151,65 @@ static int em28xx_usb_probe(struct usb_interface *interface,
goto err;
}
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ em28xx_err(DRIVER_NAME ": out of memory!\n");
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ /* compute alternate max packet sizes */
+ dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) *
+ interface->num_altsetting, GFP_KERNEL);
+ if (dev->alt_max_pkt_size == NULL) {
+ em28xx_errdev("out of memory!\n");
+ kfree(dev);
+ retval = -ENOMEM;
+ goto err;
+ }
+
/* Get endpoints */
for (i = 0; i < interface->num_altsetting; i++) {
int ep;
for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
- struct usb_host_endpoint *e;
- e = &interface->altsetting[i].endpoint[ep];
-
- if (e->desc.bEndpointAddress == 0x83)
- has_audio = true;
+ const struct usb_endpoint_descriptor *e;
+ int sizedescr, size;
+
+ e = &interface->altsetting[i].endpoint[ep].desc;
+
+ sizedescr = le16_to_cpu(e->wMaxPacketSize);
+ size = sizedescr & 0x7ff;
+
+ if (udev->speed == USB_SPEED_HIGH)
+ size = size * hb_mult(sizedescr);
+
+ if (usb_endpoint_xfer_isoc(e) &&
+ usb_endpoint_dir_in(e)) {
+ switch (e->bEndpointAddress) {
+ case EM28XX_EP_AUDIO:
+ has_audio = true;
+ break;
+ case EM28XX_EP_ANALOG:
+ has_video = true;
+ dev->alt_max_pkt_size[i] = size;
+ break;
+ case EM28XX_EP_DIGITAL:
+ has_dvb = true;
+ if (size > dev->dvb_max_pkt_size) {
+ dev->dvb_max_pkt_size = size;
+ dev->dvb_alt = i;
+ }
+ break;
+ }
+ }
}
}
- endpoint = &interface->cur_altsetting->endpoint[0].desc;
-
- /* check if the device has the iso in endpoint at the correct place */
- if (usb_endpoint_xfer_isoc(endpoint)
- &&
- (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) {
- /* It's a newer em2874/em2875 device */
- isoc_pipe = 0;
- } else {
- int check_interface = 1;
- isoc_pipe = 1;
- endpoint = &interface->cur_altsetting->endpoint[1].desc;
- if (!usb_endpoint_xfer_isoc(endpoint))
- check_interface = 0;
-
- if (usb_endpoint_dir_out(endpoint))
- check_interface = 0;
-
- if (!check_interface) {
- if (has_audio) {
- is_audio_only = true;
- } else {
- em28xx_err(DRIVER_NAME " video device (%04x:%04x): "
- "interface %i, class %i found.\n",
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct),
- ifnum,
- interface->altsetting[0].desc.bInterfaceClass);
- em28xx_err(DRIVER_NAME " This is an anciliary "
- "interface not used by the driver\n");
-
- retval = -ENODEV;
- goto err;
- }
- }
+ if (!(has_audio || has_video || has_dvb)) {
+ retval = -ENODEV;
+ goto err_free;
}
switch (udev->speed) {
@@ -3141,6 +3235,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
strlcat(descr, " ", sizeof(descr));
strlcat(descr, udev->product, sizeof(descr));
}
+
if (*descr)
strlcat(descr, " ", sizeof(descr));
@@ -3157,6 +3252,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
printk(KERN_INFO DRIVER_NAME
": Audio Vendor Class interface %i found\n",
ifnum);
+ if (has_video)
+ printk(KERN_INFO DRIVER_NAME
+ ": Video interface %i found\n",
+ ifnum);
+ if (has_dvb)
+ printk(KERN_INFO DRIVER_NAME
+ ": DVB interface %i found\n",
+ ifnum);
/*
* Make sure we have 480 Mbps of bandwidth, otherwise things like
@@ -3168,22 +3271,14 @@ static int em28xx_usb_probe(struct usb_interface *interface,
printk(DRIVER_NAME ": Device must be connected to a high-speed"
" USB 2.0 port.\n");
retval = -ENODEV;
- goto err;
- }
-
- /* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- em28xx_err(DRIVER_NAME ": out of memory!\n");
- retval = -ENOMEM;
- goto err;
+ goto err_free;
}
snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
dev->devno = nr;
dev->model = id->driver_info;
dev->alt = -1;
- dev->is_audio_only = is_audio_only;
+ dev->is_audio_only = has_audio && !(has_video || has_dvb);
dev->has_alsa_audio = has_audio;
dev->audio_ifnum = ifnum;
@@ -3196,26 +3291,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
}
- /* compute alternate max packet sizes */
dev->num_alt = interface->num_altsetting;
- dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);
-
- if (dev->alt_max_pkt_size == NULL) {
- em28xx_errdev("out of memory!\n");
- kfree(dev);
- retval = -ENOMEM;
- goto err;
- }
-
- for (i = 0; i < dev->num_alt ; i++) {
- u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
- unsigned int size = tmp & 0x7ff;
-
- if (udev->speed == USB_SPEED_HIGH)
- size = size * hb_mult(tmp);
-
- dev->alt_max_pkt_size[i] = size;
- }
if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
dev->model = card[nr];
@@ -3226,12 +3302,9 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* allocate device struct */
mutex_init(&dev->lock);
mutex_lock(&dev->lock);
- retval = em28xx_init_dev(&dev, udev, interface, nr);
+ retval = em28xx_init_dev(dev, udev, interface, nr);
if (retval) {
- mutex_unlock(&dev->lock);
- kfree(dev->alt_max_pkt_size);
- kfree(dev);
- goto err;
+ goto unlock_and_free;
}
request_modules(dev);
@@ -3250,6 +3323,13 @@ static int em28xx_usb_probe(struct usb_interface *interface,
return 0;
+unlock_and_free:
+ mutex_unlock(&dev->lock);
+
+err_free:
+ kfree(dev->alt_max_pkt_size);
+ kfree(dev);
+
err:
clear_bit(nr, &em28xx_devused);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 804a4ab..0aacc96 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -568,7 +568,7 @@ int em28xx_audio_setup(struct em28xx *dev)
em28xx_warn("AC97 features = 0x%04x\n", feat);
/* Try to identify what audio processor we have */
- if ((vid == 0xffffffff) && (feat == 0x6a90))
+ if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
dev->audio_mode.ac97 = EM28XX_AC97_EM202;
else if ((vid >> 8) == 0x838476)
dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL;
@@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
should also be using 'desc.bInterval'
*/
pipe = usb_rcvisocpipe(dev->udev,
- dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84);
+ dev->mode == EM28XX_ANALOG_MODE ?
+ EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
usb_fill_int_urb(urb, dev->udev, pipe,
dev->isoc_ctl.transfer_buffer[i], sb_size,
@@ -1108,62 +1109,6 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
}
EXPORT_SYMBOL_GPL(em28xx_init_isoc);
-/* Determine the packet size for the DVB stream for the given device
- (underlying value programmed into the eeprom) */
-int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev)
-{
- unsigned int chip_cfg2;
- unsigned int packet_size;
-
- switch (dev->chip_id) {
- case CHIP_ID_EM2710:
- case CHIP_ID_EM2750:
- case CHIP_ID_EM2800:
- case CHIP_ID_EM2820:
- case CHIP_ID_EM2840:
- case CHIP_ID_EM2860:
- /* No DVB support */
- return -EINVAL;
- case CHIP_ID_EM2870:
- case CHIP_ID_EM2883:
- /* TS max packet size stored in bits 1-0 of R01 */
- chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2);
- switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) {
- case EM28XX_CHIPCFG2_TS_PACKETSIZE_188:
- packet_size = 188;
- break;
- case EM28XX_CHIPCFG2_TS_PACKETSIZE_376:
- packet_size = 376;
- break;
- case EM28XX_CHIPCFG2_TS_PACKETSIZE_564:
- packet_size = 564;
- break;
- case EM28XX_CHIPCFG2_TS_PACKETSIZE_752:
- packet_size = 752;
- break;
- }
- break;
- case CHIP_ID_EM2874:
- /*
- * FIXME: for now assumes 564 like it was before, but the
- * em2874 code should be added to return the proper value
- */
- packet_size = 564;
- break;
- case CHIP_ID_EM2884:
- case CHIP_ID_EM28174:
- default:
- /*
- * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T
- * but not enough for 44 Mbit DVB-C.
- */
- packet_size = 752;
- }
-
- return packet_size;
-}
-EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize);
-
/*
* em28xx_wake_i2c()
* configure i2c attached devices
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index cef7a2d..9449423 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -44,6 +44,7 @@
#include "drxk.h"
#include "tda10071.h"
#include "a8293.h"
+#include "qt1010.h"
MODULE_DESCRIPTION("driver for em28xx based DVB cards");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -163,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb)
struct em28xx *dev = dvb->adapter.priv;
int max_dvb_packet_size;
- usb_set_interface(dev->udev, 0, 1);
+ usb_set_interface(dev->udev, 0, dev->dvb_alt);
rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
if (rc < 0)
return rc;
- max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev);
+ max_dvb_packet_size = dev->dvb_max_pkt_size;
if (max_dvb_packet_size < 0)
return max_dvb_packet_size;
dprintk(1, "Using %d buffers each with %d bytes\n",
@@ -302,10 +303,12 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
};
static struct drxd_config em28xx_drxd = {
- .index = 0, .demod_address = 0x70, .demod_revision = 0xa2,
- .demoda_address = 0x00, .pll_address = 0x00,
- .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1,
- .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000,
+ .demod_address = 0x70,
+ .demod_revision = 0xa2,
+ .pll_type = DRXD_PLL_NONE,
+ .clock = 12000,
+ .insert_rs_byte = 1,
+ .IF = 42800000,
.disable_i2c_gate_ctrl = 1,
};
@@ -316,6 +319,14 @@ struct drxk_config terratec_h5_drxk = {
.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
};
+struct drxk_config hauppauge_930c_drxk = {
+ .adr = 0x29,
+ .single_master = 1,
+ .no_i2c_bridge = 1,
+ .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
+ .chunk_size = 56,
+};
+
static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct em28xx_dvb *dvb = fe->sec_priv;
@@ -334,6 +345,73 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
return status;
}
+static void hauppauge_hvr930c_init(struct em28xx *dev)
+{
+ int i;
+
+ struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
+ {EM2874_R80_GPIO, 0xff, 0xff, 0x65},
+ {EM2874_R80_GPIO, 0xfb, 0xff, 0x32},
+ {EM2874_R80_GPIO, 0xff, 0xff, 0xb8},
+ { -1, -1, -1, -1},
+ };
+ struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x01},
+ {EM2874_R80_GPIO, 0xaf, 0xff, 0x65},
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x76},
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x01},
+ {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b},
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x40},
+
+ {EM2874_R80_GPIO, 0xcf, 0xff, 0x65},
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x65},
+ {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b},
+ {EM2874_R80_GPIO, 0xef, 0xff, 0x65},
+
+ { -1, -1, -1, -1},
+ };
+
+ struct {
+ unsigned char r[4];
+ int len;
+ } regs[] = {
+ {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+ {{ 0x01, 0x02 }, 2},
+ {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+ {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+ {{ 0x01, 0x00 }, 2},
+ {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+ {{ 0x04, 0x00 }, 2},
+ {{ 0x00, 0x04 }, 2},
+ {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+ {{ 0x04, 0x14 }, 2},
+ {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+ };
+
+ em28xx_gpio_set(dev, hauppauge_hvr930c_init);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+ msleep(10);
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+ msleep(10);
+
+ dev->i2c_client.addr = 0x82 >> 1;
+
+ for (i = 0; i < ARRAY_SIZE(regs); i++)
+ i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+ em28xx_gpio_set(dev, hauppauge_hvr930c_end);
+
+ msleep(100);
+
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+ msleep(30);
+
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+ msleep(10);
+
+}
+
static void terratec_h5_init(struct em28xx *dev)
{
int i;
@@ -425,13 +503,6 @@ static struct tda10023_config em28xx_tda10023_config = {
static struct cxd2820r_config em28xx_cxd2820r_config = {
.i2c_address = (0xd8 >> 1),
.ts_mode = CXD2820R_TS_SERIAL,
- .if_dvbt_6 = 3300,
- .if_dvbt_7 = 3500,
- .if_dvbt_8 = 4000,
- .if_dvbt2_6 = 3300,
- .if_dvbt2_7 = 3500,
- .if_dvbt2_8 = 4000,
- .if_dvbc = 5000,
/* enable LNA for DVB-T2 and DVB-C */
.gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
@@ -456,6 +527,17 @@ static const struct a8293_config em28xx_a8293_config = {
.i2c_addr = 0x08, /* (0x10 >> 1) */
};
+static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
+ .demod_address = (0x1e >> 1),
+ .disable_i2c_gate_ctrl = 1,
+ .no_tuner = 1,
+ .parallel_ts = 1,
+};
+static struct qt1010_config em28xx_qt1010_config = {
+ .i2c_address = 0x62
+
+};
+
/* ------------------------------------------------------------------ */
static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
@@ -708,6 +790,14 @@ static int em28xx_dvb_init(struct em28xx *dev)
goto out_free;
}
break;
+ case EM2870_BOARD_KWORLD_355U:
+ dvb->fe[0] = dvb_attach(zl10353_attach,
+ &em28xx_zl10353_no_i2c_gate_dev,
+ &dev->i2c_adap);
+ if (dvb->fe[0] != NULL)
+ dvb_attach(qt1010_attach, dvb->fe[0],
+ &dev->i2c_adap, &em28xx_qt1010_config);
+ break;
case EM2883_BOARD_KWORLD_HYBRID_330U:
case EM2882_BOARD_EVGA_INDTUBE:
dvb->fe[0] = dvb_attach(s5h1409_attach,
@@ -761,50 +851,72 @@ static int em28xx_dvb_init(struct em28xx *dev)
&dev->i2c_adap, &kworld_a340_config);
break;
case EM28174_BOARD_PCTV_290E:
- /* MFE
- * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */
- /* FE 0 */
dvb->fe[0] = dvb_attach(cxd2820r_attach,
- &em28xx_cxd2820r_config, &dev->i2c_adap, NULL);
+ &em28xx_cxd2820r_config,
+ &dev->i2c_adap,
+ NULL);
if (dvb->fe[0]) {
/* FE 0 attach tuner */
- if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
- &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
+ if (!dvb_attach(tda18271_attach,
+ dvb->fe[0],
+ 0x60,
+ &dev->i2c_adap,
+ &em28xx_cxd2820r_tda18271_config)) {
+
dvb_frontend_detach(dvb->fe[0]);
result = -EINVAL;
goto out_free;
}
- /* FE 1. This dvb_attach() cannot fail. */
- dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL,
- dvb->fe[0]);
- dvb->fe[1]->id = 1;
- /* FE 1 attach tuner */
- if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60,
- &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) {
- dvb_frontend_detach(dvb->fe[1]);
- /* leave FE 0 still active */
- }
+ }
+ break;
+ case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
+ {
+ struct xc5000_config cfg;
+ hauppauge_hvr930c_init(dev);
+
+ dvb->fe[0] = dvb_attach(drxk_attach,
+ &hauppauge_930c_drxk, &dev->i2c_adap);
+ if (!dvb->fe[0]) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ /* FIXME: do we need a pll semaphore? */
+ dvb->fe[0]->sec_priv = dvb;
+ sema_init(&dvb->pll_mutex, 1);
+ dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+ dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
- mfe_shared = 1;
+ /* Attach xc5000 */
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.i2c_address = 0x61;
+ cfg.if_khz = 4000;
+
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+ if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
+ &cfg)) {
+ result = -EINVAL;
+ goto out_free;
}
+ if (dvb->fe[0]->ops.i2c_gate_ctrl)
+ dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
break;
+ }
case EM2884_BOARD_TERRATEC_H5:
+ case EM2884_BOARD_CINERGY_HTC_STICK:
terratec_h5_init(dev);
- dvb->dont_attach_fe1 = 1;
-
- dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]);
+ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
if (!dvb->fe[0]) {
result = -EINVAL;
goto out_free;
}
-
/* FIXME: do we need a pll semaphore? */
dvb->fe[0]->sec_priv = dvb;
sema_init(&dvb->pll_mutex, 1);
dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
- dvb->fe[1]->id = 1;
/* Attach tda18271 to DVB-C frontend */
if (dvb->fe[0]->ops.i2c_gate_ctrl)
@@ -816,12 +928,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
if (dvb->fe[0]->ops.i2c_gate_ctrl)
dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
- /* Hack - needed by drxk/tda18271c2dd */
- dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv;
- memcpy(&dvb->fe[1]->ops.tuner_ops,
- &dvb->fe[0]->ops.tuner_ops,
- sizeof(dvb->fe[0]->ops.tuner_ops));
-
break;
case EM28174_BOARD_PCTV_460E:
/* attach demod */
@@ -845,6 +951,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
}
/* define general-purpose callback pointer */
dvb->fe[0]->callback = em28xx_tuner_callback;
+ if (dvb->fe[1])
+ dvb->fe[1]->callback = em28xx_tuner_callback;
/* register everything */
result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 679da48..2630b26 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -306,7 +306,8 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
poll_result.rc_data[0],
poll_result.toggle_bit);
- if (ir->dev->chip_id == CHIP_ID_EM2874)
+ if (ir->dev->chip_id == CHIP_ID_EM2874 ||
+ ir->dev->chip_id == CHIP_ID_EM2884)
/* The em2874 clears the readcount field every time the
register is read. The em2860/2880 datasheet says that it
is supposed to clear the readcount, but it doesn't. So with
@@ -371,13 +372,15 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
case CHIP_ID_EM2883:
ir->get_key = default_polling_getkey;
break;
+ case CHIP_ID_EM2884:
case CHIP_ID_EM2874:
case CHIP_ID_EM28174:
ir->get_key = em2874_polling_getkey;
em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
break;
default:
- printk("Unrecognized em28xx chip id: IR not supported\n");
+ printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
+ dev->chip_id);
rc = -EINVAL;
}
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
index 66f7923..2f62685 100644
--- a/drivers/media/video/em28xx/em28xx-reg.h
+++ b/drivers/media/video/em28xx/em28xx-reg.h
@@ -12,6 +12,11 @@
#define EM_GPO_2 (1 << 2)
#define EM_GPO_3 (1 << 3)
+/* em28xx endpoints */
+#define EM28XX_EP_ANALOG 0x82
+#define EM28XX_EP_AUDIO 0x83
+#define EM28XX_EP_DIGITAL 0x84
+
/* em2800 registers */
#define EM2800_R08_AUDIOSRC 0x08
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 9b4557a..613300b 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1070,6 +1070,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
/* the em2800 can only scale down to 50% */
height = height > (3 * maxh / 4) ? maxh : maxh / 2;
width = width > (3 * maxw / 4) ? maxw : maxw / 2;
+ /* MaxPacketSize for em2800 is too small to capture at full resolution
+ * use half of maxw as the scaler can only scale to 50% */
+ if (width == maxw && height == maxh)
+ width /= 2;
} else {
/* width must even because of the YUYV format
height must be even because of interlacing */
@@ -2503,6 +2507,7 @@ int em28xx_register_analog_devices(struct em28xx *dev)
{
u8 val;
int ret;
+ unsigned int maxw;
printk(KERN_INFO "%s: v4l2 driver version %s\n",
dev->name, EM28XX_VERSION);
@@ -2515,8 +2520,15 @@ int em28xx_register_analog_devices(struct em28xx *dev)
/* Analog specific initialization */
dev->format = &format[0];
+
+ maxw = norm_maxw(dev);
+ /* MaxPacketSize for em2800 is too small to capture at full resolution
+ * use half of maxw as the scaler can only scale to 50% */
+ if (dev->board.is_em2800)
+ maxw /= 2;
+
em28xx_set_video_format(dev, format[0].fourcc,
- norm_maxw(dev), norm_maxh(dev));
+ maxw, norm_maxh(dev));
video_mux(dev, dev->ctl_input);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 2a2cb7e..22e252b 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -38,6 +38,7 @@
#include <media/videobuf-dvb.h>
#endif
#include "tuner-xc2028.h"
+#include "xc5000.h"
#include "em28xx-reg.h"
/* Boards supported by driver */
@@ -121,6 +122,9 @@
#define EM28174_BOARD_PCTV_290E 78
#define EM2884_BOARD_TERRATEC_H5 79
#define EM28174_BOARD_PCTV_460E 80
+#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81
+#define EM2884_BOARD_CINERGY_HTC_STICK 82
+#define EM2860_BOARD_HT_VIDBOX_NW03 83
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -594,6 +598,8 @@ struct em28xx {
int max_pkt_size; /* max packet size of isoc transaction */
int num_alt; /* Number of alternative settings */
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+ int dvb_alt; /* alternate for DVB */
+ unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc
transfer */
@@ -825,7 +831,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev)
if (dev->board.is_webcam)
return dev->sensor_xres;
- if (dev->board.max_range_640_480 || dev->board.is_em2800)
+ if (dev->board.max_range_640_480)
return 640;
return 720;
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 40f214a..5539f09 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -76,8 +76,8 @@ MODULE_PARM_DESC(video_nr,
"\none and for every other camera."
"\n");
-static short force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
- ET61X251_FORCE_MUNMAP};
+static bool force_munmap[] = {[0 ... ET61X251_MAX_DEVICES-1] =
+ ET61X251_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
"\n<0|1[,...]> Force the application to unmap previously"
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c
index 27cb197..27e3e0c 100644
--- a/drivers/media/video/fsl-viu.c
+++ b/drivers/media/video/fsl-viu.c
@@ -1661,18 +1661,7 @@ static struct platform_driver viu_of_platform_driver = {
},
};
-static int __init viu_init(void)
-{
- return platform_driver_register(&viu_of_platform_driver);
-}
-
-static void __exit viu_exit(void)
-{
- platform_driver_unregister(&viu_of_platform_driver);
-}
-
-module_init(viu_init);
-module_exit(viu_exit);
+module_platform_driver(viu_of_platform_driver);
MODULE_DESCRIPTION("Freescale Video-In(VIU)");
MODULE_AUTHOR("Hongjun Chen");
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 103af3f..dfe268b 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ
To compile this driver as a module, choose M here: the
module will be called gspca_jeilinj.
+config USB_GSPCA_JL2005BCD
+ tristate "JL2005B/C/D USB V4L2 driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based the
+ JL2005B, JL2005C, or JL2005D chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_jl2005bcd.
+
config USB_GSPCA_KINECT
tristate "Kinect sensor device USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index f345f49..79ebe46 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o
obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o
obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o
obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o
+obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o
obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o
obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
@@ -49,6 +50,7 @@ gspca_cpia1-objs := cpia1.o
gspca_etoms-objs := etoms.o
gspca_finepix-objs := finepix.o
gspca_jeilinj-objs := jeilinj.o
+gspca_jl2005bcd-objs := jl2005bcd.o
gspca_kinect-objs := kinect.o
gspca_konica-objs := konica.o
gspca_mars-objs := mars.o
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
index 636627b..9769f17 100644
--- a/drivers/media/video/gspca/benq.c
+++ b/drivers/media/video/gspca/benq.c
@@ -76,7 +76,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->cam.cam_mode = vga_mode;
gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
gspca_dev->cam.no_urb_create = 1;
- gspca_dev->cam.reverse_alts = 1;
return 0;
}
@@ -135,13 +134,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
static void sd_stopN(struct gspca_dev *gspca_dev)
{
+ struct usb_interface *intf;
+
reg_w(gspca_dev, 0x003c, 0x0003);
reg_w(gspca_dev, 0x003c, 0x0004);
reg_w(gspca_dev, 0x003c, 0x0005);
reg_w(gspca_dev, 0x003c, 0x0006);
reg_w(gspca_dev, 0x003c, 0x0007);
+
+ intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
usb_set_interface(gspca_dev->dev, gspca_dev->iface,
- gspca_dev->nbalt - 1);
+ intf->num_altsetting - 1);
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
index a8f54c2..c84e260 100644
--- a/drivers/media/video/gspca/gl860/gl860.c
+++ b/drivers/media/video/gspca/gl860/gl860.c
@@ -337,7 +337,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
return -1;
cam = &gspca_dev->cam;
- gspca_dev->nbalt = 4;
switch (sd->sensor) {
case ID_MI1320:
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 2ca10df..ca5a2b1 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -633,23 +633,32 @@ static u32 which_bandwidth(struct gspca_dev *gspca_dev)
u32 bandwidth;
int i;
+ /* get the (max) image size */
i = gspca_dev->curr_mode;
bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
- /* if the image is compressed, estimate the mean image size */
- if (bandwidth < gspca_dev->cam.cam_mode[i].width *
+ /* if the image is compressed, estimate its mean size */
+ if (!gspca_dev->cam.needs_full_bandwidth &&
+ bandwidth < gspca_dev->cam.cam_mode[i].width *
gspca_dev->cam.cam_mode[i].height)
- bandwidth /= 3;
+ bandwidth = bandwidth * 3 / 8; /* 0.375 */
/* estimate the frame rate */
if (gspca_dev->sd_desc->get_streamparm) {
struct v4l2_streamparm parm;
- parm.parm.capture.timeperframe.denominator = 15;
gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
bandwidth *= parm.parm.capture.timeperframe.denominator;
+ bandwidth /= parm.parm.capture.timeperframe.numerator;
} else {
- bandwidth *= 15; /* 15 fps */
+
+ /* don't hope more than 15 fps with USB 1.1 and
+ * image resolution >= 640x480 */
+ if (gspca_dev->width >= 640
+ && gspca_dev->dev->speed == USB_SPEED_FULL)
+ bandwidth *= 15; /* 15 fps */
+ else
+ bandwidth *= 30; /* 30 fps */
}
PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
@@ -667,9 +676,8 @@ struct ep_tb_s {
* build the table of the endpoints
* and compute the minimum bandwidth for the image transfer
*/
-static int build_ep_tb(struct gspca_dev *gspca_dev,
+static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
struct usb_interface *intf,
- int xfer,
struct ep_tb_s *ep_tb)
{
struct usb_host_endpoint *ep;
@@ -687,17 +695,21 @@ static int build_ep_tb(struct gspca_dev *gspca_dev,
ep_tb->bandwidth = 2000 * 2000 * 120;
found = 0;
for (j = 0; j < nbalt; j++) {
- ep = alt_xfer(&intf->altsetting[j], xfer);
+ ep = alt_xfer(&intf->altsetting[j],
+ USB_ENDPOINT_XFER_ISOC);
if (ep == NULL)
continue;
+ if (ep->desc.bInterval == 0) {
+ pr_err("alt %d iso endp with 0 interval\n", j);
+ continue;
+ }
psize = le16_to_cpu(ep->desc.wMaxPacketSize);
- if (!gspca_dev->cam.bulk) /* isoc */
- psize = (psize & 0x07ff) *
- (1 + ((psize >> 11) & 3));
- bandwidth = psize * ep->desc.bInterval * 1000;
+ psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+ bandwidth = psize * 1000;
if (gspca_dev->dev->speed == USB_SPEED_HIGH
|| gspca_dev->dev->speed == USB_SPEED_SUPER)
bandwidth *= 8;
+ bandwidth /= 1 << (ep->desc.bInterval - 1);
if (bandwidth <= last_bw)
continue;
if (bandwidth < ep_tb->bandwidth) {
@@ -715,6 +727,23 @@ static int build_ep_tb(struct gspca_dev *gspca_dev,
ep_tb++;
}
+ /*
+ * If the camera:
+ * has a usb audio class interface (a built in usb mic); and
+ * is a usb 1 full speed device; and
+ * uses the max full speed iso bandwidth; and
+ * and has more than 1 alt setting
+ * then skip the highest alt setting to spare bandwidth for the mic
+ */
+ if (gspca_dev->audio &&
+ gspca_dev->dev->speed == USB_SPEED_FULL &&
+ last_bw >= 1000000 &&
+ i > 1) {
+ PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt");
+ i--;
+ ep_tb--;
+ }
+
/* get the requested bandwidth and start at the highest atlsetting */
bandwidth = which_bandwidth(gspca_dev);
ep_tb--;
@@ -790,10 +819,7 @@ static int create_urbs(struct gspca_dev *gspca_dev,
ep->desc.bEndpointAddress);
urb->transfer_flags = URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP;
- if (gspca_dev->dev->speed == USB_SPEED_LOW)
- urb->interval = ep->desc.bInterval;
- else
- urb->interval = 1 << (ep->desc.bInterval - 1);
+ urb->interval = 1 << (ep->desc.bInterval - 1);
urb->complete = isoc_irq;
urb->number_of_packets = npkt;
for (i = 0; i < npkt; i++) {
@@ -848,7 +874,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
: USB_ENDPOINT_XFER_ISOC;
- /* if the subdriver forced an altsetting, get the endpoint */
+ /* if bulk or the subdriver forced an altsetting, get the endpoint */
if (gspca_dev->alt != 0) {
gspca_dev->alt--; /* (previous version compatibility) */
ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
@@ -863,7 +889,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* else, compute the minimum bandwidth
* and build the endpoint table */
- alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb);
+ alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb);
if (alt_idx <= 0) {
pr_err("no transfer endpoint found\n");
ret = -EIO;
@@ -880,7 +906,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
for (;;) {
if (alt != gspca_dev->alt) {
alt = gspca_dev->alt;
- if (gspca_dev->nbalt > 1) {
+ if (intf->num_altsetting > 1) {
ret = usb_set_interface(gspca_dev->dev,
gspca_dev->iface,
alt);
@@ -2300,15 +2326,14 @@ int gspca_dev_probe2(struct usb_interface *intf,
}
gspca_dev->dev = dev;
gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
- gspca_dev->nbalt = intf->num_altsetting;
/* check if any audio device */
- if (dev->config->desc.bNumInterfaces != 1) {
+ if (dev->actconfig->desc.bNumInterfaces != 1) {
int i;
struct usb_interface *intf2;
- for (i = 0; i < dev->config->desc.bNumInterfaces; i++) {
- intf2 = dev->config->interface[i];
+ for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+ intf2 = dev->actconfig->interface[i];
if (intf2 != NULL
&& intf2->altsetting != NULL
&& intf2->altsetting->desc.bInterfaceClass ==
@@ -2389,7 +2414,7 @@ int gspca_dev_probe(struct usb_interface *intf,
}
/* the USB video interface must be the first one */
- if (dev->config->desc.bNumInterfaces != 1
+ if (dev->actconfig->desc.bNumInterfaces != 1
&& intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index e444f16..589009f 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -69,7 +69,9 @@ struct cam {
u8 bulk; /* image transfer by 0:isoc / 1:bulk */
u8 npkt; /* number of packets in an ISOC message
* 0 is the default value: 32 packets */
- u8 reverse_alts; /* Alt settings are in high to low order */
+ u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc.
+ * code that the cam fills all image buffers to
+ * the max, even when using compression. */
};
struct gspca_dev;
@@ -208,7 +210,6 @@ struct gspca_dev {
char memory; /* memory type (V4L2_MEMORY_xxx) */
__u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */
- __u8 nbalt; /* number of USB alternate settings */
u8 audio; /* presence of audio device */
};
diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c
new file mode 100644
index 0000000..53f58ef
--- /dev/null
+++ b/drivers/media/video/gspca/jl2005bcd.c
@@ -0,0 +1,554 @@
+/*
+ * Jeilin JL2005B/C/D library
+ *
+ * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * 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
+ * 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
+ */
+
+#define MODULE_NAME "jl2005bcd"
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define JL2005C_CMD_TIMEOUT 500
+#define JL2005C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define JL2005C_MAX_TRANSFER 0x200
+#define FRAME_HEADER_LEN 16
+
+
+/* specific webcam descriptor */
+struct sd {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+ unsigned char firmware_id[6];
+ const struct v4l2_pix_format *cap_mode;
+ /* Driver stuff */
+ struct work_struct work_struct;
+ struct workqueue_struct *work_thread;
+ u8 frame_brightness;
+ int block_size; /* block size of camera */
+ int vga; /* 1 if vga cam, 0 if cif cam */
+};
+
+
+/* Camera has two resolution settings. What they are depends on model. */
+static const struct v4l2_pix_format cif_mode[] = {
+ {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+ .bytesperline = 176,
+ .sizeimage = 176 * 144,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+ {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+ .bytesperline = 352,
+ .sizeimage = 352 * 288,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+ {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+ {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+ .bytesperline = 640,
+ .sizeimage = 640 * 480,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0},
+};
+
+/*
+ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
+ * and 0x82 for bulk data transfer.
+ */
+
+/* All commands are two bytes only */
+static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
+{
+ int retval;
+
+ memcpy(gspca_dev->usb_buf, command, 2);
+ retval = usb_bulk_msg(gspca_dev->dev,
+ usb_sndbulkpipe(gspca_dev->dev, 3),
+ gspca_dev->usb_buf, 2, NULL, 500);
+ if (retval < 0)
+ pr_err("command write [%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
+ return retval;
+}
+
+/* Response to a command is one byte in usb_buf[0], only if requested. */
+static int jl2005c_read1(struct gspca_dev *gspca_dev)
+{
+ int retval;
+
+ retval = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x84),
+ gspca_dev->usb_buf, 1, NULL, 500);
+ if (retval < 0)
+ pr_err("read command [0x%02x] error %d\n",
+ gspca_dev->usb_buf[0], retval);
+ return retval;
+}
+
+/* Response appears in gspca_dev->usb_buf[0] */
+static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
+{
+ int retval;
+
+ static u8 instruction[2] = {0x95, 0x00};
+ /* put register to read in byte 1 */
+ instruction[1] = reg;
+ /* Send the read request */
+ retval = jl2005c_write2(gspca_dev, instruction);
+ if (retval < 0)
+ return retval;
+ retval = jl2005c_read1(gspca_dev);
+
+ return retval;
+}
+
+static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval;
+ int frame_brightness = 0;
+
+ static u8 instruction[2] = {0x7f, 0x01};
+
+ retval = jl2005c_write2(gspca_dev, instruction);
+ if (retval < 0)
+ return retval;
+
+ i = 0;
+ while (i < 20 && !frame_brightness) {
+ /* If we tried 20 times, give up. */
+ retval = jl2005c_read_reg(gspca_dev, 0x7e);
+ if (retval < 0)
+ return retval;
+ frame_brightness = gspca_dev->usb_buf[0];
+ retval = jl2005c_read_reg(gspca_dev, 0x7d);
+ if (retval < 0)
+ return retval;
+ i++;
+ }
+ PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
+ return retval;
+}
+
+static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
+ unsigned char value)
+{
+ int retval;
+ u8 instruction[2];
+
+ instruction[0] = reg;
+ instruction[1] = value;
+
+ retval = jl2005c_write2(gspca_dev, instruction);
+ if (retval < 0)
+ return retval;
+
+ return retval;
+}
+
+static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *)gspca_dev;
+ int i = 0;
+ int retval = -1;
+ unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
+
+ PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
+ /* Read the first ID byte once for warmup */
+ retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
+ PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
+ if (retval < 0)
+ return retval;
+ /* Now actually get the ID string */
+ for (i = 0; i < 6; i++) {
+ retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
+ if (retval < 0)
+ return retval;
+ sd->firmware_id[i] = gspca_dev->usb_buf[0];
+ }
+ PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
+ sd->firmware_id[0],
+ sd->firmware_id[1],
+ sd->firmware_id[2],
+ sd->firmware_id[3],
+ sd->firmware_id[4],
+ sd->firmware_id[5]);
+ return 0;
+}
+
+static int jl2005c_stream_start_vga_lg
+ (struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval = -1;
+ static u8 instruction[][2] = {
+ {0x05, 0x00},
+ {0x7c, 0x00},
+ {0x7d, 0x18},
+ {0x02, 0x00},
+ {0x01, 0x00},
+ {0x04, 0x52},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+ msleep(60);
+ retval = jl2005c_write2(gspca_dev, instruction[i]);
+ if (retval < 0)
+ return retval;
+ }
+ msleep(60);
+ return retval;
+}
+
+static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval = -1;
+ static u8 instruction[][2] = {
+ {0x06, 0x00},
+ {0x7c, 0x00},
+ {0x7d, 0x1a},
+ {0x02, 0x00},
+ {0x01, 0x00},
+ {0x04, 0x52},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+ msleep(60);
+ retval = jl2005c_write2(gspca_dev, instruction[i]);
+ if (retval < 0)
+ return retval;
+ }
+ msleep(60);
+ return retval;
+}
+
+static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval = -1;
+ static u8 instruction[][2] = {
+ {0x05, 0x00},
+ {0x7c, 0x00},
+ {0x7d, 0x30},
+ {0x02, 0x00},
+ {0x01, 0x00},
+ {0x04, 0x42},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+ msleep(60);
+ retval = jl2005c_write2(gspca_dev, instruction[i]);
+ if (retval < 0)
+ return retval;
+ }
+ msleep(60);
+ return retval;
+}
+
+static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
+{
+ int i;
+ int retval = -1;
+ static u8 instruction[][2] = {
+ {0x06, 0x00},
+ {0x7c, 0x00},
+ {0x7d, 0x32},
+ {0x02, 0x00},
+ {0x01, 0x00},
+ {0x04, 0x42},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+ msleep(60);
+ retval = jl2005c_write2(gspca_dev, instruction[i]);
+ if (retval < 0)
+ return retval;
+ }
+ msleep(60);
+ return retval;
+}
+
+
+static int jl2005c_stop(struct gspca_dev *gspca_dev)
+{
+ int retval;
+
+ retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
+ return retval;
+}
+
+/* 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.
+ */
+static void jl2005c_dostream(struct work_struct *work)
+{
+ struct sd *dev = container_of(work, struct sd, work_struct);
+ struct gspca_dev *gspca_dev = &dev->gspca_dev;
+ int bytes_left = 0; /* bytes remaining in current frame. */
+ int data_len; /* size to use for the next read. */
+ int header_read = 0;
+ unsigned char header_sig[2] = {0x4a, 0x4c};
+ int act_len;
+ int packet_type;
+ int ret;
+ u8 *buffer;
+
+ buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+ if (!buffer) {
+ pr_err("Couldn't allocate USB buffer\n");
+ goto quit_stream;
+ }
+
+ while (gspca_dev->present && gspca_dev->streaming) {
+ /* Check if this is a new frame. If so, start the frame first */
+ if (!header_read) {
+ mutex_lock(&gspca_dev->usb_lock);
+ ret = jl2005c_start_new_frame(gspca_dev);
+ mutex_unlock(&gspca_dev->usb_lock);
+ if (ret < 0)
+ goto quit_stream;
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+ buffer, JL2005C_MAX_TRANSFER, &act_len,
+ JL2005C_DATA_TIMEOUT);
+ PDEBUG(D_PACK,
+ "Got %d bytes out of %d for header",
+ act_len, JL2005C_MAX_TRANSFER);
+ if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
+ goto quit_stream;
+ /* Check whether we actually got the first blodk */
+ if (memcmp(header_sig, buffer, 2) != 0) {
+ pr_err("First block is not the first block\n");
+ goto quit_stream;
+ }
+ /* total size to fetch is byte 7, times blocksize
+ * of which we already got act_len */
+ bytes_left = buffer[0x07] * dev->block_size - act_len;
+ PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
+ /* We keep the header. It has other information, too.*/
+ packet_type = FIRST_PACKET;
+ gspca_frame_add(gspca_dev, packet_type,
+ buffer, act_len);
+ header_read = 1;
+ }
+ 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,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+ buffer, data_len, &act_len,
+ JL2005C_DATA_TIMEOUT);
+ if (ret < 0 || act_len < data_len)
+ goto quit_stream;
+ PDEBUG(D_PACK,
+ "Got %d bytes out of %d for frame",
+ data_len, bytes_left);
+ bytes_left -= data_len;
+ if (bytes_left == 0) {
+ packet_type = LAST_PACKET;
+ header_read = 0;
+ } else
+ packet_type = INTER_PACKET;
+ gspca_frame_add(gspca_dev, packet_type,
+ buffer, data_len);
+ }
+ }
+quit_stream:
+ if (gspca_dev->present) {
+ mutex_lock(&gspca_dev->usb_lock);
+ jl2005c_stop(gspca_dev);
+ mutex_unlock(&gspca_dev->usb_lock);
+ }
+ kfree(buffer);
+}
+
+
+
+
+/* This function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct cam *cam;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ cam = &gspca_dev->cam;
+ /* We don't use the buffer gspca allocates so make it small. */
+ cam->bulk_size = 64;
+ cam->bulk = 1;
+ /* For the rest, the camera needs to be detected */
+ jl2005c_get_firmware_id(gspca_dev);
+ /* Here are some known firmware IDs
+ * First some JL2005B cameras
+ * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam
+ * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B
+ * JL2005C cameras
+ * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512
+ * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly
+ * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz
+ *
+ * Based upon this scanty evidence, we can detect a CIF camera by
+ * testing byte 0 for 0x4x.
+ */
+ if ((sd->firmware_id[0] & 0xf0) == 0x40) {
+ cam->cam_mode = cif_mode;
+ cam->nmodes = ARRAY_SIZE(cif_mode);
+ sd->block_size = 0x80;
+ } else {
+ cam->cam_mode = vga_mode;
+ cam->nmodes = ARRAY_SIZE(vga_mode);
+ sd->block_size = 0x200;
+ }
+
+ INIT_WORK(&sd->work_struct, jl2005c_dostream);
+
+ return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+
+ struct sd *sd = (struct sd *) gspca_dev;
+ sd->cap_mode = gspca_dev->cam.cam_mode;
+
+ switch (gspca_dev->width) {
+ case 640:
+ PDEBUG(D_STREAM, "Start streaming at vga resolution");
+ jl2005c_stream_start_vga_lg(gspca_dev);
+ break;
+ case 320:
+ PDEBUG(D_STREAM, "Start streaming at qvga resolution");
+ jl2005c_stream_start_vga_small(gspca_dev);
+ break;
+ case 352:
+ PDEBUG(D_STREAM, "Start streaming at cif resolution");
+ jl2005c_stream_start_cif_lg(gspca_dev);
+ break;
+ case 176:
+ PDEBUG(D_STREAM, "Start streaming at qcif resolution");
+ jl2005c_stream_start_cif_small(gspca_dev);
+ break;
+ default:
+ pr_err("Unknown resolution specified\n");
+ return -1;
+ }
+
+ /* Start the workqueue function to do the streaming */
+ sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+ queue_work(sd->work_thread, &sd->work_struct);
+
+ return 0;
+}
+
+/* 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 *dev = (struct sd *) gspca_dev;
+
+ /* wait for the work queue to terminate */
+ mutex_unlock(&gspca_dev->usb_lock);
+ /* This waits for sq905c_dostream to finish */
+ destroy_workqueue(dev->work_thread);
+ dev->work_thread = NULL;
+ mutex_lock(&gspca_dev->usb_lock);
+}
+
+
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ /* .ctrls = none have been detected */
+ /* .nctrls = ARRAY_SIZE(sd_ctrls), */
+ .config = sd_config,
+ .init = sd_init,
+ .start = sd_start,
+ .stop0 = sd_stop0,
+};
+
+/* -- module initialisation -- */
+static const __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x0979, 0x0227)},
+ {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ int ret;
+
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c
index b1da7f4..f0c0d74 100644
--- a/drivers/media/video/gspca/konica.c
+++ b/drivers/media/video/gspca/konica.c
@@ -247,9 +247,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->cam.cam_mode = vga_mode;
gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
gspca_dev->cam.no_urb_create = 1;
- /* The highest alt setting has an isoc packetsize of 0, so we
- don't want to use it */
- gspca_dev->nbalt--;
sd->brightness = BRIGHTNESS_DEFAULT;
sd->contrast = CONTRAST_DEFAULT;
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index 9fe3816b..0c44936 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -27,8 +27,8 @@
/* Kernel module parameters */
int force_sensor;
-static int dump_bridge;
-int dump_sensor;
+static bool dump_bridge;
+bool dump_sensor;
static const struct usb_device_id m5602_table[] = {
{USB_DEVICE(0x0402, 0x5602)},
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
index b1f0c49..8c672b5 100644
--- a/drivers/media/video/gspca/m5602/m5602_mt9m111.h
+++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
@@ -106,7 +106,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int mt9m111_probe(struct sd *sd);
int mt9m111_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h
index 2efd607..2b6a13b 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov7660.h
+++ b/drivers/media/video/gspca/m5602/m5602_ov7660.h
@@ -86,7 +86,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int ov7660_probe(struct sd *sd);
int ov7660_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
index da9a129..f7aa5bf 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h
@@ -135,7 +135,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int ov9650_probe(struct sd *sd);
int ov9650_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
index 3383595..81a2bcb 100644
--- a/drivers/media/video/gspca/m5602/m5602_po1030.h
+++ b/drivers/media/video/gspca/m5602/m5602_po1030.h
@@ -147,7 +147,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int po1030_probe(struct sd *sd);
int po1030_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
index 8cc7a3f..8e0035e 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
@@ -65,7 +65,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int s5k4aa_probe(struct sd *sd);
int s5k4aa_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
index 80a63a2..7995224 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.h
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
@@ -41,7 +41,7 @@
/* Kernel module parameters */
extern int force_sensor;
-extern int dump_sensor;
+extern bool dump_sensor;
int s5k83a_probe(struct sd *sd);
int s5k83a_init(struct sd *sd);
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 5c2ea05c..b023146 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -263,7 +263,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = ARRAY_SIZE(vga_mode);
cam->ctrls = sd->ctrls;
sd->quality = QUALITY_DEF;
- gspca_dev->nbalt = 9; /* use the altsetting 08 */
return 0;
}
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c
index d4bec93..7167cac 100644
--- a/drivers/media/video/gspca/nw80x.c
+++ b/drivers/media/video/gspca/nw80x.c
@@ -1763,8 +1763,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
if ((unsigned) webcam >= NWEBCAMS)
webcam = 0;
sd->webcam = webcam;
- gspca_dev->cam.reverse_alts = 1;
gspca_dev->cam.ctrls = sd->ctrls;
+ gspca_dev->cam.needs_full_bandwidth = 1;
sd->ag_cnt = -1;
/*
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 08b8ce1..739e8a2 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -3348,7 +3348,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
case BRIDGE_W9968CF:
cam->cam_mode = w9968cf_vga_mode;
cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
- cam->reverse_alts = 1;
break;
}
@@ -3684,8 +3683,8 @@ static void ov511_mode_init_regs(struct sd *sd)
/* Check if we have enough bandwidth to disable compression */
fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
- /* 1400 is a conservative estimate of the max nr of isoc packets/sec */
- if (needed > 1400 * packet_size) {
+ /* 1000 isoc packets/sec */
+ if (needed > 1000 * packet_size) {
/* Enable Y and UV quantization and compression */
reg_w(sd, R511_COMP_EN, 0x07);
reg_w(sd, R511_COMP_LUT_EN, 0x03);
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
index f30060d..fbfa02a 100644
--- a/drivers/media/video/gspca/ov534_9.c
+++ b/drivers/media/video/gspca/ov534_9.c
@@ -71,6 +71,7 @@ struct sd {
enum sensors {
SENSOR_OV965x, /* ov9657 */
SENSOR_OV971x, /* ov9712 */
+ SENSOR_OV562x, /* ov5621 */
NSENSORS
};
@@ -207,6 +208,14 @@ static const struct v4l2_pix_format ov971x_mode[] = {
}
};
+static const struct v4l2_pix_format ov562x_mode[] = {
+ {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 2592,
+ .sizeimage = 2592 * 1680,
+ .colorspace = V4L2_COLORSPACE_SRGB
+ }
+};
+
static const u8 bridge_init[][2] = {
{0x88, 0xf8},
{0x89, 0xff},
@@ -830,6 +839,124 @@ static const u8 ov965x_start_2_sxga[][2] = {
{0xa3, 0x41}, /* bd60 */
};
+static const u8 ov562x_init[][2] = {
+ {0x88, 0x20},
+ {0x89, 0x0a},
+ {0x8a, 0x90},
+ {0x8b, 0x06},
+ {0x8c, 0x01},
+ {0x8d, 0x10},
+ {0x1c, 0x00},
+ {0x1d, 0x48},
+ {0x1d, 0x00},
+ {0x1d, 0xff},
+ {0x1c, 0x0a},
+ {0x1d, 0x2e},
+ {0x1d, 0x1e},
+};
+
+static const u8 ov562x_init_2[][2] = {
+ {0x12, 0x80},
+ {0x11, 0x41},
+ {0x13, 0x00},
+ {0x10, 0x1e},
+ {0x3b, 0x07},
+ {0x5b, 0x40},
+ {0x39, 0x07},
+ {0x53, 0x02},
+ {0x54, 0x60},
+ {0x04, 0x20},
+ {0x27, 0x04},
+ {0x3d, 0x40},
+ {0x36, 0x00},
+ {0xc5, 0x04},
+ {0x4e, 0x00},
+ {0x4f, 0x93},
+ {0x50, 0x7b},
+ {0xca, 0x0c},
+ {0xcb, 0x0f},
+ {0x39, 0x07},
+ {0x4a, 0x10},
+ {0x3e, 0x0a},
+ {0x3d, 0x00},
+ {0x0c, 0x38},
+ {0x38, 0x90},
+ {0x46, 0x30},
+ {0x4f, 0x93},
+ {0x50, 0x7b},
+ {0xab, 0x00},
+ {0xca, 0x0c},
+ {0xcb, 0x0f},
+ {0x37, 0x02},
+ {0x44, 0x48},
+ {0x8d, 0x44},
+ {0x2a, 0x00},
+ {0x2b, 0x00},
+ {0x32, 0x00},
+ {0x38, 0x90},
+ {0x53, 0x02},
+ {0x54, 0x60},
+ {0x12, 0x00},
+ {0x17, 0x12},
+ {0x18, 0xb4},
+ {0x19, 0x0c},
+ {0x1a, 0xf4},
+ {0x03, 0x4a},
+ {0x89, 0x20},
+ {0x83, 0x80},
+ {0xb7, 0x9d},
+ {0xb6, 0x11},
+ {0xb5, 0x55},
+ {0xb4, 0x00},
+ {0xa9, 0xf0},
+ {0xa8, 0x0a},
+ {0xb8, 0xf0},
+ {0xb9, 0xf0},
+ {0xba, 0xf0},
+ {0x81, 0x07},
+ {0x63, 0x44},
+ {0x13, 0xc7},
+ {0x14, 0x60},
+ {0x33, 0x75},
+ {0x2c, 0x00},
+ {0x09, 0x00},
+ {0x35, 0x30},
+ {0x27, 0x04},
+ {0x3c, 0x07},
+ {0x3a, 0x0a},
+ {0x3b, 0x07},
+ {0x01, 0x40},
+ {0x02, 0x40},
+ {0x16, 0x40},
+ {0x52, 0xb0},
+ {0x51, 0x83},
+ {0x21, 0xbb},
+ {0x22, 0x10},
+ {0x23, 0x03},
+ {0x35, 0x38},
+ {0x20, 0x90},
+ {0x28, 0x30},
+ {0x73, 0xe1},
+ {0x6c, 0x00},
+ {0x6d, 0x80},
+ {0x6e, 0x00},
+ {0x70, 0x04},
+ {0x71, 0x00},
+ {0x8d, 0x04},
+ {0x64, 0x00},
+ {0x65, 0x00},
+ {0x66, 0x00},
+ {0x67, 0x00},
+ {0x68, 0x00},
+ {0x69, 0x00},
+ {0x6a, 0x00},
+ {0x6b, 0x00},
+ {0x71, 0x94},
+ {0x74, 0x20},
+ {0x80, 0x09},
+ {0x85, 0xc0},
+};
+
static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
{
struct usb_device *udev = gspca_dev->dev;
@@ -1210,6 +1337,17 @@ static int sd_init(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x56, 0x1f);
else
reg_w(gspca_dev, 0x56, 0x17);
+ } else if ((sensor_id & 0xfff0) == 0x5620) {
+ sd->sensor = SENSOR_OV562x;
+
+ gspca_dev->cam.cam_mode = ov562x_mode;
+ gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
+
+ reg_w_array(gspca_dev, ov562x_init,
+ ARRAY_SIZE(ov562x_init));
+ sccb_w_array(gspca_dev, ov562x_init_2,
+ ARRAY_SIZE(ov562x_init_2));
+ reg_w(gspca_dev, 0xe0, 0x00);
} else {
err("Unknown sensor %04x", sensor_id);
return -EINVAL;
@@ -1222,7 +1360,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- if (sd->sensor == SENSOR_OV971x)
+ if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x)
return gspca_dev->usb_err;
switch (gspca_dev->curr_mode) {
case QVGA_MODE: /* 320x240 */
@@ -1409,6 +1547,7 @@ static const struct sd_desc sd_desc = {
static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x05a9, 0x8065)},
{USB_DEVICE(0x06f8, 0x3003)},
+ {USB_DEVICE(0x05a9, 0x1550)},
{}
};
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index ece8b1e..3844c49 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -41,14 +41,14 @@ MODULE_LICENSE("GPL");
#define PAC207_BRIGHTNESS_DEFAULT 46
#define PAC207_EXPOSURE_MIN 3
-#define PAC207_EXPOSURE_MAX 26
+#define PAC207_EXPOSURE_MAX 90 /* 1 sec expo time / 1 fps */
#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */
-#define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */
+#define PAC207_EXPOSURE_KNEE 9 /* fps: 90 / exposure -> 9: 10 fps */
#define PAC207_GAIN_MIN 0
#define PAC207_GAIN_MAX 31
-#define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
-#define PAC207_GAIN_KNEE 31
+#define PAC207_GAIN_DEFAULT 7 /* power on default: 9 */
+#define PAC207_GAIN_KNEE 15
#define PAC207_AUTOGAIN_DEADZONE 30
@@ -332,7 +332,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
if (sd->autogain_ignore_frames > 0)
sd->autogain_ignore_frames--;
else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
- 100, PAC207_AUTOGAIN_DEADZONE,
+ 90, PAC207_AUTOGAIN_DEADZONE,
PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
}
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index 2811195..9db2b34 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -1197,6 +1197,7 @@ static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
{USB_DEVICE(0x093a, 0x262a)},
{USB_DEVICE(0x093a, 0x262c)},
+ {USB_DEVICE(0x145f, 0x013c)},
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
index 1494e18..bb70092 100644
--- a/drivers/media/video/gspca/se401.c
+++ b/drivers/media/video/gspca/se401.c
@@ -376,7 +376,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->bulk_size = BULK_SIZE;
cam->bulk_nurbs = 4;
cam->ctrls = sd->ctrls;
- gspca_dev->nbalt = 1; /* Ignore the bogus isoc alt settings */
sd->resetlevel = 0x2d; /* Set initial resetlevel */
/* See if the camera supports brightness */
@@ -395,6 +394,14 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+ gspca_dev->alt = 1; /* Ignore the bogus isoc alt settings */
+
+ return gspca_dev->usb_err;
+}
+
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
@@ -714,6 +721,7 @@ static const struct sd_desc sd_desc = {
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
+ .isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,
.dq_callback = sd_dq_callback,
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 33cabc3..9e198b4 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -2048,6 +2048,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
struct cam *cam;
cam = &gspca_dev->cam;
+ cam->needs_full_bandwidth = 1;
sd->sensor = (id->driver_info >> 8) & 0xff;
sd->i2c_addr = id->driver_info & 0xff;
@@ -2233,6 +2234,42 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
}
}
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+ struct usb_interface *intf;
+ u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
+
+ /*
+ * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
+ * than our regular bandwidth calculations reserve, so we force the
+ * use of a specific altsetting when using the SN9C20X_I420 fmt.
+ */
+ if (!(flags & (MODE_RAW | MODE_JPEG))) {
+ intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+
+ if (intf->num_altsetting != 9) {
+ pr_warn("sn9c20x camera with unknown number of alt "
+ "settings (%d), please report!\n",
+ intf->num_altsetting);
+ gspca_dev->alt = intf->num_altsetting;
+ return 0;
+ }
+
+ switch (gspca_dev->width) {
+ case 160: /* 160x120 */
+ gspca_dev->alt = 2;
+ break;
+ case 320: /* 320x240 */
+ gspca_dev->alt = 6;
+ break;
+ default: /* >= 640x480 */
+ gspca_dev->alt = 9;
+ }
+ }
+
+ return 0;
+}
+
#define HW_WIN(mode, hstart, vstart) \
((const u8 []){hstart, 0, vstart, 0, \
(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
@@ -2473,6 +2510,7 @@ static const struct sd_desc sd_desc = {
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
+ .isoc_init = sd_isoc_init,
.start = sd_start,
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index ddb392d..6a1148d 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -1079,20 +1079,23 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
cam->npkt = 36; /* 36 packets per ISOC message */
- if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
- sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
- sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
- sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
- }
-
return 0;
}
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
const __u8 stop = 0x09; /* Disable stream turn of LED */
+ if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
+ sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
+ sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
+ sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
+ if (sd->ctrls[EXPOSURE].val > COARSE_EXPOSURE_MAX)
+ sd->ctrls[EXPOSURE].val = COARSE_EXPOSURE_DEF;
+ }
+
reg_w(gspca_dev, 0x01, &stop, 1);
return 0;
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index afa3186..0c9e6dd 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -1235,7 +1235,7 @@ static const u8 po2030n_sensor_param1[][8] = {
{DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
{0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
- {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10},
+ {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
/*param2*/
{0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
@@ -1779,10 +1779,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->ag_cnt = -1;
sd->quality = QUALITY_DEF;
- /* if USB 1.1, let some bandwidth for the audio device */
- if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
- gspca_dev->nbalt--;
-
INIT_WORK(&sd->work, qual_upd);
return 0;
@@ -2063,6 +2059,16 @@ static void setredblue(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ if (sd->sensor == SENSOR_PO2030N) {
+ u8 rg1b[] = /* red green1 blue (no g2) */
+ {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
+
+ /* 0x40 = normal value = gain x 1 */
+ rg1b[3] = sd->ctrls[RED].val * 2;
+ rg1b[5] = sd->ctrls[BLUE].val * 2;
+ i2c_w8(gspca_dev, rg1b);
+ return;
+ }
reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
/* reg_w1(gspca_dev, 0x07, 32); */
reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
@@ -2397,7 +2403,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x17, reg17);
reg01 &= ~S_PWR_DN; /* sensor power on */
reg_w1(gspca_dev, 0x01, reg01);
- reg01 &= ~SYS_SEL_48M;
+ reg01 &= ~SCL_SEL_OD; /* remove open-drain mode */
reg_w1(gspca_dev, 0x01, reg01);
switch (sd->sensor) {
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index 259a0c7..4a5f209 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -451,7 +451,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
}
cam = &gspca_dev->cam;
- gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
+ cam->needs_full_bandwidth = 1;
sd->chip_revision = id->driver_info;
if (sd->chip_revision == Rev012A) {
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index 0ab425f..91d99b4 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -36,8 +36,8 @@ MODULE_AUTHOR("Erik Andrén");
MODULE_DESCRIPTION("STV06XX USB Camera Driver");
MODULE_LICENSE("GPL");
-static int dump_bridge;
-static int dump_sensor;
+static bool dump_bridge;
+static bool dump_sensor;
int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
{
@@ -304,7 +304,7 @@ static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
- alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
alt->endpoint[0].desc.wMaxPacketSize =
cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
@@ -317,7 +317,7 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
struct usb_host_interface *alt;
struct sd *sd = (struct sd *) gspca_dev;
- alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
if (packet_size <= min_packet_size)
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index ea44deb..9b9f85a 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -30,6 +30,7 @@
#define MODULE_NAME "t613"
+#include <linux/input.h>
#include <linux/slab.h>
#include "gspca.h"
@@ -57,6 +58,7 @@ struct sd {
u8 effect;
u8 sensor;
+ u8 button_pressed;
};
enum sensors {
SENSOR_OM6802,
@@ -1095,15 +1097,35 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
msleep(20);
reg_w(gspca_dev, 0x0309);
}
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ /* If the last button state is pressed, release it now! */
+ if (sd->button_pressed) {
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+ input_sync(gspca_dev->input_dev);
+ sd->button_pressed = 0;
+ }
+#endif
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
u8 *data, /* isoc packet */
int len) /* iso packet length */
{
+ struct sd *sd = (struct sd *) gspca_dev;
int pkt_type;
if (data[0] == 0x5a) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ if (len > 20) {
+ u8 state = (data[20] & 0x80) ? 1 : 0;
+ if (sd->button_pressed != state) {
+ input_report_key(gspca_dev->input_dev,
+ KEY_CAMERA, state);
+ input_sync(gspca_dev->input_dev);
+ sd->button_pressed = state;
+ }
+ }
+#endif
/* Control Packet, after this came the header again,
* but extra bytes came in the packet before this,
* sometimes an EOF arrives, sometimes not... */
@@ -1410,6 +1432,9 @@ static const struct sd_desc sd_desc = {
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
.querymenu = sd_querymenu,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ .other_input = 1,
+#endif
};
/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/video/gspca/topro.c
index b2695b1..444d3c5 100644
--- a/drivers/media/video/gspca/topro.c
+++ b/drivers/media/video/gspca/topro.c
@@ -3946,7 +3946,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
/* 640x480 * 30 fps does not work */
if (i == 6 /* if 30 fps */
&& gspca_dev->width == 640)
- i = 0x86; /* 15 fps */
+ i = 0x05; /* 15 fps */
} else {
for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
if (sd->framerate >= rates_6810[i])
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c
index d12ea151..911152e 100644
--- a/drivers/media/video/gspca/vicam.c
+++ b/drivers/media/video/gspca/vicam.c
@@ -324,7 +324,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
dev->work_thread = NULL;
mutex_lock(&gspca_dev->usb_lock);
- vicam_set_camera_power(gspca_dev, 0);
+ if (gspca_dev->present)
+ vicam_set_camera_power(gspca_dev, 0);
}
/* Table of supported USB devices */
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index fbb6ed2..ecada17 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -995,14 +995,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
case CIT_MODEL0:
cam->cam_mode = model0_mode;
cam->nmodes = ARRAY_SIZE(model0_mode);
- cam->reverse_alts = 1;
gspca_dev->ctrl_dis = ~((1 << SD_CONTRAST) | (1 << SD_HFLIP));
sd->sof_len = 4;
break;
case CIT_MODEL1:
cam->cam_mode = cif_yuv_mode;
cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
- cam->reverse_alts = 1;
gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_HFLIP);
sd->sof_len = 4;
break;
@@ -2791,7 +2789,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
}
/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
- alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
return 0;
@@ -2814,7 +2812,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
break;
}
- alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
if (packet_size <= min_packet_size)
return -EIO;
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 0202fea..b9e15bb 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -5381,12 +5381,12 @@ static const struct usb_action tas5130c_NoFlikerScale[] = {
{}
};
-static const struct usb_action gc0303_InitialScale[] = {
+/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */
+static const struct usb_action gc0303_Initial[] = {
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
- {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc,
- * 0<->10 */
+ {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
@@ -5405,29 +5405,22 @@ static const struct usb_action gc0303_InitialScale[] = {
* 6<->8 */
{0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
{0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
- {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
- {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
- {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
- {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
- {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
-/*?? {0xaa, 0x01, 0x0000}, */
{0xaa, 0x01, 0x0000},
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
{0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
+ {0xaa, 0x1b, 0x0000},
{0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
{0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
{0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
{0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
- {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
- {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
- {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
- {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
- {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
- {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
- {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
- {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
-/*?? {0xa0, 0x00, 0x0039},
- {0xa1, 0x01, 0x0037}, */
+ {0xaa, 0x0a, 0x0002},
+ {0xaa, 0x0b, 0x0000},
+ {0xaa, 0x0c, 0x0002},
+ {0xaa, 0x0d, 0x0000},
+ {0xaa, 0x0e, 0x0002},
+ {0xaa, 0x0f, 0x0000},
+ {0xaa, 0x10, 0x0002},
+ {0xaa, 0x11, 0x0000},
{0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
{0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */
{0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
@@ -5442,17 +5435,18 @@ static const struct usb_action gc0303_InitialScale[] = {
{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
- {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
+ {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
{0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
{0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
+ {0xaa, 0x1b, 0x0000},
{}
};
-static const struct usb_action gc0303_Initial[] = {
+static const struct usb_action gc0303_InitialScale[] = {
{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
{0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
- {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc, */
+ {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
@@ -5471,34 +5465,26 @@ static const struct usb_action gc0303_Initial[] = {
* 8<->6 */
{0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
{0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
- {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
- {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
- {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
- {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
- {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
-/*?? {0xaa, 0x01, 0x0000}, */
{0xaa, 0x01, 0x0000},
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
{0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
+ {0xaa, 0x1b, 0x0000},
{0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
{0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
{0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
{0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
- {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
- {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
- {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
- {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
- {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
- {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
- {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
- {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
-/*?? {0xa0, 0x00, 0x0039},
- {0xa1, 0x01, 0x0037}, */
+ {0xaa, 0x0a, 0x0001},
+ {0xaa, 0x0b, 0x0000},
+ {0xaa, 0x0c, 0x0001},
+ {0xaa, 0x0d, 0x0000},
+ {0xaa, 0x0e, 0x0001},
+ {0xaa, 0x0f, 0x0000},
+ {0xaa, 0x10, 0x0001},
+ {0xaa, 0x11, 0x0000},
{0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
{0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */
{0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
{0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */
- {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
{0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
@@ -5508,36 +5494,37 @@ static const struct usb_action gc0303_Initial[] = {
{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
- {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
+ {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
{0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
{0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
+ {0xaa, 0x1b, 0x0000},
{}
};
-static const struct usb_action gc0303_50HZScale[] = {
+static const struct usb_action gc0303_50HZ[] = {
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
- {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */
+ {0xaa, 0x84, 0x0063},
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
{0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
{0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
- {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
+ {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
{0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
{0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
{0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
- {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
+ {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},
{0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
{0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
{0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
{0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
- {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
+ {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
{}
};
-static const struct usb_action gc0303_50HZ[] = {
+static const struct usb_action gc0303_50HZScale[] = {
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
{0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
@@ -5550,21 +5537,21 @@ static const struct usb_action gc0303_50HZ[] = {
{0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
{0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
{0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
- {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
+ {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
{0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
{0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
{0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
{0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
- {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
+ {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
{}
};
-static const struct usb_action gc0303_60HZScale[] = {
+static const struct usb_action gc0303_60HZ[] = {
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
- {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
- {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */
+ {0xaa, 0x83, 0x0000},
+ {0xaa, 0x84, 0x003b},
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
{0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
{0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
@@ -5581,14 +5568,14 @@ static const struct usb_action gc0303_60HZScale[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
{0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
- {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
+ {0xa0, 0x80, ZC3XX_R18D_YTARGET},
{}
};
-static const struct usb_action gc0303_60HZ[] = {
+static const struct usb_action gc0303_60HZScale[] = {
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
- {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
- {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */
+ {0xaa, 0x83, 0x0000},
+ {0xaa, 0x84, 0x0076},
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
{0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */
{0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */
@@ -5605,18 +5592,18 @@ static const struct usb_action gc0303_60HZ[] = {
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */
{0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
- {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,d,78,cc */
+ {0xa0, 0x80, ZC3XX_R18D_YTARGET},
{}
};
-static const struct usb_action gc0303_NoFlikerScale[] = {
+static const struct usb_action gc0303_NoFliker[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
{0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */
- {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
- {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
+ {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+ {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
{0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
@@ -5631,14 +5618,14 @@ static const struct usb_action gc0303_NoFlikerScale[] = {
{}
};
-static const struct usb_action gc0303_NoFliker[] = {
+static const struct usb_action gc0303_NoFlikerScale[] = {
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
{0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
- {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc, */
- {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc, */
+ {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+ {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
{0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
@@ -5809,7 +5796,7 @@ static void setmatrix(struct gspca_dev *gspca_dev)
static const u8 tas5130c_matrix[9] =
{0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
static const u8 gc0303_matrix[9] =
- {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
+ {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c};
static const u8 *matrix_tb[SENSOR_MAX] = {
[SENSOR_ADCM2700] = adcm2700_matrix,
[SENSOR_CS2102] = ov7620_matrix,
@@ -6426,10 +6413,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
gspca_dev->cam.ctrls = sd->ctrls;
sd->quality = QUALITY_DEF;
- /* if USB 1.1, let some bandwidth for the audio device */
- if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
- gspca_dev->nbalt--;
-
return 0;
}
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index 3f1a5b1..e5eb56a 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -49,7 +49,7 @@ module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / "
"1=RCA front / 2=S/PDIF");
-static int boost_audio;
+static bool boost_audio;
module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(boost_audio, "boost the audio signal");
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 3ab875d..a7c41d3 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -244,7 +244,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
/* ----------------------------------------------------------------------- */
-static void ir_key_poll(struct IR_i2c *ir)
+static int ir_key_poll(struct IR_i2c *ir)
{
static u32 ir_key, ir_raw;
int rc;
@@ -253,20 +253,28 @@ static void ir_key_poll(struct IR_i2c *ir)
rc = ir->get_key(ir, &ir_key, &ir_raw);
if (rc < 0) {
dprintk(2,"error\n");
- return;
+ return rc;
}
if (rc) {
dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
rc_keydown(ir->rc, ir_key, 0);
}
+ return 0;
}
static void ir_work(struct work_struct *work)
{
+ int rc;
struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
- ir_key_poll(ir);
+ rc = ir_key_poll(ir);
+ if (rc == -ENODEV) {
+ rc_unregister_device(ir->rc);
+ ir->rc = NULL;
+ return;
+ }
+
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
}
@@ -446,7 +454,8 @@ static int ir_remove(struct i2c_client *client)
cancel_delayed_work_sync(&ir->work);
/* unregister device */
- rc_unregister_device(ir->rc);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
/* free memory */
kfree(ir);
@@ -489,11 +498,3 @@ static void __exit ir_fini(void)
module_init(ir_init);
module_exit(ir_fini);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 41108a9a..544af91c 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
static unsigned int cardtype_c = 1;
static unsigned int tuner_c = 1;
-static unsigned int radio_c = 1;
+static bool radio_c = 1;
static unsigned int i2c_clock_period_c = 1;
static char pal[] = "---";
static char secam[] = "--";
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h
index 9332920..7b9ec1c 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.h
+++ b/drivers/media/video/ivtv/ivtv-i2c.h
@@ -25,7 +25,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv);
int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
-/* init + register i2c algo-bit adapter */
+/* init + register i2c adapter */
int init_ivtv_i2c(struct ivtv *itv);
void exit_ivtv_i2c(struct ivtv *itv);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 6b7c9c8..d0fbfcf 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -58,7 +58,7 @@
/* card parameters */
static int ivtvfb_card_id = -1;
static int ivtvfb_debug = 0;
-static int osd_laced;
+static bool osd_laced;
static int osd_depth;
static int osd_upper;
static int osd_left;
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h
index 82c8817..4b021e1 100644
--- a/drivers/media/video/m5mols/m5mols.h
+++ b/drivers/media/video/m5mols/m5mols.h
@@ -163,7 +163,6 @@ struct m5mols_version {
* @ffmt: current fmt according to resolution type
* @res_type: current resolution type
* @irq_waitq: waitqueue for the capture
- * @work_irq: workqueue for the IRQ
* @flags: state variable for the interrupt handler
* @handle: control handler
* @autoexposure: Auto Exposure control
@@ -175,14 +174,12 @@ struct m5mols_version {
* @ver: information of the version
* @cap: the capture mode attributes
* @power: current sensor's power status
- * @ctrl_sync: true means all controls of the sensor are initialized
- * @int_capture: true means the capture interrupt is issued once
+ * @isp_ready: 1 when the ISP controller has completed booting
+ * @ctrl_sync: 1 when the control handler state is restored in H/W
* @lock_ae: true means the Auto Exposure is locked
* @lock_awb: true means the Aut WhiteBalance is locked
* @resolution: register value for current resolution
- * @interrupt: register value for current interrupt status
* @mode: register value for current operation mode
- * @mode_save: register value for current operation mode for saving
* @set_power: optional power callback to the board code
*/
struct m5mols_info {
@@ -191,16 +188,16 @@ struct m5mols_info {
struct media_pad pad;
struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
int res_type;
+
wait_queue_head_t irq_waitq;
- struct work_struct work_irq;
- unsigned long flags;
+ atomic_t irq_done;
struct v4l2_ctrl_handler handle;
+
/* Autoexposure/exposure control cluster */
- struct {
- struct v4l2_ctrl *autoexposure;
- struct v4l2_ctrl *exposure;
- };
+ struct v4l2_ctrl *autoexposure;
+ struct v4l2_ctrl *exposure;
+
struct v4l2_ctrl *autowb;
struct v4l2_ctrl *colorfx;
struct v4l2_ctrl *saturation;
@@ -208,21 +205,19 @@ struct m5mols_info {
struct m5mols_version ver;
struct m5mols_capture cap;
- bool power;
- bool ctrl_sync;
+
+ unsigned int isp_ready:1;
+ unsigned int power:1;
+ unsigned int ctrl_sync:1;
+
bool lock_ae;
bool lock_awb;
u8 resolution;
- u8 interrupt;
u8 mode;
- u8 mode_save;
+
int (*set_power)(struct device *dev, int on);
};
-#define ST_CAPT_IRQ 0
-
-#define is_powered(__info) (__info->power)
-#define is_ctrl_synced(__info) (__info->ctrl_sync)
#define is_available_af(__info) (__info->ver.af)
#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
#define is_manufacturer(__info, __manufacturer) \
@@ -257,7 +252,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
+
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+ int timeout);
+
+/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
+#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16)
+/* ISP state transition timeout, in ms */
+#define M5MOLS_MODE_CHANGE_TIMEOUT 200
+#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250
/*
* Mode operation of the M-5MOLS
@@ -282,7 +285,8 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
int m5mols_mode(struct m5mols_info *info, u8 mode);
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
-int m5mols_sync_controls(struct m5mols_info *info);
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
+int m5mols_restore_controls(struct m5mols_info *info);
int m5mols_start_capture(struct m5mols_info *info);
int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
int m5mols_lock_3a(struct m5mols_info *info, bool lock);
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c
index 3248ac8..ba25e8e 100644
--- a/drivers/media/video/m5mols/m5mols_capture.c
+++ b/drivers/media/video/m5mols/m5mols_capture.c
@@ -1,3 +1,4 @@
+
/*
* The Capture code for Fujitsu M-5MOLS ISP
*
@@ -25,26 +26,11 @@
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
#include "m5mols.h"
#include "m5mols_reg.h"
-static int m5mols_capture_error_handler(struct m5mols_info *info,
- int timeout)
-{
- int ret;
-
- /* Disable all interrupts and clear relevant interrupt staus bits */
- ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,
- info->interrupt & ~(REG_INT_CAPTURE));
- if (ret)
- return ret;
-
- if (timeout == 0)
- return -ETIMEDOUT;
-
- return 0;
-}
/**
* m5mols_read_rational - I2C read of a rational number
*
@@ -121,69 +107,54 @@ int m5mols_start_capture(struct m5mols_info *info)
{
struct v4l2_subdev *sd = &info->sd;
u8 resolution = info->resolution;
- int timeout;
int ret;
/*
- * Preparing capture. Setting control & interrupt before entering
- * capture mode
- *
- * 1) change to MONITOR mode for operating control & interrupt
- * 2) set controls (considering v4l2_control value & lock 3A)
- * 3) set interrupt
- * 4) change to CAPTURE mode
+ * Synchronize the controls, set the capture frame resolution and color
+ * format. The frame capture is initiated during switching from Monitor
+ * to Capture mode.
*/
ret = m5mols_mode(info, REG_MONITOR);
if (!ret)
- ret = m5mols_sync_controls(info);
+ ret = m5mols_restore_controls(info);
if (!ret)
- ret = m5mols_lock_3a(info, true);
+ ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
+ if (!ret)
+ ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
if (!ret)
- ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
+ ret = m5mols_lock_3a(info, true);
if (!ret)
ret = m5mols_mode(info, REG_CAPTURE);
- if (!ret) {
- /* Wait for capture interrupt, after changing capture mode */
- timeout = wait_event_interruptible_timeout(info->irq_waitq,
- test_bit(ST_CAPT_IRQ, &info->flags),
- msecs_to_jiffies(2000));
- if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags))
- ret = m5mols_capture_error_handler(info, timeout);
- }
+ if (!ret)
+ /* Wait until a frame is captured to ISP internal memory */
+ ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
if (!ret)
ret = m5mols_lock_3a(info, false);
if (ret)
return ret;
+
/*
- * Starting capture. Setting capture frame count and resolution and
- * the format(available format: JPEG, Bayer RAW, YUV).
- *
- * 1) select single or multi(enable to 25), format, size
- * 2) set interrupt
- * 3) start capture(for main image, now)
- * 4) get information
- * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)
+ * Initiate the captured data transfer to a MIPI-CSI receiver.
*/
ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
if (!ret)
- ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
- if (!ret)
- ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
- if (!ret)
- ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
- if (!ret)
ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
if (!ret) {
+ bool captured = false;
+ unsigned int size;
+
/* Wait for the capture completion interrupt */
- timeout = wait_event_interruptible_timeout(info->irq_waitq,
- test_bit(ST_CAPT_IRQ, &info->flags),
- msecs_to_jiffies(2000));
- if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) {
+ ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
+ if (!ret) {
+ captured = true;
ret = m5mols_capture_info(info);
- if (!ret)
- v4l2_subdev_notify(sd, 0, &info->cap.total);
}
+ size = captured ? info->cap.main : 0;
+ v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n",
+ __func__, size, info->cap.thumb);
+
+ v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size);
}
- return m5mols_capture_error_handler(info, timeout);
+ return ret;
}
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c
index e0f09e5..93d768d 100644
--- a/drivers/media/video/m5mols/m5mols_core.c
+++ b/drivers/media/video/m5mols/m5mols_core.c
@@ -135,10 +135,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
* @reg: combination of size, category and command for the I2C packet
* @size: desired size of I2C packet
* @val: read value
+ *
+ * Returns 0 on success, or else negative errno.
*/
static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct m5mols_info *info = to_m5mols(sd);
u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
u8 category = I2C_CATEGORY(reg);
u8 cmd = I2C_COMMAND(reg);
@@ -168,15 +171,17 @@ static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
usleep_range(200, 200);
ret = i2c_transfer(client->adapter, msg, 2);
- if (ret < 0) {
- v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
- size, category, cmd, ret);
- return ret;
+
+ if (ret == 2) {
+ *val = m5mols_swap_byte(&rbuf[1], size);
+ return 0;
}
- *val = m5mols_swap_byte(&rbuf[1], size);
+ if (info->isp_ready)
+ v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
+ size, category, cmd, ret);
- return 0;
+ return ret < 0 ? ret : -EIO;
}
int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
@@ -229,10 +234,13 @@ int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
* m5mols_write - I2C command write function
* @reg: combination of size, category and command for the I2C packet
* @val: value to write
+ *
+ * Returns 0 on success, or else negative errno.
*/
int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct m5mols_info *info = to_m5mols(sd);
u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
u8 category = I2C_CATEGORY(reg);
u8 cmd = I2C_COMMAND(reg);
@@ -263,28 +271,45 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
usleep_range(200, 200);
ret = i2c_transfer(client->adapter, msg, 1);
- if (ret < 0) {
- v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n",
- size, category, cmd, ret);
- return ret;
- }
+ if (ret == 1)
+ return 0;
- return 0;
+ if (info->isp_ready)
+ v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
+ category, cmd, ret);
+
+ return ret < 0 ? ret : -EIO;
}
-int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
+/**
+ * m5mols_busy_wait - Busy waiting with I2C register polling
+ * @reg: the I2C_REG() address of an 8-bit status register to check
+ * @value: expected status register value
+ * @mask: bit mask for the read status register value
+ * @timeout: timeout in miliseconds, or -1 for default timeout
+ *
+ * The @reg register value is ORed with @mask before comparing with @value.
+ *
+ * Return: 0 if the requested condition became true within less than
+ * @timeout ms, or else negative errno.
+ */
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+ int timeout)
{
- u8 busy;
- int i;
- int ret;
+ int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
+ unsigned long end = jiffies + msecs_to_jiffies(ms);
+ u8 status;
- for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
- ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
- if (ret < 0)
+ do {
+ int ret = m5mols_read_u8(sd, reg, &status);
+
+ if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
return ret;
- if ((busy & mask) == mask)
+ if (!ret && (status & mask & 0xff) == (value & 0xff))
return 0;
- }
+ usleep_range(100, 250);
+ } while (ms > 0 && time_is_after_jiffies(end));
+
return -EBUSY;
}
@@ -307,6 +332,20 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
return ret;
}
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
+{
+ struct m5mols_info *info = to_m5mols(sd);
+
+ int ret = wait_event_interruptible_timeout(info->irq_waitq,
+ atomic_add_unless(&info->irq_done, -1, 0),
+ msecs_to_jiffies(timeout));
+ if (ret <= 0)
+ return ret ? ret : -ETIMEDOUT;
+
+ return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
+ M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
+}
+
/**
* m5mols_reg_mode - Write the mode and check busy status
*
@@ -316,8 +355,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
{
int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
-
- return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode);
+ if (ret < 0)
+ return ret;
+ return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
+ M5MOLS_MODE_CHANGE_TIMEOUT);
}
/**
@@ -338,13 +379,13 @@ int m5mols_mode(struct m5mols_info *info, u8 mode)
return ret;
ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
- if ((!ret && reg == mode) || ret)
+ if (ret || reg == mode)
return ret;
switch (reg) {
case REG_PARAMETER:
ret = m5mols_reg_mode(sd, REG_MONITOR);
- if (!ret && mode == REG_MONITOR)
+ if (mode == REG_MONITOR)
break;
if (!ret)
ret = m5mols_reg_mode(sd, REG_CAPTURE);
@@ -361,7 +402,7 @@ int m5mols_mode(struct m5mols_info *info, u8 mode)
case REG_CAPTURE:
ret = m5mols_reg_mode(sd, REG_MONITOR);
- if (!ret && mode == REG_MONITOR)
+ if (mode == REG_MONITOR)
break;
if (!ret)
ret = m5mols_reg_mode(sd, REG_PARAMETER);
@@ -570,26 +611,25 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
};
/**
- * m5mols_sync_controls - Apply default scene mode and the current controls
+ * m5mols_restore_controls - Apply current control values to the registers
*
- * This is used only streaming for syncing between v4l2_ctrl framework and
- * m5mols's controls. First, do the scenemode to the sensor, then call
- * v4l2_ctrl_handler_setup. It can be same between some commands and
- * the scenemode's in the default v4l2_ctrls. But, such commands of control
- * should be prior to the scenemode's one.
+ * m5mols_do_scenemode() handles all parameters for which there is yet no
+ * individual control. It should be replaced at some point by setting each
+ * control individually, in required register set up order.
*/
-int m5mols_sync_controls(struct m5mols_info *info)
+int m5mols_restore_controls(struct m5mols_info *info)
{
- int ret = -EINVAL;
+ int ret;
- if (!is_ctrl_synced(info)) {
- ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
- if (ret)
- return ret;
+ if (info->ctrl_sync)
+ return 0;
- v4l2_ctrl_handler_setup(&info->handle);
- info->ctrl_sync = true;
- }
+ ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
+ if (ret)
+ return ret;
+
+ ret = v4l2_ctrl_handler_setup(&info->handle);
+ info->ctrl_sync = !ret;
return ret;
}
@@ -613,7 +653,7 @@ static int m5mols_start_monitor(struct m5mols_info *info)
if (!ret)
ret = m5mols_mode(info, REG_MONITOR);
if (!ret)
- ret = m5mols_sync_controls(info);
+ ret = m5mols_restore_controls(info);
return ret;
}
@@ -645,17 +685,25 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = to_sd(ctrl);
struct m5mols_info *info = to_m5mols(sd);
+ int ispstate = info->mode;
int ret;
- info->mode_save = info->mode;
+ /*
+ * If needed, defer restoring the controls until
+ * the device is fully initialized.
+ */
+ if (!info->isp_ready) {
+ info->ctrl_sync = 0;
+ return 0;
+ }
ret = m5mols_mode(info, REG_PARAMETER);
- if (!ret)
- ret = m5mols_set_ctrl(ctrl);
- if (!ret)
- ret = m5mols_mode(info, info->mode_save);
-
- return ret;
+ if (ret < 0)
+ return ret;
+ ret = m5mols_set_ctrl(ctrl);
+ if (ret < 0)
+ return ret;
+ return m5mols_mode(info, ispstate);
}
static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
@@ -669,10 +717,10 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
const struct m5mols_platform_data *pdata = info->pdata;
int ret;
- if (enable) {
- if (is_powered(info))
- return 0;
+ if (info->power == enable)
+ return 0;
+ if (enable) {
if (info->set_power) {
ret = info->set_power(&client->dev, 1);
if (ret)
@@ -686,15 +734,11 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
}
gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
- usleep_range(1000, 1000);
- info->power = true;
+ info->power = 1;
return ret;
}
- if (!is_powered(info))
- return 0;
-
ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
if (ret)
return ret;
@@ -703,8 +747,9 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
info->set_power(&client->dev, 0);
gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
- usleep_range(1000, 1000);
- info->power = false;
+
+ info->isp_ready = 0;
+ info->power = 0;
return ret;
}
@@ -717,21 +762,29 @@ int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
}
/**
- * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core.
+ * m5mols_fw_start - M-5MOLS internal ARM controller initialization
*
- * Booting internal ARM core makes the M-5MOLS is ready for getting commands
- * with I2C. It's the first thing to be done after it powered up. It must wait
- * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting.
+ * Execute the M-5MOLS internal ARM controller initialization sequence.
+ * This function should be called after the supply voltage has been
+ * applied and before any requests to the device are made.
*/
-static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
+static int m5mols_fw_start(struct v4l2_subdev *sd)
{
+ struct m5mols_info *info = to_m5mols(sd);
int ret;
- ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+ atomic_set(&info->irq_done, 0);
+ /* Wait until I2C slave is initialized in Flash Writer mode */
+ ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
+ M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
+ if (!ret)
+ ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+ if (!ret)
+ ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
if (ret < 0)
return ret;
- msleep(520);
+ info->isp_ready = 1;
ret = m5mols_get_version(sd);
if (!ret)
@@ -743,7 +796,8 @@ static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
if (!ret)
- ret = m5mols_enable_interrupt(sd, REG_INT_AF);
+ ret = m5mols_enable_interrupt(sd,
+ REG_INT_AF | REG_INT_CAPTURE);
return ret;
}
@@ -780,7 +834,7 @@ static int m5mols_init_controls(struct m5mols_info *info)
4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE);
info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle,
&m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
- 1, 0, V4L2_EXPOSURE_MANUAL);
+ 1, 0, V4L2_EXPOSURE_AUTO);
sd->ctrl_handler = &info->handle;
if (info->handle.error) {
@@ -809,16 +863,7 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
if (on) {
ret = m5mols_sensor_power(info, true);
if (!ret)
- ret = m5mols_sensor_armboot(sd);
- if (!ret)
- ret = m5mols_init_controls(info);
- if (ret)
- return ret;
-
- info->ffmt[M5MOLS_RESTYPE_MONITOR] =
- m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR];
- info->ffmt[M5MOLS_RESTYPE_CAPTURE] =
- m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE];
+ ret = m5mols_fw_start(sd);
return ret;
}
@@ -829,17 +874,14 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
if (!ret)
ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
if (!ret)
- ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS,
- REG_AF_IDLE);
- if (!ret)
- v4l2_info(sd, "Success soft-landing lens\n");
+ ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
+ 0xff, -1);
+ if (ret < 0)
+ v4l2_warn(sd, "Soft landing lens failed\n");
}
ret = m5mols_sensor_power(info, false);
- if (!ret) {
- v4l2_ctrl_handler_free(&info->handle);
- info->ctrl_sync = false;
- }
+ info->ctrl_sync = 0;
return ret;
}
@@ -865,52 +907,33 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = {
.log_status = m5mols_log_status,
};
+/*
+ * V4L2 subdev internal operations
+ */
+static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+ *format = m5mols_default_ffmt[0];
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
+ .open = m5mols_open,
+};
+
static const struct v4l2_subdev_ops m5mols_ops = {
.core = &m5mols_core_ops,
.pad = &m5mols_pad_ops,
.video = &m5mols_video_ops,
};
-static void m5mols_irq_work(struct work_struct *work)
-{
- struct m5mols_info *info =
- container_of(work, struct m5mols_info, work_irq);
- struct v4l2_subdev *sd = &info->sd;
- u8 reg;
- int ret;
-
- if (!is_powered(info) ||
- m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
- return;
-
- switch (info->interrupt & REG_INT_MASK) {
- case REG_INT_AF:
- if (!is_available_af(info))
- break;
- ret = m5mols_read_u8(sd, AF_STATUS, &reg);
- v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
- reg == REG_AF_FAIL ? "Failed" :
- reg == REG_AF_SUCCESS ? "Success" :
- reg == REG_AF_IDLE ? "Idle" : "Busy");
- break;
- case REG_INT_CAPTURE:
- if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags))
- wake_up_interruptible(&info->irq_waitq);
-
- v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n");
- break;
- default:
- v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg);
- break;
- };
-}
-
static irqreturn_t m5mols_irq_handler(int irq, void *data)
{
- struct v4l2_subdev *sd = data;
- struct m5mols_info *info = to_m5mols(sd);
+ struct m5mols_info *info = to_m5mols(data);
- schedule_work(&info->work_irq);
+ atomic_set(&info->irq_done, 1);
+ wake_up_interruptible(&info->irq_waitq);
return IRQ_HANDLED;
}
@@ -961,7 +984,9 @@ static int __devinit m5mols_probe(struct i2c_client *client,
sd = &info->sd;
strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ sd->internal_ops = &m5mols_subdev_internal_ops;
info->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
if (ret < 0)
@@ -969,7 +994,6 @@ static int __devinit m5mols_probe(struct i2c_client *client,
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
init_waitqueue_head(&info->irq_waitq);
- INIT_WORK(&info->work_irq, m5mols_irq_work);
ret = request_irq(client->irq, m5mols_irq_handler,
IRQF_TRIGGER_RISING, MODULE_NAME, sd);
if (ret) {
@@ -977,7 +1001,20 @@ static int __devinit m5mols_probe(struct i2c_client *client,
goto out_me;
}
info->res_type = M5MOLS_RESTYPE_MONITOR;
- return 0;
+ info->ffmt[0] = m5mols_default_ffmt[0];
+ info->ffmt[1] = m5mols_default_ffmt[1];
+
+ ret = m5mols_sensor_power(info, true);
+ if (ret)
+ goto out_me;
+
+ ret = m5mols_fw_start(sd);
+ if (!ret)
+ ret = m5mols_init_controls(info);
+
+ m5mols_sensor_power(info, false);
+ if (!ret)
+ return 0;
out_me:
media_entity_cleanup(&sd->entity);
out_reg:
@@ -995,6 +1032,7 @@ static int __devexit m5mols_remove(struct i2c_client *client)
struct m5mols_info *info = to_m5mols(sd);
v4l2_device_unregister_subdev(sd);
+ v4l2_ctrl_handler_free(sd->ctrl_handler);
free_irq(client->irq, sd);
regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h
index c755bd6..ae4aced 100644
--- a/drivers/media/video/m5mols/m5mols_reg.h
+++ b/drivers/media/video/m5mols/m5mols_reg.h
@@ -55,39 +55,31 @@
* There is many registers between customer version address and awb one. For
* more specific contents, see definition if file m5mols.h.
*/
-#define CAT0_VER_CUSTOMER 0x00 /* customer version */
-#define CAT0_VER_PROJECT 0x01 /* project version */
-#define CAT0_VER_FIRMWARE 0x02 /* Firmware version */
-#define CAT0_VER_HARDWARE 0x04 /* Hardware version */
-#define CAT0_VER_PARAMETER 0x06 /* Parameter version */
-#define CAT0_VER_AWB 0x08 /* Auto WB version */
-#define CAT0_VER_STRING 0x0a /* string including M-5MOLS */
-#define CAT0_SYSMODE 0x0b /* SYSTEM mode register */
-#define CAT0_STATUS 0x0c /* SYSTEM mode status register */
-#define CAT0_INT_FACTOR 0x10 /* interrupt pending register */
-#define CAT0_INT_ENABLE 0x11 /* interrupt enable register */
-
-#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1)
-#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1)
-#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2)
-#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2)
-#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2)
-#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2)
-
-#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1)
+#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, 0x00, 1)
+#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, 0x01, 1)
+#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, 0x02, 2)
+#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, 0x04, 2)
+#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, 0x06, 2)
+#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, 0x08, 2)
+
+#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, 0x0b, 1)
#define REG_SYSINIT 0x00 /* SYSTEM mode */
#define REG_PARAMETER 0x01 /* PARAMETER mode */
#define REG_MONITOR 0x02 /* MONITOR mode */
#define REG_CAPTURE 0x03 /* CAPTURE mode */
#define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1)
-#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1)
+#define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, 0x0a, 1)
#define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */
#define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */
#define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */
+/* SYSTEM mode status */
+#define SYSTEM_STATUS I2C_REG(CAT_SYSTEM, 0x0c, 1)
-#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1)
-#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1)
+/* Interrupt pending register */
+#define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, 0x10, 1)
+/* interrupt enable register */
+#define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, 0x11, 1)
#define REG_INT_MODE (1 << 0)
#define REG_INT_AF (1 << 1)
#define REG_INT_ZOOM (1 << 2)
@@ -105,20 +97,20 @@
* can handle with preview(MONITOR) resolution size/frame per second/interface
* between the sensor and the Application Processor/even the image effect.
*/
-#define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */
-#define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */
-#define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */
-#define CAT1_EFFECT 0x0b /* image effects */
-#define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1)
+/* Resolution in the MONITOR mode */
+#define PARM_MON_SIZE I2C_REG(CAT_PARAM, 0x01, 1)
-#define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1)
+/* Frame rate */
+#define PARM_MON_FPS I2C_REG(CAT_PARAM, 0x02, 1)
#define REG_FPS_30 0x02
-#define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1)
+/* Video bus between the sensor and a host processor */
+#define PARM_INTERFACE I2C_REG(CAT_PARAM, 0x00, 1)
#define REG_INTERFACE_MIPI 0x02
-#define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1)
+/* Image effects */
+#define PARM_EFFECT I2C_REG(CAT_PARAM, 0x0b, 1)
#define REG_EFFECT_OFF 0x00
#define REG_EFFECT_NEGA 0x01
#define REG_EFFECT_EMBOSS 0x06
@@ -135,39 +127,37 @@
* another options like zoom/color effect(different with effect in PARAMETER
* mode)/anti hand shaking algorithm.
*/
-#define CAT2_ZOOM 0x01 /* set the zoom position & execute */
-#define CAT2_ZOOM_STEP 0x03 /* set the zoom step */
-#define CAT2_CFIXB 0x09 /* CB value for color effect */
-#define CAT2_CFIXR 0x0a /* CR value for color effect */
-#define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */
-#define CAT2_CHROMA_LVL 0x0f /* set chroma level */
-#define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */
-#define CAT2_EDGE_LVL 0x11 /* set sharpness level */
-#define CAT2_EDGE_EN 0x12 /* set on/off sharpness */
-#define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */
-
-#define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1)
-
-#define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1)
-#define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1)
+
+/* Target digital zoom position */
+#define MON_ZOOM I2C_REG(CAT_MONITOR, 0x01, 1)
+
+/* CR value for color effect */
+#define MON_CFIXR I2C_REG(CAT_MONITOR, 0x0a, 1)
+/* CB value for color effect */
+#define MON_CFIXB I2C_REG(CAT_MONITOR, 0x09, 1)
#define REG_CFIXB_SEPIA 0xd8
#define REG_CFIXR_SEPIA 0x18
-#define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1)
+#define MON_EFFECT I2C_REG(CAT_MONITOR, 0x0b, 1)
#define REG_COLOR_EFFECT_OFF 0x00
#define REG_COLOR_EFFECT_ON 0x01
-#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1)
-#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1)
+/* Chroma enable */
+#define MON_CHROMA_EN I2C_REG(CAT_MONITOR, 0x10, 1)
+/* Chroma level */
+#define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, 0x0f, 1)
#define REG_CHROMA_OFF 0x00
#define REG_CHROMA_ON 0x01
-#define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1)
-#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1)
+/* Sharpness on/off */
+#define MON_EDGE_EN I2C_REG(CAT_MONITOR, 0x12, 1)
+/* Sharpness level */
+#define MON_EDGE_LVL I2C_REG(CAT_MONITOR, 0x11, 1)
#define REG_EDGE_OFF 0x00
#define REG_EDGE_ON 0x01
-#define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1)
+/* Set color tone (contrast) */
+#define MON_TONE_CTL I2C_REG(CAT_MONITOR, 0x25, 1)
/*
* Category 3 - Auto Exposure
@@ -179,27 +169,20 @@
* different. So, this category also provide getting the max/min values. And,
* each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
*/
-#define CAT3_AE_LOCK 0x00 /* locking Auto exposure */
-#define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */
-#define CAT3_ISO 0x05 /* set ISO */
-#define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */
-#define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */
-#define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */
-#define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */
-#define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */
-#define CAT3_AE_INDEX 0x38 /* AE index */
-
-#define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1)
+
+/* Auto Exposure locking */
+#define AE_LOCK I2C_REG(CAT_AE, 0x00, 1)
#define REG_AE_UNLOCK 0x00
#define REG_AE_LOCK 0x01
-#define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1)
+/* Auto Exposure algorithm mode */
+#define AE_MODE I2C_REG(CAT_AE, 0x01, 1)
#define REG_AE_OFF 0x00 /* AE off */
#define REG_AE_ALL 0x01 /* calc AE in all block integral */
#define REG_AE_CENTER 0x03 /* calc AE in center weighted */
#define REG_AE_SPOT 0x06 /* calc AE in specific spot */
-#define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1)
+#define AE_ISO I2C_REG(CAT_AE, 0x05, 1)
#define REG_ISO_AUTO 0x00
#define REG_ISO_50 0x01
#define REG_ISO_100 0x02
@@ -207,8 +190,10 @@
#define REG_ISO_400 0x04
#define REG_ISO_800 0x05
-#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1)
-#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1)
+/* EV (scenemode) preset for MONITOR */
+#define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, 0x0a, 1)
+/* EV (scenemode) preset for CAPTURE */
+#define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, 0x0b, 1)
#define REG_SCENE_NORMAL 0x00
#define REG_SCENE_PORTRAIT 0x01
#define REG_SCENE_LANDSCAPE 0x02
@@ -224,11 +209,14 @@
#define REG_SCENE_TEXT 0x0c
#define REG_SCENE_CANDLE 0x0d
-#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2)
-#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2)
-#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2)
+/* Manual gain in MONITOR mode */
+#define AE_MAN_GAIN_MON I2C_REG(CAT_AE, 0x12, 2)
+/* Maximum gain in MONITOR mode */
+#define AE_MAX_GAIN_MON I2C_REG(CAT_AE, 0x1a, 2)
+/* Manual gain in CAPTURE mode */
+#define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, 0x26, 2)
-#define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1)
+#define AE_INDEX I2C_REG(CAT_AE, 0x38, 1)
#define REG_AE_INDEX_20_NEG 0x00
#define REG_AE_INDEX_15_NEG 0x01
#define REG_AE_INDEX_10_NEG 0x02
@@ -241,22 +229,19 @@
/*
* Category 6 - White Balance
- *
- * This category provide AWB locking/mode/preset/speed/gain bias, etc.
*/
-#define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */
-#define CAT6_AWB_MODE 0x02 /* set Auto or Manual */
-#define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */
-#define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1)
+/* Auto Whitebalance locking */
+#define AWB_LOCK I2C_REG(CAT_WB, 0x00, 1)
#define REG_AWB_UNLOCK 0x00
#define REG_AWB_LOCK 0x01
-#define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1)
+#define AWB_MODE I2C_REG(CAT_WB, 0x02, 1)
#define REG_AWB_AUTO 0x01 /* AWB off */
#define REG_AWB_PRESET 0x02 /* AWB preset */
-#define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1)
+/* Manual WB (preset) */
+#define AWB_MANUAL I2C_REG(CAT_WB, 0x03, 1)
#define REG_AWB_INCANDESCENT 0x01
#define REG_AWB_FLUORESCENT_1 0x02
#define REG_AWB_FLUORESCENT_2 0x03
@@ -269,42 +254,25 @@
/*
* Category 7 - EXIF information
*/
-#define CAT7_INFO_EXPTIME_NU 0x00
-#define CAT7_INFO_EXPTIME_DE 0x04
-#define CAT7_INFO_TV_NU 0x08
-#define CAT7_INFO_TV_DE 0x0c
-#define CAT7_INFO_AV_NU 0x10
-#define CAT7_INFO_AV_DE 0x14
-#define CAT7_INFO_BV_NU 0x18
-#define CAT7_INFO_BV_DE 0x1c
-#define CAT7_INFO_EBV_NU 0x20
-#define CAT7_INFO_EBV_DE 0x24
-#define CAT7_INFO_ISO 0x28
-#define CAT7_INFO_FLASH 0x2a
-#define CAT7_INFO_SDR 0x2c
-#define CAT7_INFO_QVAL 0x2e
-
-#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4)
-#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4)
-#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4)
-#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4)
-#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4)
-#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4)
-#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4)
-#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4)
-#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4)
-#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4)
-#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2)
-#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2)
-#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2)
-#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2)
+#define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, 0x00, 4)
+#define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, 0x04, 4)
+#define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, 0x08, 4)
+#define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, 0x0c, 4)
+#define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, 0x10, 4)
+#define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, 0x14, 4)
+#define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, 0x18, 4)
+#define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, 0x1c, 4)
+#define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, 0x20, 4)
+#define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, 0x24, 4)
+#define EXIF_INFO_ISO I2C_REG(CAT_EXIF, 0x28, 2)
+#define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, 0x2a, 2)
+#define EXIF_INFO_SDR I2C_REG(CAT_EXIF, 0x2c, 2)
+#define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, 0x2e, 2)
/*
* Category 9 - Face Detection
*/
-#define CAT9_FD_CTL 0x00
-
-#define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1)
+#define FD_CTL I2C_REG(CAT_FD, 0x00, 1)
#define BIT_FD_EN 0
#define BIT_FD_DRAW_FACE_FRAME 4
#define BIT_FD_DRAW_SMILE_LVL 6
@@ -314,62 +282,50 @@
/*
* Category A - Lens Parameter
*/
-#define CATA_AF_MODE 0x01
-#define CATA_AF_EXECUTE 0x02
-#define CATA_AF_STATUS 0x03
-#define CATA_AF_VERSION 0x0a
-
-#define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1)
+#define AF_MODE I2C_REG(CAT_LENS, 0x01, 1)
#define REG_AF_NORMAL 0x00 /* Normal AF, one time */
#define REG_AF_MACRO 0x01 /* Macro AF, one time */
#define REG_AF_POWEROFF 0x07
-#define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1)
+#define AF_EXECUTE I2C_REG(CAT_LENS, 0x02, 1)
#define REG_AF_STOP 0x00
#define REG_AF_EXE_AUTO 0x01
#define REG_AF_EXE_CAF 0x02
-#define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1)
+#define AF_STATUS I2C_REG(CAT_LENS, 0x03, 1)
#define REG_AF_FAIL 0x00
#define REG_AF_SUCCESS 0x02
#define REG_AF_IDLE 0x04
#define REG_AF_BUSY 0x05
-#define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1)
+#define AF_VERSION I2C_REG(CAT_LENS, 0x0a, 1)
/*
* Category B - CAPTURE Parameter
*/
-#define CATB_YUVOUT_MAIN 0x00
-#define CATB_MAIN_IMAGE_SIZE 0x01
-#define CATB_MCC_MODE 0x1d
-#define CATB_WDR_EN 0x2c
-#define CATB_LIGHT_CTRL 0x40
-#define CATB_FLASH_CTRL 0x41
-
-#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1)
+#define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, 0x00, 1)
#define REG_YUV422 0x00
#define REG_BAYER10 0x05
#define REG_BAYER8 0x06
#define REG_JPEG 0x10
-#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1)
+#define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1)
-#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1)
+#define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
#define REG_MCC_OFF 0x00
#define REG_MCC_NORMAL 0x01
-#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1)
+#define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, 0x2c, 1)
#define REG_WDR_OFF 0x00
#define REG_WDR_ON 0x01
#define REG_WDR_AUTO 0x02
-#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1)
+#define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, 0x40, 1)
#define REG_LIGHT_OFF 0x00
#define REG_LIGHT_ON 0x01
#define REG_LIGHT_AUTO 0x02
-#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1)
+#define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, 0x41, 1)
#define REG_FLASH_OFF 0x00
#define REG_FLASH_ON 0x01
#define REG_FLASH_AUTO 0x02
@@ -377,34 +333,29 @@
/*
* Category C - CAPTURE Control
*/
-#define CATC_CAP_MODE 0x00
-#define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */
-#define CATC_CAP_START 0x09
-#define CATC_CAP_IMAGE_SIZE 0x0d
-#define CATC_CAP_THUMB_SIZE 0x11
-
-#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1)
+#define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, 0x00, 1)
#define REG_CAP_NONE 0x00
#define REG_CAP_ANTI_SHAKE 0x02
-#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1)
+/* Select single- or multi-shot capture */
+#define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, 0x06, 1)
-#define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1)
+#define CAPC_START I2C_REG(CAT_CAPT_CTRL, 0x09, 1)
#define REG_CAP_START_MAIN 0x01
#define REG_CAP_START_THUMB 0x03
-#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4)
-#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4)
+#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, 0x0d, 4)
+#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, 0x11, 4)
/*
* Category F - Flash
*
* This mode provides functions about internal flash stuff and system startup.
*/
-#define CATF_CAM_START 0x12 /* It starts internal ARM core booting
- * after power-up */
-#define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1)
-#define REG_START_ARM_BOOT 0x01
+/* Starts internal ARM core booting after power-up */
+#define FLASH_CAM_START I2C_REG(CAT_FLASH, 0x12, 1)
+#define REG_START_ARM_BOOT 0x01 /* write value */
+#define REG_IN_FLASH_MODE 0x00 /* read value */
#endif /* M5MOLS_REG_H */
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
index 80ec64d..37d20e7 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.c
+++ b/drivers/media/video/marvell-ccic/mcam-core.c
@@ -51,7 +51,7 @@ static int delivered;
* sense.
*/
-static int alloc_bufs_at_read;
+static bool alloc_bufs_at_read;
module_param(alloc_bufs_at_read, bool, 0444);
MODULE_PARM_DESC(alloc_bufs_at_read,
"Non-zero value causes DMA buffers to be allocated when the "
@@ -73,11 +73,11 @@ MODULE_PARM_DESC(dma_buf_size,
"parameters require larger buffers, an attempt to reallocate "
"will be made.");
#else /* MCAM_MODE_VMALLOC */
-static const int alloc_bufs_at_read = 0;
+static const bool alloc_bufs_at_read = 0;
static const int n_dma_bufs = 3; /* Used by S/G_PARM */
#endif /* MCAM_MODE_VMALLOC */
-static int flip;
+static bool flip;
module_param(flip, bool, 0444);
MODULE_PARM_DESC(flip,
"If set, the sensor will be instructed to flip the image "
@@ -522,6 +522,15 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam)
*/
static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
{
+ /*
+ * The list-empty condition can hit us at resume time
+ * if the buffer list was empty when the system was suspended.
+ */
+ if (list_empty(&cam->buffers)) {
+ set_bit(CF_SG_RESTART, &cam->flags);
+ return;
+ }
+
mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD);
mcam_sg_next_buffer(cam);
mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA);
@@ -566,6 +575,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
} else {
set_bit(CF_SG_RESTART, &cam->flags);
singles++;
+ cam->vb_bufs[0] = NULL;
}
/*
* Now we can give the completed frame back to user space.
@@ -661,10 +671,10 @@ static int mcam_ctlr_configure(struct mcam_camera *cam)
unsigned long flags;
spin_lock_irqsave(&cam->dev_lock, flags);
+ clear_bit(CF_SG_RESTART, &cam->flags);
cam->dma_setup(cam);
mcam_ctlr_image(cam);
mcam_set_config_needed(cam, 0);
- clear_bit(CF_SG_RESTART, &cam->flags);
spin_unlock_irqrestore(&cam->dev_lock, flags);
return 0;
}
@@ -873,7 +883,8 @@ static int mcam_read_setup(struct mcam_camera *cam)
mcam_reset_buffers(cam);
mcam_ctlr_irq_enable(cam);
cam->state = S_STREAMING;
- mcam_ctlr_start(cam);
+ if (!test_bit(CF_SG_RESTART, &cam->flags))
+ mcam_ctlr_start(cam);
spin_unlock_irqrestore(&cam->dev_lock, flags);
return 0;
}
@@ -1818,11 +1829,15 @@ void mccic_shutdown(struct mcam_camera *cam)
void mccic_suspend(struct mcam_camera *cam)
{
- enum mcam_state cstate = cam->state;
+ mutex_lock(&cam->s_mutex);
+ if (cam->users > 0) {
+ enum mcam_state cstate = cam->state;
- mcam_ctlr_stop_dma(cam);
- mcam_ctlr_power_down(cam);
- cam->state = cstate;
+ mcam_ctlr_stop_dma(cam);
+ mcam_ctlr_power_down(cam);
+ cam->state = cstate;
+ }
+ mutex_unlock(&cam->s_mutex);
}
int mccic_resume(struct mcam_camera *cam)
@@ -1839,8 +1854,15 @@ int mccic_resume(struct mcam_camera *cam)
mutex_unlock(&cam->s_mutex);
set_bit(CF_CONFIG_NEEDED, &cam->flags);
- if (cam->state == S_STREAMING)
+ if (cam->state == S_STREAMING) {
+ /*
+ * If there was a buffer in the DMA engine at suspend
+ * time, put it back on the queue or we'll forget about it.
+ */
+ if (cam->buffer_mode == B_DMA_sg && cam->vb_bufs[0])
+ list_add(&cam->vb_bufs[0]->queue, &cam->buffers);
ret = mcam_read_setup(cam);
+ }
return ret;
}
#endif /* CONFIG_PM */
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c
index fb0b124..0d64e2d 100644
--- a/drivers/media/video/marvell-ccic/mmp-driver.c
+++ b/drivers/media/video/marvell-ccic/mmp-driver.c
@@ -26,6 +26,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/list.h>
+#include <linux/pm.h>
#include "mcam-core.h"
@@ -310,10 +311,44 @@ static int mmpcam_platform_remove(struct platform_device *pdev)
return mmpcam_remove(cam);
}
+/*
+ * Suspend/resume support.
+ */
+#ifdef CONFIG_PM
+
+static int mmpcam_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mmp_camera *cam = mmpcam_find_device(pdev);
+
+ if (state.event != PM_EVENT_SUSPEND)
+ return 0;
+ mccic_suspend(&cam->mcam);
+ return 0;
+}
+
+static int mmpcam_resume(struct platform_device *pdev)
+{
+ struct mmp_camera *cam = mmpcam_find_device(pdev);
+
+ /*
+ * Power up unconditionally just in case the core tries to
+ * touch a register even if nothing was active before; trust
+ * me, it's better this way.
+ */
+ mmpcam_power_up(&cam->mcam);
+ return mccic_resume(&cam->mcam);
+}
+
+#endif
+
static struct platform_driver mmpcam_driver = {
.probe = mmpcam_probe,
.remove = mmpcam_platform_remove,
+#ifdef CONFIG_PM
+ .suspend = mmpcam_suspend,
+ .resume = mmpcam_resume,
+#endif
.driver = {
.name = "mmp-camera",
.owner = THIS_MODULE
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index d0f5388..d7cd0f6 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -69,12 +69,12 @@ MODULE_LICENSE("GPL");
/* module parameters */
static int opmode = OPMODE_AUTO;
int msp_debug; /* msp_debug output */
-int msp_once; /* no continuous stereo monitoring */
-int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france),
+bool msp_once; /* no continuous stereo monitoring */
+bool msp_amsound; /* hard-wire AM sound at 6.5 Hz (france),
the autoscan seems work well only with FM... */
int msp_standard = 1; /* Override auto detect of audio msp_standard,
if needed. */
-int msp_dolby;
+bool msp_dolby;
int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
(msp34xxg only) 0x00a0-0x03c0 */
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 831e8db..fbe5e07 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -44,10 +44,10 @@
/* module parameters */
extern int msp_debug;
-extern int msp_once;
-extern int msp_amsound;
+extern bool msp_once;
+extern bool msp_amsound;
extern int msp_standard;
-extern int msp_dolby;
+extern bool msp_dolby;
extern int msp_stereo_thresh;
struct msp_state {
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index e2b1029..097c9d3 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -109,14 +109,13 @@ static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
static int reg_read(struct i2c_client *client, const u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
- return data < 0 ? data : swab16(data);
+ return i2c_smbus_read_word_swapped(client, reg);
}
static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- return i2c_smbus_write_word_data(client, reg, swab16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int reg_set(struct i2c_client *client, const u8 reg,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 398f96f..bee65bf 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -139,25 +139,52 @@
#define MT9M111_MAX_HEIGHT 1024
#define MT9M111_MAX_WIDTH 1280
+struct mt9m111_context {
+ u16 read_mode;
+ u16 blanking_h;
+ u16 blanking_v;
+ u16 reducer_xzoom;
+ u16 reducer_yzoom;
+ u16 reducer_xsize;
+ u16 reducer_ysize;
+ u16 output_fmt_ctrl2;
+ u16 control;
+};
+
+static struct mt9m111_context context_a = {
+ .read_mode = MT9M111_READ_MODE_A,
+ .blanking_h = MT9M111_HORIZONTAL_BLANKING_A,
+ .blanking_v = MT9M111_VERTICAL_BLANKING_A,
+ .reducer_xzoom = MT9M111_REDUCER_XZOOM_A,
+ .reducer_yzoom = MT9M111_REDUCER_YZOOM_A,
+ .reducer_xsize = MT9M111_REDUCER_XSIZE_A,
+ .reducer_ysize = MT9M111_REDUCER_YSIZE_A,
+ .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_A,
+ .control = MT9M111_CTXT_CTRL_RESTART,
+};
+
+static struct mt9m111_context context_b = {
+ .read_mode = MT9M111_READ_MODE_B,
+ .blanking_h = MT9M111_HORIZONTAL_BLANKING_B,
+ .blanking_v = MT9M111_VERTICAL_BLANKING_B,
+ .reducer_xzoom = MT9M111_REDUCER_XZOOM_B,
+ .reducer_yzoom = MT9M111_REDUCER_YZOOM_B,
+ .reducer_xsize = MT9M111_REDUCER_XSIZE_B,
+ .reducer_ysize = MT9M111_REDUCER_YSIZE_B,
+ .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_B,
+ .control = MT9M111_CTXT_CTRL_RESTART |
+ MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |
+ MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |
+ MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |
+ MT9M111_CTXT_CTRL_HBLANK_SEL_B,
+};
+
/* MT9M111 has only one fixed colorspace per pixelcode */
struct mt9m111_datafmt {
enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
-/* Find a data format by a pixel code in an array */
-static const struct mt9m111_datafmt *mt9m111_find_datafmt(
- enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt,
- int n)
-{
- int i;
- for (i = 0; i < n; i++)
- if (fmt[i].code == code)
- return fmt + i;
-
- return NULL;
-}
-
static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
{V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
@@ -173,27 +200,35 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
};
-enum mt9m111_context {
- HIGHPOWER = 0,
- LOWPOWER,
-};
-
struct mt9m111 {
struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *gain;
int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
* from v4l2-chip-ident.h */
- enum mt9m111_context context;
- struct v4l2_rect rect;
+ struct mt9m111_context *ctx;
+ struct v4l2_rect rect; /* cropping rectangle */
+ int width; /* output */
+ int height; /* sizes */
struct mutex power_lock; /* lock to protect power_count */
int power_count;
const struct mt9m111_datafmt *fmt;
int lastpage; /* PageMap cache value */
unsigned char datawidth;
- unsigned int powered:1;
};
+/* Find a data format by a pixel code */
+static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,
+ enum v4l2_mbus_pixelcode code)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)
+ if (mt9m111_colour_fmts[i].code == code)
+ return mt9m111_colour_fmts + i;
+
+ return mt9m111->fmt;
+}
+
static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
{
return container_of(i2c_get_clientdata(client), struct mt9m111, subdev);
@@ -211,7 +246,7 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg)
if (page > 2)
return -EINVAL;
- ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
+ ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page);
if (!ret)
mt9m111->lastpage = page;
return ret;
@@ -223,7 +258,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff));
+ ret = i2c_smbus_read_word_swapped(client, reg & 0xff);
dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret);
return ret;
@@ -236,8 +271,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = i2c_smbus_write_word_data(client, reg & 0xff,
- swab16(data));
+ ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data);
dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret;
}
@@ -276,76 +310,63 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
}
static int mt9m111_set_context(struct mt9m111 *mt9m111,
- enum mt9m111_context ctxt)
+ struct mt9m111_context *ctx)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
- int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
- | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
- | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
- | MT9M111_CTXT_CTRL_VBLANK_SEL_B
- | MT9M111_CTXT_CTRL_HBLANK_SEL_B;
- int valA = MT9M111_CTXT_CTRL_RESTART;
-
- if (ctxt == HIGHPOWER)
- return reg_write(CONTEXT_CONTROL, valB);
- else
- return reg_write(CONTEXT_CONTROL, valA);
+ return reg_write(CONTEXT_CONTROL, ctx->control);
}
-static int mt9m111_setup_rect(struct mt9m111 *mt9m111,
- struct v4l2_rect *rect)
+static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,
+ struct mt9m111_context *ctx, struct v4l2_rect *rect,
+ unsigned int width, unsigned int height)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
- int ret, is_raw_format;
- int width = rect->width;
- int height = rect->height;
+ int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, rect->width);
+ if (!ret)
+ ret = mt9m111_reg_write(client, ctx->reducer_yzoom, rect->height);
+ if (!ret)
+ ret = mt9m111_reg_write(client, ctx->reducer_xsize, width);
+ if (!ret)
+ ret = mt9m111_reg_write(client, ctx->reducer_ysize, height);
+ return ret;
+}
- if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
- mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE)
- is_raw_format = 1;
- else
- is_raw_format = 0;
+static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,
+ int width, int height, enum v4l2_mbus_pixelcode code)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+ int ret;
ret = reg_write(COLUMN_START, rect->left);
if (!ret)
ret = reg_write(ROW_START, rect->top);
- if (is_raw_format) {
- if (!ret)
- ret = reg_write(WINDOW_WIDTH, width);
- if (!ret)
- ret = reg_write(WINDOW_HEIGHT, height);
- } else {
- if (!ret)
- ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH);
- if (!ret)
- ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
- if (!ret)
- ret = reg_write(REDUCER_XSIZE_B, width);
- if (!ret)
- ret = reg_write(REDUCER_YSIZE_B, height);
- if (!ret)
- ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
- if (!ret)
- ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
+ if (!ret)
+ ret = reg_write(WINDOW_WIDTH, rect->width);
+ if (!ret)
+ ret = reg_write(WINDOW_HEIGHT, rect->height);
+
+ if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+ /* IFP in use, down-scaling possible */
if (!ret)
- ret = reg_write(REDUCER_XSIZE_A, width);
+ ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,
+ rect, width, height);
if (!ret)
- ret = reg_write(REDUCER_YSIZE_A, height);
+ ret = mt9m111_setup_rect_ctx(mt9m111, &context_a,
+ rect, width, height);
}
+ dev_dbg(&client->dev, "%s(%x): %ux%u@%u:%u -> %ux%u = %d\n",
+ __func__, code, rect->width, rect->height, rect->left, rect->top,
+ width, height, ret);
+
return ret;
}
static int mt9m111_enable(struct mt9m111 *mt9m111)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
- int ret;
-
- ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE);
- if (!ret)
- mt9m111->powered = 1;
- return ret;
+ return reg_write(RESET, MT9M111_RESET_CHIP_ENABLE);
}
static int mt9m111_reset(struct mt9m111 *mt9m111)
@@ -363,43 +384,41 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
return ret;
}
-static int mt9m111_make_rect(struct mt9m111 *mt9m111,
- struct v4l2_rect *rect)
+static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
{
+ struct v4l2_rect rect = a->c;
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+ int width, height;
+ int ret;
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
/* Bayer format - even size lengths */
- rect->width = ALIGN(rect->width, 2);
- rect->height = ALIGN(rect->height, 2);
+ rect.width = ALIGN(rect.width, 2);
+ rect.height = ALIGN(rect.height, 2);
/* Let the user play with the starting pixel */
}
/* FIXME: the datasheet doesn't specify minimum sizes */
- soc_camera_limit_side(&rect->left, &rect->width,
+ soc_camera_limit_side(&rect.left, &rect.width,
MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH);
- soc_camera_limit_side(&rect->top, &rect->height,
+ soc_camera_limit_side(&rect.top, &rect.height,
MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT);
- return mt9m111_setup_rect(mt9m111, rect);
-}
-
-static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
-{
- struct v4l2_rect rect = a->c;
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
- int ret;
-
- dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
- __func__, rect.left, rect.top, rect.width, rect.height);
+ width = min(mt9m111->width, rect.width);
+ height = min(mt9m111->height, rect.height);
- if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- ret = mt9m111_make_rect(mt9m111, &rect);
- if (!ret)
+ ret = mt9m111_setup_geometry(mt9m111, &rect, width, height, mt9m111->fmt->code);
+ if (!ret) {
mt9m111->rect = rect;
+ mt9m111->width = width;
+ mt9m111->height = height;
+ }
+
return ret;
}
@@ -434,8 +453,8 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd,
{
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
- mf->width = mt9m111->rect.width;
- mf->height = mt9m111->rect.height;
+ mf->width = mt9m111->width;
+ mf->height = mt9m111->height;
mf->code = mt9m111->fmt->code;
mf->colorspace = mt9m111->fmt->colorspace;
mf->field = V4L2_FIELD_NONE;
@@ -504,46 +523,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
return -EINVAL;
}
- ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2,
- mask_outfmt2);
+ ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
+ data_outfmt2, mask_outfmt2);
if (!ret)
- ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2,
- mask_outfmt2);
-
- return ret;
-}
-
-static int mt9m111_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- const struct mt9m111_datafmt *fmt;
- struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
- struct v4l2_rect rect = {
- .left = mt9m111->rect.left,
- .top = mt9m111->rect.top,
- .width = mf->width,
- .height = mf->height,
- };
- int ret;
-
- fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
- ARRAY_SIZE(mt9m111_colour_fmts));
- if (!fmt)
- return -EINVAL;
-
- dev_dbg(&client->dev,
- "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
- mf->code, rect.left, rect.top, rect.width, rect.height);
-
- ret = mt9m111_make_rect(mt9m111, &rect);
- if (!ret)
- ret = mt9m111_set_pixfmt(mt9m111, mf->code);
- if (!ret) {
- mt9m111->rect = rect;
- mt9m111->fmt = fmt;
- mf->colorspace = fmt->colorspace;
- }
+ ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,
+ data_outfmt2, mask_outfmt2);
return ret;
}
@@ -551,42 +535,71 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
static int mt9m111_try_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf)
{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
const struct mt9m111_datafmt *fmt;
- bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
- mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
-
- fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
- ARRAY_SIZE(mt9m111_colour_fmts));
- if (!fmt) {
- fmt = mt9m111->fmt;
- mf->code = fmt->code;
- }
+ struct v4l2_rect *rect = &mt9m111->rect;
+ bool bayer;
+
+ fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+
+ bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+ fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
/*
* With Bayer format enforce even side lengths, but let the user play
* with the starting pixel
*/
+ if (bayer) {
+ rect->width = ALIGN(rect->width, 2);
+ rect->height = ALIGN(rect->height, 2);
+ }
- if (mf->height > MT9M111_MAX_HEIGHT)
- mf->height = MT9M111_MAX_HEIGHT;
- else if (mf->height < 2)
- mf->height = 2;
- else if (bayer)
- mf->height = ALIGN(mf->height, 2);
+ if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+ /* IFP bypass mode, no scaling */
+ mf->width = rect->width;
+ mf->height = rect->height;
+ } else {
+ /* No upscaling */
+ if (mf->width > rect->width)
+ mf->width = rect->width;
+ if (mf->height > rect->height)
+ mf->height = rect->height;
+ }
- if (mf->width > MT9M111_MAX_WIDTH)
- mf->width = MT9M111_MAX_WIDTH;
- else if (mf->width < 2)
- mf->width = 2;
- else if (bayer)
- mf->width = ALIGN(mf->width, 2);
+ dev_dbg(&client->dev, "%s(): %ux%u, code=%x\n", __func__,
+ mf->width, mf->height, fmt->code);
+ mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
return 0;
}
+static int mt9m111_s_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *mf)
+{
+ const struct mt9m111_datafmt *fmt;
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+ struct v4l2_rect *rect = &mt9m111->rect;
+ int ret;
+
+ mt9m111_try_fmt(sd, mf);
+ fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+ /* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */
+
+ ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);
+ if (!ret)
+ ret = mt9m111_set_pixfmt(mt9m111, mf->code);
+ if (!ret) {
+ mt9m111->width = mf->width;
+ mt9m111->height = mf->height;
+ mt9m111->fmt = fmt;
+ }
+
+ return ret;
+}
+
static int mt9m111_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *id)
{
@@ -650,17 +663,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret;
- if (mt9m111->context == HIGHPOWER) {
- if (flip)
- ret = reg_set(READ_MODE_B, mask);
- else
- ret = reg_clear(READ_MODE_B, mask);
- } else {
- if (flip)
- ret = reg_set(READ_MODE_A, mask);
- else
- ret = reg_clear(READ_MODE_A, mask);
- }
+ if (flip)
+ ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);
+ else
+ ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);
return ret;
}
@@ -738,30 +744,39 @@ static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
static int mt9m111_suspend(struct mt9m111 *mt9m111)
{
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+ int ret;
+
v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
- return 0;
+ ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+ if (!ret)
+ ret = reg_set(RESET, MT9M111_RESET_RESET_SOC |
+ MT9M111_RESET_OUTPUT_DISABLE |
+ MT9M111_RESET_ANALOG_STANDBY);
+ if (!ret)
+ ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
+
+ return ret;
}
static void mt9m111_restore_state(struct mt9m111 *mt9m111)
{
- mt9m111_set_context(mt9m111, mt9m111->context);
+ mt9m111_set_context(mt9m111, mt9m111->ctx);
mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
- mt9m111_setup_rect(mt9m111, &mt9m111->rect);
+ mt9m111_setup_geometry(mt9m111, &mt9m111->rect,
+ mt9m111->width, mt9m111->height, mt9m111->fmt->code);
v4l2_ctrl_handler_setup(&mt9m111->hdl);
}
static int mt9m111_resume(struct mt9m111 *mt9m111)
{
- int ret = 0;
+ int ret = mt9m111_enable(mt9m111);
+ if (!ret)
+ ret = mt9m111_reset(mt9m111);
+ if (!ret)
+ mt9m111_restore_state(mt9m111);
- if (mt9m111->powered) {
- ret = mt9m111_enable(mt9m111);
- if (!ret)
- ret = mt9m111_reset(mt9m111);
- if (!ret)
- mt9m111_restore_state(mt9m111);
- }
return ret;
}
@@ -770,12 +785,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret;
- mt9m111->context = HIGHPOWER;
+ /* Default HIGHPOWER context */
+ mt9m111->ctx = &context_b;
ret = mt9m111_enable(mt9m111);
if (!ret)
ret = mt9m111_reset(mt9m111);
if (!ret)
- ret = mt9m111_set_context(mt9m111, mt9m111->context);
+ ret = mt9m111_set_context(mt9m111, mt9m111->ctx);
if (ret)
dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
return ret;
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
index 73c0689..93c3ec7 100644
--- a/drivers/media/video/mt9p031.c
+++ b/drivers/media/video/mt9p031.c
@@ -132,13 +132,12 @@ static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
static int mt9p031_read(struct i2c_client *client, u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
- return data < 0 ? data : be16_to_cpu(data);
+ return i2c_smbus_read_word_swapped(client, reg);
}
static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
{
- return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c
index 08074b8..cd81d04a 100644
--- a/drivers/media/video/mt9t001.c
+++ b/drivers/media/video/mt9t001.c
@@ -133,13 +133,12 @@ static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
static int mt9t001_read(struct i2c_client *client, u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
- return data < 0 ? data : be16_to_cpu(data);
+ return i2c_smbus_read_word_swapped(client, reg);
}
static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
{
- return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 0e78477..84add1a 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -90,14 +90,13 @@ static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
static int reg_read(struct i2c_client *client, const u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
- return data < 0 ? data : swab16(data);
+ return i2c_smbus_read_word_swapped(client, reg);
}
static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- return i2c_smbus_write_word_data(client, reg, swab16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int reg_set(struct i2c_client *client, const u8 reg,
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 690ee0d..9449407 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -130,14 +130,13 @@ static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
static int reg_read(struct i2c_client *client, const u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
- return data < 0 ? data : swab16(data);
+ return i2c_smbus_read_word_swapped(client, reg);
}
static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- return i2c_smbus_write_word_data(client, reg, swab16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int reg_set(struct i2c_client *client, const u8 reg,
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c
index f080c16..d90b982 100644
--- a/drivers/media/video/mt9v032.c
+++ b/drivers/media/video/mt9v032.c
@@ -139,10 +139,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
static int mt9v032_read(struct i2c_client *client, const u8 reg)
{
- s32 data = i2c_smbus_read_word_data(client, reg);
+ s32 data = i2c_smbus_read_word_swapped(client, reg);
dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
- swab16(data), reg);
- return data < 0 ? data : swab16(data);
+ data, reg);
+ return data;
}
static int mt9v032_write(struct i2c_client *client, const u8 reg,
@@ -150,7 +150,7 @@ static int mt9v032_write(struct i2c_client *client, const u8 reg,
{
dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
data, reg);
- return i2c_smbus_write_word_data(client, reg, swab16(data));
+ return i2c_smbus_write_word_swapped(client, reg, data);
}
static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 18e94c7..055d11d 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -487,7 +487,7 @@ static int mx1_camera_set_crop(struct soc_camera_device *icd,
return v4l2_subdev_call(sd, video, s_crop, a);
}
-static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index a803d9e..04aab0c 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -210,6 +210,22 @@
#define MAX_VIDEO_MEM 16
+struct mx2_prp_cfg {
+ int channel;
+ u32 in_fmt;
+ u32 out_fmt;
+ u32 src_pixel;
+ u32 ch1_pixel;
+ u32 irq_flags;
+};
+
+/* prp configuration for a client-host fmt pair */
+struct mx2_fmt_cfg {
+ enum v4l2_mbus_pixelcode in_fmt;
+ u32 out_fmt;
+ struct mx2_prp_cfg cfg;
+};
+
struct mx2_camera_dev {
struct device *dev;
struct soc_camera_host soc_host;
@@ -241,6 +257,8 @@ struct mx2_camera_dev {
void *discard_buffer;
dma_addr_t discard_buffer_dma;
size_t discard_size;
+ struct mx2_fmt_cfg *emma_prp;
+ u32 frame_count;
};
/* buffer for one video frame */
@@ -253,6 +271,59 @@ struct mx2_buffer {
int bufnum;
};
+static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
+ /*
+ * This is a generic configuration which is valid for most
+ * prp input-output format combinations.
+ * We set the incomming and outgoing pixelformat to a
+ * 16 Bit wide format and adjust the bytesperline
+ * accordingly. With this configuration the inputdata
+ * will not be changed by the emma and could be any type
+ * of 16 Bit Pixelformat.
+ */
+ {
+ .in_fmt = 0,
+ .out_fmt = 0,
+ .cfg = {
+ .channel = 1,
+ .in_fmt = PRP_CNTL_DATA_IN_RGB16,
+ .out_fmt = PRP_CNTL_CH1_OUT_RGB16,
+ .src_pixel = 0x2ca00565, /* RGB565 */
+ .ch1_pixel = 0x2ca00565, /* RGB565 */
+ .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
+ PRP_INTR_CH1FC | PRP_INTR_LBOVF,
+ }
+ },
+ {
+ .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8,
+ .out_fmt = V4L2_PIX_FMT_YUV420,
+ .cfg = {
+ .channel = 2,
+ .in_fmt = PRP_CNTL_DATA_IN_YUV422,
+ .out_fmt = PRP_CNTL_CH2_OUT_YUV420,
+ .src_pixel = 0x22000888, /* YUV422 (YUYV) */
+ .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR |
+ PRP_INTR_CH2FC | PRP_INTR_LBOVF |
+ PRP_INTR_CH2OVF,
+ }
+ },
+};
+
+static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
+ enum v4l2_mbus_pixelcode in_fmt,
+ u32 out_fmt)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++)
+ if ((mx27_emma_prp_table[i].in_fmt == in_fmt) &&
+ (mx27_emma_prp_table[i].out_fmt == out_fmt)) {
+ return &mx27_emma_prp_table[i];
+ }
+ /* If no match return the most generic configuration */
+ return &mx27_emma_prp_table[0];
+};
+
static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
{
unsigned long flags;
@@ -301,6 +372,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
pcdev->icd = icd;
+ pcdev->frame_count = 0;
dev_info(icd->parent, "Camera driver attached to camera %d\n",
icd->devnum);
@@ -719,55 +791,77 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
struct soc_camera_host *ici =
to_soc_camera_host(icd->parent);
struct mx2_camera_dev *pcdev = ici->priv;
+ struct mx2_fmt_cfg *prp = pcdev->emma_prp;
+ u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
+
+ if (prp->cfg.channel == 1) {
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_DEST_RGB1_PTR);
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_DEST_RGB2_PTR);
+
+ writel(PRP_CNTL_CH1EN |
+ PRP_CNTL_CSIEN |
+ prp->cfg.in_fmt |
+ prp->cfg.out_fmt |
+ PRP_CNTL_CH1_LEN |
+ PRP_CNTL_CH1BYP |
+ PRP_CNTL_CH1_TSKIP(0) |
+ PRP_CNTL_IN_TSKIP(0),
+ pcdev->base_emma + PRP_CNTL);
+
+ writel((icd->user_width << 16) | icd->user_height,
+ pcdev->base_emma + PRP_SRC_FRAME_SIZE);
+ writel((icd->user_width << 16) | icd->user_height,
+ pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
+ writel(bytesperline,
+ pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
+ writel(prp->cfg.src_pixel,
+ pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
+ writel(prp->cfg.ch1_pixel,
+ pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
+ } else { /* channel 2 */
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_DEST_Y_PTR);
+ writel(pcdev->discard_buffer_dma,
+ pcdev->base_emma + PRP_SOURCE_Y_PTR);
+
+ if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
+ writel(pcdev->discard_buffer_dma + imgsize,
+ pcdev->base_emma + PRP_DEST_CB_PTR);
+ writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
+ pcdev->base_emma + PRP_DEST_CR_PTR);
+ writel(pcdev->discard_buffer_dma + imgsize,
+ pcdev->base_emma + PRP_SOURCE_CB_PTR);
+ writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4),
+ pcdev->base_emma + PRP_SOURCE_CR_PTR);
+ }
- writel(pcdev->discard_buffer_dma,
- pcdev->base_emma + PRP_DEST_RGB1_PTR);
- writel(pcdev->discard_buffer_dma,
- pcdev->base_emma + PRP_DEST_RGB2_PTR);
-
- /*
- * We only use the EMMA engine to get rid of the broken
- * DMA Engine. No color space consversion at the moment.
- * We set the incomming and outgoing pixelformat to an
- * 16 Bit wide format and adjust the bytesperline
- * accordingly. With this configuration the inputdata
- * will not be changed by the emma and could be any type
- * of 16 Bit Pixelformat.
- */
- writel(PRP_CNTL_CH1EN |
+ writel(PRP_CNTL_CH2EN |
PRP_CNTL_CSIEN |
- PRP_CNTL_DATA_IN_RGB16 |
- PRP_CNTL_CH1_OUT_RGB16 |
- PRP_CNTL_CH1_LEN |
- PRP_CNTL_CH1BYP |
- PRP_CNTL_CH1_TSKIP(0) |
+ prp->cfg.in_fmt |
+ prp->cfg.out_fmt |
+ PRP_CNTL_CH2_LEN |
+ PRP_CNTL_CH2_TSKIP(0) |
PRP_CNTL_IN_TSKIP(0),
pcdev->base_emma + PRP_CNTL);
- writel(((bytesperline >> 1) << 16) | icd->user_height,
+ writel((icd->user_width << 16) | icd->user_height,
pcdev->base_emma + PRP_SRC_FRAME_SIZE);
- writel(((bytesperline >> 1) << 16) | icd->user_height,
- pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
- writel(bytesperline,
- pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
- writel(0x2ca00565, /* RGB565 */
+
+ writel((icd->user_width << 16) | icd->user_height,
+ pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
+
+ writel(prp->cfg.src_pixel,
pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
- writel(0x2ca00565, /* RGB565 */
- pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
+
+ }
/* Enable interrupts */
- writel(PRP_INTR_RDERR |
- PRP_INTR_CH1WERR |
- PRP_INTR_CH2WERR |
- PRP_INTR_CH1FC |
- PRP_INTR_CH2FC |
- PRP_INTR_LBOVF |
- PRP_INTR_CH2OVF,
- pcdev->base_emma + PRP_INTR_CNTL);
+ writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL);
}
-static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
- __u32 pixfmt)
+static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -911,9 +1005,58 @@ static int mx2_camera_set_crop(struct soc_camera_device *icd,
return ret;
}
+static int mx2_camera_get_formats(struct soc_camera_device *icd,
+ unsigned int idx,
+ struct soc_camera_format_xlate *xlate)
+{
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ const struct soc_mbus_pixelfmt *fmt;
+ struct device *dev = icd->parent;
+ enum v4l2_mbus_pixelcode code;
+ int ret, formats = 0;
+
+ ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ if (ret < 0)
+ /* no more formats */
+ return 0;
+
+ fmt = soc_mbus_get_fmtdesc(code);
+ if (!fmt) {
+ dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
+ return 0;
+ }
+
+ if (code == V4L2_MBUS_FMT_YUYV8_2X8) {
+ formats++;
+ if (xlate) {
+ /*
+ * CH2 can output YUV420 which is a standard format in
+ * soc_mediabus.c
+ */
+ xlate->host_fmt =
+ soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8);
+ 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) {
+ xlate->host_fmt = fmt;
+ xlate->code = code;
+ xlate++;
+ }
+ return formats;
+}
+
static int mx2_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+ struct mx2_camera_dev *pcdev = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
@@ -946,6 +1089,10 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd,
pix->colorspace = mf.colorspace;
icd->current_fmt = xlate;
+ if (mx27_camera_emma(pcdev))
+ pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code,
+ xlate->host_fmt->fourcc);
+
return 0;
}
@@ -1011,7 +1158,12 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd,
if (mf.field == V4L2_FIELD_ANY)
mf.field = V4L2_FIELD_NONE;
- if (mf.field != V4L2_FIELD_NONE) {
+ /*
+ * Driver supports interlaced images provided they have
+ * both fields so that they can be processed as if they
+ * were progressive.
+ */
+ if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) {
dev_err(icd->parent, "Field type %d unsupported.\n",
mf.field);
return -EINVAL;
@@ -1173,6 +1325,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
.remove = mx2_camera_remove_device,
.set_fmt = mx2_camera_set_fmt,
.set_crop = mx2_camera_set_crop,
+ .get_formats = mx2_camera_get_formats,
.try_fmt = mx2_camera_try_fmt,
.init_videobuf = mx2_camera_init_videobuf,
.reqbufs = mx2_camera_reqbufs,
@@ -1184,6 +1337,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = {
static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
int bufnum, int state)
{
+ u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width;
+ struct mx2_fmt_cfg *prp = pcdev->emma_prp;
struct mx2_buffer *buf;
struct videobuf_buffer *vb;
unsigned long phys;
@@ -1197,12 +1352,22 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
vb = &buf->vb;
#ifdef DEBUG
phys = videobuf_to_dma_contig(vb);
- if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum)
- != phys) {
- dev_err(pcdev->dev, "%p != %p\n", phys,
- readl(pcdev->base_emma +
- PRP_DEST_RGB1_PTR +
- 4 * bufnum));
+ if (prp->cfg.channel == 1) {
+ if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR +
+ 4 * bufnum) != phys) {
+ dev_err(pcdev->dev, "%p != %p\n", phys,
+ readl(pcdev->base_emma +
+ PRP_DEST_RGB1_PTR +
+ 4 * bufnum));
+ }
+ } else {
+ if (readl(pcdev->base_emma + PRP_DEST_Y_PTR -
+ 0x14 * bufnum) != phys) {
+ dev_err(pcdev->dev, "%p != %p\n", phys,
+ readl(pcdev->base_emma +
+ PRP_DEST_Y_PTR -
+ 0x14 * bufnum));
+ }
}
#endif
dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb,
@@ -1211,14 +1376,29 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
list_del(&vb->queue);
vb->state = state;
do_gettimeofday(&vb->ts);
- vb->field_count++;
+ vb->field_count = pcdev->frame_count * 2;
+ pcdev->frame_count++;
wake_up(&vb->done);
}
if (list_empty(&pcdev->capture)) {
- writel(pcdev->discard_buffer_dma, pcdev->base_emma +
- PRP_DEST_RGB1_PTR + 4 * bufnum);
+ if (prp->cfg.channel == 1) {
+ writel(pcdev->discard_buffer_dma, pcdev->base_emma +
+ PRP_DEST_RGB1_PTR + 4 * bufnum);
+ } else {
+ writel(pcdev->discard_buffer_dma, pcdev->base_emma +
+ PRP_DEST_Y_PTR -
+ 0x14 * bufnum);
+ if (prp->out_fmt == V4L2_PIX_FMT_YUV420) {
+ writel(pcdev->discard_buffer_dma + imgsize,
+ pcdev->base_emma + PRP_DEST_CB_PTR -
+ 0x14 * bufnum);
+ writel(pcdev->discard_buffer_dma +
+ ((5 * imgsize) / 4), pcdev->base_emma +
+ PRP_DEST_CR_PTR - 0x14 * bufnum);
+ }
+ }
return;
}
@@ -1233,7 +1413,18 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
vb->state = VIDEOBUF_ACTIVE;
phys = videobuf_to_dma_contig(vb);
- writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
+ if (prp->cfg.channel == 1) {
+ writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
+ } else {
+ writel(phys, pcdev->base_emma +
+ PRP_DEST_Y_PTR - 0x14 * bufnum);
+ if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) {
+ writel(phys + imgsize, pcdev->base_emma +
+ PRP_DEST_CB_PTR - 0x14 * bufnum);
+ writel(phys + ((5 * imgsize) / 4), pcdev->base_emma +
+ PRP_DEST_CR_PTR - 0x14 * bufnum);
+ }
+ }
}
static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
@@ -1253,10 +1444,12 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
* the next one.
*/
cntl = readl(pcdev->base_emma + PRP_CNTL);
- writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL);
+ writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN),
+ pcdev->base_emma + PRP_CNTL);
writel(cntl, pcdev->base_emma + PRP_CNTL);
}
- if ((status & (3 << 5)) == (3 << 5)
+ if ((((status & (3 << 5)) == (3 << 5)) ||
+ ((status & (3 << 3)) == (3 << 3)))
&& !list_empty(&pcdev->active_bufs)) {
/*
* Both buffers have triggered, process the one we're expecting
@@ -1267,9 +1460,9 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE);
status &= ~(1 << (6 - buf->bufnum)); /* mark processed */
}
- if (status & (1 << 6))
+ if ((status & (1 << 6)) || (status & (1 << 4)))
mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE);
- if (status & (1 << 5))
+ if ((status & (1 << 5)) || (status & (1 << 3)))
mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE);
writel(status, pcdev->base_emma + PRP_INTRSTATUS);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index f96f92f..7452277 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -287,7 +287,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
sg_dma_len(sg) = new_size;
txd = ichan->dma_chan.device->device_prep_slave_sg(
- &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+ &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!txd)
goto error;
@@ -982,12 +982,13 @@ static int mx3_camera_querycap(struct soc_camera_host *ici,
return 0;
}
-static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int mx3_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+ u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
unsigned long bus_flags, common_flags;
u32 dw, sens_conf;
const struct soc_mbus_pixelfmt *fmt;
@@ -1285,19 +1286,7 @@ static struct platform_driver mx3_camera_driver = {
.remove = __devexit_p(mx3_camera_remove),
};
-
-static int __init mx3_camera_init(void)
-{
- return platform_driver_register(&mx3_camera_driver);
-}
-
-static void __exit mx3_camera_exit(void)
-{
- platform_driver_unregister(&mx3_camera_driver);
-}
-
-module_init(mx3_camera_init);
-module_exit(mx3_camera_exit);
+module_platform_driver(mx3_camera_driver);
MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index ee0d0b3..a277f95 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -70,9 +70,9 @@ static u32 video1_numbuffers = 3;
static u32 video2_numbuffers = 3;
static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
-static u32 vid1_static_vrfb_alloc;
-static u32 vid2_static_vrfb_alloc;
-static int debug;
+static bool vid1_static_vrfb_alloc;
+static bool vid2_static_vrfb_alloc;
+static bool debug;
/* Module parameters */
module_param(video1_numbuffers, uint, S_IRUGO);
@@ -424,7 +424,7 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
"%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
"out_height=%d rotation_type=%d screen_width=%d\n",
- __func__, info.enabled, info.paddr, info.width, info.height,
+ __func__, ovl->is_enabled(ovl), info.paddr, info.width, info.height,
info.color_mode, info.rotation, info.mirror, info.pos_x,
info.pos_y, info.out_width, info.out_height, info.rotation_type,
info.screen_width);
@@ -524,10 +524,50 @@ static int omapvid_apply_changes(struct omap_vout_device *vout)
return 0;
}
+static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
+ unsigned int irqstatus, struct timeval timevalue)
+{
+ u32 fid;
+
+ if (vout->first_int) {
+ vout->first_int = 0;
+ goto err;
+ }
+
+ if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
+ fid = 1;
+ else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
+ fid = 0;
+ else
+ goto err;
+
+ vout->field_id ^= 1;
+ if (fid != vout->field_id) {
+ if (fid == 0)
+ vout->field_id = fid;
+ } else if (0 == fid) {
+ if (vout->cur_frm == vout->next_frm)
+ goto err;
+
+ vout->cur_frm->ts = timevalue;
+ vout->cur_frm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->cur_frm->done);
+ vout->cur_frm = vout->next_frm;
+ } else {
+ if (list_empty(&vout->dma_queue) ||
+ (vout->cur_frm != vout->next_frm))
+ goto err;
+ }
+
+ return vout->field_id;
+err:
+ return 0;
+}
+
static void omap_vout_isr(void *arg, unsigned int irqstatus)
{
- int ret;
- u32 addr, fid;
+ int ret, fid, mgr_id;
+ u32 addr, irq;
struct omap_overlay *ovl;
struct timeval timevalue;
struct omapvideo_info *ovid;
@@ -543,112 +583,73 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus)
if (!ovl->manager || !ovl->manager->device)
return;
+ mgr_id = ovl->manager->id;
cur_display = ovl->manager->device;
spin_lock(&vout->vbq_lock);
do_gettimeofday(&timevalue);
- if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) {
- switch (cur_display->type) {
- case OMAP_DISPLAY_TYPE_DPI:
- if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2)))
- goto vout_isr_err;
- break;
- case OMAP_DISPLAY_TYPE_HDMI:
- if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
- goto vout_isr_err;
- break;
- default:
- goto vout_isr_err;
- }
- if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
- vout->cur_frm->ts = timevalue;
- vout->cur_frm->state = VIDEOBUF_DONE;
- wake_up_interruptible(&vout->cur_frm->done);
- vout->cur_frm = vout->next_frm;
- }
- vout->first_int = 0;
- if (list_empty(&vout->dma_queue))
+ switch (cur_display->type) {
+ case OMAP_DISPLAY_TYPE_DSI:
+ case OMAP_DISPLAY_TYPE_DPI:
+ if (mgr_id == OMAP_DSS_CHANNEL_LCD)
+ irq = DISPC_IRQ_VSYNC;
+ else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
+ irq = DISPC_IRQ_VSYNC2;
+ else
goto vout_isr_err;
- vout->next_frm = list_entry(vout->dma_queue.next,
- struct videobuf_buffer, queue);
- list_del(&vout->next_frm->queue);
-
- vout->next_frm->state = VIDEOBUF_ACTIVE;
+ if (!(irqstatus & irq))
+ goto vout_isr_err;
+ break;
+ case OMAP_DISPLAY_TYPE_VENC:
+ fid = omapvid_handle_interlace_display(vout, irqstatus,
+ timevalue);
+ if (!fid)
+ goto vout_isr_err;
+ break;
+ case OMAP_DISPLAY_TYPE_HDMI:
+ if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
+ goto vout_isr_err;
+ break;
+ default:
+ goto vout_isr_err;
+ }
- addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
- + vout->cropped_offset;
+ if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
+ vout->cur_frm->ts = timevalue;
+ vout->cur_frm->state = VIDEOBUF_DONE;
+ wake_up_interruptible(&vout->cur_frm->done);
+ vout->cur_frm = vout->next_frm;
+ }
- /* First save the configuration in ovelray structure */
- ret = omapvid_init(vout, addr);
- if (ret)
- printk(KERN_ERR VOUT_NAME
- "failed to set overlay info\n");
- /* Enable the pipeline and set the Go bit */
- ret = omapvid_apply_changes(vout);
- if (ret)
- printk(KERN_ERR VOUT_NAME "failed to change mode\n");
- } else {
+ vout->first_int = 0;
+ if (list_empty(&vout->dma_queue))
+ goto vout_isr_err;
- if (vout->first_int) {
- vout->first_int = 0;
- goto vout_isr_err;
- }
- if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
- fid = 1;
- else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
- fid = 0;
- else
- goto vout_isr_err;
+ vout->next_frm = list_entry(vout->dma_queue.next,
+ struct videobuf_buffer, queue);
+ list_del(&vout->next_frm->queue);
- vout->field_id ^= 1;
- if (fid != vout->field_id) {
- if (0 == fid)
- vout->field_id = fid;
+ vout->next_frm->state = VIDEOBUF_ACTIVE;
- goto vout_isr_err;
- }
- if (0 == fid) {
- if (vout->cur_frm == vout->next_frm)
- goto vout_isr_err;
-
- vout->cur_frm->ts = timevalue;
- vout->cur_frm->state = VIDEOBUF_DONE;
- wake_up_interruptible(&vout->cur_frm->done);
- vout->cur_frm = vout->next_frm;
- } else if (1 == fid) {
- if (list_empty(&vout->dma_queue) ||
- (vout->cur_frm != vout->next_frm))
- goto vout_isr_err;
-
- vout->next_frm = list_entry(vout->dma_queue.next,
- struct videobuf_buffer, queue);
- list_del(&vout->next_frm->queue);
-
- vout->next_frm->state = VIDEOBUF_ACTIVE;
- addr = (unsigned long)
- vout->queued_buf_addr[vout->next_frm->i] +
- vout->cropped_offset;
- /* First save the configuration in ovelray structure */
- ret = omapvid_init(vout, addr);
- if (ret)
- printk(KERN_ERR VOUT_NAME
- "failed to set overlay info\n");
- /* Enable the pipeline and set the Go bit */
- ret = omapvid_apply_changes(vout);
- if (ret)
- printk(KERN_ERR VOUT_NAME
- "failed to change mode\n");
- }
+ addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i]
+ + vout->cropped_offset;
- }
+ /* First save the configuration in ovelray structure */
+ ret = omapvid_init(vout, addr);
+ if (ret)
+ printk(KERN_ERR VOUT_NAME
+ "failed to set overlay info\n");
+ /* Enable the pipeline and set the Go bit */
+ ret = omapvid_apply_changes(vout);
+ if (ret)
+ printk(KERN_ERR VOUT_NAME "failed to change mode\n");
vout_isr_err:
spin_unlock(&vout->vbq_lock);
}
-
/* Video buffer call backs */
/*
@@ -664,10 +665,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
u32 phy_addr = 0, virt_addr = 0;
struct omap_vout_device *vout = q->priv_data;
struct omapvideo_info *ovid = &vout->vid_info;
+ int vid_max_buf_size;
if (!vout)
return -EINVAL;
+ vid_max_buf_size = vout->vid == OMAP_VIDEO1 ? video1_bufsize :
+ video2_bufsize;
+
if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
return -EINVAL;
@@ -690,7 +695,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
video1_numbuffers : video2_numbuffers;
/* Check the size of the buffer */
- if (*size > vout->buffer_size) {
+ if (*size > vid_max_buf_size) {
v4l2_err(&vout->vid_dev->v4l2_dev,
"buffer allocation mismatch [%u] [%u]\n",
*size, vout->buffer_size);
@@ -943,12 +948,8 @@ static int omap_vout_release(struct file *file)
/* Disable all the overlay managers connected with this interface */
for (i = 0; i < ovid->num_overlays; i++) {
struct omap_overlay *ovl = ovid->overlays[i];
- if (ovl->manager && ovl->manager->device) {
- struct omap_overlay_info info;
- ovl->get_overlay_info(ovl, &info);
- info.enabled = 0;
- ovl->set_overlay_info(ovl, &info);
- }
+ if (ovl->manager && ovl->manager->device)
+ ovl->disable(ovl);
}
/* Turn off the pipeline */
ret = omapvid_apply_changes(vout);
@@ -1668,7 +1669,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
if (ovl->manager && ovl->manager->device) {
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
- info.enabled = 1;
info.paddr = addr;
if (ovl->set_overlay_info(ovl, &info)) {
ret = -EINVAL;
@@ -1687,6 +1687,16 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
if (ret)
v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
+ for (j = 0; j < ovid->num_overlays; j++) {
+ struct omap_overlay *ovl = ovid->overlays[j];
+
+ if (ovl->manager && ovl->manager->device) {
+ ret = ovl->enable(ovl);
+ if (ret)
+ goto streamon_err1;
+ }
+ }
+
ret = 0;
streamon_err1:
@@ -1716,16 +1726,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
for (j = 0; j < ovid->num_overlays; j++) {
struct omap_overlay *ovl = ovid->overlays[j];
- if (ovl->manager && ovl->manager->device) {
- struct omap_overlay_info info;
-
- ovl->get_overlay_info(ovl, &info);
- info.enabled = 0;
- ret = ovl->set_overlay_info(ovl, &info);
- if (ret)
- v4l2_err(&vout->vid_dev->v4l2_dev,
- "failed to update overlay info in streamoff\n");
- }
+ if (ovl->manager && ovl->manager->device)
+ ovl->disable(ovl);
}
/* Turn of the pipeline */
diff --git a/drivers/media/video/omap/omap_vout_vrfb.c b/drivers/media/video/omap/omap_vout_vrfb.c
index ebebcac4..4be26abf6c 100644
--- a/drivers/media/video/omap/omap_vout_vrfb.c
+++ b/drivers/media/video/omap/omap_vout_vrfb.c
@@ -84,7 +84,7 @@ void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout)
}
int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
- u32 static_vrfb_allocation)
+ bool static_vrfb_allocation)
{
int ret = 0, i, j;
struct omap_vout_device *vout;
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
index d793501..27a95d2 100644
--- a/drivers/media/video/omap/omap_voutdef.h
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -25,7 +25,7 @@
#define MAC_VRFB_CTXS 4
#define MAX_VOUT_DEV 2
#define MAX_OVLS 3
-#define MAX_DISPLAYS 3
+#define MAX_DISPLAYS 10
#define MAX_MANAGERS 3
#define QQVGA_WIDTH 160
diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c
index 6a6cf38..c20f5ec 100644
--- a/drivers/media/video/omap1_camera.c
+++ b/drivers/media/video/omap1_camera.c
@@ -1436,13 +1436,13 @@ static int omap1_cam_querycap(struct soc_camera_host *ici,
return 0;
}
-static int omap1_cam_set_bus_param(struct soc_camera_device *icd,
- __u32 pixfmt)
+static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct omap1_cam_dev *pcdev = ici->priv;
+ u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
const struct soc_camera_format_xlate *xlate;
const struct soc_mbus_pixelfmt *fmt;
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
@@ -1713,17 +1713,7 @@ static struct platform_driver omap1_cam_driver = {
.remove = __exit_p(omap1_cam_remove),
};
-static int __init omap1_cam_init(void)
-{
- return platform_driver_register(&omap1_cam_driver);
-}
-module_init(omap1_cam_init);
-
-static void __exit omap1_cam_exit(void)
-{
- platform_driver_unregister(&omap1_cam_driver);
-}
-module_exit(omap1_cam_exit);
+module_platform_driver(omap1_cam_driver);
module_param(sg_mode, bool, 0644);
MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg");
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 45522e6..7d38641 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1868,21 +1868,7 @@ static struct platform_driver omap24xxcam_driver = {
},
};
-/*
- *
- * Module initialisation and deinitialisation
- *
- */
-
-static int __init omap24xxcam_init(void)
-{
- return platform_driver_register(&omap24xxcam_driver);
-}
-
-static void __exit omap24xxcam_cleanup(void)
-{
- platform_driver_unregister(&omap24xxcam_driver);
-}
+module_platform_driver(omap24xxcam_driver);
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver");
@@ -1894,6 +1880,3 @@ MODULE_PARM_DESC(video_nr,
module_param(capture_mem, int, 0);
MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture "
"buffers (default 4800kiB)");
-
-module_init(omap24xxcam_init);
-module_exit(omap24xxcam_cleanup);
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index d4c48ef2..12d5f92 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -403,6 +403,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
static void isp_isr_sbl(struct isp_device *isp)
{
struct device *dev = isp->dev;
+ struct isp_pipeline *pipe;
u32 sbl_pcr;
/*
@@ -416,27 +417,38 @@ static void isp_isr_sbl(struct isp_device *isp)
if (sbl_pcr)
dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
- if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
- | ISPSBL_PCR_CSIB_WBL_OVF)) {
- isp->isp_ccdc.error = 1;
- if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
- isp->isp_prev.error = 1;
- if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
- isp->isp_res.error = 1;
+ if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) {
+ pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity);
+ if (pipe != NULL)
+ pipe->error = true;
+ }
+
+ if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) {
+ pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity);
+ if (pipe != NULL)
+ pipe->error = true;
+ }
+
+ if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) {
+ pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity);
+ if (pipe != NULL)
+ pipe->error = true;
}
if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
- isp->isp_prev.error = 1;
- if (isp->isp_res.input == RESIZER_INPUT_VP &&
- !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
- isp->isp_res.error = 1;
+ pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity);
+ if (pipe != NULL)
+ pipe->error = true;
}
if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
| ISPSBL_PCR_RSZ2_WBL_OVF
| ISPSBL_PCR_RSZ3_WBL_OVF
- | ISPSBL_PCR_RSZ4_WBL_OVF))
- isp->isp_res.error = 1;
+ | ISPSBL_PCR_RSZ4_WBL_OVF)) {
+ pipe = to_isp_pipeline(&isp->isp_res.subdev.entity);
+ if (pipe != NULL)
+ pipe->error = true;
+ }
if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
omap3isp_stat_sbl_overflow(&isp->isp_af);
@@ -464,24 +476,17 @@ static irqreturn_t isp_isr(int irq, void *_isp)
IRQ0STATUS_HS_VS_IRQ;
struct isp_device *isp = _isp;
u32 irqstatus;
- int ret;
irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
isp_isr_sbl(isp);
- if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
- ret = omap3isp_csi2_isr(&isp->isp_csi2a);
- if (ret)
- isp->isp_ccdc.error = 1;
- }
+ if (irqstatus & IRQ0STATUS_CSIA_IRQ)
+ omap3isp_csi2_isr(&isp->isp_csi2a);
- if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
- ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
- if (ret)
- isp->isp_ccdc.error = 1;
- }
+ if (irqstatus & IRQ0STATUS_CSIB_IRQ)
+ omap3isp_ccp2_isr(&isp->isp_ccp2);
if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
@@ -2222,24 +2227,7 @@ static struct platform_driver omap3isp_driver = {
},
};
-/*
- * isp_init - ISP module initialization.
- */
-static int __init isp_init(void)
-{
- return platform_driver_register(&omap3isp_driver);
-}
-
-/*
- * isp_cleanup - ISP module cleanup.
- */
-static void __exit isp_cleanup(void)
-{
- platform_driver_unregister(&omap3isp_driver);
-}
-
-module_init(isp_init);
-module_exit(isp_cleanup);
+module_platform_driver(omap3isp_driver);
MODULE_AUTHOR("Nokia Corporation");
MODULE_DESCRIPTION("TI OMAP3 ISP driver");
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index d341ba1..a74a797 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -1406,9 +1406,8 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
{
- struct isp_pipeline *pipe =
- to_isp_pipeline(&ccdc->video_out.video.entity);
- struct video_device *vdev = ccdc->subdev.devnode;
+ struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+ struct video_device *vdev = &ccdc->subdev.devnode;
struct v4l2_event event;
memset(&event, 0, sizeof(event));
@@ -1428,8 +1427,11 @@ static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
unsigned long flags;
if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
+ struct isp_pipeline *pipe =
+ to_isp_pipeline(&ccdc->subdev.entity);
+
ccdc_lsc_error_handler(ccdc);
- ccdc->error = 1;
+ pipe->error = true;
dev_dbg(to_device(ccdc), "lsc prefetch error\n");
}
@@ -1504,7 +1506,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
goto done;
}
- buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
+ buffer = omap3isp_video_buffer_next(&ccdc->video_out);
if (buffer != NULL) {
ccdc_set_outaddr(ccdc, buffer->isp_addr);
restart = 1;
@@ -1518,7 +1520,6 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
ISP_PIPELINE_STREAM_SINGLESHOT);
done:
- ccdc->error = 0;
return restart;
}
@@ -1744,7 +1745,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
*/
ccdc_config_vp(ccdc);
ccdc_enable_vp(ccdc, 1);
- ccdc->error = 0;
ccdc_print_status(ccdc);
}
diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/video/omap3isp/ispccdc.h
index 483a19c..6d0264b 100644
--- a/drivers/media/video/omap3isp/ispccdc.h
+++ b/drivers/media/video/omap3isp/ispccdc.h
@@ -150,7 +150,6 @@ struct ispccdc_lsc {
* @input: Active input
* @output: Active outputs
* @video_out: Output video node
- * @error: A hardware error occurred during capture
* @alaw: A-law compression enabled (1) or disabled (0)
* @lpf: Low pass filter enabled (1) or disabled (0)
* @obclamp: Optical-black clamp enabled (1) or disabled (0)
@@ -178,7 +177,6 @@ struct isp_ccdc_device {
enum ccdc_input_entity input;
unsigned int output;
struct isp_video video_out;
- unsigned int error;
unsigned int alaw:1,
lpf:1,
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c
index 904ca8c..70ddbf3 100644
--- a/drivers/media/video/omap3isp/ispccp2.c
+++ b/drivers/media/video/omap3isp/ispccp2.c
@@ -556,7 +556,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
struct isp_buffer *buffer;
- buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
+ buffer = omap3isp_video_buffer_next(&ccp2->video_in);
if (buffer != NULL)
ccp2_set_inaddr(ccp2, buffer->isp_addr);
@@ -567,8 +567,6 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
omap3isp_pipeline_set_stream(pipe,
ISP_PIPELINE_STREAM_SINGLESHOT);
}
-
- ccp2->error = 0;
}
/*
@@ -576,13 +574,11 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
* @ccp2: Pointer to ISP CCP2 device
*
* This will handle the CCP2 interrupts
- *
- * Returns -EIO in case of error, or 0 on success.
*/
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
{
+ struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
struct isp_device *isp = to_isp_device(ccp2);
- int ret = 0;
static const u32 ISPCCP2_LC01_ERROR =
ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
@@ -604,19 +600,18 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
ISPCCP2_LCM_IRQSTATUS);
/* Errors */
if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
- ccp2->error = 1;
+ pipe->error = true;
dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
- return -EIO;
+ return;
}
if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
- ccp2->error = 1;
+ pipe->error = true;
dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
- ret = -EIO;
}
if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
- return 0;
+ return;
/* Frame number propagation */
if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
@@ -629,8 +624,6 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
/* Handle queued buffers on frame end interrupts */
if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
ccp2_isr_buffer(ccp2);
-
- return ret;
}
/* -----------------------------------------------------------------------------
@@ -867,7 +860,6 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
if (enable == ISP_PIPELINE_STREAM_STOPPED)
return 0;
atomic_set(&ccp2->stopping, 0);
- ccp2->error = 0;
}
switch (enable) {
diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h
index 6674e9d..76d65f4 100644
--- a/drivers/media/video/omap3isp/ispccp2.h
+++ b/drivers/media/video/omap3isp/ispccp2.h
@@ -82,7 +82,6 @@ struct isp_ccp2_device {
struct isp_video video_in;
struct isp_csiphy *phy;
struct regulator *vdds_csib;
- unsigned int error;
enum isp_pipeline_stream_state state;
wait_queue_head_t wait;
atomic_t stopping;
@@ -94,6 +93,6 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp);
int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
struct v4l2_device *vdev);
void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
#endif /* OMAP3_ISP_CCP2_H */
diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c
index 0c5f1cb..fcb5168 100644
--- a/drivers/media/video/omap3isp/ispcsi2.c
+++ b/drivers/media/video/omap3isp/ispcsi2.c
@@ -667,7 +667,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2)
csi2_ctx_enable(isp, csi2, 0, 0);
- buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
+ buffer = omap3isp_video_buffer_next(&csi2->video_out);
/*
* Let video queue operation restart engine if there is an underrun
@@ -727,17 +727,15 @@ static void csi2_isr_ctx(struct isp_csi2_device *csi2,
/*
* omap3isp_csi2_isr - CSI2 interrupt handling.
- *
- * Return -EIO on Transmission error
*/
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2)
{
+ struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
u32 csi2_irqstatus, cpxio1_irqstatus;
struct isp_device *isp = csi2->isp;
- int retval = 0;
if (!csi2->available)
- return -ENODEV;
+ return;
csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
@@ -750,7 +748,7 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
"%x\n", cpxio1_irqstatus);
- retval = -EIO;
+ pipe->error = true;
}
if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
@@ -775,11 +773,11 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
(csi2_irqstatus &
ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
- retval = -EIO;
+ pipe->error = true;
}
if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
- return 0;
+ return;
/* Successful cases */
if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
@@ -787,8 +785,6 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
dev_dbg(isp->dev, "CSI2: ECC correction done\n");
-
- return retval;
}
/* -----------------------------------------------------------------------------
diff --git a/drivers/media/video/omap3isp/ispcsi2.h b/drivers/media/video/omap3isp/ispcsi2.h
index 456fb7f..885ad79 100644
--- a/drivers/media/video/omap3isp/ispcsi2.h
+++ b/drivers/media/video/omap3isp/ispcsi2.h
@@ -156,7 +156,7 @@ struct isp_csi2_device {
atomic_t stopping;
};
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
int omap3isp_csi2_init(struct isp_device *isp);
void omap3isp_csi2_cleanup(struct isp_device *isp);
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c
index ccb876f..6d0fb2c 100644
--- a/drivers/media/video/omap3isp/isppreview.c
+++ b/drivers/media/video/omap3isp/isppreview.c
@@ -116,11 +116,11 @@ static struct omap3isp_prev_csc flr_prev_csc = {
#define PREV_MIN_IN_HEIGHT 8
#define PREV_MAX_IN_HEIGHT 16384
-#define PREV_MIN_OUT_WIDTH 0
-#define PREV_MIN_OUT_HEIGHT 0
-#define PREV_MAX_OUT_WIDTH 1280
-#define PREV_MAX_OUT_WIDTH_ES2 3300
-#define PREV_MAX_OUT_WIDTH_3630 4096
+#define PREV_MIN_OUT_WIDTH 0
+#define PREV_MIN_OUT_HEIGHT 0
+#define PREV_MAX_OUT_WIDTH_REV_1 1280
+#define PREV_MAX_OUT_WIDTH_REV_2 3300
+#define PREV_MAX_OUT_WIDTH_REV_15 4096
/*
* Coeficient Tables for the submodules in Preview.
@@ -1306,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev)
switch (isp->revision) {
case ISP_REVISION_1_0:
- return PREV_MAX_OUT_WIDTH;
+ return PREV_MAX_OUT_WIDTH_REV_1;
case ISP_REVISION_2_0:
default:
- return PREV_MAX_OUT_WIDTH_ES2;
+ return PREV_MAX_OUT_WIDTH_REV_2;
case ISP_REVISION_15_0:
- return PREV_MAX_OUT_WIDTH_3630;
+ return PREV_MAX_OUT_WIDTH_REV_15;
}
}
@@ -1404,16 +1404,14 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
int restart = 0;
if (prev->input == PREVIEW_INPUT_MEMORY) {
- buffer = omap3isp_video_buffer_next(&prev->video_in,
- prev->error);
+ buffer = omap3isp_video_buffer_next(&prev->video_in);
if (buffer != NULL)
preview_set_inaddr(prev, buffer->isp_addr);
pipe->state |= ISP_PIPELINE_IDLE_INPUT;
}
if (prev->output & PREVIEW_OUTPUT_MEMORY) {
- buffer = omap3isp_video_buffer_next(&prev->video_out,
- prev->error);
+ buffer = omap3isp_video_buffer_next(&prev->video_out);
if (buffer != NULL) {
preview_set_outaddr(prev, buffer->isp_addr);
restart = 1;
@@ -1440,8 +1438,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
default:
return;
}
-
- prev->error = 0;
}
/*
@@ -1565,7 +1561,6 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
preview_configure(prev);
atomic_set(&prev->stopping, 0);
- prev->error = 0;
preview_print_status(prev);
}
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h
index f54e775..0968660 100644
--- a/drivers/media/video/omap3isp/isppreview.h
+++ b/drivers/media/video/omap3isp/isppreview.h
@@ -157,7 +157,6 @@ struct isptables_update {
* @output: Bitmask of the active output
* @video_in: Input video entity
* @video_out: Output video entity
- * @error: A hardware error occurred during capture
* @params: Module configuration data
* @shadow_update: If set, update the hardware configured in the next interrupt
* @underrun: Whether the preview entity has queued buffers on the output
@@ -179,7 +178,6 @@ struct isp_prev_device {
unsigned int output;
struct isp_video video_in;
struct isp_video video_out;
- unsigned int error;
struct prev_params params;
unsigned int shadow_update:1;
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c
index 50e593b..6958a9e 100644
--- a/drivers/media/video/omap3isp/ispresizer.c
+++ b/drivers/media/video/omap3isp/ispresizer.c
@@ -1038,7 +1038,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
/* Complete the output buffer and, if reading from memory, the input
* buffer.
*/
- buffer = omap3isp_video_buffer_next(&res->video_out, res->error);
+ buffer = omap3isp_video_buffer_next(&res->video_out);
if (buffer != NULL) {
resizer_set_outaddr(res, buffer->isp_addr);
restart = 1;
@@ -1047,7 +1047,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
if (res->input == RESIZER_INPUT_MEMORY) {
- buffer = omap3isp_video_buffer_next(&res->video_in, 0);
+ buffer = omap3isp_video_buffer_next(&res->video_in);
if (buffer != NULL)
resizer_set_inaddr(res, buffer->isp_addr);
pipe->state |= ISP_PIPELINE_IDLE_INPUT;
@@ -1064,8 +1064,6 @@ static void resizer_isr_buffer(struct isp_res_device *res)
if (restart)
resizer_enable_oneshot(res);
}
-
- res->error = 0;
}
/*
@@ -1154,7 +1152,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
resizer_configure(res);
- res->error = 0;
resizer_print_status(res);
}
diff --git a/drivers/media/video/omap3isp/ispresizer.h b/drivers/media/video/omap3isp/ispresizer.h
index 76abc2e..70c1c0e 100644
--- a/drivers/media/video/omap3isp/ispresizer.h
+++ b/drivers/media/video/omap3isp/ispresizer.h
@@ -107,7 +107,6 @@ struct isp_res_device {
enum resizer_input_entity input;
struct isp_video video_in;
struct isp_video video_out;
- unsigned int error;
u32 addr_base; /* stored source buffer address in memory mode */
u32 crop_offset; /* additional offset for crop in memory mode */
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index bd3aeba..b020700 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -211,14 +211,14 @@ static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
mbus->width = pix->width;
mbus->height = pix->height;
- for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ /* Skip the last format in the loop so that it will be selected if no
+ * match is found.
+ */
+ for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
if (formats[i].pixelformat == pix->pixelformat)
break;
}
- if (WARN_ON(i == ARRAY_SIZE(formats)))
- return;
-
mbus->code = formats[i].code;
mbus->colorspace = pix->colorspace;
mbus->field = pix->field;
@@ -581,21 +581,20 @@ static const struct isp_video_queue_operations isp_video_queue_ops = {
/*
* omap3isp_video_buffer_next - Complete the current buffer and return the next
* @video: ISP video object
- * @error: Whether an error occurred during capture
*
* Remove the current video buffer from the DMA queue and fill its timestamp,
* field count and state fields before waking up its completion handler.
*
- * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0)
- * or VIDEOBUF_ERROR otherwise (@error is non-zero).
+ * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
+ * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
+ * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
*
* The DMA queue is expected to contain at least one buffer.
*
* Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
* empty.
*/
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
- unsigned int error)
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
{
struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
struct isp_video_queue *queue = video->queue;
@@ -630,7 +629,13 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
else
buf->vbuf.sequence = atomic_read(&pipe->frame_number);
- buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
+ /* Report pipeline errors to userspace on the capture device side. */
+ if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
+ buf->state = ISP_BUF_STATE_ERROR;
+ pipe->error = false;
+ } else {
+ buf->state = ISP_BUF_STATE_DONE;
+ }
wake_up(&buf->wait);
@@ -1016,6 +1021,8 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
if (ret < 0)
goto error;
+ pipe->error = false;
+
spin_lock_irqsave(&pipe->lock, flags);
pipe->state &= ~ISP_PIPELINE_STREAM;
pipe->state |= state;
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
index 08cbfa1..d91bdb9 100644
--- a/drivers/media/video/omap3isp/ispvideo.h
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -85,6 +85,10 @@ enum isp_pipeline_state {
ISP_PIPELINE_STREAM = 64,
};
+/*
+ * struct isp_pipeline - An ISP hardware pipeline
+ * @error: A hardware error occurred during capture
+ */
struct isp_pipeline {
struct media_pipeline pipe;
spinlock_t lock; /* Pipeline state and queue flags */
@@ -96,6 +100,7 @@ struct isp_pipeline {
unsigned int max_rate;
atomic_t frame_number;
bool do_propagation; /* of frame number */
+ bool error;
struct v4l2_fract max_timeperframe;
};
@@ -194,8 +199,7 @@ void omap3isp_video_cleanup(struct isp_video *video);
int omap3isp_video_register(struct isp_video *video,
struct v4l2_device *vdev);
void omap3isp_video_unregister(struct isp_video *video);
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
- unsigned int error);
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
void omap3isp_video_resume(struct isp_video *video, int continuous);
struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 8aa0585..6a56496 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -25,7 +25,7 @@ MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
MODULE_LICENSE("GPL");
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 122b457..ebc2c7e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -2546,8 +2546,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
}
/* Define and configure additional controls from cx2341x module. */
- hdw->mpeg_ctrl_info = kzalloc(
- sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+ hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT,
+ sizeof(*(hdw->mpeg_ctrl_info)),
+ GFP_KERNEL);
if (!hdw->mpeg_ctrl_info) goto fail;
for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
cptr = hdw->controls + idx + CTRLDEF_COUNT;
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 3977add..905d41d 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
#include "pwc-nala.h"
};
-static void pwc_set_image_buffer_size(struct pwc_device *pdev);
-
/****************************************************************************/
static int _send_control_msg(struct pwc_device *pdev,
@@ -113,10 +111,9 @@ static int _send_control_msg(struct pwc_device *pdev,
void *kbuf = NULL;
if (buflen) {
- kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
+ kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */
if (kbuf == NULL)
return -ENOMEM;
- memcpy(kbuf, buf, buflen);
}
rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
@@ -171,7 +168,8 @@ int send_control_msg(struct pwc_device *pdev,
request, value, pdev->vcinterface, buf, buflen);
}
-static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames,
+ int *compression)
{
unsigned char buf[3];
int ret, fps;
@@ -221,10 +219,10 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
/* Set various parameters */
pdev->vframes = frames;
- pdev->vsize = size;
pdev->valternate = pEntry->alternate;
- pdev->image = pwc_image_sizes[size];
- pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
+ pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
if (pEntry->compressed) {
if (pdev->release < 5) { /* 4 fold compression */
pdev->vbandlength = 528;
@@ -237,38 +235,40 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
}
else
pdev->vbandlength = 0;
+
+ /* Let pwc-if.c:isoc_init know we don't support higher compression */
+ *compression = 3;
+
return 0;
}
-static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames,
+ int *compression)
{
unsigned char buf[13];
const struct Timon_table_entry *pChoose;
int ret, fps;
- if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
+ *compression < 0 || *compression > 3)
return -EINVAL;
if (size == PSZ_VGA && frames > 15)
return -EINVAL;
fps = (frames / 5) - 1;
- /* Find a supported framerate with progressively higher compression ratios
- if the preferred ratio is not available.
- */
+ /* Find a supported framerate with progressively higher compression */
pChoose = NULL;
- while (compression <= 3) {
- pChoose = &Timon_table[size][fps][compression];
- if (pChoose->alternate != 0)
- break;
- compression++;
+ while (*compression <= 3) {
+ pChoose = &Timon_table[size][fps][*compression];
+ if (pChoose->alternate != 0)
+ break;
+ (*compression)++;
}
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
memcpy(buf, pChoose->mode, 13);
- if (snapshot)
- buf[0] |= 0x80;
ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
if (ret < 0)
return ret;
@@ -284,55 +284,38 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
/* Set various parameters */
pdev->vframes = frames;
- pdev->vsize = size;
- pdev->vsnapshot = snapshot;
pdev->valternate = pChoose->alternate;
- pdev->image = pwc_image_sizes[size];
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
pdev->vbandlength = pChoose->bandlength;
if (pChoose->bandlength > 0)
- pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+ pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
else
- pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+ pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
return 0;
}
-static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames,
+ int *compression)
{
const struct Kiara_table_entry *pChoose = NULL;
int fps, ret;
unsigned char buf[12];
- struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
- if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 ||
+ *compression < 0 || *compression > 3)
return -EINVAL;
if (size == PSZ_VGA && frames > 15)
return -EINVAL;
fps = (frames / 5) - 1;
- /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
- if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420)
- {
- /* Only available in case the raw palette is selected or
- we have the decompressor available. This mode is
- only available in compressed form
- */
- PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
- pChoose = &RawEntry;
- }
- else
- {
- /* Find a supported framerate with progressively higher compression ratios
- if the preferred ratio is not available.
- Skip this step when using RAW modes.
- */
- snapshot = 0;
- while (compression <= 3) {
- pChoose = &Kiara_table[size][fps][compression];
- if (pChoose->alternate != 0)
- break;
- compression++;
- }
+ /* Find a supported framerate with progressively higher compression */
+ while (*compression <= 3) {
+ pChoose = &Kiara_table[size][fps][*compression];
+ if (pChoose->alternate != 0)
+ break;
+ (*compression)++;
}
if (pChoose == NULL || pChoose->alternate == 0)
return -ENOENT; /* Not supported. */
@@ -341,8 +324,6 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
/* usb_control_msg won't take staticly allocated arrays as argument?? */
memcpy(buf, pChoose->mode, 12);
- if (snapshot)
- buf[0] |= 0x80;
/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12);
@@ -359,61 +340,43 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
memcpy(pdev->cmd_buf, buf, 12);
/* All set and go */
pdev->vframes = frames;
- pdev->vsize = size;
- pdev->vsnapshot = snapshot;
pdev->valternate = pChoose->alternate;
- pdev->image = pwc_image_sizes[size];
+ pdev->width = pwc_image_sizes[size][0];
+ pdev->height = pwc_image_sizes[size][1];
pdev->vbandlength = pChoose->bandlength;
if (pdev->vbandlength > 0)
- pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
+ pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
else
- pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
- PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
- pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
+ pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+ PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
+ pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
return 0;
}
-
-
-/**
- @pdev: device structure
- @width: viewport width
- @height: viewport height
- @frame: framerate, in fps
- @compression: preferred compression ratio
- @snapshot: snapshot mode or streaming
- */
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+ int frames, int *compression)
{
int ret, size;
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
- size = pwc_decode_size(pdev, width, height);
- if (size < 0) {
- PWC_DEBUG_MODULE("Could not find suitable size.\n");
- return -ERANGE;
- }
+ size = pwc_get_size(pdev, width, height);
PWC_TRACE("decode_size = %d.\n", size);
if (DEVICE_USE_CODEC1(pdev->type)) {
- ret = set_video_mode_Nala(pdev, size, frames);
+ ret = set_video_mode_Nala(pdev, size, frames, compression);
} else if (DEVICE_USE_CODEC3(pdev->type)) {
- ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+ ret = set_video_mode_Kiara(pdev, size, frames, compression);
} else {
- ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+ ret = set_video_mode_Timon(pdev, size, frames, compression);
}
if (ret < 0) {
PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
return ret;
}
- pdev->view.x = width;
- pdev->view.y = height;
- pdev->vcompression = compression;
pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
- pwc_set_image_buffer_size(pdev);
- PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+ PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
return 0;
}
@@ -470,34 +433,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i
return ret;
}
-static void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
- int factor = 0;
-
- /* for V4L2_PIX_FMT_YUV420 */
- switch (pdev->pixfmt) {
- case V4L2_PIX_FMT_YUV420:
- factor = 6;
- break;
- case V4L2_PIX_FMT_PWC1:
- case V4L2_PIX_FMT_PWC2:
- factor = 6; /* can be uncompressed YUV420P */
- break;
- }
-
- /* Set sizes in bytes */
- pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
- pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
-
- /* Align offset, or you'll get some very weird results in
- YUV420 mode... x must be multiple of 4 (to get the Y's in
- place), and y even (or you'll mixup U & V). This is less of a
- problem for YUV420P.
- */
- pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
- pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-}
-
int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
@@ -598,54 +533,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
power ? "on" : "off", r);
}
-static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
-{
- unsigned char buf;
-
- /* useful range is 0x01..0x20 */
- buf = speed / 0x7f0;
- return send_control_msg(pdev,
- SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
-}
-
-static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
-{
- unsigned char buf;
- int ret;
-
- ret = recv_control_msg(pdev,
- GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
- if (ret < 0)
- return ret;
- *value = buf * 0x7f0;
- return 0;
-}
-
-
-static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
-{
- unsigned char buf;
-
- /* useful range is 0x01..0x3F */
- buf = (delay >> 10);
- return send_control_msg(pdev,
- SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
-}
-
-static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
-{
- unsigned char buf;
- int ret;
-
- ret = recv_control_msg(pdev,
- GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
- if (ret < 0)
- return ret;
- *value = buf << 10;
- return 0;
-}
-
-
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{
unsigned char buf[2];
@@ -675,108 +562,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
return r;
}
-static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
-{
- unsigned char buf[2];
- int ret;
-
- if (pdev->type < 730) {
- *on_value = -1;
- *off_value = -1;
- return 0;
- }
-
- ret = recv_control_msg(pdev,
- GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
- if (ret < 0)
- return ret;
- *on_value = buf[0] * 100;
- *off_value = buf[1] * 100;
- return 0;
-}
-
-static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
-{
- unsigned char buf;
-
- buf = flags & 0x03; // only lower two bits are currently used
- return send_control_msg(pdev,
- SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_mpt_reset(struct pwc_device *pdev, int flags)
-{
- int ret;
- ret = _pwc_mpt_reset(pdev, flags);
- if (ret >= 0) {
- pdev->pan_angle = 0;
- pdev->tilt_angle = 0;
- }
- return ret;
-}
-
-static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
-{
- unsigned char buf[4];
-
- /* set new relative angle; angles are expressed in degrees * 100,
- but cam as .5 degree resolution, hence divide by 200. Also
- the angle must be multiplied by 64 before it's send to
- the cam (??)
- */
- pan = 64 * pan / 100;
- tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
- buf[0] = pan & 0xFF;
- buf[1] = (pan >> 8) & 0xFF;
- buf[2] = tilt & 0xFF;
- buf[3] = (tilt >> 8) & 0xFF;
- return send_control_msg(pdev,
- SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
-}
-
-int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
-{
- int ret;
-
- /* check absolute ranges */
- if (pan < pdev->angle_range.pan_min ||
- pan > pdev->angle_range.pan_max ||
- tilt < pdev->angle_range.tilt_min ||
- tilt > pdev->angle_range.tilt_max)
- return -ERANGE;
-
- /* go to relative range, check again */
- pan -= pdev->pan_angle;
- tilt -= pdev->tilt_angle;
- /* angles are specified in degrees * 100, thus the limit = 36000 */
- if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
- return -ERANGE;
-
- ret = _pwc_mpt_set_angle(pdev, pan, tilt);
- if (ret >= 0) {
- pdev->pan_angle += pan;
- pdev->tilt_angle += tilt;
- }
- if (ret == -EPIPE) /* stall -> out of range */
- ret = -ERANGE;
- return ret;
-}
-
-static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
-{
- int ret;
- unsigned char buf[5];
-
- ret = recv_control_msg(pdev,
- GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
- if (ret < 0)
- return ret;
- status->status = buf[0] & 0x7; // 3 bits are used for reporting
- status->time_pan = (buf[1] << 8) + buf[2];
- status->time_tilt = (buf[3] << 8) + buf[4];
- return 0;
-}
-
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
{
@@ -801,420 +586,3 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
return 0;
}
#endif
-
- /* End of Add-Ons */
- /* ************************************************* */
-
-/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
- ioctl() calls. With 2.4, you have to do tedious copy_from_user()
- and copy_to_user() calls. With these macros we circumvent this,
- and let me maintain only one source file. The functionality is
- exactly the same otherwise.
- */
-
-/* define local variable for arg */
-#define ARG_DEF(ARG_type, ARG_name)\
- ARG_type *ARG_name = arg;
-/* copy arg to local variable */
-#define ARG_IN(ARG_name) /* nothing */
-/* argument itself (referenced) */
-#define ARGR(ARG_name) (*ARG_name)
-/* argument address */
-#define ARGA(ARG_name) ARG_name
-/* copy local variable to arg */
-#define ARG_OUT(ARG_name) /* nothing */
-
-/*
- * Our ctrls use native values, but the old custom pwc ioctl interface expects
- * values from 0 - 65535, define 2 helper functions to scale things. */
-static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl)
-{
- return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum;
-}
-
-static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val)
-{
- return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535);
-}
-
-long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
-{
- long ret = 0;
-
- switch(cmd) {
- case VIDIOCPWCRUSER:
- ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
- break;
-
- case VIDIOCPWCSUSER:
- ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
- break;
-
- case VIDIOCPWCFACTORY:
- ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
- break;
-
- case VIDIOCPWCSCQUAL:
- {
- ARG_DEF(int, qual)
-
- if (vb2_is_streaming(&pdev->vb_queue)) {
- ret = -EBUSY;
- break;
- }
-
- ARG_IN(qual)
- if (ARGR(qual) < 0 || ARGR(qual) > 3)
- ret = -EINVAL;
- else
- ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
- break;
- }
-
- case VIDIOCPWCGCQUAL:
- {
- ARG_DEF(int, qual)
-
- ARGR(qual) = pdev->vcompression;
- ARG_OUT(qual)
- break;
- }
-
- case VIDIOCPWCPROBE:
- {
- ARG_DEF(struct pwc_probe, probe)
-
- strcpy(ARGR(probe).name, pdev->vdev.name);
- ARGR(probe).type = pdev->type;
- ARG_OUT(probe)
- break;
- }
-
- case VIDIOCPWCGSERIAL:
- {
- ARG_DEF(struct pwc_serial, serial)
-
- strcpy(ARGR(serial).serial, pdev->serial);
- ARG_OUT(serial)
- break;
- }
-
- case VIDIOCPWCSAGC:
- {
- ARG_DEF(int, agc)
- ARG_IN(agc)
- ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0);
- if (ret == 0 && ARGR(agc) >= 0)
- ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc));
- break;
- }
-
- case VIDIOCPWCGAGC:
- {
- ARG_DEF(int, agc)
- if (v4l2_ctrl_g_ctrl(pdev->autogain))
- ARGR(agc) = -1;
- else
- ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain);
- ARG_OUT(agc)
- break;
- }
-
- case VIDIOCPWCSSHUTTER:
- {
- ARG_DEF(int, shutter)
- ARG_IN(shutter)
- ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto,
- /* Menu idx 0 = auto, idx 1 = manual */
- ARGR(shutter) >= 0);
- if (ret == 0 && ARGR(shutter) >= 0)
- ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter));
- break;
- }
-
- case VIDIOCPWCSAWB:
- {
- ARG_DEF(struct pwc_whitebalance, wb)
- ARG_IN(wb)
- ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance,
- ARGR(wb).mode);
- if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
- ret = pwc_ioctl_s_ctrl(pdev->red_balance,
- ARGR(wb).manual_red);
- if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
- ret = pwc_ioctl_s_ctrl(pdev->blue_balance,
- ARGR(wb).manual_blue);
- break;
- }
-
- case VIDIOCPWCGAWB:
- {
- ARG_DEF(struct pwc_whitebalance, wb)
- ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance);
- ARGR(wb).manual_red = ARGR(wb).read_red =
- pwc_ioctl_g_ctrl(pdev->red_balance);
- ARGR(wb).manual_blue = ARGR(wb).read_blue =
- pwc_ioctl_g_ctrl(pdev->blue_balance);
- ARG_OUT(wb)
- break;
- }
-
- case VIDIOCPWCSAWBSPEED:
- {
- ARG_DEF(struct pwc_wb_speed, wbs)
-
- if (ARGR(wbs).control_speed > 0) {
- ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
- }
- if (ARGR(wbs).control_delay > 0) {
- ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
- }
- break;
- }
-
- case VIDIOCPWCGAWBSPEED:
- {
- ARG_DEF(struct pwc_wb_speed, wbs)
-
- ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
- if (ret < 0)
- break;
- ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
- if (ret < 0)
- break;
- ARG_OUT(wbs)
- break;
- }
-
- case VIDIOCPWCSLED:
- {
- ARG_DEF(struct pwc_leds, leds)
-
- ARG_IN(leds)
- ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
- break;
- }
-
-
- case VIDIOCPWCGLED:
- {
- ARG_DEF(struct pwc_leds, leds)
-
- ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
- ARG_OUT(leds)
- break;
- }
-
- case VIDIOCPWCSCONTOUR:
- {
- ARG_DEF(int, contour)
- ARG_IN(contour)
- ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0);
- if (ret == 0 && ARGR(contour) >= 0)
- ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour));
- break;
- }
-
- case VIDIOCPWCGCONTOUR:
- {
- ARG_DEF(int, contour)
- if (v4l2_ctrl_g_ctrl(pdev->autocontour))
- ARGR(contour) = -1;
- else
- ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour);
- ARG_OUT(contour)
- break;
- }
-
- case VIDIOCPWCSBACKLIGHT:
- {
- ARG_DEF(int, backlight)
- ARG_IN(backlight)
- ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight));
- break;
- }
-
- case VIDIOCPWCGBACKLIGHT:
- {
- ARG_DEF(int, backlight)
- ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight);
- ARG_OUT(backlight)
- break;
- }
-
- case VIDIOCPWCSFLICKER:
- {
- ARG_DEF(int, flicker)
- ARG_IN(flicker)
- ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker));
- break;
- }
-
- case VIDIOCPWCGFLICKER:
- {
- ARG_DEF(int, flicker)
- ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker);
- ARG_OUT(flicker)
- break;
- }
-
- case VIDIOCPWCSDYNNOISE:
- {
- ARG_DEF(int, dynnoise)
- ARG_IN(dynnoise)
- ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise));
- break;
- }
-
- case VIDIOCPWCGDYNNOISE:
- {
- ARG_DEF(int, dynnoise)
- ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction);
- ARG_OUT(dynnoise);
- break;
- }
-
- case VIDIOCPWCGREALSIZE:
- {
- ARG_DEF(struct pwc_imagesize, size)
-
- ARGR(size).width = pdev->image.x;
- ARGR(size).height = pdev->image.y;
- ARG_OUT(size)
- break;
- }
-
- case VIDIOCPWCMPTRESET:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- ARG_DEF(int, flags)
-
- ARG_IN(flags)
- ret = pwc_mpt_reset(pdev, ARGR(flags));
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTGRANGE:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- ARG_DEF(struct pwc_mpt_range, range)
-
- ARGR(range) = pdev->angle_range;
- ARG_OUT(range)
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTSANGLE:
- {
- int new_pan, new_tilt;
-
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- ARG_DEF(struct pwc_mpt_angles, angles)
-
- ARG_IN(angles)
- /* The camera can only set relative angles, so
- do some calculations when getting an absolute angle .
- */
- if (ARGR(angles).absolute)
- {
- new_pan = ARGR(angles).pan;
- new_tilt = ARGR(angles).tilt;
- }
- else
- {
- new_pan = pdev->pan_angle + ARGR(angles).pan;
- new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
- }
- ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTGANGLE:
- {
-
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- ARG_DEF(struct pwc_mpt_angles, angles)
-
- ARGR(angles).absolute = 1;
- ARGR(angles).pan = pdev->pan_angle;
- ARGR(angles).tilt = pdev->tilt_angle;
- ARG_OUT(angles)
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCMPTSTATUS:
- {
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- {
- ARG_DEF(struct pwc_mpt_status, status)
-
- ret = pwc_mpt_get_status(pdev, ARGA(status));
- ARG_OUT(status)
- }
- else
- {
- ret = -ENXIO;
- }
- break;
- }
-
- case VIDIOCPWCGVIDCMD:
- {
- ARG_DEF(struct pwc_video_command, vcmd);
-
- ARGR(vcmd).type = pdev->type;
- ARGR(vcmd).release = pdev->release;
- ARGR(vcmd).command_len = pdev->cmd_len;
- memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
- ARGR(vcmd).bandlength = pdev->vbandlength;
- ARGR(vcmd).frame_size = pdev->frame_size;
- ARG_OUT(vcmd)
- break;
- }
- /*
- case VIDIOCPWCGVIDTABLE:
- {
- ARG_DEF(struct pwc_table_init_buffer, table);
- ARGR(table).len = pdev->cmd_len;
- memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
- ARG_OUT(table)
- break;
- }
- */
-
- default:
- ret = -ENOIOCTLCMD;
- break;
- }
-
- if (ret > 0)
- return 0;
- return ret;
-}
-
-
-/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
index 06a4e87..2c67091 100644
--- a/drivers/media/video/pwc/pwc-dec23.c
+++ b/drivers/media/video/pwc/pwc-dec23.c
@@ -27,7 +27,6 @@
#include "pwc-timon.h"
#include "pwc-kiara.h"
#include "pwc-dec23.h"
-#include <media/pwc-ioctl.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -51,13 +50,6 @@
# define USE_LOOKUP_TABLE_TO_CLAMP 1
#endif
-/*
- * ENABLE_BAYER_DECODER
- * 0: bayer decoder is not build (save some space)
- * 1: bayer decoder is build and can be used
- */
-#define ENABLE_BAYER_DECODER 0
-
static void build_subblock_pattern(struct pwc_dec23_private *pdec)
{
static const unsigned int initial_values[12] = {
@@ -315,6 +307,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
}
pdec = pwc->decompress_data;
+ mutex_init(&pdec->lock);
+
if (DEVICE_USE_CODEC3(type)) {
flags = cmd[2] & 0x18;
if (flags == 8)
@@ -467,123 +461,6 @@ static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned i
#endif
}
-#if ENABLE_BAYER_DECODER
-/*
- * Format: 8x2 pixels
- * . G . G . G . G . G . G . G
- * . . . . . . . . . . . . . .
- * . G . G . G . G . G . G . G
- * . . . . . . . . . . . . . .
- * or
- * . . . . . . . . . . . . . .
- * G . G . G . G . G . G . G .
- * . . . . . . . . . . . . . .
- * G . G . G . G . G . G . G .
-*/
-static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
- /* Unroll all loops */
- const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
- unsigned char *d = dst;
- const int *c = src;
-
- d[0] = cm[c[0] >> scalebits];
- d[2] = cm[c[1] >> scalebits];
- d[4] = cm[c[2] >> scalebits];
- d[6] = cm[c[3] >> scalebits];
- d[8] = cm[c[4] >> scalebits];
- d[10] = cm[c[5] >> scalebits];
- d[12] = cm[c[6] >> scalebits];
- d[14] = cm[c[7] >> scalebits];
-
- d = dst + bytes_per_line;
- d[0] = cm[c[8] >> scalebits];
- d[2] = cm[c[9] >> scalebits];
- d[4] = cm[c[10] >> scalebits];
- d[6] = cm[c[11] >> scalebits];
- d[8] = cm[c[12] >> scalebits];
- d[10] = cm[c[13] >> scalebits];
- d[12] = cm[c[14] >> scalebits];
- d[14] = cm[c[15] >> scalebits];
-#else
- int i;
- unsigned char *d;
- const int *c = src;
-
- d = dst;
- for (i = 0; i < 8; i++, c++)
- d[i*2] = CLAMP((*c) >> scalebits);
-
- d = dst + bytes_per_line;
- for (i = 0; i < 8; i++, c++)
- d[i*2] = CLAMP((*c) >> scalebits);
-#endif
-}
-#endif
-
-#if ENABLE_BAYER_DECODER
-/*
- * Format: 4x4 pixels
- * R . R . R . R
- * . B . B . B .
- * R . R . R . R
- * . B . B . B .
- */
-static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
- /* Unroll all loops */
- const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
- unsigned char *d = dst;
- const int *c = src;
-
- d[0] = cm[c[0] >> scalebits];
- d[2] = cm[c[1] >> scalebits];
- d[4] = cm[c[2] >> scalebits];
- d[6] = cm[c[3] >> scalebits];
-
- d = dst + bytes_per_line;
- d[1] = cm[c[4] >> scalebits];
- d[3] = cm[c[5] >> scalebits];
- d[5] = cm[c[6] >> scalebits];
- d[7] = cm[c[7] >> scalebits];
-
- d = dst + bytes_per_line*2;
- d[0] = cm[c[8] >> scalebits];
- d[2] = cm[c[9] >> scalebits];
- d[4] = cm[c[10] >> scalebits];
- d[6] = cm[c[11] >> scalebits];
-
- d = dst + bytes_per_line*3;
- d[1] = cm[c[12] >> scalebits];
- d[3] = cm[c[13] >> scalebits];
- d[5] = cm[c[14] >> scalebits];
- d[7] = cm[c[15] >> scalebits];
-#else
- int i;
- unsigned char *d;
- const int *c = src;
-
- d = dst;
- for (i = 0; i < 4; i++, c++)
- d[i*2] = CLAMP((*c) >> scalebits);
-
- d = dst + bytes_per_line;
- for (i = 0; i < 4; i++, c++)
- d[i*2+1] = CLAMP((*c) >> scalebits);
-
- d = dst + bytes_per_line*2;
- for (i = 0; i < 4; i++, c++)
- d[i*2] = CLAMP((*c) >> scalebits);
-
- d = dst + bytes_per_line*3;
- for (i = 0; i < 4; i++, c++)
- d[i*2+1] = CLAMP((*c) >> scalebits);
-#endif
-}
-#endif
-
/*
* To manage the stream, we keep bits in a 32 bits register.
* fill_nbits(n): fill the reservoir with at least n bits
@@ -775,146 +652,45 @@ static void DecompressBand23(struct pwc_dec23_private *pdec,
}
-#if ENABLE_BAYER_DECODER
-/*
- * Size need to be a multiple of 8 in width
- *
- * Return a block of four line encoded like this:
- *
- * G R G R G R G R G R G R G R G R
- * B G B G B G B G B G B G B G B G
- * G R G R G R G R G R G R G R G R
- * B G B G B G B G B G B G B G B G
- *
- */
-static void DecompressBandBayer(struct pwc_dec23_private *pdec,
- const unsigned char *rawyuv,
- unsigned char *rgbbayer,
- unsigned int compressed_image_width,
- unsigned int real_image_width)
-{
- int compression_index, nblocks;
- const unsigned char *ptable0004;
- const unsigned char *ptable8004;
- unsigned char *dest;
-
- pdec->reservoir = 0;
- pdec->nbits_in_reservoir = 0;
- pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */
-
- get_nbits(pdec, 4, compression_index);
-
- /* pass 1: uncompress RB component */
- nblocks = compressed_image_width / 4;
-
- ptable0004 = pdec->table_0004_pass1[compression_index];
- ptable8004 = pdec->table_8004_pass1[compression_index];
- dest = rgbbayer;
-
- /* Each block decode a square of 4x4 */
- while (nblocks) {
- decode_block(pdec, ptable0004, ptable8004);
- copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
- dest += 8;
- nblocks--;
- }
-
- /* pass 2: uncompress G component */
- nblocks = compressed_image_width / 8;
-
- ptable0004 = pdec->table_0004_pass2[compression_index];
- ptable8004 = pdec->table_8004_pass2[compression_index];
-
- /* Each block decode a square of 4x4 */
- while (nblocks) {
- decode_block(pdec, ptable0004, ptable8004);
- copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
-
- decode_block(pdec, ptable0004, ptable8004);
- copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
-
- rgbbayer += 16;
- nblocks -= 2;
- }
-}
-#endif
-
-
/**
*
* Uncompress a pwc23 buffer.
*
- * pwc.view: size of the image wanted
- * pwc.image: size of the image returned by the camera
- * pwc.offset: (x,y) to displayer image in the view
- *
* src: raw data
* dst: image output
- * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
*/
void pwc_dec23_decompress(const struct pwc_device *pwc,
const void *src,
- void *dst,
- int flags)
+ void *dst)
{
- int bandlines_left, stride, bytes_per_block;
-
- bandlines_left = pwc->image.y / 4;
- bytes_per_block = pwc->view.x * 4;
-
- if (flags & PWCX_FLAG_BAYER) {
-#if ENABLE_BAYER_DECODER
- /* RGB Bayer format */
- unsigned char *rgbout;
-
- stride = pwc->view.x * pwc->offset.y;
- rgbout = dst + stride + pwc->offset.x;
-
-
- while (bandlines_left--) {
-
- DecompressBandBayer(pwc->decompress_data,
- src,
- rgbout,
- pwc->image.x, pwc->view.x);
-
- src += pwc->vbandlength;
- rgbout += bytes_per_block;
-
- }
-#else
- memset(dst, 0, pwc->view.x * pwc->view.y);
-#endif
-
- } else {
- /* YUV420P image format */
- unsigned char *pout_planar_y;
- unsigned char *pout_planar_u;
- unsigned char *pout_planar_v;
- unsigned int plane_size;
-
- plane_size = pwc->view.x * pwc->view.y;
-
- /* offset in Y plane */
- stride = pwc->view.x * pwc->offset.y;
- pout_planar_y = dst + stride + pwc->offset.x;
-
- /* offsets in U/V planes */
- stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
- pout_planar_u = dst + plane_size + stride;
- pout_planar_v = dst + plane_size + plane_size / 4 + stride;
-
- while (bandlines_left--) {
-
- DecompressBand23(pwc->decompress_data,
- src,
- pout_planar_y, pout_planar_u, pout_planar_v,
- pwc->image.x, pwc->view.x);
- src += pwc->vbandlength;
- pout_planar_y += bytes_per_block;
- pout_planar_u += pwc->view.x;
- pout_planar_v += pwc->view.x;
-
- }
+ int bandlines_left, bytes_per_block;
+ struct pwc_dec23_private *pdec = pwc->decompress_data;
+
+ /* YUV420P image format */
+ unsigned char *pout_planar_y;
+ unsigned char *pout_planar_u;
+ unsigned char *pout_planar_v;
+ unsigned int plane_size;
+
+ mutex_lock(&pdec->lock);
+
+ bandlines_left = pwc->height / 4;
+ bytes_per_block = pwc->width * 4;
+ plane_size = pwc->height * pwc->width;
+
+ pout_planar_y = dst;
+ pout_planar_u = dst + plane_size;
+ pout_planar_v = dst + plane_size + plane_size / 4;
+
+ while (bandlines_left--) {
+ DecompressBand23(pwc->decompress_data,
+ src,
+ pout_planar_y, pout_planar_u, pout_planar_v,
+ pwc->width, pwc->width);
+ src += pwc->vbandlength;
+ pout_planar_y += bytes_per_block;
+ pout_planar_u += pwc->width;
+ pout_planar_v += pwc->width;
}
+ mutex_unlock(&pdec->lock);
}
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
index a0ac4f3..d64a3c2 100644
--- a/drivers/media/video/pwc/pwc-dec23.h
+++ b/drivers/media/video/pwc/pwc-dec23.h
@@ -29,6 +29,8 @@
struct pwc_dec23_private
{
+ struct mutex lock;
+
unsigned int scalebits;
unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
@@ -52,6 +54,5 @@ struct pwc_dec23_private
int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
void pwc_dec23_decompress(const struct pwc_device *pwc,
const void *src,
- void *dst,
- int flags);
+ void *dst);
#endif
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 01ff643..943d37a 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -134,7 +134,6 @@ static int default_fps = 10;
#endif
static int power_save = -1;
static int led_on = 100, led_off; /* defaults to LED that is on while in use */
-static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
static struct {
int type;
char serial_number[30];
@@ -144,17 +143,15 @@ static struct {
/***/
-static int pwc_video_open(struct file *file);
static int pwc_video_close(struct file *file);
static ssize_t pwc_video_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-static void pwc_video_release(struct video_device *vfd);
static const struct v4l2_file_operations pwc_fops = {
.owner = THIS_MODULE,
- .open = pwc_video_open,
+ .open = v4l2_fh_open,
.release = pwc_video_close,
.read = pwc_video_read,
.poll = pwc_video_poll,
@@ -163,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = {
};
static struct video_device pwc_template = {
.name = "Philips Webcam", /* Filled in later */
- .release = pwc_video_release,
+ .release = video_device_release_empty,
.fops = &pwc_fops,
.ioctl_ops = &pwc_ioctl_ops,
};
@@ -191,7 +188,6 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down)
{
if (down) {
PWC_TRACE("Snapshot button pressed.\n");
- pdev->snapshot_button_status = 1;
} else {
PWC_TRACE("Snapshot button released.\n");
}
@@ -375,6 +371,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
int i, j, ret;
struct usb_interface *intf;
struct usb_host_interface *idesc = NULL;
+ int compression = 0; /* 0..3 = uncompressed..high */
if (pdev->iso_init)
return 0;
@@ -386,6 +383,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
pdev->visoc_errors = 0;
udev = pdev->udev;
+retry:
+ /* We first try with low compression and then retry with a higher
+ compression setting if there is not enough bandwidth. */
+ ret = pwc_set_video_mode(pdev, pdev->width, pdev->height,
+ pdev->vframes, &compression);
+
/* Get the current alternate interface, adjust packet size */
intf = usb_ifnum_to_if(udev, 0);
if (intf)
@@ -408,9 +411,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
}
/* Set alternate interface */
- ret = 0;
PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ goto retry;
+ }
if (ret < 0)
return ret;
@@ -454,6 +460,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
/* link */
for (i = 0; i < MAX_ISO_BUFS; i++) {
ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ pdev->iso_init = 1;
+ pwc_isoc_cleanup(pdev);
+ goto retry;
+ }
if (ret) {
PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
pdev->iso_init = 1;
@@ -517,12 +529,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
}
-/*
- * Release all queued buffers, no need to take queued_bufs_lock, since all
- * iso urbs have been killed when we're called so pwc_isoc_handler won't run.
- */
static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
while (!list_empty(&pdev->queued_bufs)) {
struct pwc_frame_buf *buf;
@@ -531,84 +542,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
-}
-
-/*********
- * sysfs
- *********/
-static struct pwc_device *cd_to_pwc(struct device *cd)
-{
- struct video_device *vdev = to_video_device(cd);
- return video_get_drvdata(vdev);
-}
-
-static ssize_t show_pan_tilt(struct device *class_dev,
- struct device_attribute *attr, char *buf)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
-}
-
-static ssize_t store_pan_tilt(struct device *class_dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- int pan, tilt;
- int ret = -EINVAL;
-
- if (strncmp(buf, "reset", 5) == 0)
- ret = pwc_mpt_reset(pdev, 0x3);
-
- else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
- ret = pwc_mpt_set_angle(pdev, pan, tilt);
-
- if (ret < 0)
- return ret;
- return strlen(buf);
-}
-static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
- store_pan_tilt);
-
-static ssize_t show_snapshot_button_status(struct device *class_dev,
- struct device_attribute *attr, char *buf)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- int status = pdev->snapshot_button_status;
- pdev->snapshot_button_status = 0;
- return sprintf(buf, "%d\n", status);
-}
-
-static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
- NULL);
-
-static int pwc_create_sysfs_files(struct pwc_device *pdev)
-{
- int rc;
-
- rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
- if (rc)
- goto err;
- if (pdev->features & FEATURE_MOTOR_PANTILT) {
- rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
- if (rc)
- goto err_button;
- }
-
- return 0;
-
-err_button:
- device_remove_file(&pdev->vdev.dev, &dev_attr_button);
-err:
- PWC_ERROR("Could not create sysfs files.\n");
- return rc;
-}
-
-static void pwc_remove_sysfs_files(struct pwc_device *pdev)
-{
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
- device_remove_file(&pdev->vdev.dev, &dev_attr_button);
+ spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
#ifdef CONFIG_USB_PWC_DEBUG
@@ -644,25 +578,25 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
/***************************************************************************/
/* Video4Linux functions */
-static int pwc_video_open(struct file *file)
+int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
{
- struct video_device *vdev = video_devdata(file);
- struct pwc_device *pdev;
-
- PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
+ int r = 0;
- pdev = video_get_drvdata(vdev);
- if (!pdev->udev)
- return -ENODEV;
-
- file->private_data = vdev;
- PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
- return 0;
+ mutex_lock(&pdev->capt_file_lock);
+ if (pdev->capt_file != NULL &&
+ pdev->capt_file != file) {
+ r = -EBUSY;
+ goto leave;
+ }
+ pdev->capt_file = file;
+leave:
+ mutex_unlock(&pdev->capt_file_lock);
+ return r;
}
-static void pwc_video_release(struct video_device *vfd)
+static void pwc_video_release(struct v4l2_device *v)
{
- struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
int hint;
/* search device_hint[] table if we occupy a slot, by any chance */
@@ -685,44 +619,33 @@ static void pwc_video_release(struct video_device *vfd)
static int pwc_video_close(struct file *file)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev;
-
- PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
+ struct pwc_device *pdev = video_drvdata(file);
- pdev = video_get_drvdata(vdev);
if (pdev->capt_file == file) {
vb2_queue_release(&pdev->vb_queue);
pdev->capt_file = NULL;
}
-
- PWC_DEBUG_OPEN("<< video_close()\n");
- return 0;
+ return v4l2_fh_release(file);
}
static ssize_t pwc_video_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (!pdev->udev)
return -ENODEV;
- if (pdev->capt_file != NULL &&
- pdev->capt_file != file)
+ if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;
- pdev->capt_file = file;
-
return vb2_read(&pdev->vb_queue, buf, count, ppos,
file->f_flags & O_NONBLOCK);
}
static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (!pdev->udev)
return POLL_ERR;
@@ -732,8 +655,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (pdev->capt_file != file)
return -EBUSY;
@@ -749,6 +671,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int sizes[], void *alloc_ctxs[])
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int size;
if (*nbuffers < MIN_FRAMES)
*nbuffers = MIN_FRAMES;
@@ -757,7 +680,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
*nplanes = 1;
- sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
+ size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
+ sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
+ pwc_image_sizes[size][1] * 3 / 2);
return 0;
}
@@ -812,56 +737,59 @@ static void buffer_queue(struct vb2_buffer *vb)
unsigned long flags = 0;
spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
- list_add_tail(&buf->list, &pdev->queued_bufs);
+ /* Check the device has not disconnected between prep and queuing */
+ if (pdev->udev)
+ list_add_tail(&buf->list, &pdev->queued_bufs);
+ else
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int r;
- if (!pdev->udev)
- return -ENODEV;
+ mutex_lock(&pdev->udevlock);
+ if (!pdev->udev) {
+ r = -ENODEV;
+ goto leave;
+ }
/* Turn on camera and set LEDS on */
pwc_camera_power(pdev, 1);
- if (pdev->power_save) {
- /* Restore video mode */
- pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
- pdev->vframes, pdev->vcompression,
- pdev->vsnapshot);
- }
pwc_set_leds(pdev, led_on, led_off);
- return pwc_isoc_init(pdev);
+ r = pwc_isoc_init(pdev);
+ if (r) {
+ /* If we failed turn camera and LEDS back off */
+ pwc_set_leds(pdev, 0, 0);
+ pwc_camera_power(pdev, 0);
+ /* And cleanup any queued bufs!! */
+ pwc_cleanup_queued_bufs(pdev);
+ }
+leave:
+ mutex_unlock(&pdev->udevlock);
+ return r;
}
static int stop_streaming(struct vb2_queue *vq)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ mutex_lock(&pdev->udevlock);
if (pdev->udev) {
pwc_set_leds(pdev, 0, 0);
pwc_camera_power(pdev, 0);
pwc_isoc_cleanup(pdev);
}
+ mutex_unlock(&pdev->udevlock);
+
pwc_cleanup_queued_bufs(pdev);
return 0;
}
-static void pwc_lock(struct vb2_queue *vq)
-{
- struct pwc_device *pdev = vb2_get_drv_priv(vq);
- mutex_lock(&pdev->modlock);
-}
-
-static void pwc_unlock(struct vb2_queue *vq)
-{
- struct pwc_device *pdev = vb2_get_drv_priv(vq);
- mutex_unlock(&pdev->modlock);
-}
-
static struct vb2_ops pwc_vb_queue_ops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
@@ -871,8 +799,6 @@ static struct vb2_ops pwc_vb_queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = pwc_unlock,
- .wait_finish = pwc_lock,
};
/***************************************************************************/
@@ -889,6 +815,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
int vendor_id, product_id, type_id;
int hint, rc;
int features = 0;
+ int compression = 0;
int video_nr = -1; /* default: use next available device */
int my_power_save = power_save;
char serial_number[30], *name;
@@ -1150,27 +1077,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
}
pdev->type = type_id;
pdev->vframes = default_fps;
- strcpy(pdev->serial, serial_number);
pdev->features = features;
- if (vendor_id == 0x046D && product_id == 0x08B5) {
- /* Logitech QuickCam Orbit
- The ranges have been determined experimentally; they may differ from cam to cam.
- Also, the exact ranges left-right and up-down are different for my cam
- */
- pdev->angle_range.pan_min = -7000;
- pdev->angle_range.pan_max = 7000;
- pdev->angle_range.tilt_min = -3000;
- pdev->angle_range.tilt_max = 2500;
- }
pwc_construct(pdev); /* set min/max sizes correct */
- mutex_init(&pdev->modlock);
+ mutex_init(&pdev->capt_file_lock);
mutex_init(&pdev->udevlock);
spin_lock_init(&pdev->queued_bufs_lock);
INIT_LIST_HEAD(&pdev->queued_bufs);
pdev->udev = udev;
- pdev->vcompression = pwc_preferred_compression;
pdev->power_save = my_power_save;
/* Init videobuf2 queue structure */
@@ -1185,9 +1100,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
/* Init video_device structure */
memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
- pdev->vdev.parent = &intf->dev;
- pdev->vdev.lock = &pdev->modlock;
strcpy(pdev->vdev.name, name);
+ set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
video_set_drvdata(&pdev->vdev, pdev);
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
@@ -1211,9 +1125,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (hint < MAX_DEV_HINTS)
device_hint[hint].pdev = pdev;
- PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
- usb_set_intfdata(intf, pdev);
-
#ifdef CONFIG_USB_PWC_DEBUG
/* Query sensor type */
if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1227,8 +1138,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pwc_set_leds(pdev, 0, 0);
/* Setup intial videomode */
- rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
- pdev->vframes, pdev->vcompression, 0);
+ rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes,
+ &compression);
if (rc)
goto err_free_mem;
@@ -1239,20 +1150,25 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
goto err_free_mem;
}
- pdev->vdev.ctrl_handler = &pdev->ctrl_handler;
-
/* And powerdown the camera until streaming starts */
pwc_camera_power(pdev, 0);
+ /* Register the v4l2_device structure */
+ pdev->v4l2_dev.release = pwc_video_release;
+ rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
+ if (rc) {
+ PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
+ goto err_free_controls;
+ }
+
+ pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+ pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+
rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
if (rc < 0) {
PWC_ERROR("Failed to register as video device (%d).\n", rc);
- goto err_free_controls;
+ goto err_unregister_v4l2_dev;
}
- rc = pwc_create_sysfs_files(pdev);
- if (rc)
- goto err_video_unreg;
-
PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
@@ -1261,7 +1177,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (!pdev->button_dev) {
PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
rc = -ENOMEM;
- pwc_remove_sysfs_files(pdev);
goto err_video_unreg;
}
@@ -1279,7 +1194,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (rc) {
input_free_device(pdev->button_dev);
pdev->button_dev = NULL;
- pwc_remove_sysfs_files(pdev);
goto err_video_unreg;
}
#endif
@@ -1287,13 +1201,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return 0;
err_video_unreg:
- if (hint < MAX_DEV_HINTS)
- device_hint[hint].pdev = NULL;
video_unregister_device(&pdev->vdev);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&pdev->v4l2_dev);
err_free_controls:
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
err_free_mem:
- usb_set_intfdata(intf, NULL);
+ if (hint < MAX_DEV_HINTS)
+ device_hint[hint].pdev = NULL;
kfree(pdev);
return rc;
}
@@ -1301,27 +1216,26 @@ err_free_mem:
/* The user yanked out the cable... */
static void usb_pwc_disconnect(struct usb_interface *intf)
{
- struct pwc_device *pdev = usb_get_intfdata(intf);
+ struct v4l2_device *v = usb_get_intfdata(intf);
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
mutex_lock(&pdev->udevlock);
- mutex_lock(&pdev->modlock);
-
- usb_set_intfdata(intf, NULL);
/* No need to keep the urbs around after disconnection */
pwc_isoc_cleanup(pdev);
- pwc_cleanup_queued_bufs(pdev);
pdev->udev = NULL;
-
- mutex_unlock(&pdev->modlock);
mutex_unlock(&pdev->udevlock);
- pwc_remove_sysfs_files(pdev);
+ pwc_cleanup_queued_bufs(pdev);
+
video_unregister_device(&pdev->vdev);
+ v4l2_device_unregister(&pdev->v4l2_dev);
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
if (pdev->button_dev)
input_unregister_device(pdev->button_dev);
#endif
+
+ v4l2_device_put(&pdev->v4l2_dev);
}
@@ -1330,7 +1244,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
*/
static int fps;
-static int compression = -1;
static int leds[2] = { -1, -1 };
static unsigned int leds_nargs;
static char *dev_hint[MAX_DEV_HINTS];
@@ -1341,7 +1254,6 @@ module_param(fps, int, 0444);
module_param_named(trace, pwc_trace, int, 0644);
#endif
module_param(power_save, int, 0644);
-module_param(compression, int, 0444);
module_param_array(leds, int, &leds_nargs, 0444);
module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
@@ -1350,7 +1262,6 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang
MODULE_PARM_DESC(trace, "For debugging purposes");
#endif
MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
-MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
MODULE_PARM_DESC(dev_hint, "Device node hints");
@@ -1384,14 +1295,6 @@ static int __init usb_pwc_init(void)
PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
}
- if (compression >= 0) {
- if (compression > 3) {
- PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
- return -EINVAL;
- }
- pwc_preferred_compression = compression;
- PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
- }
if (leds[0] >= 0)
led_on = leds[0];
if (leds[1] >= 0)
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h
index 047dad8..8e02b7a 100644
--- a/drivers/media/video/pwc/pwc-kiara.h
+++ b/drivers/media/video/pwc/pwc-kiara.h
@@ -27,7 +27,7 @@
#ifndef PWC_KIARA_H
#define PWC_KIARA_H
-#include <media/pwc-ioctl.h>
+#include "pwc.h"
#define PWC_FPS_MAX_KIARA 6
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
index 0b03133..23a55b5 100644
--- a/drivers/media/video/pwc/pwc-misc.c
+++ b/drivers/media/video/pwc/pwc-misc.c
@@ -27,67 +27,47 @@
#include "pwc.h"
-const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+const int pwc_image_sizes[PSZ_MAX][2] =
{
- { 128, 96, 0 }, /* sqcif */
- { 160, 120, 0 }, /* qsif */
- { 176, 144, 0 }, /* qcif */
- { 320, 240, 0 }, /* sif */
- { 352, 288, 0 }, /* cif */
- { 640, 480, 0 }, /* vga */
+ { 128, 96 }, /* sqcif */
+ { 160, 120 }, /* qsif */
+ { 176, 144 }, /* qcif */
+ { 320, 240 }, /* sif */
+ { 352, 288 }, /* cif */
+ { 640, 480 }, /* vga */
};
/* x,y -> PSZ_ */
-int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+int pwc_get_size(struct pwc_device *pdev, int width, int height)
{
- int i, find;
-
- /* Make sure we don't go beyond our max size.
- NB: we have different limits for RAW and normal modes. In case
- you don't have the decompressor loaded or use RAW mode,
- the maximum viewable size is smaller.
- */
- if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
- {
- if (width > pdev->abs_max.x || height > pdev->abs_max.y)
- {
- PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
- return -1;
- }
- }
- else
- {
- if (width > pdev->view_max.x || height > pdev->view_max.y)
- {
- PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
- return -1;
- }
- }
+ int i;
/* Find the largest size supported by the camera that fits into the
- requested size.
- */
- find = -1;
+ requested size. */
+ for (i = PSZ_MAX - 1; i >= 0; i--) {
+ if (!(pdev->image_mask & (1 << i)))
+ continue;
+
+ if (pwc_image_sizes[i][0] <= width &&
+ pwc_image_sizes[i][1] <= height)
+ return i;
+ }
+
+ /* No mode found, return the smallest mode we have */
for (i = 0; i < PSZ_MAX; i++) {
- if (pdev->image_mask & (1 << i)) {
- if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
- find = i;
- }
+ if (pdev->image_mask & (1 << i))
+ return i;
}
- return find;
+
+ /* Never reached there always is atleast one supported mode */
+ return 0;
}
-/* initialize variables depending on type and decompressor*/
+/* initialize variables depending on type and decompressor */
void pwc_construct(struct pwc_device *pdev)
{
if (DEVICE_USE_CODEC1(pdev->type)) {
- pdev->view_min.x = 128;
- pdev->view_min.y = 96;
- pdev->view_max.x = 352;
- pdev->view_max.y = 288;
- pdev->abs_max.x = 352;
- pdev->abs_max.y = 288;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
pdev->vcinterface = 2;
pdev->vendpoint = 4;
@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev)
} else if (DEVICE_USE_CODEC3(pdev->type)) {
- pdev->view_min.x = 160;
- pdev->view_min.y = 120;
- pdev->view_max.x = 640;
- pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
- pdev->abs_max.x = 640;
- pdev->abs_max.y = 480;
pdev->vcinterface = 3;
pdev->vendpoint = 5;
pdev->frame_header_size = TOUCAM_HEADER_SIZE;
@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev)
} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
- pdev->view_min.x = 128;
- pdev->view_min.y = 96;
- /* Anthill bug #38: PWC always reports max size, even without PWCX */
- pdev->view_max.x = 640;
- pdev->view_max.y = 480;
pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
- pdev->abs_max.x = 640;
- pdev->abs_max.y = 480;
pdev->vcinterface = 3;
pdev->vendpoint = 4;
pdev->frame_header_size = 0;
pdev->frame_trailer_size = 0;
}
pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
- pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
- pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
}
diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h
index a6e22224..270c5b9 100644
--- a/drivers/media/video/pwc/pwc-timon.h
+++ b/drivers/media/video/pwc/pwc-timon.h
@@ -42,7 +42,7 @@
#ifndef PWC_TIMON_H
#define PWC_TIMON_H
-#include <media/pwc-ioctl.h>
+#include "pwc.h"
#define PWC_FPS_MAX_TIMON 6
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
index 5126509..b65903f 100644
--- a/drivers/media/video/pwc/pwc-uncompress.c
+++ b/drivers/media/video/pwc/pwc-uncompress.c
@@ -35,7 +35,7 @@
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
{
- int n, line, col, stride;
+ int n, line, col;
void *yuv, *image;
u16 *src;
u16 *dsty, *dstu, *dstv;
@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
return 0;
}
- vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size);
+ vb2_set_plane_payload(&fbuf->vb, 0,
+ pdev->width * pdev->height * 3 / 2);
if (pdev->vbandlength == 0) {
/* Uncompressed mode.
- * We copy the data into the output buffer, using the viewport
- * size (which may be larger than the image size).
- * Unfortunately we have to do a bit of byte stuffing to get
- * the desired output format/size.
*
* We do some byte shuffling here to go from the
* native format to YUV420P.
*/
src = (u16 *)yuv;
- n = pdev->view.x * pdev->view.y;
+ n = pdev->width * pdev->height;
+ dsty = (u16 *)(image);
+ dstu = (u16 *)(image + n);
+ dstv = (u16 *)(image + n + n / 4);
- /* offset in Y plane */
- stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
- dsty = (u16 *)(image + stride);
-
- /* offsets in U/V planes */
- stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
- dstu = (u16 *)(image + n + stride);
- dstv = (u16 *)(image + n + n / 4 + stride);
-
- /* increment after each line */
- stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
- for (line = 0; line < pdev->image.y; line++) {
- for (col = 0; col < pdev->image.x; col += 4) {
+ for (line = 0; line < pdev->height; line++) {
+ for (col = 0; col < pdev->width; col += 4) {
*dsty++ = *src++;
*dsty++ = *src++;
if (line & 1)
@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
else
*dstu++ = *src++;
}
- dsty += stride;
- if (line & 1)
- dstv += (stride >> 1);
- else
- dstu += (stride >> 1);
}
return 0;
@@ -111,12 +94,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
* the decompressor routines will write the data in planar format
* immediately.
*/
- if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
- PWC_ERROR("Mode Bayer is not supported for now\n");
- /* flags |= PWCX_FLAG_BAYER; */
- return -ENXIO; /* No such device or address: missing decompressor */
- }
-
if (DEVICE_USE_CODEC1(pdev->type)) {
/* TODO & FIXME */
@@ -124,10 +101,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
return -ENXIO; /* No such device or address: missing decompressor */
} else {
- pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR);
+ pwc_dec23_decompress(pdev, yuv, image);
}
return 0;
}
-
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index a10ff6b..80e2584 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -49,6 +49,7 @@ static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
enum { custom_autocontour, custom_contour, custom_noise_reduction,
+ custom_awb_speed, custom_awb_delay,
custom_save_user, custom_restore_user, custom_restore_factory };
const char * const pwc_auto_whitebal_qmenu[] = {
@@ -138,6 +139,26 @@ static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
.name = "Restore Factory Settings",
};
+static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(awb_speed),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Auto White Balance Speed",
+ .min = 1,
+ .max = 32,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
+ .ops = &pwc_ctrl_ops,
+ .id = PWC_CID_CUSTOM(awb_delay),
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Auto White Balance Delay",
+ .min = 0,
+ .max = 63,
+ .step = 1,
+};
+
int pwc_init_controls(struct pwc_device *pdev)
{
struct v4l2_ctrl_handler *hdl;
@@ -338,6 +359,23 @@ int pwc_init_controls(struct pwc_device *pdev)
if (pdev->restore_factory)
pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
+ /* Auto White Balance speed & delay */
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ AWB_CONTROL_SPEED_FORMATTER, &def);
+ if (r || def < 1 || def > 32)
+ def = 1;
+ cfg = pwc_awb_speed_cfg;
+ cfg.def = def;
+ pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+ r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+ AWB_CONTROL_DELAY_FORMATTER, &def);
+ if (r || def > 63)
+ def = 0;
+ cfg = pwc_awb_delay_cfg;
+ cfg.def = def;
+ pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
if (!(pdev->features & FEATURE_MOTOR_PANTILT))
return hdl->error;
@@ -357,25 +395,16 @@ int pwc_init_controls(struct pwc_device *pdev)
return hdl->error;
}
-static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
+static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
+ int width, int height, u32 pixfmt)
{
memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
- f->fmt.pix.width = pdev->view.x;
- f->fmt.pix.height = pdev->view.y;
+ f->fmt.pix.width = width;
+ f->fmt.pix.height = height;
f->fmt.pix.field = V4L2_FIELD_NONE;
- if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
- f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
- f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
- } else {
- /* vbandlength contains 4 lines ... */
- f->fmt.pix.bytesperline = pdev->vbandlength/4;
- f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
- if (DEVICE_USE_CODEC1(pdev->type))
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1;
- else
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2;
- }
+ f->fmt.pix.pixelformat = pixfmt;
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
"width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
f->fmt.pix.width,
@@ -391,6 +420,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma
/* ioctl(VIDIOC_TRY_FMT) */
static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
{
+ int size;
+
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
return -EINVAL;
@@ -417,15 +448,11 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
}
- if (f->fmt.pix.width > pdev->view_max.x)
- f->fmt.pix.width = pdev->view_max.x;
- else if (f->fmt.pix.width < pdev->view_min.x)
- f->fmt.pix.width = pdev->view_min.x;
-
- if (f->fmt.pix.height > pdev->view_max.y)
- f->fmt.pix.height = pdev->view_max.y;
- else if (f->fmt.pix.height < pdev->view_min.y)
- f->fmt.pix.height = pdev->view_min.y;
+ size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
+ pwc_vidioc_fill_fmt(f,
+ pwc_image_sizes[size][0],
+ pwc_image_sizes[size][1],
+ f->fmt.pix.pixelformat);
return 0;
}
@@ -435,68 +462,50 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
{
struct pwc_device *pdev = video_drvdata(file);
- int ret, fps, snapshot, compression, pixelformat;
-
- if (!pdev->udev)
- return -ENODEV;
+ int ret, pixelformat, compression = 0;
- if (pdev->capt_file != NULL &&
- pdev->capt_file != file)
+ if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;
- pdev->capt_file = file;
-
ret = pwc_vidioc_try_fmt(pdev, f);
- if (ret<0)
+ if (ret < 0)
return ret;
pixelformat = f->fmt.pix.pixelformat;
- compression = pdev->vcompression;
- snapshot = 0;
- fps = pdev->vframes;
- if (f->fmt.pix.priv) {
- compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
- snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
- fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
- if (fps == 0)
- fps = pdev->vframes;
- }
- if (pixelformat != V4L2_PIX_FMT_YUV420 &&
- pixelformat != V4L2_PIX_FMT_PWC1 &&
- pixelformat != V4L2_PIX_FMT_PWC2)
- return -EINVAL;
+ mutex_lock(&pdev->udevlock);
+ if (!pdev->udev) {
+ ret = -ENODEV;
+ goto leave;
+ }
- if (vb2_is_streaming(&pdev->vb_queue))
- return -EBUSY;
+ if (pdev->iso_init) {
+ ret = -EBUSY;
+ goto leave;
+ }
PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
- "compression=%d snapshot=%d format=%c%c%c%c\n",
- f->fmt.pix.width, f->fmt.pix.height, fps,
- compression, snapshot,
+ "format=%c%c%c%c\n",
+ f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
(pixelformat)&255,
(pixelformat>>8)&255,
(pixelformat>>16)&255,
(pixelformat>>24)&255);
- ret = pwc_set_video_mode(pdev,
- f->fmt.pix.width,
- f->fmt.pix.height,
- fps,
- compression,
- snapshot);
+ ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
+ pdev->vframes, &compression);
PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
- if (ret)
- return ret;
-
- pdev->pixfmt = pixelformat;
-
- pwc_vidioc_fill_fmt(pdev, f);
-
- return 0;
+ if (ret == 0) {
+ pdev->pixfmt = pixelformat;
+ pwc_vidioc_fill_fmt(f, pdev->width, pdev->height,
+ pdev->pixfmt);
+ }
+leave:
+ mutex_unlock(&pdev->udevlock);
+ return ret;
}
static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
@@ -536,30 +545,14 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i)
return i ? -EINVAL : 0;
}
-static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl)
{
struct pwc_device *pdev =
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
int ret = 0;
- /*
- * Sometimes it can take quite long for the pwc to complete usb control
- * transfers, so release the modlock to give streaming by another
- * process / thread the chance to continue with a dqbuf.
- */
- mutex_unlock(&pdev->modlock);
-
- /*
- * Take the udev-lock to protect against the disconnect handler
- * completing and setting dev->udev to NULL underneath us. Other code
- * does not need to do this since it is protected by the modlock.
- */
- mutex_lock(&pdev->udevlock);
-
- if (!pdev->udev) {
- ret = -ENODEV;
- goto leave;
- }
+ if (!pdev->udev)
+ return -ENODEV;
switch (ctrl->id) {
case V4L2_CID_AUTO_WHITE_BALANCE:
@@ -624,9 +617,18 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
if (ret)
PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
-leave:
+ return ret;
+}
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct pwc_device *pdev =
+ container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+ int ret;
+
+ mutex_lock(&pdev->udevlock);
+ ret = pwc_g_volatile_ctrl_unlocked(ctrl);
mutex_unlock(&pdev->udevlock);
- mutex_lock(&pdev->modlock);
return ret;
}
@@ -643,6 +645,15 @@ static int pwc_set_awb(struct pwc_device *pdev)
if (pdev->auto_white_balance->val != awb_manual)
pdev->color_bal_valid = false; /* Force cache update */
+
+ /*
+ * If this is a preset, update our red / blue balance values
+ * so that events get generated for the new preset values
+ */
+ if (pdev->auto_white_balance->val == awb_indoor ||
+ pdev->auto_white_balance->val == awb_outdoor ||
+ pdev->auto_white_balance->val == awb_fl)
+ pwc_g_volatile_ctrl_unlocked(pdev->auto_white_balance);
}
if (pdev->auto_white_balance->val != awb_manual)
return 0;
@@ -806,8 +817,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
container_of(ctrl->handler, struct pwc_device, ctrl_handler);
int ret = 0;
- /* See the comments on locking in pwc_g_volatile_ctrl */
- mutex_unlock(&pdev->modlock);
mutex_lock(&pdev->udevlock);
if (!pdev->udev) {
@@ -891,6 +900,16 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
ret = pwc_button_ctrl(pdev,
RESTORE_FACTORY_DEFAULTS_FORMATTER);
break;
+ case PWC_CID_CUSTOM(awb_speed):
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ AWB_CONTROL_SPEED_FORMATTER,
+ ctrl->val);
+ break;
+ case PWC_CID_CUSTOM(awb_delay):
+ ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+ AWB_CONTROL_DELAY_FORMATTER,
+ ctrl->val);
+ break;
case V4L2_CID_PAN_RELATIVE:
ret = pwc_set_motor(pdev);
break;
@@ -903,7 +922,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
leave:
mutex_unlock(&pdev->udevlock);
- mutex_lock(&pdev->modlock);
return ret;
}
@@ -933,9 +951,14 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
{
struct pwc_device *pdev = video_drvdata(file);
+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */
PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
- pdev->image.x, pdev->image.y);
- pwc_vidioc_fill_fmt(pdev, f);
+ pdev->width, pdev->height);
+ pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+ mutex_unlock(&pdev->udevlock);
return 0;
}
@@ -951,12 +974,9 @@ static int pwc_reqbufs(struct file *file, void *fh,
{
struct pwc_device *pdev = video_drvdata(file);
- if (pdev->capt_file != NULL &&
- pdev->capt_file != file)
+ if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;
- pdev->capt_file = file;
-
return vb2_reqbufs(&pdev->vb_queue, rb);
}
@@ -1025,25 +1045,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh,
struct pwc_device *pdev = video_drvdata(file);
unsigned int i = 0, index = fsize->index;
- if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
+ if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
+ (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
+ DEVICE_USE_CODEC1(pdev->type)) ||
+ (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
+ DEVICE_USE_CODEC23(pdev->type))) {
for (i = 0; i < PSZ_MAX; i++) {
- if (pdev->image_mask & (1UL << i)) {
- if (!index--) {
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete.width = pwc_image_sizes[i].x;
- fsize->discrete.height = pwc_image_sizes[i].y;
- return 0;
- }
+ if (!(pdev->image_mask & (1UL << i)))
+ continue;
+ if (!index--) {
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = pwc_image_sizes[i][0];
+ fsize->discrete.height = pwc_image_sizes[i][1];
+ return 0;
}
}
- } else if (fsize->index == 0 &&
- ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
- (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
-
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete.width = pdev->abs_max.x;
- fsize->discrete.height = pdev->abs_max.y;
- return 0;
}
return -EINVAL;
}
@@ -1056,8 +1072,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
unsigned int i;
for (i = 0; i < PSZ_MAX; i++) {
- if (pwc_image_sizes[i].x == fival->width &&
- pwc_image_sizes[i].y == fival->height) {
+ if (pwc_image_sizes[i][0] == fival->width &&
+ pwc_image_sizes[i][1] == fival->height) {
size = i;
break;
}
@@ -1086,14 +1102,6 @@ static int pwc_log_status(struct file *file, void *priv)
return 0;
}
-static long pwc_default(struct file *file, void *fh, bool valid_prio,
- int cmd, void *arg)
-{
- struct pwc_device *pdev = video_drvdata(file);
-
- return pwc_ioctl(pdev, cmd, arg);
-}
-
const struct v4l2_ioctl_ops pwc_ioctl_ops = {
.vidioc_querycap = pwc_querycap,
.vidioc_enum_input = pwc_enum_input,
@@ -1112,8 +1120,4 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
.vidioc_log_status = pwc_log_status,
.vidioc_enum_framesizes = pwc_enum_framesizes,
.vidioc_enum_frameintervals = pwc_enum_frameintervals,
- .vidioc_default = pwc_default,
};
-
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 0e4e2d7..47c518f 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -35,15 +35,16 @@
#include <asm/errno.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.h>
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
#include <linux/input.h>
#endif
-#include <media/pwc-ioctl.h>
-
/* Version block */
#define PWC_VERSION "10.0.15"
#define PWC_NAME "pwc"
@@ -106,6 +107,9 @@
#define FEATURE_CODEC1 0x0002
#define FEATURE_CODEC2 0x0004
+#define MAX_WIDTH 640
+#define MAX_HEIGHT 480
+
/* Ignore errors in the first N frames, to allow for startup delays */
#define FRAME_LOWMARK 5
@@ -186,6 +190,24 @@
#define PT_RESET_CONTROL_FORMATTER 0x02
#define PT_STATUS_FORMATTER 0x03
+/* Enumeration of image sizes */
+#define PSZ_SQCIF 0x00
+#define PSZ_QSIF 0x01
+#define PSZ_QCIF 0x02
+#define PSZ_SIF 0x03
+#define PSZ_CIF 0x04
+#define PSZ_VGA 0x05
+#define PSZ_MAX 6
+
+struct pwc_raw_frame {
+ __le16 type; /* type of the webcam */
+ __le16 vbandlength; /* Size of 4 lines compressed (used by the
+ decompressor) */
+ __u8 cmd[4]; /* the four byte of the command (in case of
+ nala, only the first 3 bytes is filled) */
+ __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */
+} __packed;
+
/* intermediate buffers with raw data from the USB cam */
struct pwc_frame_buf
{
@@ -198,33 +220,30 @@ struct pwc_frame_buf
struct pwc_device
{
struct video_device vdev;
- struct mutex modlock;
+ struct v4l2_device v4l2_dev;
/* Pointer to our usb_device, may be NULL after unplug */
struct usb_device *udev;
- /* Protects the setting of udev to NULL by our disconnect handler */
struct mutex udevlock;
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int type;
int release; /* release number */
int features; /* feature bits */
- char serial[30]; /* serial number (string) */
/*** Video data ***/
struct file *capt_file; /* file doing video capture */
+ struct mutex capt_file_lock;
int vendpoint; /* video isoc endpoint */
int vcinterface; /* video control interface */
int valternate; /* alternate interface needed */
- int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
+ int vframes; /* frames-per-second */
int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
int vframe_count; /* received frames */
int vmax_packet_size; /* USB maxpacket size */
int vlast_packet_size; /* for frame synchronisation */
int visoc_errors; /* number of contiguous ISOC errors */
- int vcompression; /* desired compression factor */
int vbandlength; /* compressed band length; 0 is uncompressed */
- char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */
char power_save; /* Do powersaving for this cam */
@@ -262,21 +281,8 @@ struct pwc_device
* a gray or black border. view_min <= image <= view <= view_max;
*/
int image_mask; /* supported sizes */
- struct pwc_coord view_min, view_max; /* minimum and maximum view */
- struct pwc_coord abs_max; /* maximum supported size */
- struct pwc_coord image, view; /* image and viewport size */
- struct pwc_coord offset; /* offset of the viewport */
-
- /*** motorized pan/tilt feature */
- struct pwc_mpt_range angle_range;
- int pan_angle; /* in degrees * 100 */
- int tilt_angle; /* absolute angle; 0,0 is home */
+ int width, height; /* current resolution */
- /*
- * Set to 1 when the user push the button, reset to 0
- * when this value is read from sysfs.
- */
- int snapshot_button_status;
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
struct input_dev *button_dev; /* webcam snapshot button input */
char button_phys[64];
@@ -328,6 +334,8 @@ struct pwc_device
struct v4l2_ctrl *save_user;
struct v4l2_ctrl *restore_user;
struct v4l2_ctrl *restore_factory;
+ struct v4l2_ctrl *awb_speed;
+ struct v4l2_ctrl *awb_delay;
struct {
/* motor control cluster */
struct v4l2_ctrl *motor_pan;
@@ -344,19 +352,20 @@ struct pwc_device
extern int pwc_trace;
#endif
+int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file);
+
/** Functions in pwc-misc.c */
/* sizes in pixels */
-extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
+extern const int pwc_image_sizes[PSZ_MAX][2];
-int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+int pwc_get_size(struct pwc_device *pdev, int width, int height);
void pwc_construct(struct pwc_device *pdev);
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
-extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+ int frames, int *compression);
extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
-extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
-extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
extern int send_control_msg(struct pwc_device *pdev,
@@ -375,9 +384,6 @@ int pwc_init_controls(struct pwc_device *pdev);
/* Power down or up the camera; not supported by all models */
extern void pwc_camera_power(struct pwc_device *pdev, int power);
-/* Private ioctl()s; see pwc-ioctl.h */
-extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
-
extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
/** pwc-uncompress.c */
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 79fb22c..0bd7da2 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1133,12 +1133,13 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd,
__raw_writel(cicr0, pcdev->base + CICR0);
}
-static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+static int pxa_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct pxa_camera_dev *pcdev = ici->priv;
struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
+ u32 pixfmt = icd->current_fmt->host_fmt->fourcc;
unsigned long bus_flags, common_flags;
int ret;
struct pxa_cam *cam = icd->host_priv;
@@ -1851,19 +1852,7 @@ static struct platform_driver pxa_camera_driver = {
.remove = __devexit_p(pxa_camera_remove),
};
-
-static int __init pxa_camera_init(void)
-{
- return platform_driver_register(&pxa_camera_driver);
-}
-
-static void __exit pxa_camera_exit(void)
-{
- platform_driver_unregister(&pxa_camera_driver);
-}
-
-module_init(pxa_camera_init);
-module_exit(pxa_camera_exit);
+module_platform_driver(pxa_camera_driver);
MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 2cc3b91..510cfab 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -63,6 +63,8 @@ static int fimc_init_capture(struct fimc_dev *fimc)
fimc_hw_set_effect(ctx, false);
fimc_hw_set_output_path(ctx);
fimc_hw_set_out_dma(ctx);
+ if (fimc->variant->has_alpha)
+ fimc_hw_set_rgb_alpha(ctx);
clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
}
spin_unlock_irqrestore(&fimc->slock, flags);
@@ -154,6 +156,8 @@ int fimc_capture_config_update(struct fimc_ctx *ctx)
fimc_hw_set_rotation(ctx);
fimc_prepare_dma_offset(ctx, &ctx->d_frame);
fimc_hw_set_out_dma(ctx);
+ if (fimc->variant->has_alpha)
+ fimc_hw_set_rgb_alpha(ctx);
clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
}
spin_unlock(&ctx->slock);
@@ -812,6 +816,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
FIMC_SD_PAD_SOURCE);
if (!ff->fmt)
return -EINVAL;
+
+ /* Update RGB Alpha control state and value range */
+ fimc_alpha_ctrl_update(ctx);
+
/* Try to match format at the host and the sensor */
if (!fimc->vid_cap.user_subdev_api) {
mf->code = ff->fmt->mbus_code;
@@ -1235,6 +1243,9 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
*mf = fmt->format;
return 0;
}
+ /* Update RGB Alpha control state and value range */
+ fimc_alpha_ctrl_update(ctx);
+
fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
ff = fmt->pad == FIMC_SD_PAD_SINK ?
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 07c6254..f5cbb8a 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -52,13 +52,29 @@ static struct fimc_fmt fimc_formats[] = {
.colplanes = 1,
.flags = FMT_FLAGS_M2M,
}, {
- .name = "XRGB-8-8-8-8, 32 bpp",
+ .name = "ARGB8888, 32 bpp",
.fourcc = V4L2_PIX_FMT_RGB32,
.depth = { 32 },
.color = S5P_FIMC_RGB888,
.memplanes = 1,
.colplanes = 1,
- .flags = FMT_FLAGS_M2M,
+ .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA,
+ }, {
+ .name = "ARGB1555",
+ .fourcc = V4L2_PIX_FMT_RGB555,
+ .depth = { 16 },
+ .color = S5P_FIMC_RGB555,
+ .memplanes = 1,
+ .colplanes = 1,
+ .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
+ }, {
+ .name = "ARGB4444",
+ .fourcc = V4L2_PIX_FMT_RGB444,
+ .depth = { 16 },
+ .color = S5P_FIMC_RGB444,
+ .memplanes = 1,
+ .colplanes = 1,
+ .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
}, {
.name = "YUV 4:2:2 packed, YCbYCr",
.fourcc = V4L2_PIX_FMT_YUYV,
@@ -171,6 +187,14 @@ static struct fimc_fmt fimc_formats[] = {
},
};
+static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
+{
+ if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return FMT_FLAGS_M2M_IN;
+ else
+ return FMT_FLAGS_M2M_OUT;
+}
+
int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh,
int dw, int dh, int rotation)
{
@@ -652,8 +676,11 @@ static void fimc_dma_run(void *priv)
if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS))
fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1);
- if (ctx->state & FIMC_PARAMS)
+ if (ctx->state & FIMC_PARAMS) {
fimc_hw_set_out_dma(ctx);
+ if (fimc->variant->has_alpha)
+ fimc_hw_set_rgb_alpha(ctx);
+ }
fimc_activate_capture(ctx);
@@ -750,12 +777,11 @@ static struct vb2_ops fimc_qops = {
#define ctrl_to_ctx(__ctrl) \
container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler)
-static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl)
{
- struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
struct fimc_dev *fimc = ctx->fimc_dev;
struct samsung_fimc_variant *variant = fimc->variant;
- unsigned long flags;
+ unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT;
int ret = 0;
if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
@@ -763,52 +789,63 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_HFLIP:
- spin_lock_irqsave(&ctx->slock, flags);
ctx->hflip = ctrl->val;
break;
case V4L2_CID_VFLIP:
- spin_lock_irqsave(&ctx->slock, flags);
ctx->vflip = ctrl->val;
break;
case V4L2_CID_ROTATE:
if (fimc_capture_pending(fimc) ||
- fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+ (ctx->state & flags) == flags) {
ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
ctx->s_frame.height, ctx->d_frame.width,
ctx->d_frame.height, ctrl->val);
- }
- if (ret) {
- v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
- return -EINVAL;
+ if (ret)
+ return -EINVAL;
}
if ((ctrl->val == 90 || ctrl->val == 270) &&
!variant->has_out_rot)
return -EINVAL;
- spin_lock_irqsave(&ctx->slock, flags);
+
ctx->rotation = ctrl->val;
break;
- default:
- v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id);
- return -EINVAL;
+ case V4L2_CID_ALPHA_COMPONENT:
+ ctx->d_frame.alpha = ctrl->val;
+ break;
}
ctx->state |= FIMC_PARAMS;
set_bit(ST_CAPT_APPLY_CFG, &fimc->state);
- spin_unlock_irqrestore(&ctx->slock, flags);
return 0;
}
+static int fimc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct fimc_ctx *ctx = ctrl_to_ctx(ctrl);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&ctx->slock, flags);
+ ret = __fimc_s_ctrl(ctx, ctrl);
+ spin_unlock_irqrestore(&ctx->slock, flags);
+
+ return ret;
+}
+
static const struct v4l2_ctrl_ops fimc_ctrl_ops = {
.s_ctrl = fimc_s_ctrl,
};
int fimc_ctrls_create(struct fimc_ctx *ctx)
{
+ struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+ unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
if (ctx->ctrls_rdy)
return 0;
- v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4);
ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
@@ -816,6 +853,13 @@ int fimc_ctrls_create(struct fimc_ctx *ctx)
V4L2_CID_VFLIP, 0, 1, 1, 0);
ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
V4L2_CID_ROTATE, 0, 270, 90, 0);
+ if (variant->has_alpha)
+ ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+ &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, max_alpha, 1, 0);
+ else
+ ctx->ctrl_alpha = NULL;
+
ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
return ctx->ctrl_handler.error;
@@ -826,11 +870,14 @@ void fimc_ctrls_delete(struct fimc_ctx *ctx)
if (ctx->ctrls_rdy) {
v4l2_ctrl_handler_free(&ctx->ctrl_handler);
ctx->ctrls_rdy = false;
+ ctx->ctrl_alpha = NULL;
}
}
void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
{
+ unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA;
+
if (!ctx->ctrls_rdy)
return;
@@ -838,6 +885,8 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
v4l2_ctrl_activate(ctx->ctrl_rotate, active);
v4l2_ctrl_activate(ctx->ctrl_hflip, active);
v4l2_ctrl_activate(ctx->ctrl_vflip, active);
+ if (ctx->ctrl_alpha)
+ v4l2_ctrl_activate(ctx->ctrl_alpha, active && has_alpha);
if (active) {
ctx->rotation = ctx->ctrl_rotate->val;
@@ -851,6 +900,24 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active)
mutex_unlock(&ctx->ctrl_handler.lock);
}
+/* Update maximum value of the alpha color control */
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *fimc = ctx->fimc_dev;
+ struct v4l2_ctrl *ctrl = ctx->ctrl_alpha;
+
+ if (ctrl == NULL || !fimc->variant->has_alpha)
+ return;
+
+ v4l2_ctrl_lock(ctrl);
+ ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt);
+
+ if (ctrl->cur.val > ctrl->maximum)
+ ctrl->cur.val = ctrl->maximum;
+
+ v4l2_ctrl_unlock(ctrl);
+}
+
/*
* V4L2 ioctl handlers
*/
@@ -874,7 +941,8 @@ static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
{
struct fimc_fmt *fmt;
- fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index);
+ fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
+ f->index);
if (!fmt)
return -EINVAL;
@@ -938,6 +1006,7 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
pix->colorspace = V4L2_COLORSPACE_JPEG;
pix->field = V4L2_FIELD_NONE;
pix->num_planes = fmt->memplanes;
+ pix->pixelformat = fmt->fourcc;
pix->height = height;
pix->width = width;
@@ -1017,7 +1086,8 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
dbg("w: %d, h: %d", pix->width, pix->height);
- fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0);
+ fmt = fimc_find_format(&pix->pixelformat, NULL,
+ get_m2m_fmt_flags(f->type), 0);
if (WARN(fmt == NULL, "Pixel format lookup failed"))
return -EINVAL;
@@ -1087,10 +1157,13 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
pix = &f->fmt.pix_mp;
frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
- FMT_FLAGS_M2M, 0);
+ get_m2m_fmt_flags(f->type), 0);
if (!frame->fmt)
return -EINVAL;
+ /* Update RGB Alpha control state and value range */
+ fimc_alpha_ctrl_update(ctx);
+
for (i = 0; i < frame->fmt->colplanes; i++) {
frame->payload[i] =
(pix->width * pix->height * frame->fmt->depth[i]) / 8;
@@ -1374,6 +1447,12 @@ static int fimc_m2m_open(struct file *file)
if (!ctx)
return -ENOMEM;
v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+ ctx->fimc_dev = fimc;
+
+ /* Default color format */
+ ctx->s_frame.fmt = &fimc_formats[0];
+ ctx->d_frame.fmt = &fimc_formats[0];
+
ret = fimc_ctrls_create(ctx);
if (ret)
goto error_fh;
@@ -1383,10 +1462,6 @@ static int fimc_m2m_open(struct file *file)
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
- ctx->fimc_dev = fimc;
- /* Default color format */
- ctx->s_frame.fmt = &fimc_formats[0];
- ctx->d_frame.fmt = &fimc_formats[0];
/* Setup the device context for memory-to-memory mode */
ctx->state = FIMC_CTX_M2M;
ctx->flags = 0;
@@ -1709,9 +1784,8 @@ static int fimc_runtime_resume(struct device *dev)
/* Resume the capture or mem-to-mem device */
if (fimc_capture_busy(fimc))
return fimc_capture_resume(fimc);
- else if (fimc_m2m_pending(fimc))
- return fimc_m2m_resume(fimc);
- return 0;
+
+ return fimc_m2m_resume(fimc);
}
static int fimc_runtime_suspend(struct device *dev)
@@ -1893,6 +1967,7 @@ static struct samsung_fimc_variant fimc0_variant_exynos4 = {
.has_cam_if = 1,
.has_cistatus2 = 1,
.has_mainscaler_ext = 1,
+ .has_alpha = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
.hor_offs_align = 2,
@@ -1906,6 +1981,7 @@ static struct samsung_fimc_variant fimc3_variant_exynos4 = {
.has_cam_if = 1,
.has_cistatus2 = 1,
.has_mainscaler_ext = 1,
+ .has_alpha = 1,
.min_inp_pixsize = 16,
.min_out_pixsize = 16,
.hor_offs_align = 2,
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index c7f01c4..4e20560 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -85,7 +85,9 @@ enum fimc_datapath {
};
enum fimc_color_fmt {
- S5P_FIMC_RGB565 = 0x10,
+ S5P_FIMC_RGB444 = 0x10,
+ S5P_FIMC_RGB555,
+ S5P_FIMC_RGB565,
S5P_FIMC_RGB666,
S5P_FIMC_RGB888,
S5P_FIMC_RGB30_LOCAL,
@@ -160,8 +162,11 @@ struct fimc_fmt {
u16 colplanes;
u8 depth[VIDEO_MAX_PLANES];
u16 flags;
-#define FMT_FLAGS_CAM (1 << 0)
-#define FMT_FLAGS_M2M (1 << 1)
+#define FMT_FLAGS_CAM (1 << 0)
+#define FMT_FLAGS_M2M_IN (1 << 1)
+#define FMT_FLAGS_M2M_OUT (1 << 2)
+#define FMT_FLAGS_M2M (1 << 1 | 1 << 2)
+#define FMT_HAS_ALPHA (1 << 3)
};
/**
@@ -283,6 +288,7 @@ struct fimc_frame {
struct fimc_addr paddr;
struct fimc_dma_offset dma_offset;
struct fimc_fmt *fmt;
+ u8 alpha;
};
/**
@@ -387,6 +393,7 @@ struct samsung_fimc_variant {
unsigned int has_cistatus2:1;
unsigned int has_mainscaler_ext:1;
unsigned int has_cam_if:1;
+ unsigned int has_alpha:1;
struct fimc_pix_limit *pix_limit;
u16 min_inp_pixsize;
u16 min_out_pixsize;
@@ -482,7 +489,8 @@ struct fimc_dev {
* @ctrl_handler: v4l2 controls handler
* @ctrl_rotate image rotation control
* @ctrl_hflip horizontal flip control
- * @ctrl_vflip vartical flip control
+ * @ctrl_vflip vertical flip control
+ * @ctrl_alpha RGB alpha control
* @ctrls_rdy: true if the control handler is initialized
*/
struct fimc_ctx {
@@ -509,6 +517,7 @@ struct fimc_ctx {
struct v4l2_ctrl *ctrl_rotate;
struct v4l2_ctrl *ctrl_hflip;
struct v4l2_ctrl *ctrl_vflip;
+ struct v4l2_ctrl *ctrl_alpha;
bool ctrls_rdy;
};
@@ -578,6 +587,17 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
}
+/* Return the alpha component bit mask */
+static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
+{
+ switch (fmt->color) {
+ case S5P_FIMC_RGB444: return 0x0f;
+ case S5P_FIMC_RGB555: return 0x01;
+ case S5P_FIMC_RGB888: return 0xff;
+ default: return 0;
+ };
+}
+
static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
{
u32 cfg = readl(dev->regs + S5P_CIGCTRL);
@@ -674,6 +694,7 @@ void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
void fimc_hw_en_capture(struct fimc_ctx *ctx);
void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active);
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx);
void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
void fimc_hw_set_input_path(struct fimc_ctx *ctx);
void fimc_hw_set_output_path(struct fimc_ctx *ctx);
@@ -695,6 +716,7 @@ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
int fimc_ctrls_create(struct fimc_ctx *ctx);
void fimc_ctrls_delete(struct fimc_ctx *ctx);
void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active);
+void fimc_alpha_ctrl_update(struct fimc_ctx *ctx);
int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f);
void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height,
struct v4l2_pix_format_mplane *pix);
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 44f5c2d..15466d0 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -117,7 +117,7 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
S5P_CITRGFMT_VSIZE_MASK);
switch (frame->fmt->color) {
- case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
+ case S5P_FIMC_RGB444...S5P_FIMC_RGB888:
cfg |= S5P_CITRGFMT_RGB;
break;
case S5P_FIMC_YCBCR420:
@@ -175,6 +175,7 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
struct fimc_dev *dev = ctx->fimc_dev;
struct fimc_frame *frame = &ctx->d_frame;
struct fimc_dma_offset *offset = &frame->dma_offset;
+ struct fimc_fmt *fmt = frame->fmt;
/* Set the input dma offsets. */
cfg = 0;
@@ -198,15 +199,22 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx)
cfg = readl(dev->regs + S5P_CIOCTRL);
cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
- S5P_CIOCTRL_YCBCR_PLANE_MASK);
+ S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK);
- if (frame->fmt->colplanes == 1)
+ if (fmt->colplanes == 1)
cfg |= ctx->out_order_1p;
- else if (frame->fmt->colplanes == 2)
+ else if (fmt->colplanes == 2)
cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
- else if (frame->fmt->colplanes == 3)
+ else if (fmt->colplanes == 3)
cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
+ if (fmt->color == S5P_FIMC_RGB565)
+ cfg |= S5P_CIOCTRL_RGB565;
+ else if (fmt->color == S5P_FIMC_RGB555)
+ cfg |= S5P_CIOCTRL_ARGB1555;
+ else if (fmt->color == S5P_FIMC_RGB444)
+ cfg |= S5P_CIOCTRL_ARGB4444;
+
writel(cfg, dev->regs + S5P_CIOCTRL);
}
@@ -278,22 +286,28 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
if (sc->copy_mode)
cfg |= S5P_CISCCTRL_ONE2ONE;
-
if (ctx->in_path == FIMC_DMA) {
- if (src_frame->fmt->color == S5P_FIMC_RGB565)
+ switch (src_frame->fmt->color) {
+ case S5P_FIMC_RGB565:
cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565;
- else if (src_frame->fmt->color == S5P_FIMC_RGB666)
+ break;
+ case S5P_FIMC_RGB666:
cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666;
- else if (src_frame->fmt->color == S5P_FIMC_RGB888)
+ break;
+ case S5P_FIMC_RGB888:
cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888;
+ break;
+ }
}
if (ctx->out_path == FIMC_DMA) {
- if (dst_frame->fmt->color == S5P_FIMC_RGB565)
+ u32 color = dst_frame->fmt->color;
+
+ if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565)
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565;
- else if (dst_frame->fmt->color == S5P_FIMC_RGB666)
+ else if (color == S5P_FIMC_RGB666)
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666;
- else if (dst_frame->fmt->color == S5P_FIMC_RGB888)
+ else if (color == S5P_FIMC_RGB888)
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
} else {
cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888;
@@ -379,6 +393,21 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active)
writel(cfg, dev->regs + S5P_CIIMGEFF);
}
+void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx)
+{
+ struct fimc_dev *dev = ctx->fimc_dev;
+ struct fimc_frame *frame = &ctx->d_frame;
+ u32 cfg;
+
+ if (!(frame->fmt->flags & FMT_HAS_ALPHA))
+ return;
+
+ cfg = readl(dev->regs + S5P_CIOCTRL);
+ cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK;
+ cfg |= (frame->alpha << 4);
+ writel(cfg, dev->regs + S5P_CIOCTRL);
+}
+
static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx)
{
struct fimc_dev *dev = ctx->fimc_dev;
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index 59d79bc..130335c 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.c
+++ b/drivers/media/video/s5p-fimc/mipi-csis.c
@@ -427,6 +427,23 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
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);
+
+ format->colorspace = V4L2_COLORSPACE_JPEG;
+ format->code = s5pcsis_formats[0].code;
+ format->width = S5PCSIS_DEF_PIX_WIDTH;
+ format->height = S5PCSIS_DEF_PIX_HEIGHT;
+ format->field = V4L2_FIELD_NONE;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
+ .open = s5pcsis_open,
+};
+
static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
.s_power = s5pcsis_s_power,
};
@@ -544,8 +561,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
state->sd.owner = THIS_MODULE;
strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
+ state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
state->csis_fmt = &s5pcsis_formats[0];
+ state->format.code = s5pcsis_formats[0].code;
+ state->format.width = S5PCSIS_DEF_PIX_WIDTH;
+ state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
+
state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&state->sd.entity,
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.h b/drivers/media/video/s5p-fimc/mipi-csis.h
index f569133..2709286 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.h
+++ b/drivers/media/video/s5p-fimc/mipi-csis.h
@@ -19,4 +19,7 @@
#define CSIS_PAD_SOURCE 1
#define CSIS_PADS_NUM 2
+#define S5PCSIS_DEF_PIX_WIDTH 640
+#define S5PCSIS_DEF_PIX_HEIGHT 480
+
#endif
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h
index c8e3b94..c7a5bc5 100644
--- a/drivers/media/video/s5p-fimc/regs-fimc.h
+++ b/drivers/media/video/s5p-fimc/regs-fimc.h
@@ -107,6 +107,11 @@
#define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3)
#define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3)
#define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
+#define S5P_CIOCTRL_ALPHA_OUT_MASK (0xff << 4)
+#define S5P_CIOCTRL_RGB16FMT_MASK (3 << 16)
+#define S5P_CIOCTRL_RGB565 (0 << 16)
+#define S5P_CIOCTRL_ARGB1555 (1 << 16)
+#define S5P_CIOCTRL_ARGB4444 (2 << 16)
#define S5P_CIOCTRL_ORDER2P_SHIFT (24)
#define S5P_CIOCTRL_ORDER2P_MASK (3 << 24)
#define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24)
diff --git a/drivers/media/video/s5p-g2d/Makefile b/drivers/media/video/s5p-g2d/Makefile
new file mode 100644
index 0000000..2c48c41
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/Makefile
@@ -0,0 +1,3 @@
+s5p-g2d-objs := g2d.o g2d-hw.o
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d.o
diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/video/s5p-g2d/g2d-hw.c
new file mode 100644
index 0000000..39937cf
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/g2d-hw.c
@@ -0,0 +1,104 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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/io.h>
+
+#include "g2d.h"
+#include "g2d-regs.h"
+
+#define w(x, a) writel((x), d->regs + (a))
+#define r(a) readl(d->regs + (a))
+
+/* g2d_reset clears all g2d registers */
+void g2d_reset(struct g2d_dev *d)
+{
+ w(1, SOFT_RESET_REG);
+}
+
+void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f)
+{
+ u32 n;
+
+ w(f->stride & 0xFFFF, SRC_STRIDE_REG);
+
+ n = f->o_height & 0xFFF;
+ n <<= 16;
+ n |= f->o_width & 0xFFF;
+ w(n, SRC_LEFT_TOP_REG);
+
+ n = f->bottom & 0xFFF;
+ n <<= 16;
+ n |= f->right & 0xFFF;
+ w(n, SRC_RIGHT_BOTTOM_REG);
+
+ w(f->fmt->hw, SRC_COLOR_MODE_REG);
+}
+
+void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a)
+{
+ w(a, SRC_BASE_ADDR_REG);
+}
+
+void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
+{
+ u32 n;
+
+ w(f->stride & 0xFFFF, DST_STRIDE_REG);
+
+ n = f->o_height & 0xFFF;
+ n <<= 16;
+ n |= f->o_width & 0xFFF;
+ w(n, DST_LEFT_TOP_REG);
+
+ n = f->bottom & 0xFFF;
+ n <<= 16;
+ n |= f->right & 0xFFF;
+ w(n, DST_RIGHT_BOTTOM_REG);
+
+ w(f->fmt->hw, DST_COLOR_MODE_REG);
+}
+
+void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a)
+{
+ w(a, DST_BASE_ADDR_REG);
+}
+
+void g2d_set_rop4(struct g2d_dev *d, u32 r)
+{
+ w(r, ROP4_REG);
+}
+
+u32 g2d_cmd_stretch(u32 e)
+{
+ e &= 1;
+ return e << 4;
+}
+
+void g2d_set_cmd(struct g2d_dev *d, u32 c)
+{
+ w(c, BITBLT_COMMAND_REG);
+}
+
+void g2d_start(struct g2d_dev *d)
+{
+ /* Clear cache */
+ w(0x7, CACHECTL_REG);
+ /* Enable interrupt */
+ w(1, INTEN_REG);
+ /* Start G2D engine */
+ w(1, BITBLT_START_REG);
+}
+
+void g2d_clear_int(struct g2d_dev *d)
+{
+ w(1, INTC_PEND_REG);
+}
diff --git a/drivers/media/video/s5p-g2d/g2d-regs.h b/drivers/media/video/s5p-g2d/g2d-regs.h
new file mode 100644
index 0000000..02e1cf5
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/g2d-regs.h
@@ -0,0 +1,115 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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
+ */
+
+/* General Registers */
+#define SOFT_RESET_REG 0x0000 /* Software reset reg */
+#define INTEN_REG 0x0004 /* Interrupt Enable reg */
+#define INTC_PEND_REG 0x000C /* Interrupt Control Pending reg */
+#define FIFO_STAT_REG 0x0010 /* Command FIFO Status reg */
+#define AXI_ID_MODE_REG 0x0014 /* AXI Read ID Mode reg */
+#define CACHECTL_REG 0x0018 /* Cache & Buffer clear reg */
+#define AXI_MODE_REG 0x001C /* AXI Mode reg */
+
+/* Command Registers */
+#define BITBLT_START_REG 0x0100 /* BitBLT Start reg */
+#define BITBLT_COMMAND_REG 0x0104 /* Command reg for BitBLT */
+
+/* Parameter Setting Registers (Rotate & Direction) */
+#define ROTATE_REG 0x0200 /* Rotation reg */
+#define SRC_MSK_DIRECT_REG 0x0204 /* Src and Mask Direction reg */
+#define DST_PAT_DIRECT_REG 0x0208 /* Dest and Pattern Direction reg */
+
+/* Parameter Setting Registers (Src) */
+#define SRC_SELECT_REG 0x0300 /* Src Image Selection reg */
+#define SRC_BASE_ADDR_REG 0x0304 /* Src Image Base Address reg */
+#define SRC_STRIDE_REG 0x0308 /* Src Stride reg */
+#define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */
+#define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */
+#define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */
+
+/* Parameter Setting Registers (Dest) */
+#define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */
+#define DST_BASE_ADDR_REG 0x0404 /* Dest Image Base Address reg */
+#define DST_STRIDE_REG 0x0408 /* Dest Stride reg */
+#define DST_COLOR_MODE_REG 0x040C /* Dest Image Color Mode reg */
+#define DST_LEFT_TOP_REG 0x0410 /* Dest Left Top Coordinate reg */
+#define DST_RIGHT_BOTTOM_REG 0x0414 /* Dest Right Bottom Coordinate reg */
+
+/* Parameter Setting Registers (Pattern) */
+#define PAT_BASE_ADDR_REG 0x0500 /* Pattern Image Base Address reg */
+#define PAT_SIZE_REG 0x0504 /* Pattern Image Size reg */
+#define PAT_COLOR_MODE_REG 0x0508 /* Pattern Image Color Mode reg */
+#define PAT_OFFSET_REG 0x050C /* Pattern Left Top Coordinate reg */
+#define PAT_STRIDE_REG 0x0510 /* Pattern Stride reg */
+
+/* Parameter Setting Registers (Mask) */
+#define MASK_BASE_ADDR_REG 0x0520 /* Mask Base Address reg */
+#define MASK_STRIDE_REG 0x0524 /* Mask Stride reg */
+
+/* Parameter Setting Registers (Clipping Window) */
+#define CW_LT_REG 0x0600 /* LeftTop coordinates of Clip Window */
+#define CW_RB_REG 0x0604 /* RightBottom coordinates of Clip
+ Window */
+
+/* Parameter Setting Registers (ROP & Alpha Setting) */
+#define THIRD_OPERAND_REG 0x0610 /* Third Operand Selection reg */
+#define ROP4_REG 0x0614 /* Raster Operation reg */
+#define ALPHA_REG 0x0618 /* Alpha value, Fading offset value */
+
+/* Parameter Setting Registers (Color) */
+#define FG_COLOR_REG 0x0700 /* Foreground Color reg */
+#define BG_COLOR_REG 0x0704 /* Background Color reg */
+#define BS_COLOR_REG 0x0708 /* Blue Screen Color reg */
+
+/* Parameter Setting Registers (Color Key) */
+#define SRC_COLORKEY_CTRL_REG 0x0710 /* Src Colorkey control reg */
+#define SRC_COLORKEY_DR_MIN_REG 0x0714 /* Src Colorkey Decision Reference
+ Min reg */
+#define SRC_COLORKEY_DR_MAX_REG 0x0718 /* Src Colorkey Decision Reference
+ Max reg */
+#define DST_COLORKEY_CTRL_REG 0x071C /* Dest Colorkey control reg */
+#define DST_COLORKEY_DR_MIN_REG 0x0720 /* Dest Colorkey Decision Reference
+ Min reg */
+#define DST_COLORKEY_DR_MAX_REG 0x0724 /* Dest Colorkey Decision Reference
+ Max reg */
+
+/* Color mode values */
+
+#define ORDER_XRGB 0
+#define ORDER_RGBX 1
+#define ORDER_XBGR 2
+#define ORDER_BGRX 3
+
+#define MODE_XRGB_8888 0
+#define MODE_ARGB_8888 1
+#define MODE_RGB_565 2
+#define MODE_XRGB_1555 3
+#define MODE_ARGB_1555 4
+#define MODE_XRGB_4444 5
+#define MODE_ARGB_4444 6
+#define MODE_PACKED_RGB_888 7
+
+#define COLOR_MODE(o, m) (((o) << 4) | (m))
+
+/* ROP4 operation values */
+#define ROP4_COPY 0xCCCC
+#define ROP4_INVERT 0x3333
+
+/* Hardware limits */
+#define MAX_WIDTH 8000
+#define MAX_HEIGHT 8000
+
+#define G2D_TIMEOUT 500
+
+#define DEFAULT_WIDTH 100
+#define DEFAULT_HEIGHT 100
+
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
new file mode 100644
index 0000000..c40b0dd
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/g2d.c
@@ -0,0 +1,810 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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/fs.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "g2d.h"
+#include "g2d-regs.h"
+
+#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh)
+
+static struct g2d_fmt formats[] = {
+ {
+ .name = "XRGB_8888",
+ .fourcc = V4L2_PIX_FMT_RGB32,
+ .depth = 32,
+ .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888),
+ },
+ {
+ .name = "RGB_565",
+ .fourcc = V4L2_PIX_FMT_RGB565X,
+ .depth = 16,
+ .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565),
+ },
+ {
+ .name = "XRGB_1555",
+ .fourcc = V4L2_PIX_FMT_RGB555X,
+ .depth = 16,
+ .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555),
+ },
+ {
+ .name = "XRGB_4444",
+ .fourcc = V4L2_PIX_FMT_RGB444,
+ .depth = 16,
+ .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444),
+ },
+ {
+ .name = "PACKED_RGB_888",
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .depth = 24,
+ .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888),
+ },
+};
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+struct g2d_frame def_frame = {
+ .width = DEFAULT_WIDTH,
+ .height = DEFAULT_HEIGHT,
+ .c_width = DEFAULT_WIDTH,
+ .c_height = DEFAULT_HEIGHT,
+ .o_width = 0,
+ .o_height = 0,
+ .fmt = &formats[0],
+ .right = DEFAULT_WIDTH,
+ .bottom = DEFAULT_HEIGHT,
+};
+
+struct g2d_fmt *find_fmt(struct v4l2_format *f)
+{
+ unsigned int i;
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].fourcc == f->fmt.pix.pixelformat)
+ return &formats[i];
+ }
+ return NULL;
+}
+
+
+static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
+ enum v4l2_buf_type type)
+{
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ return &ctx->in;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return &ctx->out;
+ default:
+ return ERR_PTR(-EINVAL);
+ }
+}
+
+static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct g2d_ctx *ctx = vb2_get_drv_priv(vq);
+ struct g2d_frame *f = get_frame(ctx, vq->type);
+
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+
+ sizes[0] = f->size;
+ *nplanes = 1;
+ alloc_ctxs[0] = ctx->dev->alloc_ctx;
+
+ if (*nbuffers == 0)
+ *nbuffers = 1;
+
+ return 0;
+}
+
+static int g2d_buf_prepare(struct vb2_buffer *vb)
+{
+ struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type);
+
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+ vb2_set_plane_payload(vb, 0, f->size);
+ return 0;
+}
+
+static void g2d_buf_queue(struct vb2_buffer *vb)
+{
+ struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+
+static struct vb2_ops g2d_qops = {
+ .queue_setup = g2d_queue_setup,
+ .buf_prepare = g2d_buf_prepare,
+ .buf_queue = g2d_buf_queue,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_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;
+ src_vq->ops = &g2d_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;
+ dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+ dst_vq->drv_priv = ctx;
+ dst_vq->ops = &g2d_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 g2d_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx,
+ ctrl_handler);
+ switch (ctrl->id) {
+ case V4L2_CID_COLORFX:
+ if (ctrl->val == V4L2_COLORFX_NEGATIVE)
+ ctx->rop = ROP4_INVERT;
+ else
+ ctx->rop = ROP4_COPY;
+ default:
+ v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops g2d_ctrl_ops = {
+ .s_ctrl = g2d_s_ctrl,
+};
+
+int g2d_setup_ctrls(struct g2d_ctx *ctx)
+{
+ struct g2d_dev *dev = ctx->dev;
+
+ v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1);
+ if (ctx->ctrl_handler.error) {
+ v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n");
+ return ctx->ctrl_handler.error;
+ }
+
+ v4l2_ctrl_new_std_menu(
+ &ctx->ctrl_handler,
+ &g2d_ctrl_ops,
+ V4L2_CID_COLORFX,
+ V4L2_COLORFX_NEGATIVE,
+ ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)),
+ V4L2_COLORFX_NONE);
+
+ if (ctx->ctrl_handler.error) {
+ v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n");
+ return ctx->ctrl_handler.error;
+ }
+
+ return 0;
+}
+
+static int g2d_open(struct file *file)
+{
+ struct g2d_dev *dev = video_drvdata(file);
+ struct g2d_ctx *ctx = NULL;
+ int ret = 0;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->dev = dev;
+ /* Set default formats */
+ ctx->in = def_frame;
+ ctx->out = def_frame;
+
+ 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);
+ kfree(ctx);
+ return ret;
+ }
+ v4l2_fh_init(&ctx->fh, video_devdata(file));
+ file->private_data = &ctx->fh;
+ v4l2_fh_add(&ctx->fh);
+
+ g2d_setup_ctrls(ctx);
+
+ /* Write the default values to the ctx struct */
+ v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+
+ ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+
+ v4l2_info(&dev->v4l2_dev, "instance opened\n");
+ return 0;
+}
+
+static int g2d_release(struct file *file)
+{
+ struct g2d_dev *dev = video_drvdata(file);
+ struct g2d_ctx *ctx = fh2ctx(file->private_data);
+
+ v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ kfree(ctx);
+ v4l2_info(&dev->v4l2_dev, "instance closed\n");
+ return 0;
+}
+
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
+ strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
+ cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
+ | V4L2_CAP_STREAMING;
+ return 0;
+}
+
+static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
+{
+ struct g2d_fmt *fmt;
+ if (f->index >= NUM_FORMATS)
+ return -EINVAL;
+ fmt = &formats[f->index];
+ f->pixelformat = fmt->fourcc;
+ strncpy(f->description, fmt->name, sizeof(f->description) - 1);
+ return 0;
+}
+
+static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+ struct g2d_ctx *ctx = prv;
+ struct vb2_queue *vq;
+ struct g2d_frame *frm;
+
+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+ if (!vq)
+ return -EINVAL;
+ frm = get_frame(ctx, f->type);
+ if (IS_ERR(frm))
+ return PTR_ERR(frm);
+
+ f->fmt.pix.width = frm->width;
+ f->fmt.pix.height = frm->height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = frm->fmt->fourcc;
+ f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = frm->size;
+ return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+ struct g2d_fmt *fmt;
+ enum v4l2_field *field;
+
+ fmt = find_fmt(f);
+ if (!fmt)
+ return -EINVAL;
+
+ field = &f->fmt.pix.field;
+ if (*field == V4L2_FIELD_ANY)
+ *field = V4L2_FIELD_NONE;
+ else if (*field != V4L2_FIELD_NONE)
+ return -EINVAL;
+
+ if (f->fmt.pix.width > MAX_WIDTH)
+ f->fmt.pix.width = MAX_WIDTH;
+ if (f->fmt.pix.height > MAX_HEIGHT)
+ f->fmt.pix.height = MAX_HEIGHT;
+
+ if (f->fmt.pix.width < 1)
+ f->fmt.pix.width = 1;
+ if (f->fmt.pix.height < 1)
+ f->fmt.pix.height = 1;
+
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+ return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ struct vb2_queue *vq;
+ struct g2d_frame *frm;
+ struct g2d_fmt *fmt;
+ int ret = 0;
+
+ /* Adjust all values accordingly to the hardware capabilities
+ * and chosen format. */
+ ret = vidioc_try_fmt(file, prv, f);
+ if (ret)
+ return ret;
+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+ if (vb2_is_busy(vq)) {
+ v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type);
+ return -EBUSY;
+ }
+ frm = get_frame(ctx, f->type);
+ if (IS_ERR(frm))
+ return PTR_ERR(frm);
+ fmt = find_fmt(f);
+ if (!fmt)
+ return -EINVAL;
+ frm->width = f->fmt.pix.width;
+ frm->height = f->fmt.pix.height;
+ frm->size = f->fmt.pix.sizeimage;
+ /* Reset crop settings */
+ frm->o_width = 0;
+ frm->o_height = 0;
+ frm->c_width = frm->width;
+ frm->c_height = frm->height;
+ frm->right = frm->width;
+ frm->bottom = frm->height;
+ frm->fmt = fmt;
+ frm->stride = f->fmt.pix.bytesperline;
+ return 0;
+}
+
+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);
+}
+
+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);
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct g2d_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 g2d_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 g2d_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 g2d_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 g2d_ctx *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 g2d_ctx *ctx = priv;
+ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+ struct v4l2_cropcap *cr)
+{
+ struct g2d_ctx *ctx = priv;
+ struct g2d_frame *f;
+
+ f = get_frame(ctx, cr->type);
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+
+ cr->bounds.left = 0;
+ cr->bounds.top = 0;
+ cr->bounds.width = f->width;
+ cr->bounds.height = f->height;
+ cr->defrect = cr->bounds;
+ return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_frame *f;
+
+ f = get_frame(ctx, cr->type);
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+
+ cr->c.left = f->o_height;
+ cr->c.top = f->o_width;
+ cr->c.width = f->c_width;
+ cr->c.height = f->c_height;
+ return 0;
+}
+
+static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ struct g2d_frame *f;
+
+ f = get_frame(ctx, cr->type);
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+
+ if (cr->c.top < 0 || cr->c.left < 0) {
+ v4l2_err(&dev->v4l2_dev,
+ "doesn't support negative values for top & left\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_frame *f;
+ int ret;
+
+ ret = vidioc_try_crop(file, prv, cr);
+ if (ret)
+ return ret;
+ f = get_frame(ctx, cr->type);
+ if (IS_ERR(f))
+ return PTR_ERR(f);
+
+ f->c_width = cr->c.width;
+ f->c_height = cr->c.height;
+ f->o_width = cr->c.left;
+ f->o_height = cr->c.top;
+ f->bottom = f->o_height + f->c_height;
+ f->right = f->o_width + f->c_width;
+ return 0;
+}
+
+static void g2d_lock(void *prv)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ mutex_lock(&dev->mutex);
+}
+
+static void g2d_unlock(void *prv)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ mutex_unlock(&dev->mutex);
+}
+
+static void job_abort(void *prv)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ int ret;
+
+ if (dev->curr == 0) /* No job currently running */
+ return;
+
+ ret = wait_event_timeout(dev->irq_queue,
+ dev->curr == 0,
+ msecs_to_jiffies(G2D_TIMEOUT));
+}
+
+static void device_run(void *prv)
+{
+ struct g2d_ctx *ctx = prv;
+ struct g2d_dev *dev = ctx->dev;
+ struct vb2_buffer *src, *dst;
+ u32 cmd = 0;
+
+ dev->curr = ctx;
+
+ src = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+
+ clk_enable(dev->gate);
+ g2d_reset(dev);
+
+ g2d_set_src_size(dev, &ctx->in);
+ g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0));
+
+ g2d_set_dst_size(dev, &ctx->out);
+ g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0));
+
+ g2d_set_rop4(dev, ctx->rop);
+ if (ctx->in.c_width != ctx->out.c_width ||
+ ctx->in.c_height != ctx->out.c_height)
+ cmd |= g2d_cmd_stretch(1);
+ g2d_set_cmd(dev, cmd);
+ g2d_start(dev);
+}
+
+static irqreturn_t g2d_isr(int irq, void *prv)
+{
+ struct g2d_dev *dev = prv;
+ struct g2d_ctx *ctx = dev->curr;
+ struct vb2_buffer *src, *dst;
+
+ g2d_clear_int(dev);
+ clk_disable(dev->gate);
+
+ BUG_ON(ctx == 0);
+
+ src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+ BUG_ON(src == 0);
+ BUG_ON(dst == 0);
+
+ v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
+ v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
+ v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
+
+ dev->curr = 0;
+ wake_up(&dev->irq_queue);
+ return IRQ_HANDLED;
+}
+
+static const struct v4l2_file_operations g2d_fops = {
+ .owner = THIS_MODULE,
+ .open = g2d_open,
+ .release = g2d_release,
+ .poll = g2d_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = g2d_mmap,
+};
+
+static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt,
+
+ .vidioc_enum_fmt_vid_out = vidioc_enum_fmt,
+ .vidioc_g_fmt_vid_out = vidioc_g_fmt,
+ .vidioc_try_fmt_vid_out = vidioc_try_fmt,
+ .vidioc_s_fmt_vid_out = vidioc_s_fmt,
+
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_cropcap = vidioc_cropcap,
+};
+
+static struct video_device g2d_videodev = {
+ .name = G2D_NAME,
+ .fops = &g2d_fops,
+ .ioctl_ops = &g2d_ioctl_ops,
+ .minor = -1,
+ .release = video_device_release,
+};
+
+static struct v4l2_m2m_ops g2d_m2m_ops = {
+ .device_run = device_run,
+ .job_abort = job_abort,
+ .lock = g2d_lock,
+ .unlock = g2d_unlock,
+};
+
+static int g2d_probe(struct platform_device *pdev)
+{
+ struct g2d_dev *dev;
+ struct video_device *vfd;
+ struct resource *res;
+ int ret = 0;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ spin_lock_init(&dev->irqlock);
+ mutex_init(&dev->mutex);
+ atomic_set(&dev->num_inst, 0);
+ init_waitqueue_head(&dev->irq_queue);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to find registers\n");
+ ret = -ENOENT;
+ goto free_dev;
+ }
+
+ dev->res_regs = request_mem_region(res->start, resource_size(res),
+ dev_name(&pdev->dev));
+
+ if (!dev->res_regs) {
+ dev_err(&pdev->dev, "failed to obtain register region\n");
+ ret = -ENOENT;
+ goto free_dev;
+ }
+
+ dev->regs = ioremap(res->start, resource_size(res));
+ if (!dev->regs) {
+ dev_err(&pdev->dev, "failed to map registers\n");
+ ret = -ENOENT;
+ goto rel_res_regs;
+ }
+
+ dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
+ if (IS_ERR_OR_NULL(dev->clk)) {
+ dev_err(&pdev->dev, "failed to get g2d clock\n");
+ ret = -ENXIO;
+ goto unmap_regs;
+ }
+
+ dev->gate = clk_get(&pdev->dev, "fimg2d");
+ if (IS_ERR_OR_NULL(dev->gate)) {
+ dev_err(&pdev->dev, "failed to get g2d clock gate\n");
+ ret = -ENXIO;
+ goto put_clk;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to find IRQ\n");
+ ret = -ENXIO;
+ goto put_clk_gate;
+ }
+
+ dev->irq = res->start;
+
+ ret = request_irq(dev->irq, g2d_isr, 0, pdev->name, dev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to install IRQ\n");
+ goto put_clk_gate;
+ }
+
+ dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ if (IS_ERR(dev->alloc_ctx)) {
+ ret = PTR_ERR(dev->alloc_ctx);
+ goto rel_irq;
+ }
+
+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+ if (ret)
+ goto alloc_ctx_cleanup;
+ vfd = video_device_alloc();
+ if (!vfd) {
+ v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+ ret = -ENOMEM;
+ goto unreg_v4l2_dev;
+ }
+ *vfd = g2d_videodev;
+ vfd->lock = &dev->mutex;
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+ goto rel_vdev;
+ }
+ video_set_drvdata(vfd, dev);
+ snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
+ dev->vfd = vfd;
+ v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
+ vfd->num);
+ platform_set_drvdata(pdev, dev);
+ dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
+ if (IS_ERR(dev->m2m_dev)) {
+ v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+ ret = PTR_ERR(dev->m2m_dev);
+ goto unreg_video_dev;
+ }
+
+ def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
+
+ return 0;
+
+unreg_video_dev:
+ video_unregister_device(dev->vfd);
+rel_vdev:
+ video_device_release(vfd);
+unreg_v4l2_dev:
+ v4l2_device_unregister(&dev->v4l2_dev);
+alloc_ctx_cleanup:
+ vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+rel_irq:
+ free_irq(dev->irq, dev);
+put_clk_gate:
+ clk_put(dev->gate);
+put_clk:
+ clk_put(dev->clk);
+unmap_regs:
+ iounmap(dev->regs);
+rel_res_regs:
+ release_resource(dev->res_regs);
+free_dev:
+ kfree(dev);
+ return ret;
+}
+
+static int g2d_remove(struct platform_device *pdev)
+{
+ struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev);
+
+ v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
+ v4l2_m2m_release(dev->m2m_dev);
+ video_unregister_device(dev->vfd);
+ v4l2_device_unregister(&dev->v4l2_dev);
+ vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+ free_irq(dev->irq, dev);
+ clk_put(dev->gate);
+ clk_put(dev->clk);
+ iounmap(dev->regs);
+ release_resource(dev->res_regs);
+ kfree(dev);
+ return 0;
+}
+
+static struct platform_driver g2d_pdrv = {
+ .probe = g2d_probe,
+ .remove = g2d_remove,
+ .driver = {
+ .name = G2D_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(g2d_pdrv);
+
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/video/s5p-g2d/g2d.h
new file mode 100644
index 0000000..5eae901
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/g2d.h
@@ -0,0 +1,83 @@
+/*
+ * Samsung S5P G2D - 2D Graphics Accelerator Driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.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 <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define G2D_NAME "s5p-g2d"
+
+struct g2d_dev {
+ struct v4l2_device v4l2_dev;
+ struct v4l2_m2m_dev *m2m_dev;
+ struct video_device *vfd;
+ struct mutex mutex;
+ spinlock_t irqlock;
+ atomic_t num_inst;
+ struct vb2_alloc_ctx *alloc_ctx;
+ struct resource *res_regs;
+ void __iomem *regs;
+ struct clk *clk;
+ struct clk *gate;
+ struct g2d_ctx *curr;
+ int irq;
+ wait_queue_head_t irq_queue;
+};
+
+struct g2d_frame {
+ /* Original dimensions */
+ u32 width;
+ u32 height;
+ /* Crop size */
+ u32 c_width;
+ u32 c_height;
+ /* Offset */
+ u32 o_width;
+ u32 o_height;
+ /* Image format */
+ struct g2d_fmt *fmt;
+ /* Variables that can calculated once and reused */
+ u32 stride;
+ u32 bottom;
+ u32 right;
+ u32 size;
+};
+
+struct g2d_ctx {
+ struct v4l2_fh fh;
+ struct g2d_dev *dev;
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct g2d_frame in;
+ struct g2d_frame out;
+ struct v4l2_ctrl_handler ctrl_handler;
+ u32 rop;
+};
+
+struct g2d_fmt {
+ char *name;
+ u32 fourcc;
+ int depth;
+ u32 hw;
+};
+
+
+void g2d_reset(struct g2d_dev *d);
+void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f);
+void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a);
+void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f);
+void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a);
+void g2d_start(struct g2d_dev *d);
+void g2d_clear_int(struct g2d_dev *d);
+void g2d_set_rop4(struct g2d_dev *d, u32 r);
+u32 g2d_cmd_stretch(u32 e);
+void g2d_set_cmd(struct g2d_dev *d, u32 c);
+
+
diff --git a/drivers/media/video/s5p-jpeg/Makefile b/drivers/media/video/s5p-jpeg/Makefile
new file mode 100644
index 0000000..ddc2900
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/Makefile
@@ -0,0 +1,2 @@
+s5p-jpeg-objs := jpeg-core.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) := s5p-jpeg.o
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
new file mode 100644
index 0000000..f841a3e
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -0,0 +1,1481 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw.h"
+
+static struct s5p_jpeg_fmt formats_enc[] = {
+ {
+ .name = "YUV 4:2:0 planar, YCbCr",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .colplanes = 3,
+ .types = MEM2MEM_CAPTURE,
+ },
+ {
+ .name = "YUV 4:2:2 packed, YCbYCr",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .colplanes = 1,
+ .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+ },
+ {
+ .name = "RGB565",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .depth = 16,
+ .colplanes = 1,
+ .types = MEM2MEM_OUTPUT,
+ },
+};
+#define NUM_FORMATS_ENC ARRAY_SIZE(formats_enc)
+
+static struct s5p_jpeg_fmt formats_dec[] = {
+ {
+ .name = "YUV 4:2:0 planar, YCbCr",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 12,
+ .colplanes = 3,
+ .h_align = 4,
+ .v_align = 4,
+ .types = MEM2MEM_CAPTURE,
+ },
+ {
+ .name = "YUV 4:2:2 packed, YCbYCr",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .colplanes = 1,
+ .h_align = 4,
+ .v_align = 3,
+ .types = MEM2MEM_CAPTURE,
+ },
+ {
+ .name = "JPEG JFIF",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .colplanes = 1,
+ .types = MEM2MEM_OUTPUT,
+ },
+};
+#define NUM_FORMATS_DEC ARRAY_SIZE(formats_dec)
+
+static const unsigned char qtbl_luminance[4][64] = {
+ {/* level 1 - high quality */
+ 8, 6, 6, 8, 12, 14, 16, 17,
+ 6, 6, 6, 8, 10, 13, 12, 15,
+ 6, 6, 7, 8, 13, 14, 18, 24,
+ 8, 8, 8, 14, 13, 19, 24, 35,
+ 12, 10, 13, 13, 20, 26, 34, 39,
+ 14, 13, 14, 19, 26, 34, 39, 39,
+ 16, 12, 18, 24, 34, 39, 39, 39,
+ 17, 15, 24, 35, 39, 39, 39, 39
+ },
+ {/* level 2 */
+ 12, 8, 8, 12, 17, 21, 24, 23,
+ 8, 9, 9, 11, 15, 19, 18, 23,
+ 8, 9, 10, 12, 19, 20, 27, 36,
+ 12, 11, 12, 21, 20, 28, 36, 53,
+ 17, 15, 19, 20, 30, 39, 51, 59,
+ 21, 19, 20, 28, 39, 51, 59, 59,
+ 24, 18, 27, 36, 51, 59, 59, 59,
+ 23, 23, 36, 53, 59, 59, 59, 59
+ },
+ {/* level 3 */
+ 16, 11, 11, 16, 23, 27, 31, 30,
+ 11, 12, 12, 15, 20, 23, 23, 30,
+ 11, 12, 13, 16, 23, 26, 35, 47,
+ 16, 15, 16, 23, 26, 37, 47, 64,
+ 23, 20, 23, 26, 39, 51, 64, 64,
+ 27, 23, 26, 37, 51, 64, 64, 64,
+ 31, 23, 35, 47, 64, 64, 64, 64,
+ 30, 30, 47, 64, 64, 64, 64, 64
+ },
+ {/*level 4 - low quality */
+ 20, 16, 25, 39, 50, 46, 62, 68,
+ 16, 18, 23, 38, 38, 53, 65, 68,
+ 25, 23, 31, 38, 53, 65, 68, 68,
+ 39, 38, 38, 53, 65, 68, 68, 68,
+ 50, 38, 53, 65, 68, 68, 68, 68,
+ 46, 53, 65, 68, 68, 68, 68, 68,
+ 62, 65, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+ }
+};
+
+static const unsigned char qtbl_chrominance[4][64] = {
+ {/* level 1 - high quality */
+ 9, 8, 9, 11, 14, 17, 19, 24,
+ 8, 10, 9, 11, 14, 13, 17, 22,
+ 9, 9, 13, 14, 13, 15, 23, 26,
+ 11, 11, 14, 14, 15, 20, 26, 33,
+ 14, 14, 13, 15, 20, 24, 33, 39,
+ 17, 13, 15, 20, 24, 32, 39, 39,
+ 19, 17, 23, 26, 33, 39, 39, 39,
+ 24, 22, 26, 33, 39, 39, 39, 39
+ },
+ {/* level 2 */
+ 13, 11, 13, 16, 20, 20, 29, 37,
+ 11, 14, 14, 14, 16, 20, 26, 32,
+ 13, 14, 15, 17, 20, 23, 35, 40,
+ 16, 14, 17, 21, 23, 30, 40, 50,
+ 20, 16, 20, 23, 30, 37, 50, 59,
+ 20, 20, 23, 30, 37, 48, 59, 59,
+ 29, 26, 35, 40, 50, 59, 59, 59,
+ 37, 32, 40, 50, 59, 59, 59, 59
+ },
+ {/* level 3 */
+ 17, 15, 17, 21, 20, 26, 38, 48,
+ 15, 19, 18, 17, 20, 26, 35, 43,
+ 17, 18, 20, 22, 26, 30, 46, 53,
+ 21, 17, 22, 28, 30, 39, 53, 64,
+ 20, 20, 26, 30, 39, 48, 64, 64,
+ 26, 26, 30, 39, 48, 63, 64, 64,
+ 38, 35, 46, 53, 64, 64, 64, 64,
+ 48, 43, 53, 64, 64, 64, 64, 64
+ },
+ {/*level 4 - low quality */
+ 21, 25, 32, 38, 54, 68, 68, 68,
+ 25, 28, 24, 38, 54, 68, 68, 68,
+ 32, 24, 32, 43, 66, 68, 68, 68,
+ 38, 38, 43, 53, 68, 68, 68, 68,
+ 54, 54, 66, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+ }
+};
+
+static const unsigned char hdctbl0[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char hdctblg0[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+static const unsigned char hactbl0[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+static const unsigned char hactblg0[162] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl,
+ unsigned long tab, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_qtbl_lum(void __iomem *regs, int quality)
+{
+ /* this driver fills quantisation table 0 with data for luma */
+ jpeg_set_qtbl(regs, qtbl_luminance[quality], S5P_JPG_QTBL_CONTENT(0),
+ ARRAY_SIZE(qtbl_luminance[quality]));
+}
+
+static inline void jpeg_set_qtbl_chr(void __iomem *regs, int quality)
+{
+ /* this driver fills quantisation table 1 with data for chroma */
+ jpeg_set_qtbl(regs, qtbl_chrominance[quality], S5P_JPG_QTBL_CONTENT(1),
+ ARRAY_SIZE(qtbl_chrominance[quality]));
+}
+
+static inline void jpeg_set_htbl(void __iomem *regs, const unsigned char *htbl,
+ unsigned long tab, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void jpeg_set_hdctbl(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0), ARRAY_SIZE(hdctbl0));
+}
+
+static inline void jpeg_set_hdctblg(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0), ARRAY_SIZE(hdctblg0));
+}
+
+static inline void jpeg_set_hactbl(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0), ARRAY_SIZE(hactbl0));
+}
+
+static inline void jpeg_set_hactblg(void __iomem *regs)
+{
+ /* this driver fills table 0 for this component */
+ jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0), ARRAY_SIZE(hactblg0));
+}
+
+/*
+ * ============================================================================
+ * Device file operations
+ * ============================================================================
+ */
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq);
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode,
+ __u32 pixelformat);
+
+static int s5p_jpeg_open(struct file *file)
+{
+ struct s5p_jpeg *jpeg = video_drvdata(file);
+ struct video_device *vfd = video_devdata(file);
+ struct s5p_jpeg_ctx *ctx;
+ struct s5p_jpeg_fmt *out_fmt;
+
+ ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ file->private_data = ctx;
+ ctx->jpeg = jpeg;
+ if (vfd == jpeg->vfd_encoder) {
+ ctx->mode = S5P_JPEG_ENCODE;
+ out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_RGB565);
+ } else {
+ ctx->mode = S5P_JPEG_DECODE;
+ out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG);
+ }
+
+ ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
+ if (IS_ERR(ctx->m2m_ctx)) {
+ int err = PTR_ERR(ctx->m2m_ctx);
+ kfree(ctx);
+ return err;
+ }
+
+ ctx->out_q.fmt = out_fmt;
+ ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV);
+
+ return 0;
+}
+
+static int s5p_jpeg_release(struct file *file)
+{
+ struct s5p_jpeg_ctx *ctx = file->private_data;
+
+ v4l2_m2m_ctx_release(ctx->m2m_ctx);
+ kfree(ctx);
+
+ return 0;
+}
+
+static unsigned int s5p_jpeg_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct s5p_jpeg_ctx *ctx = file->private_data;
+
+ return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+}
+
+static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct s5p_jpeg_ctx *ctx = file->private_data;
+
+ return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations s5p_jpeg_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_jpeg_open,
+ .release = s5p_jpeg_release,
+ .poll = s5p_jpeg_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = s5p_jpeg_mmap,
+};
+
+/*
+ * ============================================================================
+ * video ioctl operations
+ * ============================================================================
+ */
+
+static int get_byte(struct s5p_jpeg_buffer *buf)
+{
+ if (buf->curr >= buf->size)
+ return -1;
+
+ return ((unsigned char *)buf->data)[buf->curr++];
+}
+
+static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
+{
+ unsigned int temp;
+ int byte;
+
+ byte = get_byte(buf);
+ if (byte == -1)
+ return -1;
+ temp = byte << 8;
+ byte = get_byte(buf);
+ if (byte == -1)
+ return -1;
+ *word = (unsigned int)byte | temp;
+ return 0;
+}
+
+static void skip(struct s5p_jpeg_buffer *buf, long len)
+{
+ if (len <= 0)
+ return;
+
+ while (len--)
+ get_byte(buf);
+}
+
+static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
+ unsigned long buffer, unsigned long size)
+{
+ int c, components, notfound;
+ unsigned int height, width, word;
+ long length;
+ struct s5p_jpeg_buffer jpeg_buffer;
+
+ jpeg_buffer.size = size;
+ jpeg_buffer.data = buffer;
+ jpeg_buffer.curr = 0;
+
+ notfound = 1;
+ while (notfound) {
+ c = get_byte(&jpeg_buffer);
+ if (c == -1)
+ break;
+ if (c != 0xff)
+ continue;
+ do
+ c = get_byte(&jpeg_buffer);
+ while (c == 0xff);
+ if (c == -1)
+ break;
+ if (c == 0)
+ continue;
+ length = 0;
+ switch (c) {
+ /* SOF0: baseline JPEG */
+ case SOF0:
+ if (get_word_be(&jpeg_buffer, &word))
+ break;
+ if (get_byte(&jpeg_buffer) == -1)
+ break;
+ if (get_word_be(&jpeg_buffer, &height))
+ break;
+ if (get_word_be(&jpeg_buffer, &width))
+ break;
+ components = get_byte(&jpeg_buffer);
+ if (components == -1)
+ break;
+ notfound = 0;
+
+ skip(&jpeg_buffer, components * 3);
+ break;
+
+ /* skip payload-less markers */
+ case RST ... RST + 7:
+ case SOI:
+ case EOI:
+ case TEM:
+ break;
+
+ /* skip uninteresting payload markers */
+ default:
+ if (get_word_be(&jpeg_buffer, &word))
+ break;
+ length = (long)word - 2;
+ skip(&jpeg_buffer, length);
+ break;
+ }
+ }
+ result->w = width;
+ result->h = height;
+ result->size = components;
+ return !notfound;
+}
+
+static int s5p_jpeg_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder",
+ sizeof(cap->driver));
+ strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
+ sizeof(cap->card));
+ } else {
+ strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder",
+ sizeof(cap->driver));
+ strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
+ sizeof(cap->card));
+ }
+ cap->bus_info[0] = 0;
+ cap->capabilities = V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_OUTPUT;
+ return 0;
+}
+
+static int enum_fmt(struct s5p_jpeg_fmt *formats, int n,
+ struct v4l2_fmtdesc *f, u32 type)
+{
+ int i, num = 0;
+
+ for (i = 0; i < n; ++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;
+ }
+ }
+
+ /* Format not found */
+ if (i >= n)
+ return -EINVAL;
+
+ strlcpy(f->description, formats[i].name, sizeof(f->description));
+ f->pixelformat = formats[i].fourcc;
+
+ return 0;
+}
+
+static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct s5p_jpeg_ctx *ctx;
+
+ ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_ENCODE)
+ return enum_fmt(formats_enc, NUM_FORMATS_ENC, f,
+ MEM2MEM_CAPTURE);
+
+ return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_CAPTURE);
+}
+
+static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct s5p_jpeg_ctx *ctx;
+
+ ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_ENCODE)
+ return enum_fmt(formats_enc, NUM_FORMATS_ENC, f,
+ MEM2MEM_OUTPUT);
+
+ return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_OUTPUT);
+}
+
+static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
+ enum v4l2_buf_type type)
+{
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return &ctx->out_q;
+ if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return &ctx->cap_q;
+
+ return NULL;
+}
+
+static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+ struct vb2_queue *vq;
+ struct s5p_jpeg_q_data *q_data = NULL;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct s5p_jpeg_ctx *ct = priv;
+
+ vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+ if (!vq)
+ return -EINVAL;
+
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
+ return -EINVAL;
+ q_data = get_q_data(ct, f->type);
+ BUG_ON(q_data == NULL);
+
+ pix->width = q_data->w;
+ pix->height = q_data->h;
+ pix->field = V4L2_FIELD_NONE;
+ pix->pixelformat = q_data->fmt->fourcc;
+ pix->bytesperline = 0;
+ if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
+ u32 bpl = q_data->w;
+ if (q_data->fmt->colplanes == 1)
+ bpl = (bpl * q_data->fmt->depth) >> 3;
+ pix->bytesperline = bpl;
+ }
+ pix->sizeimage = q_data->size;
+
+ return 0;
+}
+
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode,
+ u32 pixelformat)
+{
+ unsigned int k;
+ struct s5p_jpeg_fmt *formats;
+ int n;
+
+ if (mode == S5P_JPEG_ENCODE) {
+ formats = formats_enc;
+ n = NUM_FORMATS_ENC;
+ } else {
+ formats = formats_dec;
+ n = NUM_FORMATS_DEC;
+ }
+
+ for (k = 0; k < n; k++) {
+ struct s5p_jpeg_fmt *fmt = &formats[k];
+ if (fmt->fourcc == pixelformat)
+ return fmt;
+ }
+
+ return NULL;
+
+}
+
+static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
+ unsigned int walign,
+ u32 *h, unsigned int hmin, unsigned int hmax,
+ unsigned int halign)
+{
+ int width, height, w_step, h_step;
+
+ width = *w;
+ height = *h;
+
+ w_step = 1 << walign;
+ h_step = 1 << halign;
+ v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
+
+ if (*w < width && (*w + w_step) < wmax)
+ *w += w_step;
+ if (*h < height && (*h + h_step) < hmax)
+ *h += h_step;
+
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
+ struct s5p_jpeg_ctx *ctx, int q_type)
+{
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ if (pix->field == V4L2_FIELD_ANY)
+ pix->field = V4L2_FIELD_NONE;
+ else if (pix->field != V4L2_FIELD_NONE)
+ return -EINVAL;
+
+ /* V4L2 specification suggests the driver corrects the format struct
+ * if any of the dimensions is unsupported */
+ if (q_type == MEM2MEM_OUTPUT)
+ jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+ S5P_JPEG_MAX_WIDTH, 0,
+ &pix->height, S5P_JPEG_MIN_HEIGHT,
+ S5P_JPEG_MAX_HEIGHT, 0);
+ else
+ jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH,
+ S5P_JPEG_MAX_WIDTH, fmt->h_align,
+ &pix->height, S5P_JPEG_MIN_HEIGHT,
+ S5P_JPEG_MAX_HEIGHT, fmt->v_align);
+
+ if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+ if (pix->sizeimage <= 0)
+ pix->sizeimage = PAGE_SIZE;
+ pix->bytesperline = 0;
+ } else {
+ u32 bpl = pix->bytesperline;
+
+ if (fmt->colplanes > 1 && bpl < pix->width)
+ bpl = pix->width; /* planar */
+
+ if (fmt->colplanes == 1 && /* packed */
+ (bpl << 3) * fmt->depth < pix->width)
+ bpl = (pix->width * fmt->depth) >> 3;
+
+ pix->bytesperline = bpl;
+ pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
+ }
+
+ return 0;
+}
+
+static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct s5p_jpeg_fmt *fmt;
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat);
+ if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
+ v4l2_err(&ctx->jpeg->v4l2_dev,
+ "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
+ return -EINVAL;
+ }
+
+ return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_CAPTURE);
+}
+
+static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct s5p_jpeg_fmt *fmt;
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat);
+ if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
+ v4l2_err(&ctx->jpeg->v4l2_dev,
+ "Fourcc format (0x%08x) invalid.\n",
+ f->fmt.pix.pixelformat);
+ return -EINVAL;
+ }
+
+ return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_OUTPUT);
+}
+
+static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
+{
+ struct vb2_queue *vq;
+ struct s5p_jpeg_q_data *q_data = NULL;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+ if (!vq)
+ return -EINVAL;
+
+ q_data = get_q_data(ct, f->type);
+ BUG_ON(q_data == NULL);
+
+ if (vb2_is_busy(vq)) {
+ v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
+ return -EBUSY;
+ }
+
+ q_data->fmt = s5p_jpeg_find_format(ct->mode, pix->pixelformat);
+ q_data->w = pix->width;
+ q_data->h = pix->height;
+ if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)
+ q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
+ else
+ q_data->size = pix->sizeimage;
+
+ return 0;
+}
+
+static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ int ret;
+
+ ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
+ if (ret)
+ return ret;
+
+ return s5p_jpeg_s_fmt(priv, f);
+}
+
+static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ int ret;
+
+ ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
+ if (ret)
+ return ret;
+
+ return s5p_jpeg_s_fmt(priv, f);
+}
+
+static int s5p_jpeg_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *reqbufs)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int s5p_jpeg_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_dqbuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int s5p_jpeg_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int s5p_jpeg_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+int s5p_jpeg_g_selection(struct file *file, void *priv,
+ struct v4l2_selection *s)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ /* For JPEG blob active == default == bounds */
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_ACTIVE:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ s->r.width = ctx->out_q.w;
+ s->r.height = ctx->out_q.h;
+ break;
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
+ s->r.width = ctx->cap_q.w;
+ s->r.height = ctx->cap_q.h;
+ break;
+ default:
+ return -EINVAL;
+ }
+ s->r.left = 0;
+ s->r.top = 0;
+ return 0;
+}
+
+static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *compr)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_DECODE)
+ return -ENOTTY;
+
+ memset(compr, 0, sizeof(*compr));
+ compr->quality = ctx->compr_quality;
+
+ return 0;
+}
+
+static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *compr)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_DECODE)
+ return -ENOTTY;
+
+ compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST,
+ S5P_JPEG_COMPR_QUAL_WORST);
+
+ ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality;
+
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
+ .vidioc_querycap = s5p_jpeg_querycap,
+
+ .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap,
+ .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out,
+
+ .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt,
+ .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt,
+
+ .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap,
+ .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out,
+
+ .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap,
+ .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out,
+
+ .vidioc_reqbufs = s5p_jpeg_reqbufs,
+ .vidioc_querybuf = s5p_jpeg_querybuf,
+
+ .vidioc_qbuf = s5p_jpeg_qbuf,
+ .vidioc_dqbuf = s5p_jpeg_dqbuf,
+
+ .vidioc_streamon = s5p_jpeg_streamon,
+ .vidioc_streamoff = s5p_jpeg_streamoff,
+
+ .vidioc_g_selection = s5p_jpeg_g_selection,
+
+ .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp,
+ .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp,
+};
+
+/*
+ * ============================================================================
+ * mem2mem callbacks
+ * ============================================================================
+ */
+
+static void s5p_jpeg_device_run(void *priv)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+ struct s5p_jpeg *jpeg = ctx->jpeg;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long src_addr, dst_addr;
+
+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+
+ jpeg_reset(jpeg->regs);
+ jpeg_poweron(jpeg->regs);
+ jpeg_proc_mode(jpeg->regs, ctx->mode);
+ if (ctx->mode == S5P_JPEG_ENCODE) {
+ if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565);
+ else
+ jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422);
+ if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_422);
+ else
+ jpeg_subsampling_mode(jpeg->regs,
+ S5P_JPEG_SUBSAMPLING_420);
+ jpeg_dri(jpeg->regs, 0);
+ jpeg_x(jpeg->regs, ctx->out_q.w);
+ jpeg_y(jpeg->regs, ctx->out_q.h);
+ jpeg_imgadr(jpeg->regs, src_addr);
+ jpeg_jpgadr(jpeg->regs, dst_addr);
+
+ /* ultimately comes from sizeimage from userspace */
+ jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
+
+ /* JPEG RGB to YCbCr conversion matrix */
+ jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
+ jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
+ jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
+ jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
+ jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
+ jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
+ jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
+ jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
+ jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
+
+ /*
+ * JPEG IP allows storing 4 quantization tables
+ * We fill table 0 for luma and table 1 for chroma
+ */
+ jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+ jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+ /* use table 0 for Y */
+ jpeg_qtbl(jpeg->regs, 1, 0);
+ /* use table 1 for Cb and Cr*/
+ jpeg_qtbl(jpeg->regs, 2, 1);
+ jpeg_qtbl(jpeg->regs, 3, 1);
+
+ /* Y, Cb, Cr use Huffman table 0 */
+ jpeg_htbl_ac(jpeg->regs, 1);
+ jpeg_htbl_dc(jpeg->regs, 1);
+ jpeg_htbl_ac(jpeg->regs, 2);
+ jpeg_htbl_dc(jpeg->regs, 2);
+ jpeg_htbl_ac(jpeg->regs, 3);
+ jpeg_htbl_dc(jpeg->regs, 3);
+ } else {
+ jpeg_rst_int_enable(jpeg->regs, true);
+ jpeg_data_num_int_enable(jpeg->regs, true);
+ jpeg_final_mcu_num_int_enable(jpeg->regs, true);
+ jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
+ jpeg_jpgadr(jpeg->regs, src_addr);
+ jpeg_imgadr(jpeg->regs, dst_addr);
+ }
+ jpeg_start(jpeg->regs);
+}
+
+static int s5p_jpeg_job_ready(void *priv)
+{
+ struct s5p_jpeg_ctx *ctx = priv;
+
+ if (ctx->mode == S5P_JPEG_DECODE)
+ return ctx->hdr_parsed;
+ return 1;
+}
+
+static void s5p_jpeg_job_abort(void *priv)
+{
+}
+
+static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
+ .device_run = s5p_jpeg_device_run,
+ .job_ready = s5p_jpeg_job_ready,
+ .job_abort = s5p_jpeg_job_abort,
+};
+
+/*
+ * ============================================================================
+ * Queue operations
+ * ============================================================================
+ */
+
+static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[],
+ void *alloc_ctxs[])
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+ struct s5p_jpeg_q_data *q_data = NULL;
+ unsigned int size, count = *nbuffers;
+
+ q_data = get_q_data(ctx, vq->type);
+ BUG_ON(q_data == NULL);
+
+ size = q_data->size;
+
+ /*
+ * header is parsed during decoding and parsed information stored
+ * in the context so we do not allow another buffer to overwrite it
+ */
+ if (ctx->mode == S5P_JPEG_DECODE)
+ count = 1;
+
+ *nbuffers = count;
+ *nplanes = 1;
+ sizes[0] = size;
+ alloc_ctxs[0] = ctx->jpeg->alloc_ctx;
+
+ return 0;
+}
+
+static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct s5p_jpeg_q_data *q_data = NULL;
+
+ q_data = get_q_data(ctx, vb->vb2_queue->type);
+ BUG_ON(q_data == NULL);
+
+ if (vb2_plane_size(vb, 0) < q_data->size) {
+ pr_err("%s data will not fit into plane (%lu < %lu)\n",
+ __func__, vb2_plane_size(vb, 0),
+ (long)q_data->size);
+ return -EINVAL;
+ }
+
+ vb2_set_plane_payload(vb, 0, q_data->size);
+
+ return 0;
+}
+
+static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ if (ctx->mode == S5P_JPEG_DECODE &&
+ vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ struct s5p_jpeg_q_data tmp, *q_data;
+ ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
+ (unsigned long)vb2_plane_vaddr(vb, 0),
+ min((unsigned long)ctx->out_q.size,
+ vb2_get_plane_payload(vb, 0)));
+ if (!ctx->hdr_parsed) {
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+ return;
+ }
+
+ q_data = &ctx->out_q;
+ q_data->w = tmp.w;
+ q_data->h = tmp.h;
+
+ q_data = &ctx->cap_q;
+ q_data->w = tmp.w;
+ q_data->h = tmp.h;
+
+ jpeg_bound_align_image(&q_data->w, S5P_JPEG_MIN_WIDTH,
+ S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,
+ &q_data->h, S5P_JPEG_MIN_HEIGHT,
+ S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align
+ );
+ q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
+ }
+ if (ctx->m2m_ctx)
+ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+static void s5p_jpeg_wait_prepare(struct vb2_queue *vq)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+
+ mutex_unlock(&ctx->jpeg->lock);
+}
+
+static void s5p_jpeg_wait_finish(struct vb2_queue *vq)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+
+ mutex_lock(&ctx->jpeg->lock);
+}
+
+static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+ int ret;
+
+ ret = pm_runtime_get_sync(ctx->jpeg->dev);
+
+ return ret > 0 ? 0 : ret;
+}
+
+static int s5p_jpeg_stop_streaming(struct vb2_queue *q)
+{
+ struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+
+ pm_runtime_put(ctx->jpeg->dev);
+
+ return 0;
+}
+
+static struct vb2_ops s5p_jpeg_qops = {
+ .queue_setup = s5p_jpeg_queue_setup,
+ .buf_prepare = s5p_jpeg_buf_prepare,
+ .buf_queue = s5p_jpeg_buf_queue,
+ .wait_prepare = s5p_jpeg_wait_prepare,
+ .wait_finish = s5p_jpeg_wait_finish,
+ .start_streaming = s5p_jpeg_start_streaming,
+ .stop_streaming = s5p_jpeg_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_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;
+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ src_vq->ops = &s5p_jpeg_qops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+
+ 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;
+ 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 = &s5p_jpeg_qops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+ return vb2_queue_init(dst_vq);
+}
+
+/*
+ * ============================================================================
+ * ISR
+ * ============================================================================
+ */
+
+static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
+{
+ struct s5p_jpeg *jpeg = dev_id;
+ struct s5p_jpeg_ctx *curr_ctx;
+ struct vb2_buffer *src_buf, *dst_buf;
+ unsigned long payload_size = 0;
+ enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+ bool enc_jpeg_too_large = false;
+ bool timer_elapsed = false;
+ bool op_completed = false;
+
+ curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+ src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+ dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
+ if (curr_ctx->mode == S5P_JPEG_ENCODE)
+ enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs);
+ timer_elapsed = jpeg_timer_stat(jpeg->regs);
+ op_completed = jpeg_result_stat_ok(jpeg->regs);
+ if (curr_ctx->mode == S5P_JPEG_DECODE)
+ op_completed = op_completed && jpeg_stream_stat_ok(jpeg->regs);
+
+ if (enc_jpeg_too_large) {
+ state = VB2_BUF_STATE_ERROR;
+ jpeg_clear_enc_stream_stat(jpeg->regs);
+ } else if (timer_elapsed) {
+ state = VB2_BUF_STATE_ERROR;
+ jpeg_clear_timer_stat(jpeg->regs);
+ } else if (!op_completed) {
+ state = VB2_BUF_STATE_ERROR;
+ } else {
+ payload_size = jpeg_compressed_size(jpeg->regs);
+ }
+
+ v4l2_m2m_buf_done(src_buf, state);
+ if (curr_ctx->mode == S5P_JPEG_ENCODE)
+ vb2_set_plane_payload(dst_buf, 0, payload_size);
+ v4l2_m2m_buf_done(dst_buf, state);
+ v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
+
+ jpeg_clear_int(jpeg->regs);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * ============================================================================
+ * Driver basic infrastructure
+ * ============================================================================
+ */
+
+static int s5p_jpeg_probe(struct platform_device *pdev)
+{
+ struct s5p_jpeg *jpeg;
+ struct resource *res;
+ int ret;
+
+ /* JPEG IP abstraction struct */
+ jpeg = kzalloc(sizeof(struct s5p_jpeg), GFP_KERNEL);
+ if (!jpeg)
+ return -ENOMEM;
+
+ mutex_init(&jpeg->lock);
+ jpeg->dev = &pdev->dev;
+
+ /* memory-mapped registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "cannot find IO resource\n");
+ ret = -ENOENT;
+ goto jpeg_alloc_rollback;
+ }
+
+ jpeg->ioarea = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+ if (!jpeg->ioarea) {
+ dev_err(&pdev->dev, "cannot request IO\n");
+ ret = -ENXIO;
+ goto jpeg_alloc_rollback;
+ }
+
+ jpeg->regs = ioremap(res->start, resource_size(res));
+ if (!jpeg->regs) {
+ dev_err(&pdev->dev, "cannot map IO\n");
+ ret = -ENXIO;
+ goto mem_region_rollback;
+ }
+
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ jpeg->regs, jpeg->ioarea, res);
+
+ /* interrupt service routine registration */
+ jpeg->irq = ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "cannot find IRQ\n");
+ goto ioremap_rollback;
+ }
+
+ ret = request_irq(jpeg->irq, s5p_jpeg_irq, 0,
+ dev_name(&pdev->dev), jpeg);
+
+ if (ret) {
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
+ goto ioremap_rollback;
+ }
+
+ /* clocks */
+ jpeg->clk = clk_get(&pdev->dev, "jpeg");
+ if (IS_ERR(jpeg->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ ret = PTR_ERR(jpeg->clk);
+ goto request_irq_rollback;
+ }
+ dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
+ clk_enable(jpeg->clk);
+
+ /* v4l2 device */
+ ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+ goto clk_get_rollback;
+ }
+
+ /* mem2mem device */
+ jpeg->m2m_dev = v4l2_m2m_init(&s5p_jpeg_m2m_ops);
+ if (IS_ERR(jpeg->m2m_dev)) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
+ ret = PTR_ERR(jpeg->m2m_dev);
+ goto device_register_rollback;
+ }
+
+ jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ if (IS_ERR(jpeg->alloc_ctx)) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
+ ret = PTR_ERR(jpeg->alloc_ctx);
+ goto m2m_init_rollback;
+ }
+
+ /* JPEG encoder /dev/videoX node */
+ jpeg->vfd_encoder = video_device_alloc();
+ if (!jpeg->vfd_encoder) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+ ret = -ENOMEM;
+ goto vb2_allocator_rollback;
+ }
+ strlcpy(jpeg->vfd_encoder->name, S5P_JPEG_M2M_NAME,
+ sizeof(jpeg->vfd_encoder->name));
+ jpeg->vfd_encoder->fops = &s5p_jpeg_fops;
+ jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
+ jpeg->vfd_encoder->minor = -1;
+ jpeg->vfd_encoder->release = video_device_release;
+ jpeg->vfd_encoder->lock = &jpeg->lock;
+ jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
+
+ ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
+ if (ret) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+ goto enc_vdev_alloc_rollback;
+ }
+
+ video_set_drvdata(jpeg->vfd_encoder, jpeg);
+ v4l2_info(&jpeg->v4l2_dev,
+ "encoder device registered as /dev/video%d\n",
+ jpeg->vfd_encoder->num);
+
+ /* JPEG decoder /dev/videoX node */
+ jpeg->vfd_decoder = video_device_alloc();
+ if (!jpeg->vfd_decoder) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+ ret = -ENOMEM;
+ goto enc_vdev_register_rollback;
+ }
+ strlcpy(jpeg->vfd_decoder->name, S5P_JPEG_M2M_NAME,
+ sizeof(jpeg->vfd_decoder->name));
+ jpeg->vfd_decoder->fops = &s5p_jpeg_fops;
+ jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops;
+ jpeg->vfd_decoder->minor = -1;
+ jpeg->vfd_decoder->release = video_device_release;
+ jpeg->vfd_decoder->lock = &jpeg->lock;
+ jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
+
+ ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
+ if (ret) {
+ v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+ goto dec_vdev_alloc_rollback;
+ }
+
+ video_set_drvdata(jpeg->vfd_decoder, jpeg);
+ v4l2_info(&jpeg->v4l2_dev,
+ "decoder device registered as /dev/video%d\n",
+ jpeg->vfd_decoder->num);
+
+ /* final statements & power management */
+ platform_set_drvdata(pdev, jpeg);
+
+ pm_runtime_enable(&pdev->dev);
+
+ v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
+
+ return 0;
+
+dec_vdev_alloc_rollback:
+ video_device_release(jpeg->vfd_decoder);
+
+enc_vdev_register_rollback:
+ video_unregister_device(jpeg->vfd_encoder);
+
+enc_vdev_alloc_rollback:
+ video_device_release(jpeg->vfd_encoder);
+
+vb2_allocator_rollback:
+ vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
+
+m2m_init_rollback:
+ v4l2_m2m_release(jpeg->m2m_dev);
+
+device_register_rollback:
+ v4l2_device_unregister(&jpeg->v4l2_dev);
+
+clk_get_rollback:
+ clk_disable(jpeg->clk);
+ clk_put(jpeg->clk);
+
+request_irq_rollback:
+ free_irq(jpeg->irq, jpeg);
+
+ioremap_rollback:
+ iounmap(jpeg->regs);
+
+mem_region_rollback:
+ release_resource(jpeg->ioarea);
+ release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea));
+
+jpeg_alloc_rollback:
+ kfree(jpeg);
+ return ret;
+}
+
+static int s5p_jpeg_remove(struct platform_device *pdev)
+{
+ struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(jpeg->dev);
+
+ video_unregister_device(jpeg->vfd_decoder);
+ video_device_release(jpeg->vfd_decoder);
+ video_unregister_device(jpeg->vfd_encoder);
+ video_device_release(jpeg->vfd_encoder);
+ vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx);
+ v4l2_m2m_release(jpeg->m2m_dev);
+ v4l2_device_unregister(&jpeg->v4l2_dev);
+
+ clk_disable(jpeg->clk);
+ clk_put(jpeg->clk);
+
+ free_irq(jpeg->irq, jpeg);
+
+ iounmap(jpeg->regs);
+
+ release_resource(jpeg->ioarea);
+ release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea));
+ kfree(jpeg);
+
+ return 0;
+}
+
+static int s5p_jpeg_runtime_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int s5p_jpeg_runtime_resume(struct device *dev)
+{
+ struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+ /*
+ * JPEG IP allows storing two Huffman tables for each component
+ * We fill table 0 for each component
+ */
+ jpeg_set_hdctbl(jpeg->regs);
+ jpeg_set_hdctblg(jpeg->regs);
+ jpeg_set_hactbl(jpeg->regs);
+ jpeg_set_hactblg(jpeg->regs);
+ return 0;
+}
+
+static const struct dev_pm_ops s5p_jpeg_pm_ops = {
+ .runtime_suspend = s5p_jpeg_runtime_suspend,
+ .runtime_resume = s5p_jpeg_runtime_resume,
+};
+
+static struct platform_driver s5p_jpeg_driver = {
+ .probe = s5p_jpeg_probe,
+ .remove = s5p_jpeg_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = S5P_JPEG_M2M_NAME,
+ .pm = &s5p_jpeg_pm_ops,
+ },
+};
+
+static int __init
+s5p_jpeg_register(void)
+{
+ int ret;
+
+ pr_info("S5P JPEG V4L2 Driver, (c) 2011 Samsung Electronics\n");
+
+ ret = platform_driver_register(&s5p_jpeg_driver);
+
+ if (ret)
+ pr_err("%s: failed to register jpeg driver\n", __func__);
+
+ return ret;
+}
+
+static void __exit
+s5p_jpeg_unregister(void)
+{
+ platform_driver_unregister(&s5p_jpeg_driver);
+}
+
+module_init(s5p_jpeg_register);
+module_exit(s5p_jpeg_unregister);
+
+MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
+MODULE_DESCRIPTION("Samsung JPEG codec driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.h b/drivers/media/video/s5p-jpeg/jpeg-core.h
new file mode 100644
index 0000000..facad61
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.h
@@ -0,0 +1,143 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef JPEG_CORE_H_
+#define JPEG_CORE_H_
+
+#include <media/v4l2-device.h>
+
+#define S5P_JPEG_M2M_NAME "s5p-jpeg"
+
+/* JPEG compression quality setting */
+#define S5P_JPEG_COMPR_QUAL_BEST 0
+#define S5P_JPEG_COMPR_QUAL_WORST 3
+
+/* JPEG RGB to YCbCr conversion matrix coefficients */
+#define S5P_JPEG_COEF11 0x4d
+#define S5P_JPEG_COEF12 0x97
+#define S5P_JPEG_COEF13 0x1e
+#define S5P_JPEG_COEF21 0x2c
+#define S5P_JPEG_COEF22 0x57
+#define S5P_JPEG_COEF23 0x83
+#define S5P_JPEG_COEF31 0x83
+#define S5P_JPEG_COEF32 0x6e
+#define S5P_JPEG_COEF33 0x13
+
+/* a selection of JPEG markers */
+#define TEM 0x01
+#define SOF0 0xc0
+#define RST 0xd0
+#define SOI 0xd8
+#define EOI 0xd9
+#define DHP 0xde
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE (1 << 0)
+#define MEM2MEM_OUTPUT (1 << 1)
+
+/**
+ * struct s5p_jpeg - JPEG IP abstraction
+ * @lock: the mutex protecting this structure
+ * @v4l2_dev: v4l2 device for mem2mem mode
+ * @vfd_encoder: video device node for encoder mem2mem mode
+ * @vfd_decoder: video device node for decoder mem2mem mode
+ * @m2m_dev: v4l2 mem2mem device data
+ * @ioarea: JPEG IP memory region
+ * @regs: JPEG IP registers mapping
+ * @irq: JPEG IP irq
+ * @clk: JPEG IP clock
+ * @dev: JPEG IP struct device
+ * @alloc_ctx: videobuf2 memory allocator's context
+ */
+struct s5p_jpeg {
+ struct mutex lock;
+
+ struct v4l2_device v4l2_dev;
+ struct video_device *vfd_encoder;
+ struct video_device *vfd_decoder;
+ struct v4l2_m2m_dev *m2m_dev;
+
+ struct resource *ioarea;
+ void __iomem *regs;
+ unsigned int irq;
+ struct clk *clk;
+ struct device *dev;
+ void *alloc_ctx;
+};
+
+/**
+ * struct jpeg_fmt - driver's internal color format data
+ * @name: format descritpion
+ * @fourcc: the fourcc code, 0 if not applicable
+ * @depth: number of bits per pixel
+ * @colplanes: number of color planes (1 for packed formats)
+ * @h_align: horizontal alignment order (align to 2^h_align)
+ * @v_align: vertical alignment order (align to 2^v_align)
+ * @types: types of queue this format is applicable to
+ */
+struct s5p_jpeg_fmt {
+ char *name;
+ u32 fourcc;
+ int depth;
+ int colplanes;
+ int h_align;
+ int v_align;
+ u32 types;
+};
+
+/**
+ * s5p_jpeg_q_data - parameters of one queue
+ * @fmt: driver-specific format of this queue
+ * @w: image width
+ * @h: image height
+ * @size: image buffer size in bytes
+ */
+struct s5p_jpeg_q_data {
+ struct s5p_jpeg_fmt *fmt;
+ u32 w;
+ u32 h;
+ u32 size;
+};
+
+/**
+ * s5p_jpeg_ctx - the device context data
+ * @jpeg: JPEG IP device for this context
+ * @mode: compression (encode) operation or decompression (decode)
+ * @compr_quality: destination image quality in compression (encode) mode
+ * @m2m_ctx: mem2mem device context
+ * @out_q: source (output) queue information
+ * @cap_fmt: destination (capture) queue queue information
+ * @hdr_parsed: set if header has been parsed during decompression
+ */
+struct s5p_jpeg_ctx {
+ struct s5p_jpeg *jpeg;
+ unsigned int mode;
+ unsigned int compr_quality;
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct s5p_jpeg_q_data out_q;
+ struct s5p_jpeg_q_data cap_q;
+ bool hdr_parsed;
+};
+
+/**
+ * s5p_jpeg_buffer - description of memory containing input JPEG data
+ * @size: buffer size
+ * @curr: current position in the buffer
+ * @data: pointer to the data
+ */
+struct s5p_jpeg_buffer {
+ unsigned long size;
+ unsigned long curr;
+ unsigned long data;
+};
+
+#endif /* JPEG_CORE_H */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw.h b/drivers/media/video/s5p-jpeg/jpeg-hw.h
new file mode 100644
index 0000000..e10c744
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-hw.h
@@ -0,0 +1,353 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef JPEG_HW_H_
+#define JPEG_HW_H_
+
+#include <linux/io.h>
+
+#include "jpeg-hw.h"
+#include "jpeg-regs.h"
+
+#define S5P_JPEG_MIN_WIDTH 32
+#define S5P_JPEG_MIN_HEIGHT 32
+#define S5P_JPEG_MAX_WIDTH 8192
+#define S5P_JPEG_MAX_HEIGHT 8192
+#define S5P_JPEG_ENCODE 0
+#define S5P_JPEG_DECODE 1
+#define S5P_JPEG_RAW_IN_565 0
+#define S5P_JPEG_RAW_IN_422 1
+#define S5P_JPEG_SUBSAMPLING_422 0
+#define S5P_JPEG_SUBSAMPLING_420 1
+#define S5P_JPEG_RAW_OUT_422 0
+#define S5P_JPEG_RAW_OUT_420 1
+
+static inline void jpeg_reset(void __iomem *regs)
+{
+ unsigned long reg;
+
+ writel(1, regs + S5P_JPG_SW_RESET);
+ reg = readl(regs + S5P_JPG_SW_RESET);
+ /* no other way but polling for when JPEG IP becomes operational */
+ while (reg != 0) {
+ cpu_relax();
+ reg = readl(regs + S5P_JPG_SW_RESET);
+ }
+}
+
+static inline void jpeg_poweron(void __iomem *regs)
+{
+ writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
+}
+
+static inline void jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned long reg, m;
+
+ m = S5P_MOD_SEL_565;
+ if (mode == S5P_JPEG_RAW_IN_565)
+ m = S5P_MOD_SEL_565;
+ else if (mode == S5P_JPEG_RAW_IN_422)
+ m = S5P_MOD_SEL_422;
+
+ reg = readl(regs + S5P_JPGCMOD);
+ reg &= ~S5P_MOD_SEL_MASK;
+ reg |= m;
+ writel(reg, regs + S5P_JPGCMOD);
+}
+
+static inline void jpeg_input_raw_y16(void __iomem *regs, bool y16)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGCMOD);
+ if (y16)
+ reg |= S5P_MODE_Y16;
+ else
+ reg &= ~S5P_MODE_Y16_MASK;
+ writel(reg, regs + S5P_JPGCMOD);
+}
+
+static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned long reg, m;
+
+ m = S5P_PROC_MODE_DECOMPR;
+ if (mode == S5P_JPEG_ENCODE)
+ m = S5P_PROC_MODE_COMPR;
+ else
+ m = S5P_PROC_MODE_DECOMPR;
+ reg = readl(regs + S5P_JPGMOD);
+ reg &= ~S5P_PROC_MODE_MASK;
+ reg |= m;
+ writel(reg, regs + S5P_JPGMOD);
+}
+
+static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode)
+{
+ unsigned long reg, m;
+
+ m = S5P_SUBSAMPLING_MODE_422;
+ if (mode == S5P_JPEG_SUBSAMPLING_422)
+ m = S5P_SUBSAMPLING_MODE_422;
+ else if (mode == S5P_JPEG_SUBSAMPLING_420)
+ m = S5P_SUBSAMPLING_MODE_420;
+ reg = readl(regs + S5P_JPGMOD);
+ reg &= ~S5P_SUBSAMPLING_MODE_MASK;
+ reg |= m;
+ writel(reg, regs + S5P_JPGMOD);
+}
+
+static inline void jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGDRI_U);
+ reg &= ~0xff;
+ reg |= (dri >> 8) & 0xff;
+ writel(reg, regs + S5P_JPGDRI_U);
+
+ reg = readl(regs + S5P_JPGDRI_L);
+ reg &= ~0xff;
+ reg |= dri & 0xff;
+ writel(reg, regs + S5P_JPGDRI_L);
+}
+
+static inline void jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_QTBL);
+ reg &= ~S5P_QT_NUMt_MASK(t);
+ reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
+ writel(reg, regs + S5P_JPG_QTBL);
+}
+
+static inline void jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_HTBL);
+ reg &= ~S5P_HT_NUMt_AC_MASK(t);
+ /* this driver uses table 0 for all color components */
+ reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
+ writel(reg, regs + S5P_JPG_HTBL);
+}
+
+static inline void jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_HTBL);
+ reg &= ~S5P_HT_NUMt_DC_MASK(t);
+ /* this driver uses table 0 for all color components */
+ reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
+ writel(reg, regs + S5P_JPG_HTBL);
+}
+
+static inline void jpeg_y(void __iomem *regs, unsigned int y)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGY_U);
+ reg &= ~0xff;
+ reg |= (y >> 8) & 0xff;
+ writel(reg, regs + S5P_JPGY_U);
+
+ reg = readl(regs + S5P_JPGY_L);
+ reg &= ~0xff;
+ reg |= y & 0xff;
+ writel(reg, regs + S5P_JPGY_L);
+}
+
+static inline void jpeg_x(void __iomem *regs, unsigned int x)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGX_U);
+ reg &= ~0xff;
+ reg |= (x >> 8) & 0xff;
+ writel(reg, regs + S5P_JPGX_U);
+
+ reg = readl(regs + S5P_JPGX_L);
+ reg &= ~0xff;
+ reg |= x & 0xff;
+ writel(reg, regs + S5P_JPGX_L);
+}
+
+static inline void jpeg_rst_int_enable(void __iomem *regs, bool enable)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGINTSE);
+ reg &= ~S5P_RSTm_INT_EN_MASK;
+ if (enable)
+ reg |= S5P_RSTm_INT_EN;
+ writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_data_num_int_enable(void __iomem *regs, bool enable)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGINTSE);
+ reg &= ~S5P_DATA_NUM_INT_EN_MASK;
+ if (enable)
+ reg |= S5P_DATA_NUM_INT_EN;
+ writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGINTSE);
+ reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
+ if (enbl)
+ reg |= S5P_FINAL_MCU_NUM_INT_EN;
+ writel(reg, regs + S5P_JPGINTSE);
+}
+
+static inline void jpeg_timer_enable(void __iomem *regs, unsigned long val)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_TIMER_SE);
+ reg |= S5P_TIMER_INT_EN;
+ reg &= ~S5P_TIMER_INIT_MASK;
+ reg |= val & S5P_TIMER_INIT_MASK;
+ writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline void jpeg_timer_disable(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_TIMER_SE);
+ reg &= ~S5P_TIMER_INT_EN_MASK;
+ writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline int jpeg_timer_stat(void __iomem *regs)
+{
+ return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
+ >> S5P_TIMER_INT_STAT_SHIFT);
+}
+
+static inline void jpeg_clear_timer_stat(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_TIMER_SE);
+ reg &= ~S5P_TIMER_INT_STAT_MASK;
+ writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+static inline void jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+ reg &= ~S5P_ENC_STREAM_BOUND_MASK;
+ reg |= S5P_ENC_STREAM_INT_EN;
+ reg |= size & S5P_ENC_STREAM_BOUND_MASK;
+ writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+static inline int jpeg_enc_stream_stat(void __iomem *regs)
+{
+ return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
+ S5P_ENC_STREAM_INT_STAT_MASK);
+}
+
+static inline void jpeg_clear_enc_stream_stat(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+ reg &= ~S5P_ENC_STREAM_INT_MASK;
+ writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+static inline void jpeg_outform_raw(void __iomem *regs, unsigned long format)
+{
+ unsigned long reg, f;
+
+ f = S5P_DEC_OUT_FORMAT_422;
+ if (format == S5P_JPEG_RAW_OUT_422)
+ f = S5P_DEC_OUT_FORMAT_422;
+ else if (format == S5P_JPEG_RAW_OUT_420)
+ f = S5P_DEC_OUT_FORMAT_420;
+ reg = readl(regs + S5P_JPG_OUTFORM);
+ reg &= ~S5P_DEC_OUT_FORMAT_MASK;
+ reg |= f;
+ writel(reg, regs + S5P_JPG_OUTFORM);
+}
+
+static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr)
+{
+ writel(addr, regs + S5P_JPG_JPGADR);
+}
+
+static inline void jpeg_imgadr(void __iomem *regs, unsigned long addr)
+{
+ writel(addr, regs + S5P_JPG_IMGADR);
+}
+
+static inline void jpeg_coef(void __iomem *regs, unsigned int i,
+ unsigned int j, unsigned int coef)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPG_COEF(i));
+ reg &= ~S5P_COEFn_MASK(j);
+ reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
+ writel(reg, regs + S5P_JPG_COEF(i));
+}
+
+static inline void jpeg_start(void __iomem *regs)
+{
+ writel(1, regs + S5P_JSTART);
+}
+
+static inline int jpeg_result_stat_ok(void __iomem *regs)
+{
+ return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
+ >> S5P_RESULT_STAT_SHIFT);
+}
+
+static inline int jpeg_stream_stat_ok(void __iomem *regs)
+{
+ return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
+ >> S5P_STREAM_STAT_SHIFT);
+}
+
+static inline void jpeg_clear_int(void __iomem *regs)
+{
+ unsigned long reg;
+
+ reg = readl(regs + S5P_JPGINTST);
+ writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
+ reg = readl(regs + S5P_JPGOPR);
+}
+
+static inline unsigned int jpeg_compressed_size(void __iomem *regs)
+{
+ unsigned long jpeg_size = 0;
+
+ jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
+ jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
+ jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
+
+ return (unsigned int)jpeg_size;
+}
+
+#endif /* JPEG_HW_H_ */
diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs.h b/drivers/media/video/s5p-jpeg/jpeg-regs.h
new file mode 100644
index 0000000..91f4dd5
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-regs.h
@@ -0,0 +1,170 @@
+/* linux/drivers/media/video/s5p-jpeg/jpeg-regs.h
+ *
+ * Register definition file for Samsung JPEG codec driver
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef JPEG_REGS_H_
+#define JPEG_REGS_H_
+
+/* JPEG mode register */
+#define S5P_JPGMOD 0x00
+#define S5P_PROC_MODE_MASK (0x1 << 3)
+#define S5P_PROC_MODE_DECOMPR (0x1 << 3)
+#define S5P_PROC_MODE_COMPR (0x0 << 3)
+#define S5P_SUBSAMPLING_MODE_MASK 0x7
+#define S5P_SUBSAMPLING_MODE_444 (0x0 << 0)
+#define S5P_SUBSAMPLING_MODE_422 (0x1 << 0)
+#define S5P_SUBSAMPLING_MODE_420 (0x2 << 0)
+#define S5P_SUBSAMPLING_MODE_GRAY (0x3 << 0)
+
+/* JPEG operation status register */
+#define S5P_JPGOPR 0x04
+
+/* Quantization tables*/
+#define S5P_JPG_QTBL 0x08
+#define S5P_QT_NUMt_SHIFT(t) (((t) - 1) << 1)
+#define S5P_QT_NUMt_MASK(t) (0x3 << S5P_QT_NUMt_SHIFT(t))
+
+/* Huffman tables */
+#define S5P_JPG_HTBL 0x0c
+#define S5P_HT_NUMt_AC_SHIFT(t) (((t) << 1) - 1)
+#define S5P_HT_NUMt_AC_MASK(t) (0x1 << S5P_HT_NUMt_AC_SHIFT(t))
+
+#define S5P_HT_NUMt_DC_SHIFT(t) (((t) - 1) << 1)
+#define S5P_HT_NUMt_DC_MASK(t) (0x1 << S5P_HT_NUMt_DC_SHIFT(t))
+
+/* JPEG restart interval register upper byte */
+#define S5P_JPGDRI_U 0x10
+
+/* JPEG restart interval register lower byte */
+#define S5P_JPGDRI_L 0x14
+
+/* JPEG vertical resolution register upper byte */
+#define S5P_JPGY_U 0x18
+
+/* JPEG vertical resolution register lower byte */
+#define S5P_JPGY_L 0x1c
+
+/* JPEG horizontal resolution register upper byte */
+#define S5P_JPGX_U 0x20
+
+/* JPEG horizontal resolution register lower byte */
+#define S5P_JPGX_L 0x24
+
+/* JPEG byte count register upper byte */
+#define S5P_JPGCNT_U 0x28
+
+/* JPEG byte count register middle byte */
+#define S5P_JPGCNT_M 0x2c
+
+/* JPEG byte count register lower byte */
+#define S5P_JPGCNT_L 0x30
+
+/* JPEG interrupt setting register */
+#define S5P_JPGINTSE 0x34
+#define S5P_RSTm_INT_EN_MASK (0x1 << 7)
+#define S5P_RSTm_INT_EN (0x1 << 7)
+#define S5P_DATA_NUM_INT_EN_MASK (0x1 << 6)
+#define S5P_DATA_NUM_INT_EN (0x1 << 6)
+#define S5P_FINAL_MCU_NUM_INT_EN_MASK (0x1 << 5)
+#define S5P_FINAL_MCU_NUM_INT_EN (0x1 << 5)
+
+/* JPEG interrupt status register */
+#define S5P_JPGINTST 0x38
+#define S5P_RESULT_STAT_SHIFT 6
+#define S5P_RESULT_STAT_MASK (0x1 << S5P_RESULT_STAT_SHIFT)
+#define S5P_STREAM_STAT_SHIFT 5
+#define S5P_STREAM_STAT_MASK (0x1 << S5P_STREAM_STAT_SHIFT)
+
+/* JPEG command register */
+#define S5P_JPGCOM 0x4c
+#define S5P_INT_RELEASE (0x1 << 2)
+
+/* Raw image data r/w address register */
+#define S5P_JPG_IMGADR 0x50
+
+/* JPEG file r/w address register */
+#define S5P_JPG_JPGADR 0x58
+
+/* Coefficient for RGB-to-YCbCr converter register */
+#define S5P_JPG_COEF(n) (0x5c + (((n) - 1) << 2))
+#define S5P_COEFn_SHIFT(j) ((3 - (j)) << 3)
+#define S5P_COEFn_MASK(j) (0xff << S5P_COEFn_SHIFT(j))
+
+/* JPEG color mode register */
+#define S5P_JPGCMOD 0x68
+#define S5P_MOD_SEL_MASK (0x7 << 5)
+#define S5P_MOD_SEL_422 (0x1 << 5)
+#define S5P_MOD_SEL_565 (0x2 << 5)
+#define S5P_MODE_Y16_MASK (0x1 << 1)
+#define S5P_MODE_Y16 (0x1 << 1)
+
+/* JPEG clock control register */
+#define S5P_JPGCLKCON 0x6c
+#define S5P_CLK_DOWN_READY (0x1 << 1)
+#define S5P_POWER_ON (0x1 << 0)
+
+/* JPEG start register */
+#define S5P_JSTART 0x70
+
+/* JPEG SW reset register */
+#define S5P_JPG_SW_RESET 0x78
+
+/* JPEG timer setting register */
+#define S5P_JPG_TIMER_SE 0x7c
+#define S5P_TIMER_INT_EN_MASK (0x1 << 31)
+#define S5P_TIMER_INT_EN (0x1 << 31)
+#define S5P_TIMER_INIT_MASK 0x7fffffff
+
+/* JPEG timer status register */
+#define S5P_JPG_TIMER_ST 0x80
+#define S5P_TIMER_INT_STAT_SHIFT 31
+#define S5P_TIMER_INT_STAT_MASK (0x1 << S5P_TIMER_INT_STAT_SHIFT)
+#define S5P_TIMER_CNT_SHIFT 0
+#define S5P_TIMER_CNT_MASK 0x7fffffff
+
+/* JPEG decompression output format register */
+#define S5P_JPG_OUTFORM 0x88
+#define S5P_DEC_OUT_FORMAT_MASK (0x1 << 0)
+#define S5P_DEC_OUT_FORMAT_422 (0x0 << 0)
+#define S5P_DEC_OUT_FORMAT_420 (0x1 << 0)
+
+/* JPEG version register */
+#define S5P_JPG_VERSION 0x8c
+
+/* JPEG compressed stream size interrupt setting register */
+#define S5P_JPG_ENC_STREAM_INTSE 0x98
+#define S5P_ENC_STREAM_INT_MASK (0x1 << 24)
+#define S5P_ENC_STREAM_INT_EN (0x1 << 24)
+#define S5P_ENC_STREAM_BOUND_MASK 0xffffff
+
+/* JPEG compressed stream size interrupt status register */
+#define S5P_JPG_ENC_STREAM_INTST 0x9c
+#define S5P_ENC_STREAM_INT_STAT_MASK 0x1
+
+/* JPEG quantizer table register */
+#define S5P_JPG_QTBL_CONTENT(n) (0x400 + (n) * 0x100)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBL(n) (0x800 + (n) * 0x400)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBLG(n) (0x840 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBL(n) (0x880 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBLG(n) (0x8c0 + (n) * 0x400)
+
+#endif /* JPEG_REGS_H_ */
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index 8be8b54..e43e128 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -1245,27 +1245,7 @@ static struct platform_driver s5p_mfc_driver = {
},
};
-static char banner[] __initdata =
- "S5P MFC V4L2 Driver, (C) 2011 Samsung Electronics\n";
-
-static int __init s5p_mfc_init(void)
-{
- int ret;
-
- pr_info("%s", banner);
- ret = platform_driver_register(&s5p_mfc_driver);
- if (ret)
- pr_err("Platform device registration failed.\n");
- return ret;
-}
-
-static void __exit s5p_mfc_exit(void)
-{
- platform_driver_unregister(&s5p_mfc_driver);
-}
-
-module_init(s5p_mfc_init);
-module_exit(s5p_mfc_exit);
+module_platform_driver(s5p_mfc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
index 0279e6e..8b41a04 100644
--- a/drivers/media/video/s5p-tv/hdmi_drv.c
+++ b/drivers/media/video/s5p-tv/hdmi_drv.c
@@ -838,8 +838,8 @@ static int hdmi_resources_init(struct hdmi_device *hdev)
dev_err(dev, "failed to get clock 'hdmiphy'\n");
goto fail;
}
- res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
- sizeof res->regul_bulk[0], GFP_KERNEL);
+ res->regul_bulk = kcalloc(ARRAY_SIZE(supply),
+ sizeof(res->regul_bulk[0]), GFP_KERNEL);
if (!res->regul_bulk) {
dev_err(dev, "failed to get memory for regulators\n");
goto fail;
@@ -1016,28 +1016,4 @@ static struct platform_driver hdmi_driver __refdata = {
}
};
-/* D R I V E R I N I T I A L I Z A T I O N */
-
-static int __init hdmi_init(void)
-{
- int ret;
- static const char banner[] __initdata = KERN_INFO \
- "Samsung HDMI output driver, "
- "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
- printk(banner);
-
- ret = platform_driver_register(&hdmi_driver);
- if (ret)
- printk(KERN_ERR "HDMI platform driver register failed\n");
-
- return ret;
-}
-module_init(hdmi_init);
-
-static void __exit hdmi_exit(void)
-{
- platform_driver_unregister(&hdmi_driver);
-}
-module_exit(hdmi_exit);
-
-
+module_platform_driver(hdmi_driver);
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
index 51ad59b3..1597078 100644
--- a/drivers/media/video/s5p-tv/mixer.h
+++ b/drivers/media/video/s5p-tv/mixer.h
@@ -86,6 +86,17 @@ struct mxr_crop {
unsigned int field;
};
+/** stages of geometry operations */
+enum mxr_geometry_stage {
+ MXR_GEOMETRY_SINK,
+ MXR_GEOMETRY_COMPOSE,
+ MXR_GEOMETRY_CROP,
+ MXR_GEOMETRY_SOURCE,
+};
+
+/* flag indicating that offset should be 0 */
+#define MXR_NO_OFFSET 0x80000000
+
/** description of transformation from source to destination image */
struct mxr_geometry {
/** cropping for source image */
@@ -133,7 +144,8 @@ struct mxr_layer_ops {
/** streaming stop/start */
void (*stream_set)(struct mxr_layer *, int);
/** adjusting geometry */
- void (*fix_geometry)(struct mxr_layer *);
+ void (*fix_geometry)(struct mxr_layer *,
+ enum mxr_geometry_stage, unsigned long);
};
/** layer instance, a single window and content displayed on output */
diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/video/s5p-tv/mixer_grp_layer.c
index de8270c..b93a21f 100644
--- a/drivers/media/video/s5p-tv/mixer_grp_layer.c
+++ b/drivers/media/video/s5p-tv/mixer_grp_layer.c
@@ -101,47 +101,132 @@ static void mxr_graph_format_set(struct mxr_layer *layer)
layer->fmt, &layer->geo);
}
-static void mxr_graph_fix_geometry(struct mxr_layer *layer)
+static inline unsigned int closest(unsigned int x, unsigned int a,
+ unsigned int b, unsigned long flags)
+{
+ unsigned int mid = (a + b) / 2;
+
+ /* choosing closest value with constraints according to table:
+ * -------------+-----+-----+-----+-------+
+ * flags | 0 | LE | GE | LE|GE |
+ * -------------+-----+-----+-----+-------+
+ * x <= a | a | a | a | a |
+ * a < x <= mid | a | a | b | a |
+ * mid < x < b | b | a | b | b |
+ * b <= x | b | b | b | b |
+ * -------------+-----+-----+-----+-------+
+ */
+
+ /* remove all non-constraint flags */
+ flags &= V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE;
+
+ if (x <= a)
+ return a;
+ if (x >= b)
+ return b;
+ if (flags == V4L2_SEL_FLAG_LE)
+ return a;
+ if (flags == V4L2_SEL_FLAG_GE)
+ return b;
+ if (x <= mid)
+ return a;
+ return b;
+}
+
+static inline unsigned int do_center(unsigned int center,
+ unsigned int size, unsigned int upper, unsigned int flags)
+{
+ unsigned int lower;
+
+ if (flags & MXR_NO_OFFSET)
+ return 0;
+
+ lower = center - min(center, size / 2);
+ return min(lower, upper - size);
+}
+
+static void mxr_graph_fix_geometry(struct mxr_layer *layer,
+ enum mxr_geometry_stage stage, unsigned long flags)
{
struct mxr_geometry *geo = &layer->geo;
+ struct mxr_crop *src = &geo->src;
+ struct mxr_crop *dst = &geo->dst;
+ unsigned int x_center, y_center;
- /* limit to boundary size */
- geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
- geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
- geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width);
- geo->src.width = min(geo->src.width, 2047U);
- /* not possible to crop of Y axis */
- geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1);
- geo->src.height = geo->src.full_height - geo->src.y_offset;
- /* limitting offset */
- geo->src.x_offset = min(geo->src.x_offset,
- geo->src.full_width - geo->src.width);
-
- /* setting position in output */
- geo->dst.width = min(geo->dst.width, geo->dst.full_width);
- geo->dst.height = min(geo->dst.height, geo->dst.full_height);
-
- /* Mixer supports only 1x and 2x scaling */
- if (geo->dst.width >= 2 * geo->src.width) {
- geo->x_ratio = 1;
- geo->dst.width = 2 * geo->src.width;
- } else {
- geo->x_ratio = 0;
- geo->dst.width = geo->src.width;
- }
+ switch (stage) {
- if (geo->dst.height >= 2 * geo->src.height) {
- geo->y_ratio = 1;
- geo->dst.height = 2 * geo->src.height;
- } else {
- geo->y_ratio = 0;
- geo->dst.height = geo->src.height;
- }
+ case MXR_GEOMETRY_SINK: /* nothing to be fixed here */
+ flags = 0;
+ /* fall through */
+
+ case MXR_GEOMETRY_COMPOSE:
+ /* remember center of the area */
+ x_center = dst->x_offset + dst->width / 2;
+ y_center = dst->y_offset + dst->height / 2;
+ /* round up/down to 2 multiple depending on flags */
+ if (flags & V4L2_SEL_FLAG_LE) {
+ dst->width = round_down(dst->width, 2);
+ dst->height = round_down(dst->height, 2);
+ } else {
+ dst->width = round_up(dst->width, 2);
+ dst->height = round_up(dst->height, 2);
+ }
+ /* assure that compose rect is inside display area */
+ dst->width = min(dst->width, dst->full_width);
+ dst->height = min(dst->height, dst->full_height);
+
+ /* ensure that compose is reachable using 2x scaling */
+ dst->width = min(dst->width, 2 * src->full_width);
+ dst->height = min(dst->height, 2 * src->full_height);
+
+ /* setup offsets */
+ dst->x_offset = do_center(x_center, dst->width,
+ dst->full_width, flags);
+ dst->y_offset = do_center(y_center, dst->height,
+ dst->full_height, flags);
+ flags = 0;
+ /* fall through */
- geo->dst.x_offset = min(geo->dst.x_offset,
- geo->dst.full_width - geo->dst.width);
- geo->dst.y_offset = min(geo->dst.y_offset,
- geo->dst.full_height - geo->dst.height);
+ case MXR_GEOMETRY_CROP:
+ /* remember center of the area */
+ x_center = src->x_offset + src->width / 2;
+ y_center = src->y_offset + src->height / 2;
+ /* ensure that cropping area lies inside the buffer */
+ if (src->full_width < dst->width)
+ src->width = dst->width / 2;
+ else
+ src->width = closest(src->width, dst->width / 2,
+ dst->width, flags);
+
+ if (src->width == dst->width)
+ geo->x_ratio = 0;
+ else
+ geo->x_ratio = 1;
+
+ if (src->full_height < dst->height)
+ src->height = dst->height / 2;
+ else
+ src->height = closest(src->height, dst->height / 2,
+ dst->height, flags);
+
+ if (src->height == dst->height)
+ geo->y_ratio = 0;
+ else
+ geo->y_ratio = 1;
+
+ /* setup offsets */
+ src->x_offset = do_center(x_center, src->width,
+ src->full_width, flags);
+ src->y_offset = do_center(y_center, src->height,
+ src->full_height, flags);
+ flags = 0;
+ /* fall through */
+ case MXR_GEOMETRY_SOURCE:
+ src->full_width = clamp_val(src->full_width,
+ src->width + src->x_offset, 32767);
+ src->full_height = clamp_val(src->full_height,
+ src->height + src->y_offset, 2047);
+ };
}
/* PUBLIC API */
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index b47d0c0..7884bae 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -170,18 +170,22 @@ static int mxr_querycap(struct file *file, void *priv,
return 0;
}
-/* Geometry handling */
-static void mxr_layer_geo_fix(struct mxr_layer *layer)
+static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo)
{
- struct mxr_device *mdev = layer->mdev;
- struct v4l2_mbus_framefmt mbus_fmt;
-
- /* TODO: add some dirty flag to avoid unnecessary adjustments */
- mxr_get_mbus_fmt(mdev, &mbus_fmt);
- layer->geo.dst.full_width = mbus_fmt.width;
- layer->geo.dst.full_height = mbus_fmt.height;
- layer->geo.dst.field = mbus_fmt.field;
- layer->ops.fix_geometry(layer);
+ mxr_dbg(mdev, "src.full_size = (%u, %u)\n",
+ geo->src.full_width, geo->src.full_height);
+ mxr_dbg(mdev, "src.size = (%u, %u)\n",
+ geo->src.width, geo->src.height);
+ mxr_dbg(mdev, "src.offset = (%u, %u)\n",
+ geo->src.x_offset, geo->src.y_offset);
+ mxr_dbg(mdev, "dst.full_size = (%u, %u)\n",
+ geo->dst.full_width, geo->dst.full_height);
+ mxr_dbg(mdev, "dst.size = (%u, %u)\n",
+ geo->dst.width, geo->dst.height);
+ mxr_dbg(mdev, "dst.offset = (%u, %u)\n",
+ geo->dst.x_offset, geo->dst.y_offset);
+ mxr_dbg(mdev, "ratio = (%u, %u)\n",
+ geo->x_ratio, geo->y_ratio);
}
static void mxr_layer_default_geo(struct mxr_layer *layer)
@@ -204,27 +208,29 @@ static void mxr_layer_default_geo(struct mxr_layer *layer)
layer->geo.src.width = layer->geo.src.full_width;
layer->geo.src.height = layer->geo.src.full_height;
- layer->ops.fix_geometry(layer);
+ mxr_geometry_dump(mdev, &layer->geo);
+ layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
+ mxr_geometry_dump(mdev, &layer->geo);
}
-static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo)
+static void mxr_layer_update_output(struct mxr_layer *layer)
{
- mxr_dbg(mdev, "src.full_size = (%u, %u)\n",
- geo->src.full_width, geo->src.full_height);
- mxr_dbg(mdev, "src.size = (%u, %u)\n",
- geo->src.width, geo->src.height);
- mxr_dbg(mdev, "src.offset = (%u, %u)\n",
- geo->src.x_offset, geo->src.y_offset);
- mxr_dbg(mdev, "dst.full_size = (%u, %u)\n",
- geo->dst.full_width, geo->dst.full_height);
- mxr_dbg(mdev, "dst.size = (%u, %u)\n",
- geo->dst.width, geo->dst.height);
- mxr_dbg(mdev, "dst.offset = (%u, %u)\n",
- geo->dst.x_offset, geo->dst.y_offset);
- mxr_dbg(mdev, "ratio = (%u, %u)\n",
- geo->x_ratio, geo->y_ratio);
-}
+ struct mxr_device *mdev = layer->mdev;
+ struct v4l2_mbus_framefmt mbus_fmt;
+
+ mxr_get_mbus_fmt(mdev, &mbus_fmt);
+ /* checking if update is needed */
+ if (layer->geo.dst.full_width == mbus_fmt.width &&
+ layer->geo.dst.full_height == mbus_fmt.width)
+ return;
+ layer->geo.dst.full_width = mbus_fmt.width;
+ layer->geo.dst.full_height = mbus_fmt.height;
+ layer->geo.dst.field = mbus_fmt.field;
+ layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0);
+
+ mxr_geometry_dump(mdev, &layer->geo);
+}
static const struct mxr_format *find_format_by_fourcc(
struct mxr_layer *layer, unsigned long fourcc);
@@ -249,37 +255,6 @@ static int mxr_enum_fmt(struct file *file, void *priv,
return 0;
}
-static int mxr_s_fmt(struct file *file, void *priv,
- struct v4l2_format *f)
-{
- struct mxr_layer *layer = video_drvdata(file);
- const struct mxr_format *fmt;
- struct v4l2_pix_format_mplane *pix;
- struct mxr_device *mdev = layer->mdev;
- struct mxr_geometry *geo = &layer->geo;
-
- mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
-
- pix = &f->fmt.pix_mp;
- fmt = find_format_by_fourcc(layer, pix->pixelformat);
- if (fmt == NULL) {
- mxr_warn(mdev, "not recognized fourcc: %08x\n",
- pix->pixelformat);
- return -EINVAL;
- }
- layer->fmt = fmt;
- geo->src.full_width = pix->width;
- geo->src.width = pix->width;
- geo->src.full_height = pix->height;
- geo->src.height = pix->height;
- /* assure consistency of geometry */
- mxr_layer_geo_fix(layer);
- mxr_dbg(mdev, "width=%u height=%u span=%u\n",
- geo->src.width, geo->src.height, geo->src.full_width);
-
- return 0;
-}
-
static unsigned int divup(unsigned int divident, unsigned int divisor)
{
return (divident + divisor - 1) / divisor;
@@ -299,6 +274,10 @@ static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes,
{
int i;
+ /* checking if nothing to fill */
+ if (!planes)
+ return;
+
memset(planes, 0, sizeof(*planes) * fmt->num_subframes);
for (i = 0; i < fmt->num_planes; ++i) {
struct v4l2_plane_pix_format *plane = planes
@@ -332,73 +311,194 @@ static int mxr_g_fmt(struct file *file, void *priv,
return 0;
}
-static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo,
- enum v4l2_buf_type type)
-{
- switch (type) {
- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- return &geo->dst;
- case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- return &geo->src;
- default:
- return NULL;
- }
-}
-
-static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+static int mxr_s_fmt(struct file *file, void *priv,
+ struct v4l2_format *f)
{
struct mxr_layer *layer = video_drvdata(file);
- struct mxr_crop *crop;
+ const struct mxr_format *fmt;
+ struct v4l2_pix_format_mplane *pix;
+ struct mxr_device *mdev = layer->mdev;
+ struct mxr_geometry *geo = &layer->geo;
- mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
- crop = choose_crop_by_type(&layer->geo, a->type);
- if (crop == NULL)
+ mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
+
+ pix = &f->fmt.pix_mp;
+ fmt = find_format_by_fourcc(layer, pix->pixelformat);
+ if (fmt == NULL) {
+ mxr_warn(mdev, "not recognized fourcc: %08x\n",
+ pix->pixelformat);
return -EINVAL;
- mxr_layer_geo_fix(layer);
- a->c.left = crop->x_offset;
- a->c.top = crop->y_offset;
- a->c.width = crop->width;
- a->c.height = crop->height;
+ }
+ layer->fmt = fmt;
+ /* set source size to highest accepted value */
+ geo->src.full_width = max(geo->dst.full_width, pix->width);
+ geo->src.full_height = max(geo->dst.full_height, pix->height);
+ layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
+ mxr_geometry_dump(mdev, &layer->geo);
+ /* set cropping to total visible screen */
+ geo->src.width = pix->width;
+ geo->src.height = pix->height;
+ geo->src.x_offset = 0;
+ geo->src.y_offset = 0;
+ /* assure consistency of geometry */
+ layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET);
+ mxr_geometry_dump(mdev, &layer->geo);
+ /* set full size to lowest possible value */
+ geo->src.full_width = 0;
+ geo->src.full_height = 0;
+ layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0);
+ mxr_geometry_dump(mdev, &layer->geo);
+
+ /* returning results */
+ mxr_g_fmt(file, priv, f);
+
return 0;
}
-static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+static int mxr_g_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
{
struct mxr_layer *layer = video_drvdata(file);
- struct mxr_crop *crop;
+ struct mxr_geometry *geo = &layer->geo;
mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
- crop = choose_crop_by_type(&layer->geo, a->type);
- if (crop == NULL)
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return -EINVAL;
+
+ switch (s->target) {
+ case V4L2_SEL_TGT_CROP_ACTIVE:
+ s->r.left = geo->src.x_offset;
+ s->r.top = geo->src.y_offset;
+ s->r.width = geo->src.width;
+ s->r.height = geo->src.height;
+ break;
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ s->r.left = 0;
+ s->r.top = 0;
+ s->r.width = geo->src.full_width;
+ s->r.height = geo->src.full_height;
+ break;
+ case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
+ s->r.left = geo->dst.x_offset;
+ s->r.top = geo->dst.y_offset;
+ s->r.width = geo->dst.width;
+ s->r.height = geo->dst.height;
+ break;
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ s->r.left = 0;
+ s->r.top = 0;
+ s->r.width = geo->dst.full_width;
+ s->r.height = geo->dst.full_height;
+ break;
+ default:
return -EINVAL;
- crop->x_offset = a->c.left;
- crop->y_offset = a->c.top;
- crop->width = a->c.width;
- crop->height = a->c.height;
- mxr_layer_geo_fix(layer);
+ }
+
return 0;
}
-static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
+/* returns 1 if rectangle 'a' is inside 'b' */
+static int mxr_is_rect_inside(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+ if (a->left < b->left)
+ return 0;
+ if (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 mxr_s_selection(struct file *file, void *fh,
+ struct v4l2_selection *s)
{
struct mxr_layer *layer = video_drvdata(file);
- struct mxr_crop *crop;
+ struct mxr_geometry *geo = &layer->geo;
+ struct mxr_crop *target = NULL;
+ enum mxr_geometry_stage stage;
+ struct mxr_geometry tmp;
+ struct v4l2_rect res;
- mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
- crop = choose_crop_by_type(&layer->geo, a->type);
- if (crop == NULL)
+ memset(&res, 0, sizeof res);
+
+ mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__,
+ s->r.width, s->r.height, s->r.left, s->r.top);
+
+ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
return -EINVAL;
- mxr_layer_geo_fix(layer);
- a->bounds.left = 0;
- a->bounds.top = 0;
- a->bounds.width = crop->full_width;
- a->bounds.top = crop->full_height;
- a->defrect = a->bounds;
- /* setting pixel aspect to 1/1 */
- a->pixelaspect.numerator = 1;
- a->pixelaspect.denominator = 1;
+
+ switch (s->target) {
+ /* ignore read-only targets */
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ res.width = geo->src.full_width;
+ res.height = geo->src.full_height;
+ break;
+
+ /* ignore read-only targets */
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ res.width = geo->dst.full_width;
+ res.height = geo->dst.full_height;
+ break;
+
+ case V4L2_SEL_TGT_CROP_ACTIVE:
+ target = &geo->src;
+ stage = MXR_GEOMETRY_CROP;
+ break;
+ case V4L2_SEL_TGT_COMPOSE_ACTIVE:
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
+ target = &geo->dst;
+ stage = MXR_GEOMETRY_COMPOSE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* apply change and update geometry if needed */
+ if (target) {
+ /* backup current geometry if setup fails */
+ memcpy(&tmp, geo, sizeof tmp);
+
+ /* apply requested selection */
+ target->x_offset = s->r.left;
+ target->y_offset = s->r.top;
+ target->width = s->r.width;
+ target->height = s->r.height;
+
+ layer->ops.fix_geometry(layer, stage, s->flags);
+
+ /* retrieve update selection rectangle */
+ res.left = target->x_offset;
+ res.top = target->y_offset;
+ res.width = target->width;
+ res.height = target->height;
+
+ mxr_geometry_dump(layer->mdev, &layer->geo);
+ }
+
+ /* checking if the rectangle satisfies constraints */
+ if ((s->flags & V4L2_SEL_FLAG_LE) && !mxr_is_rect_inside(&res, &s->r))
+ goto fail;
+ if ((s->flags & V4L2_SEL_FLAG_GE) && !mxr_is_rect_inside(&s->r, &res))
+ goto fail;
+
+ /* return result rectangle */
+ s->r = res;
+
return 0;
+fail:
+ /* restore old geometry, which is not touched if target is NULL */
+ if (target)
+ memcpy(geo, &tmp, sizeof tmp);
+ return -ERANGE;
}
static int mxr_enum_dv_presets(struct file *file, void *fh,
@@ -438,6 +538,8 @@ static int mxr_s_dv_preset(struct file *file, void *fh,
mutex_unlock(&mdev->mutex);
+ mxr_layer_update_output(layer);
+
/* any failure should return EINVAL according to V4L2 doc */
return ret ? -EINVAL : 0;
}
@@ -478,6 +580,8 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
mutex_unlock(&mdev->mutex);
+ mxr_layer_update_output(layer);
+
return ret ? -EINVAL : 0;
}
@@ -526,25 +630,27 @@ static int mxr_s_output(struct file *file, void *fh, unsigned int i)
struct video_device *vfd = video_devdata(file);
struct mxr_layer *layer = video_drvdata(file);
struct mxr_device *mdev = layer->mdev;
- int ret = 0;
if (i >= mdev->output_cnt || mdev->output[i] == NULL)
return -EINVAL;
mutex_lock(&mdev->mutex);
if (mdev->n_output > 0) {
- ret = -EBUSY;
- goto done;
+ mutex_unlock(&mdev->mutex);
+ return -EBUSY;
}
mdev->current_output = i;
vfd->tvnorms = 0;
v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output,
&vfd->tvnorms);
+ mutex_unlock(&mdev->mutex);
+
+ /* update layers geometry */
+ mxr_layer_update_output(layer);
+
mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms);
-done:
- mutex_unlock(&mdev->mutex);
- return ret;
+ return 0;
}
static int mxr_g_output(struct file *file, void *fh, unsigned int *p)
@@ -633,10 +739,9 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
.vidioc_enum_output = mxr_enum_output,
.vidioc_s_output = mxr_s_output,
.vidioc_g_output = mxr_g_output,
- /* Crop ioctls */
- .vidioc_g_crop = mxr_g_crop,
- .vidioc_s_crop = mxr_s_crop,
- .vidioc_cropcap = mxr_cropcap,
+ /* selection ioctls */
+ .vidioc_g_selection = mxr_g_selection,
+ .vidioc_s_selection = mxr_s_selection,
};
static int mxr_video_open(struct file *file)
@@ -805,10 +910,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
/* block any changes in output configuration */
mxr_output_get(mdev);
- /* update layers geometry */
- mxr_layer_geo_fix(layer);
- mxr_geometry_dump(mdev, &layer->geo);
-
+ mxr_layer_update_output(layer);
layer->ops.format_set(layer);
/* enabling layer in hardware */
spin_lock_irqsave(&layer->enq_slock, flags);
diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/video/s5p-tv/mixer_vp_layer.c
index f3bb2e3..3d13a63 100644
--- a/drivers/media/video/s5p-tv/mixer_vp_layer.c
+++ b/drivers/media/video/s5p-tv/mixer_vp_layer.c
@@ -127,47 +127,77 @@ static void mxr_vp_format_set(struct mxr_layer *layer)
mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo);
}
-static void mxr_vp_fix_geometry(struct mxr_layer *layer)
+static inline unsigned int do_center(unsigned int center,
+ unsigned int size, unsigned int upper, unsigned int flags)
{
- struct mxr_geometry *geo = &layer->geo;
+ unsigned int lower;
+
+ if (flags & MXR_NO_OFFSET)
+ return 0;
+
+ lower = center - min(center, size / 2);
+ return min(lower, upper - size);
+}
- /* align horizontal size to 8 pixels */
- geo->src.full_width = ALIGN(geo->src.full_width, 8);
- /* limit to boundary size */
- geo->src.full_width = clamp_val(geo->src.full_width, 8, 8192);
- geo->src.full_height = clamp_val(geo->src.full_height, 1, 8192);
- geo->src.width = clamp_val(geo->src.width, 32, geo->src.full_width);
- geo->src.width = min(geo->src.width, 2047U);
- geo->src.height = clamp_val(geo->src.height, 4, geo->src.full_height);
- geo->src.height = min(geo->src.height, 2047U);
-
- /* setting size of output window */
- geo->dst.width = clamp_val(geo->dst.width, 8, geo->dst.full_width);
- geo->dst.height = clamp_val(geo->dst.height, 1, geo->dst.full_height);
-
- /* ensure that scaling is in range 1/4x to 16x */
- if (geo->src.width >= 4 * geo->dst.width)
- geo->src.width = 4 * geo->dst.width;
- if (geo->dst.width >= 16 * geo->src.width)
- geo->dst.width = 16 * geo->src.width;
- if (geo->src.height >= 4 * geo->dst.height)
- geo->src.height = 4 * geo->dst.height;
- if (geo->dst.height >= 16 * geo->src.height)
- geo->dst.height = 16 * geo->src.height;
-
- /* setting scaling ratio */
- geo->x_ratio = (geo->src.width << 16) / geo->dst.width;
- geo->y_ratio = (geo->src.height << 16) / geo->dst.height;
-
- /* adjust offsets */
- geo->src.x_offset = min(geo->src.x_offset,
- geo->src.full_width - geo->src.width);
- geo->src.y_offset = min(geo->src.y_offset,
- geo->src.full_height - geo->src.height);
- geo->dst.x_offset = min(geo->dst.x_offset,
- geo->dst.full_width - geo->dst.width);
- geo->dst.y_offset = min(geo->dst.y_offset,
- geo->dst.full_height - geo->dst.height);
+static void mxr_vp_fix_geometry(struct mxr_layer *layer,
+ enum mxr_geometry_stage stage, unsigned long flags)
+{
+ struct mxr_geometry *geo = &layer->geo;
+ struct mxr_crop *src = &geo->src;
+ struct mxr_crop *dst = &geo->dst;
+ unsigned long x_center, y_center;
+
+ switch (stage) {
+
+ case MXR_GEOMETRY_SINK: /* nothing to be fixed here */
+ case MXR_GEOMETRY_COMPOSE:
+ /* remember center of the area */
+ x_center = dst->x_offset + dst->width / 2;
+ y_center = dst->y_offset + dst->height / 2;
+
+ /* ensure that compose is reachable using 16x scaling */
+ dst->width = clamp(dst->width, 8U, 16 * src->full_width);
+ dst->height = clamp(dst->height, 1U, 16 * src->full_height);
+
+ /* setup offsets */
+ dst->x_offset = do_center(x_center, dst->width,
+ dst->full_width, flags);
+ dst->y_offset = do_center(y_center, dst->height,
+ dst->full_height, flags);
+ flags = 0; /* remove possible MXR_NO_OFFSET flag */
+ /* fall through */
+ case MXR_GEOMETRY_CROP:
+ /* remember center of the area */
+ x_center = src->x_offset + src->width / 2;
+ y_center = src->y_offset + src->height / 2;
+
+ /* ensure scaling is between 0.25x .. 16x */
+ src->width = clamp(src->width, round_up(dst->width / 16, 4),
+ dst->width * 4);
+ src->height = clamp(src->height, round_up(dst->height / 16, 4),
+ dst->height * 4);
+
+ /* hardware limits */
+ src->width = clamp(src->width, 32U, 2047U);
+ src->height = clamp(src->height, 4U, 2047U);
+
+ /* setup offsets */
+ src->x_offset = do_center(x_center, src->width,
+ src->full_width, flags);
+ src->y_offset = do_center(y_center, src->height,
+ src->full_height, flags);
+
+ /* setting scaling ratio */
+ geo->x_ratio = (src->width << 16) / dst->width;
+ geo->y_ratio = (src->height << 16) / dst->height;
+ /* fall through */
+
+ case MXR_GEOMETRY_SOURCE:
+ src->full_width = clamp(src->full_width,
+ ALIGN(src->width + src->x_offset, 8), 8192U);
+ src->full_height = clamp(src->full_height,
+ src->height + src->y_offset, 8192U);
+ };
}
/* PUBLIC API */
diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/video/s5p-tv/sdo_drv.c
index 8cec67e..059e774 100644
--- a/drivers/media/video/s5p-tv/sdo_drv.c
+++ b/drivers/media/video/s5p-tv/sdo_drv.c
@@ -457,24 +457,4 @@ static struct platform_driver sdo_driver __refdata = {
}
};
-static int __init sdo_init(void)
-{
- int ret;
- static const char banner[] __initdata = KERN_INFO \
- "Samsung Standard Definition Output (SDO) driver, "
- "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
- printk(banner);
-
- ret = platform_driver_register(&sdo_driver);
- if (ret)
- printk(KERN_ERR "SDO platform driver register failed\n");
-
- return ret;
-}
-module_init(sdo_init);
-
-static void __exit sdo_exit(void)
-{
- platform_driver_unregister(&sdo_driver);
-}
-module_exit(sdo_exit);
+module_platform_driver(sdo_driver);
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 5cfdbc7..0ef5484 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -57,7 +57,7 @@ MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
"Hans Verkuil, Mauro Carvalho Chehab");
MODULE_LICENSE("GPL");
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 0f9fb99..065d0f6 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -5691,6 +5691,27 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_SENSORAY811_911] = {
+ .name = "Sensoray 811/911",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ }, {
+ .name = name_comp3,
+ .vmux = 2,
+ .amux = LINE1,
+ }, {
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ } },
+ },
};
@@ -6914,6 +6935,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0xd136,
.driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x6000,
+ .subdevice = 0x0811,
+ .driver_data = SAA7134_BOARD_SENSORAY811_911,
+ }, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x6000,
+ .subdevice = 0x0911,
+ .driver_data = SAA7134_BOARD_SENSORAY811_911,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index ca65cda..5fbb4e4 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1263,7 +1263,6 @@ static int saa7134_resume(struct pci_dev *pci_dev)
saa7134_tvaudio_setmute(dev);
saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
saa7134_tvaudio_init(dev);
- saa7134_tvaudio_do_scan(dev);
saa7134_enable_i2s(dev);
saa7134_hw_enable2(dev);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 1e4ef16..089fa0f 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -183,9 +183,9 @@ static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe)
return 0;
}
-static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+static int mt352_pinnacle_tuner_set_params(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u8 off[] = { 0x00, 0xf1};
u8 on[] = { 0x00, 0x71};
struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)};
@@ -196,7 +196,7 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
/* set frequency (mt2050) */
f.tuner = 0;
f.type = V4L2_TUNER_DIGITAL_TV;
- f.frequency = params->frequency / 1000 * 16 / 1000;
+ f.frequency = c->frequency / 1000 * 16 / 1000;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(&dev->i2c_adap, &msg, 1);
@@ -287,8 +287,9 @@ static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
* these tuners are tu1216, td1316(a)
*/
-static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda6651_pll_set(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct saa7134_dev *dev = fe->dvb->priv;
struct tda1004x_state *state = fe->demodulator_priv;
u8 addr = state->config->tuner_address;
@@ -299,7 +300,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
u8 band, cp, filter;
/* determine charge pump */
- tuner_frequency = params->frequency + 36166000;
+ tuner_frequency = c->frequency + 36166000;
if (tuner_frequency < 87000000)
return -EINVAL;
else if (tuner_frequency < 130000000)
@@ -324,28 +325,28 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
return -EINVAL;
/* determine band */
- if (params->frequency < 49000000)
+ if (c->frequency < 49000000)
return -EINVAL;
- else if (params->frequency < 161000000)
+ else if (c->frequency < 161000000)
band = 1;
- else if (params->frequency < 444000000)
+ else if (c->frequency < 444000000)
band = 2;
- else if (params->frequency < 861000000)
+ else if (c->frequency < 861000000)
band = 4;
else
return -EINVAL;
/* setup PLL filter */
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
+ switch (c->bandwidth_hz) {
+ case 6000000:
filter = 0;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
filter = 0;
break;
- case BANDWIDTH_8_MHZ:
+ case 8000000:
filter = 1;
break;
@@ -356,7 +357,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
/* calculate divisor
* ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
*/
- tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
+ tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
/* setup tuner buffer */
tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
@@ -436,9 +437,9 @@ static int philips_td1316_tuner_init(struct dvb_frontend *fe)
return 0;
}
-static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_td1316_tuner_set_params(struct dvb_frontend *fe)
{
- return philips_tda6651_pll_set(fe, params);
+ return philips_tda6651_pll_set(fe);
}
static int philips_td1316_tuner_sleep(struct dvb_frontend *fe)
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index d4ee24b..22ecd72 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -235,22 +235,25 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
- unsigned char buf[5], cod4, code3, code4;
+ unsigned char buf[5];
/* poll IR chip */
if (5 != i2c_master_recv(ir->c, buf, 5))
return -EIO;
- cod4 = buf[4];
- code4 = (cod4 >> 2);
- code3 = buf[3];
- if (code3 == 0)
- /* no key pressed */
+ /* Check if some key were pressed */
+ if (!(buf[0] & 0x80))
return 0;
- /* return key */
- *ir_key = code4;
- *ir_raw = code4;
+ /*
+ * buf[3] & 0x80 is always high.
+ * buf[3] & 0x40 is a parity bit. A repeat event is marked
+ * by preserving it into two separate readings
+ * buf[4] bits 0 and 1, and buf[1] and buf[2] are always
+ * zero.
+ */
+ *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
+ *ir_raw = *ir_key;
return 1;
}
@@ -752,7 +755,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
polling = 50; /* ms */
break;
case SAA7134_BOARD_VIDEOMATE_M1F:
- ir_codes = RC_MAP_VIDEOMATE_M1F;
+ ir_codes = RC_MAP_VIDEOMATE_K100;
mask_keycode = 0x0ff00;
mask_keyup = 0x040000;
break;
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 57e646b..b7a99be 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -332,6 +332,13 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
{
__s32 left,right,value;
+ if (!(dev->tvnorm->id & scan->std)) {
+ value = 0;
+ dprintk("skipping %d.%03d MHz [%4s]\n",
+ scan->carr / 1000, scan->carr % 1000, scan->name);
+ return 0;
+ }
+
if (audio_debug > 1) {
int i;
dprintk("debug %d:",scan->carr);
@@ -348,30 +355,25 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
}
printk("\n");
}
- if (dev->tvnorm->id & scan->std) {
- tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
- saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
- if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
- return -1;
- left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
- tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
- saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
- if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
- return -1;
- right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
- left >>= 16;
- right >>= 16;
- value = left > right ? left - right : right - left;
- dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n",
- scan->carr / 1000, scan->carr % 1000,
- scan->name, value, left, right);
- } else {
- value = 0;
- dprintk("skipping %d.%03d MHz [%4s]\n",
- scan->carr / 1000, scan->carr % 1000, scan->name);
- }
+
+ tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
+ saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+ return -1;
+ left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+ tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
+ saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+ if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+ return -1;
+ right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+ left >>= 16;
+ right >>= 16;
+ value = left > right ? left - right : right - left;
+ dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n",
+ scan->carr / 1000, scan->carr % 1000,
+ scan->name, value, left, right);
return value;
}
@@ -546,6 +548,7 @@ static int tvaudio_thread(void *data)
dev->tvnorm->name, carrier/1000, carrier%1000,
max1, max2);
dev->last_carrier = carrier;
+ dev->automute = 0;
} else if (0 != dev->last_carrier) {
/* no carrier -- try last detected one as fallback */
@@ -553,6 +556,7 @@ static int tvaudio_thread(void *data)
dprintk("audio carrier scan failed, "
"using %d.%03d MHz [last detected]\n",
carrier/1000, carrier%1000);
+ dev->automute = 1;
} else {
/* no carrier + no fallback -- use default */
@@ -560,9 +564,9 @@ static int tvaudio_thread(void *data)
dprintk("audio carrier scan failed, "
"using %d.%03d MHz [default]\n",
carrier/1000, carrier%1000);
+ dev->automute = 1;
}
tvaudio_setcarrier(dev,carrier,carrier);
- dev->automute = 0;
saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
saa7134_tvaudio_setmute(dev);
/* find the exact tv audio norm */
@@ -601,7 +605,7 @@ static int tvaudio_thread(void *data)
if (kthread_should_stop())
break;
if (UNSET == dev->thread.mode) {
- rx = tvaudio_getstereo(dev,&tvaudio[i]);
+ rx = tvaudio_getstereo(dev, &tvaudio[audio]);
mode = saa7134_tvaudio_rx2mode(rx);
} else {
mode = dev->thread.mode;
@@ -1020,6 +1024,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
}
dev->thread.thread = NULL;
+ dev->thread.scan1 = dev->thread.scan2 = 0;
if (my_thread) {
saa7134_tvaudio_init(dev);
/* start tvaudio thread */
@@ -1029,13 +1034,19 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
dev->name);
/* XXX: missing error handling here */
}
- saa7134_tvaudio_do_scan(dev);
}
saa7134_enable_i2s(dev);
return 0;
}
+int saa7134_tvaudio_close(struct saa7134_dev *dev)
+{
+ dev->automute = 1;
+ /* anything else to undo? */
+ return 0;
+}
+
int saa7134_tvaudio_fini(struct saa7134_dev *dev)
{
/* shutdown tvaudio thread */
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 9cf7914f..417034e 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1462,6 +1462,8 @@ static int video_release(struct file *file)
struct saa6588_command cmd;
unsigned long flags;
+ saa7134_tvaudio_close(dev);
+
/* turn off overlay */
if (res_check(fh, RESOURCE_OVERLAY)) {
spin_lock_irqsave(&dev->slock,flags);
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 9b55068..42fba4f 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -330,6 +330,7 @@ struct saa7134_card_ir {
#define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185
#define SAA7134_BOARD_BEHOLD_501 186
#define SAA7134_BOARD_BEHOLD_503FM 187
+#define SAA7134_BOARD_SENSORAY811_911 188
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
@@ -817,6 +818,7 @@ void saa7134_tvaudio_init(struct saa7134_dev *dev);
int saa7134_tvaudio_init2(struct saa7134_dev *dev);
int saa7134_tvaudio_fini(struct saa7134_dev *dev);
int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
+int saa7134_tvaudio_close(struct saa7134_dev *dev);
int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
index 466e1b0..a7f58a9 100644
--- a/drivers/media/video/saa7164/saa7164-bus.c
+++ b/drivers/media/video/saa7164/saa7164-bus.c
@@ -149,7 +149,7 @@ int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
saa7164_bus_verify(dev);
msg->size = cpu_to_le16(msg->size);
- msg->command = cpu_to_le16(msg->command);
+ msg->command = cpu_to_le32(msg->command);
msg->controlselector = cpu_to_le16(msg->controlselector);
if (msg->size > dev->bus.m_wMaxReqSize) {
@@ -464,7 +464,7 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
peekout:
msg->size = le16_to_cpu(msg->size);
- msg->command = le16_to_cpu(msg->command);
+ msg->command = le32_to_cpu(msg->command);
msg->controlselector = le16_to_cpu(msg->controlselector);
ret = SAA_OK;
out:
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index c51decf..f854d85 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -786,8 +786,7 @@ static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev,
V4L2_MBUS_DATA_ACTIVE_HIGH)
/* Capture is not running, no interrupts, no locking needed */
-static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
- __u32 pixfmt)
+static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -925,11 +924,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
ceu_write(pcdev, CDOCR, value);
ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
- dev_dbg(icd->parent, "S_FMT successful for %c%c%c%c %ux%u\n",
- pixfmt & 0xff, (pixfmt >> 8) & 0xff,
- (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff,
- icd->user_width, icd->user_height);
-
capture_restore(pcdev, capsr);
/* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */
@@ -1966,8 +1960,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
if (!ret) {
icd->user_width = out_width & ~3;
icd->user_height = out_height & ~3;
- ret = sh_mobile_ceu_set_bus_param(icd,
- icd->current_fmt->host_fmt->fourcc);
+ ret = sh_mobile_ceu_set_bus_param(icd);
}
}
diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c
index 8a652b5..0528650 100644
--- a/drivers/media/video/sh_mobile_csi2.c
+++ b/drivers/media/video/sh_mobile_csi2.c
@@ -390,18 +390,7 @@ static struct platform_driver __refdata sh_csi2_pdrv = {
},
};
-static int __init sh_csi2_init(void)
-{
- return platform_driver_register(&sh_csi2_pdrv);
-}
-
-static void __exit sh_csi2_exit(void)
-{
- platform_driver_unregister(&sh_csi2_pdrv);
-}
-
-module_init(sh_csi2_init);
-module_exit(sh_csi2_exit);
+module_platform_driver(sh_csi2_pdrv);
MODULE_DESCRIPTION("SH-Mobile MIPI CSI-2 driver");
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 7025be1..c2882fa 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -75,8 +75,8 @@ MODULE_PARM_DESC(video_nr,
"\none and for every other camera."
"\n");
-static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
- SN9C102_FORCE_MUNMAP};
+static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
+ SN9C102_FORCE_MUNMAP};
module_param_array(force_munmap, bool, NULL, 0444);
MODULE_PARM_DESC(force_munmap,
" <0|1[,...]>"
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 62e4312..b827107 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -487,7 +487,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
icd->user_width, icd->user_height);
/* set physical bus parameters */
- return ici->ops->set_bus_param(icd, pix->pixelformat);
+ return ici->ops->set_bus_param(icd);
}
static int soc_camera_open(struct file *file)
@@ -600,9 +600,9 @@ static int soc_camera_close(struct file *file)
pm_runtime_suspend(&icd->vdev->dev);
pm_runtime_disable(&icd->vdev->dev);
- ici->ops->remove(icd);
if (ici->ops->init_videobuf2)
vb2_queue_release(&icd->vb2_vidq);
+ ici->ops->remove(icd);
soc_camera_power_off(icd, icl);
}
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 4402a8a..f59ccad 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -189,18 +189,7 @@ static struct platform_driver soc_camera_platform_driver = {
.remove = soc_camera_platform_remove,
};
-static int __init soc_camera_platform_module_init(void)
-{
- return platform_driver_register(&soc_camera_platform_driver);
-}
-
-static void __exit soc_camera_platform_module_exit(void)
-{
- platform_driver_unregister(&soc_camera_platform_driver);
-}
-
-module_init(soc_camera_platform_module_init);
-module_exit(soc_camera_platform_module_exit);
+module_platform_driver(soc_camera_platform_driver);
MODULE_DESCRIPTION("SoC Camera Platform driver");
MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index b7fb5a5..d427f84 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -38,11 +38,11 @@
#include "stk-webcam.h"
-static int hflip = 1;
+static bool hflip = 1;
module_param(hflip, bool, 0444);
MODULE_PARM_DESC(hflip, "Horizontal image flip (mirror). Defaults to 1");
-static int vflip = 1;
+static bool vflip = 1;
module_param(vflip, bool, 0444);
MODULE_PARM_DESC(vflip, "Vertical image flip. Defaults to 1");
@@ -377,8 +377,8 @@ static int stk_prepare_iso(struct stk_camera *dev)
if (dev->isobufs)
STK_ERROR("isobufs already allocated. Bad\n");
else
- dev->isobufs = kzalloc(MAX_ISO_BUFS * sizeof(*dev->isobufs),
- GFP_KERNEL);
+ dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs),
+ GFP_KERNEL);
if (dev->isobufs == NULL) {
STK_ERROR("Unable to allocate iso buffers\n");
return -ENOMEM;
diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c
index a0895bf..4ed1c7c2 100644
--- a/drivers/media/video/timblogiw.c
+++ b/drivers/media/video/timblogiw.c
@@ -565,7 +565,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
spin_unlock_irq(&fh->queue_lock);
desc = fh->chan->device->device_prep_slave_sg(fh->chan,
- buf->sg, sg_elems, DMA_FROM_DEVICE,
+ buf->sg, sg_elems, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
if (!desc) {
spin_lock_irq(&fh->queue_lock);
@@ -872,20 +872,7 @@ static struct platform_driver timblogiw_platform_driver = {
.remove = __devexit_p(timblogiw_remove),
};
-/* Module functions */
-
-static int __init timblogiw_init(void)
-{
- return platform_driver_register(&timblogiw_platform_driver);
-}
-
-static void __exit timblogiw_exit(void)
-{
- platform_driver_unregister(&timblogiw_platform_driver);
-}
-
-module_init(timblogiw_init);
-module_exit(timblogiw_exit);
+module_platform_driver(timblogiw_platform_driver);
MODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h
index 56564e6..5dd73b7 100644
--- a/drivers/media/video/tlg2300/pd-common.h
+++ b/drivers/media/video/tlg2300/pd-common.h
@@ -140,7 +140,7 @@ struct pd_dvb_adapter {
u8 reserved[3];
/* data for power resume*/
- struct dvb_frontend_parameters fe_param;
+ struct dtv_frontend_properties fe_param;
/* for channel scanning */
int prev_freq;
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c
index d0da11a..30fcb11 100644
--- a/drivers/media/video/tlg2300/pd-dvb.c
+++ b/drivers/media/video/tlg2300/pd-dvb.c
@@ -12,9 +12,9 @@
static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
static int dvb_bandwidth[][2] = {
- { TLG_BW_8, BANDWIDTH_8_MHZ },
- { TLG_BW_7, BANDWIDTH_7_MHZ },
- { TLG_BW_6, BANDWIDTH_6_MHZ }
+ { TLG_BW_8, 8000000 },
+ { TLG_BW_7, 7000000 },
+ { TLG_BW_6, 6000000 }
};
static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
@@ -146,9 +146,9 @@ static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
return msec > 800 ? true : false;
}
-static int poseidon_set_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int poseidon_set_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
s32 ret = 0, cmd_status = 0;
s32 i, bandwidth = -1;
struct poseidon *pd = fe->demodulator_priv;
@@ -159,7 +159,7 @@ static int poseidon_set_fe(struct dvb_frontend *fe,
mutex_lock(&pd->lock);
for (i = 0; i < dvb_bandwidth_length; i++)
- if (fep->u.ofdm.bandwidth == dvb_bandwidth[i][1])
+ if (fep->bandwidth_hz == dvb_bandwidth[i][1])
bandwidth = dvb_bandwidth[i][0];
if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
@@ -210,7 +210,7 @@ static int pm_dvb_resume(struct poseidon *pd)
poseidon_check_mode_dvbt(pd);
msleep(300);
- poseidon_set_fe(&pd_dvb->dvb_fe, &pd_dvb->fe_param);
+ poseidon_set_fe(&pd_dvb->dvb_fe);
dvb_start_streaming(pd_dvb);
return 0;
@@ -227,13 +227,13 @@ static s32 poseidon_fe_init(struct dvb_frontend *fe)
pd->pm_resume = pm_dvb_resume;
#endif
memset(&pd_dvb->fe_param, 0,
- sizeof(struct dvb_frontend_parameters));
+ sizeof(struct dtv_frontend_properties));
return 0;
}
-static int poseidon_get_fe(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int poseidon_get_fe(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct poseidon *pd = fe->demodulator_priv;
struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
@@ -332,9 +332,9 @@ static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
}
static struct dvb_frontend_ops poseidon_frontend_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "Poseidon DVB-T",
- .type = FE_OFDM,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 62500,/* FIXME */
diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig
index 114eec8..a43b77a 100644
--- a/drivers/media/video/tm6000/Kconfig
+++ b/drivers/media/video/tm6000/Kconfig
@@ -1,6 +1,6 @@
config VIDEO_TM6000
tristate "TV Master TM5600/6000/6010 driver"
- depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
+ depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB
select VIDEO_TUNER
select MEDIA_TUNER_XC2028
select MEDIA_TUNER_XC5000
@@ -16,7 +16,7 @@ config VIDEO_TM6000
config VIDEO_TM6000_ALSA
tristate "TV Master TM5600/6000/6010 audio support"
- depends on VIDEO_TM6000 && SND && EXPERIMENTAL
+ depends on VIDEO_TM6000 && SND
select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio for
@@ -27,7 +27,7 @@ config VIDEO_TM6000_ALSA
config VIDEO_TM6000_DVB
tristate "DVB Support for tm6000 based TV cards"
- depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL
+ depends on VIDEO_TM6000 && DVB_CORE && USB
select DVB_ZL10353
---help---
This adds support for DVB cards based on the tm5600/tm6000 chip.
diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c
index 7d675c72..bd07ec7 100644
--- a/drivers/media/video/tm6000/tm6000-alsa.c
+++ b/drivers/media/video/tm6000/tm6000-alsa.c
@@ -42,7 +42,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
@@ -146,20 +146,21 @@ static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
#define DEFAULT_FIFO_SIZE 4096
static struct snd_pcm_hardware snd_tm6000_digital_hw = {
- .info = SNDRV_PCM_INFO_MMAP |
+ .info = SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.period_bytes_min = 64,
.period_bytes_max = 12544,
- .periods_min = 1,
+ .periods_min = 2,
.periods_max = 98,
.buffer_bytes_max = 62720 * 8,
};
@@ -181,6 +182,7 @@ static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
chip->substream = substream;
runtime->hw = snd_tm6000_digital_hw;
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
return 0;
_error:
@@ -347,9 +349,13 @@ static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
int err = 0;
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+ case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
case SNDRV_PCM_TRIGGER_START:
atomic_set(&core->stream_started, 1);
break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+ case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
case SNDRV_PCM_TRIGGER_STOP:
atomic_set(&core->stream_started, 0);
break;
@@ -371,6 +377,14 @@ static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
return chip->buf_pos;
}
+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);
+}
+
/*
* operators
*/
@@ -383,6 +397,7 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = {
.prepare = snd_tm6000_prepare,
.trigger = snd_tm6000_card_trigger,
.pointer = snd_tm6000_pointer,
+ .page = snd_pcm_get_vmalloc_page,
};
/*
diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c
index ff939bc..034659b 100644
--- a/drivers/media/video/tm6000/tm6000-cards.c
+++ b/drivers/media/video/tm6000/tm6000-cards.c
@@ -351,6 +351,7 @@ static struct tm6000_board tm6000_boards[] = {
.tuner_addr = 0xc2 >> 1,
.demod_addr = 0x1e >> 1,
.type = TM6010,
+ .ir_codes = RC_MAP_HAUPPAUGE,
.caps = {
.has_tuner = 1,
.has_dvb = 1,
@@ -639,6 +640,7 @@ static struct usb_device_id tm6000_id_table[] = {
{ USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
{ }
};
+MODULE_DEVICE_TABLE(usb, tm6000_id_table);
/* Control power led for show some activity */
void tm6000_flash_led(struct tm6000_core *dev, u8 state)
@@ -941,6 +943,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev)
case TM6010_BOARD_HAUPPAUGE_900H:
case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
case TM6010_BOARD_TWINHAN_TU501:
+ ctl.max_len = 80;
ctl.fname = "xc3028L-v36.fw";
break;
default:
@@ -1002,6 +1005,7 @@ static int fill_board_specific_data(struct tm6000_core *dev)
/* setup per-model quirks */
switch (dev->model) {
case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+ case TM6010_BOARD_HAUPPAUGE_900H:
dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
break;
@@ -1050,6 +1054,33 @@ static void use_alternative_detection_method(struct tm6000_core *dev)
tm6000_boards[model].name, model);
}
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+ struct tm6000_core *dev = container_of(work, struct tm6000_core,
+ request_module_wk);
+
+ request_module("tm6000-alsa");
+
+ if (dev->caps.has_dvb)
+ request_module("tm6000-dvb");
+}
+
+static void request_modules(struct tm6000_core *dev)
+{
+ INIT_WORK(&dev->request_module_wk, request_module_async);
+ schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct tm6000_core *dev)
+{
+ flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
static int tm6000_init_dev(struct tm6000_core *dev)
{
struct v4l2_frequency f;
@@ -1112,6 +1143,8 @@ static int tm6000_init_dev(struct tm6000_core *dev)
tm6000_ir_init(dev);
+ request_modules(dev);
+
mutex_unlock(&dev->lock);
return 0;
@@ -1324,6 +1357,8 @@ static void tm6000_usb_disconnect(struct usb_interface *interface)
printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
+ flush_request_modules(dev);
+
tm6000_ir_fini(dev);
if (dev->gpio.power_led) {
diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c
index 9783616..22cc011 100644
--- a/drivers/media/video/tm6000/tm6000-core.c
+++ b/drivers/media/video/tm6000/tm6000-core.c
@@ -38,6 +38,7 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
int ret, i;
unsigned int pipe;
u8 *data = NULL;
+ int delay = 5000;
mutex_lock(&dev->usb_lock);
@@ -88,7 +89,20 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
}
kfree(data);
- msleep(5);
+
+ if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
+ delay = 0;
+
+ if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
+ unsigned int tsleep;
+ /* Calculate delay time, 14000us for 64 bytes */
+ tsleep = (len * 200) + 200;
+ if (tsleep < delay)
+ tsleep = delay;
+ usleep_range(tsleep, tsleep + 1000);
+ }
+ else if (delay)
+ usleep_range(delay, delay + 1000);
mutex_unlock(&dev->usb_lock);
return ret;
@@ -125,14 +139,14 @@ int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
u8 new_index;
rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
- value, index, buf, 1);
+ value, 0, buf, 1);
if (rc < 0)
return rc;
new_index = (buf[0] & ~mask) | (index & mask);
- if (new_index == index)
+ if (new_index == buf[0])
return 0;
return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
@@ -536,16 +550,16 @@ static struct reg_init tm6010_init_tab[] = {
{ TM6010_REQ05_R18_IMASK7, 0x00 },
- { TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
- { TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
- { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
- { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
+ { TM6010_REQ07_RDC_IR_LEADER1, 0xaa },
+ { TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
+ { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
+ { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
{ REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
- { TM6010_REQ07_RD8_IR, 0x2f },
+ { TM6010_REQ07_RD8_IR, 0x0f },
/* set remote wakeup key:any key wakeup */
{ TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe },
- { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff },
+ { TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff },
};
int tm6000_init(struct tm6000_core *dev)
@@ -599,55 +613,6 @@ int tm6000_init(struct tm6000_core *dev)
return rc;
}
-int tm6000_reset(struct tm6000_core *dev)
-{
- int pipe;
- int err;
-
- msleep(500);
-
- err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
- if (err < 0) {
- tm6000_err("failed to select interface %d, alt. setting 0\n",
- dev->isoc_in.bInterfaceNumber);
- return err;
- }
-
- err = usb_reset_configuration(dev->udev);
- if (err < 0) {
- tm6000_err("failed to reset configuration\n");
- return err;
- }
-
- if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
- msleep(5);
-
- /*
- * Not all devices have int_in defined
- */
- if (!dev->int_in.endp)
- return 0;
-
- err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
- if (err < 0) {
- tm6000_err("failed to select interface %d, alt. setting 2\n",
- dev->isoc_in.bInterfaceNumber);
- return err;
- }
-
- msleep(5);
-
- pipe = usb_rcvintpipe(dev->udev,
- dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-
- err = usb_clear_halt(dev->udev, pipe);
- if (err < 0) {
- tm6000_err("usb_clear_halt failed: %d\n", err);
- return err;
- }
-
- return 0;
-}
int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
{
@@ -696,11 +661,13 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev)
if (dev->dev_type == TM6010) {
/* Audio crossbar setting, default SIF1 */
u8 areg_f0;
+ u8 areg_07 = 0x10;
switch (dev->rinput.amux) {
case TM6000_AMUX_SIF1:
case TM6000_AMUX_SIF2:
areg_f0 = 0x03;
+ areg_07 = 0x30;
break;
case TM6000_AMUX_ADC1:
areg_f0 = 0x00;
@@ -720,6 +687,9 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev)
/* Set audio input crossbar */
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
areg_f0, 0x0f);
+ /* Mux overflow workaround */
+ tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+ areg_07, 0xf0);
} else {
u8 areg_eb;
/* Audio setting, default LINE1 */
diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c
index 5e6c129..e1f3f66 100644
--- a/drivers/media/video/tm6000/tm6000-dvb.c
+++ b/drivers/media/video/tm6000/tm6000-dvb.c
@@ -89,9 +89,19 @@ static void tm6000_urb_received(struct urb *urb)
int ret;
struct tm6000_core *dev = urb->context;
- if (urb->status != 0)
+ switch (urb->status) {
+ case 0:
+ case -ETIMEDOUT:
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ return;
+ default:
print_err_status(dev, 0, urb->status);
- else if (urb->actual_length > 0)
+ }
+
+ if (urb->actual_length > 0)
dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
urb->actual_length);
@@ -151,7 +161,7 @@ static int tm6000_start_stream(struct tm6000_core *dev)
printk(KERN_ERR "tm6000: pipe resetted\n");
/* mutex_lock(&tm6000_driver.open_close_mutex); */
- ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
+ ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
/* mutex_unlock(&tm6000_driver.open_close_mutex); */
if (ret) {
@@ -396,6 +406,11 @@ static int dvb_init(struct tm6000_core *dev)
if (!dev->caps.has_dvb)
return 0;
+ if (dev->udev->speed == USB_SPEED_FULL) {
+ printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
+ return 0;
+ }
+
dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
if (!dvb) {
printk(KERN_INFO "Cannot allocate memory\n");
diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c
index 0290bbf..c7e23e3 100644
--- a/drivers/media/video/tm6000/tm6000-i2c.c
+++ b/drivers/media/video/tm6000/tm6000-i2c.c
@@ -46,11 +46,10 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
__u8 reg, char *buf, int len)
{
int rc;
- unsigned int tsleep;
unsigned int i2c_packet_limit = 16;
if (dev->dev_type == TM6010)
- i2c_packet_limit = 64;
+ i2c_packet_limit = 80;
if (!buf)
return -1;
@@ -71,10 +70,6 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
return rc;
}
- /* Calculate delay time, 14000us for 64 bytes */
- tsleep = ((len * 200) + 200 + 1000) / 1000;
- msleep(tsleep);
-
/* release mutex */
return rc;
}
@@ -145,7 +140,6 @@ static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
return rc;
}
- msleep(1400 / 1000);
rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
reg, 0, buf, len);
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c
index 405d127..7844607 100644
--- a/drivers/media/video/tm6000/tm6000-input.c
+++ b/drivers/media/video/tm6000/tm6000-input.c
@@ -31,22 +31,25 @@
static unsigned int ir_debug;
module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
+MODULE_PARM_DESC(ir_debug, "debug message level");
static unsigned int enable_ir = 1;
module_param(enable_ir, int, 0644);
MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
-/* number of 50ms for ON-OFF-ON power led */
-/* show IR activity */
-#define PWLED_OFF 2
+static unsigned int ir_clock_mhz = 12;
+module_param(ir_clock_mhz, int, 0644);
+MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
+
+#define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */
+#define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */
#undef dprintk
-#define dprintk(fmt, arg...) \
- if (ir_debug) { \
+#define dprintk(level, fmt, arg...) do {\
+ if (ir_debug >= level) \
printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
- }
+ } while (0)
struct tm6000_ir_poll_result {
u16 rc_data;
@@ -62,20 +65,15 @@ struct tm6000_IR {
int polling;
struct delayed_work work;
u8 wait:1;
- u8 key:1;
- u8 pwled:1;
- u8 pwledcnt;
+ u8 pwled:2;
+ u8 submit_urb:1;
u16 key_addr;
struct urb *int_urb;
- u8 *urb_data;
-
- int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
/* IR device properties */
u64 rc_type;
};
-
void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
{
struct tm6000_IR *ir = dev->ir;
@@ -83,62 +81,84 @@ void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
if (!dev->ir)
return;
+ dprintk(2, "%s: %i\n",__func__, ir->wait);
+
if (state)
ir->wait = 1;
else
ir->wait = 0;
}
-
static int tm6000_ir_config(struct tm6000_IR *ir)
{
struct tm6000_core *dev = ir->dev;
- u8 buf[10];
- int rc;
+ u32 pulse = 0, leader = 0;
+
+ dprintk(2, "%s\n",__func__);
+
+ /*
+ * The IR decoder supports RC-5 or NEC, with a configurable timing.
+ * The timing configuration there is not that accurate, as it uses
+ * approximate values. The NEC spec mentions a 562.5 unit period,
+ * and RC-5 uses a 888.8 period.
+ * Currently, driver assumes a clock provided by a 12 MHz XTAL, but
+ * a modprobe parameter can adjust it.
+ * Adjustments are required for other timings.
+ * It seems that the 900ms timing for NEC is used to detect a RC-5
+ * IR, in order to discard such decoding
+ */
switch (ir->rc_type) {
case RC_TYPE_NEC:
- /* Setup IR decoder for NEC standard 12MHz system clock */
- /* IR_LEADER_CNT = 0.9ms */
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
- /* IR_PULSE_CNT = 0.7ms */
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
- /* Remote WAKEUP = enable */
- tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
- /* IR_WKUP_SEL = Low byte in decoded IR data */
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
- /* IR_WKU_ADD code */
- tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
- tm6000_flash_led(dev, 0);
- msleep(100);
- tm6000_flash_led(dev, 1);
+ leader = 900; /* ms */
+ pulse = 700; /* ms - the actual value would be 562 */
break;
default:
- /* hack */
- buf[0] = 0xff;
- buf[1] = 0xff;
- buf[2] = 0xf2;
- buf[3] = 0x2b;
- buf[4] = 0x20;
- buf[5] = 0x35;
- buf[6] = 0x60;
- buf[7] = 0x04;
- buf[8] = 0xc0;
- buf[9] = 0x08;
-
- rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
- USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
- msleep(100);
-
- if (rc < 0) {
- printk(KERN_INFO "IR configuration failed");
- return rc;
- }
+ case RC_TYPE_RC5:
+ leader = 900; /* ms - from the NEC decoding */
+ pulse = 1780; /* ms - The actual value would be 1776 */
break;
}
+ pulse = ir_clock_mhz * pulse;
+ leader = ir_clock_mhz * leader;
+ if (ir->rc_type == RC_TYPE_NEC)
+ leader = leader | 0x8000;
+
+ dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
+ __func__,
+ (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+ ir_clock_mhz, leader, pulse);
+
+ /* Remote WAKEUP = enable, normal mode, from IR decoder output */
+ tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+
+ /* Enable IR reception on non-busrt mode */
+ tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
+
+ /* IR_WKUP_SEL = Low byte in decoded IR data */
+ tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
+ /* IR_WKU_ADD code */
+ tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
+
+ tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
+ tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
+
+ tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
+ tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
+
+ if (!ir->polling)
+ tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+ else
+ tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
+ msleep(10);
+
+ /* Shows that IR is working via the LED */
+ tm6000_flash_led(dev, 0);
+ msleep(100);
+ tm6000_flash_led(dev, 1);
+ ir->pwled = 1;
+
return 0;
}
@@ -146,132 +166,124 @@ static void tm6000_ir_urb_received(struct urb *urb)
{
struct tm6000_core *dev = urb->context;
struct tm6000_IR *ir = dev->ir;
+ struct tm6000_ir_poll_result poll_result;
+ char *buf;
int rc;
- if (urb->status != 0)
- printk(KERN_INFO "not ready\n");
- else if (urb->actual_length > 0) {
- memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
+ dprintk(2, "%s\n",__func__);
+ if (urb->status < 0 || urb->actual_length <= 0) {
+ printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
+ urb->status, urb->actual_length);
+ ir->submit_urb = 1;
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+ return;
+ }
+ buf = urb->transfer_buffer;
- dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
- ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+ if (ir_debug)
+ print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
+ DUMP_PREFIX_OFFSET,16, 1,
+ buf, urb->actual_length, false);
- ir->key = 1;
- }
+ poll_result.rc_data = buf[0];
+ if (urb->actual_length > 1)
+ poll_result.rc_data |= buf[1] << 8;
+
+ dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+ rc_keydown(ir->rc, poll_result.rc_data, 0);
rc = usb_submit_urb(urb, GFP_ATOMIC);
+ /*
+ * Flash the led. We can't do it here, as it is running on IRQ context.
+ * So, use the scheduler to do it, in a few ms.
+ */
+ ir->pwled = 2;
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
}
-static int default_polling_getkey(struct tm6000_IR *ir,
- struct tm6000_ir_poll_result *poll_result)
+static void tm6000_ir_handle_key(struct work_struct *work)
{
+ struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
struct tm6000_core *dev = ir->dev;
+ struct tm6000_ir_poll_result poll_result;
int rc;
u8 buf[2];
- if (ir->wait && !&dev->int_in)
- return 0;
-
- if (&dev->int_in) {
- switch (ir->rc_type) {
- case RC_TYPE_RC5:
- poll_result->rc_data = ir->urb_data[0];
- break;
- case RC_TYPE_NEC:
- if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
- poll_result->rc_data = ir->urb_data[0]
- | ir->urb_data[1] << 8;
- }
- break;
- default:
- poll_result->rc_data = ir->urb_data[0]
- | ir->urb_data[1] << 8;
- break;
- }
- } else {
- tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
- msleep(10);
- tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
- msleep(10);
-
- if (ir->rc_type == RC_TYPE_RC5) {
- rc = tm6000_read_write_usb(dev, USB_DIR_IN |
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- REQ_02_GET_IR_CODE, 0, 0, buf, 1);
-
- msleep(10);
-
- dprintk("read data=%02x\n", buf[0]);
- if (rc < 0)
- return rc;
+ if (ir->wait)
+ return;
- poll_result->rc_data = buf[0];
- } else {
- rc = tm6000_read_write_usb(dev, USB_DIR_IN |
- USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+ dprintk(3, "%s\n",__func__);
- msleep(10);
+ rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+ if (rc < 0)
+ return;
- dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
- if (rc < 0)
- return rc;
+ if (rc > 1)
+ poll_result.rc_data = buf[0] | buf[1] << 8;
+ else
+ poll_result.rc_data = buf[0];
- poll_result->rc_data = buf[0] | buf[1] << 8;
+ /* Check if something was read */
+ if ((poll_result.rc_data & 0xff) == 0xff) {
+ if (!ir->pwled) {
+ tm6000_flash_led(dev, 1);
+ ir->pwled = 1;
}
- if ((poll_result->rc_data & 0x00ff) != 0xff)
- ir->key = 1;
+ return;
}
- return 0;
+
+ dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+ rc_keydown(ir->rc, poll_result.rc_data, 0);
+ tm6000_flash_led(dev, 0);
+ ir->pwled = 0;
+
+ /* Re-schedule polling */
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
}
-static void tm6000_ir_handle_key(struct tm6000_IR *ir)
+static void tm6000_ir_int_work(struct work_struct *work)
{
+ struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
struct tm6000_core *dev = ir->dev;
- int result;
- struct tm6000_ir_poll_result poll_result;
+ int rc;
- /* read the registers containing the IR status */
- result = ir->get_key(ir, &poll_result);
- if (result < 0) {
- printk(KERN_INFO "ir->get_key() failed %d\n", result);
- return;
- }
+ dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
+ ir->pwled);
- dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
+ if (ir->submit_urb) {
+ dprintk(3, "Resubmit urb\n");
+ tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
- if (ir->pwled) {
- if (ir->pwledcnt >= PWLED_OFF) {
- ir->pwled = 0;
- ir->pwledcnt = 0;
- tm6000_flash_led(dev, 1);
- } else
- ir->pwledcnt += 1;
+ rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
+ if (rc < 0) {
+ printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
+ rc);
+ /* Retry in 100 ms */
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+ return;
+ }
+ ir->submit_urb = 0;
}
- if (ir->key) {
- rc_keydown(ir->rc, poll_result.rc_data, 0);
- ir->key = 0;
- ir->pwled = 1;
- ir->pwledcnt = 0;
+ /* Led is enabled only if USB submit doesn't fail */
+ if (ir->pwled == 2) {
tm6000_flash_led(dev, 0);
+ ir->pwled = 0;
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
+ } else if (!ir->pwled) {
+ tm6000_flash_led(dev, 1);
+ ir->pwled = 1;
}
- return;
-}
-
-static void tm6000_ir_work(struct work_struct *work)
-{
- struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
-
- tm6000_ir_handle_key(ir);
- schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
}
static int tm6000_ir_start(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
- INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
+ dprintk(2, "%s\n",__func__);
+
schedule_delayed_work(&ir->work, 0);
return 0;
@@ -281,6 +293,8 @@ static void tm6000_ir_stop(struct rc_dev *rc)
{
struct tm6000_IR *ir = rc->priv;
+ dprintk(2, "%s\n",__func__);
+
cancel_delayed_work_sync(&ir->work);
}
@@ -291,10 +305,11 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
if (!ir)
return 0;
+ dprintk(2, "%s\n",__func__);
+
if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
- ir->get_key = default_polling_getkey;
ir->rc_type = rc_type;
tm6000_ir_config(ir);
@@ -302,17 +317,19 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
return 0;
}
-int tm6000_ir_int_start(struct tm6000_core *dev)
+static int __tm6000_ir_int_start(struct rc_dev *rc)
{
- struct tm6000_IR *ir = dev->ir;
+ struct tm6000_IR *ir = rc->priv;
+ struct tm6000_core *dev = ir->dev;
int pipe, size;
int err = -ENOMEM;
-
if (!ir)
return -ENODEV;
- ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+ dprintk(2, "%s\n",__func__);
+
+ ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!ir->int_urb)
return -ENOMEM;
@@ -321,42 +338,59 @@ int tm6000_ir_int_start(struct tm6000_core *dev)
& USB_ENDPOINT_NUMBER_MASK);
size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
- dprintk("IR max size: %d\n", size);
+ dprintk(1, "IR max size: %d\n", size);
- ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+ ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
if (ir->int_urb->transfer_buffer == NULL) {
usb_free_urb(ir->int_urb);
return err;
}
- dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
+ dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval);
+
usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
ir->int_urb->transfer_buffer, size,
tm6000_ir_urb_received, dev,
dev->int_in.endp->desc.bInterval);
- err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
- if (err) {
- kfree(ir->int_urb->transfer_buffer);
- usb_free_urb(ir->int_urb);
- return err;
- }
- ir->urb_data = kzalloc(size, GFP_KERNEL);
+
+ ir->submit_urb = 1;
+ schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
return 0;
}
-void tm6000_ir_int_stop(struct tm6000_core *dev)
+static void __tm6000_ir_int_stop(struct rc_dev *rc)
{
- struct tm6000_IR *ir = dev->ir;
+ struct tm6000_IR *ir = rc->priv;
- if (!ir)
+ if (!ir || !ir->int_urb)
return;
+ dprintk(2, "%s\n",__func__);
+
usb_kill_urb(ir->int_urb);
kfree(ir->int_urb->transfer_buffer);
usb_free_urb(ir->int_urb);
ir->int_urb = NULL;
- kfree(ir->urb_data);
- ir->urb_data = NULL;
+}
+
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+ struct tm6000_IR *ir = dev->ir;
+
+ if (!ir)
+ return 0;
+
+ return __tm6000_ir_int_start(ir->rc);
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+ struct tm6000_IR *ir = dev->ir;
+
+ if (!ir || !ir->rc)
+ return;
+
+ __tm6000_ir_int_stop(ir->rc);
}
int tm6000_ir_init(struct tm6000_core *dev)
@@ -374,29 +408,36 @@ int tm6000_ir_init(struct tm6000_core *dev)
if (!dev->ir_codes)
return 0;
- ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
rc = rc_allocate_device();
if (!ir || !rc)
goto out;
+ dprintk(2, "%s\n", __func__);
+
/* record handles to ourself */
ir->dev = dev;
dev->ir = ir;
ir->rc = rc;
- /* input einrichten */
+ /* input setup */
rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+ /* Neded, in order to support NEC remotes with 24 or 32 bits */
+ rc->scanmask = 0xffff;
rc->priv = ir;
rc->change_protocol = tm6000_ir_change_protocol;
- rc->open = tm6000_ir_start;
- rc->close = tm6000_ir_stop;
+ if (dev->int_in.endp) {
+ rc->open = __tm6000_ir_int_start;
+ rc->close = __tm6000_ir_int_stop;
+ INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
+ } else {
+ rc->open = tm6000_ir_start;
+ rc->close = tm6000_ir_stop;
+ ir->polling = 50;
+ INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
+ }
rc->driver_type = RC_DRIVER_SCANCODE;
- ir->polling = 50;
- ir->pwled = 0;
- ir->pwledcnt = 0;
-
-
snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
dev->name);
@@ -415,15 +456,6 @@ int tm6000_ir_init(struct tm6000_core *dev)
rc->driver_name = "tm6000";
rc->dev.parent = &dev->udev->dev;
- if (&dev->int_in) {
- dprintk("IR over int\n");
-
- err = tm6000_ir_int_start(dev);
-
- if (err)
- goto out;
- }
-
/* ir register */
err = rc_register_device(rc);
if (err)
@@ -447,10 +479,19 @@ int tm6000_ir_fini(struct tm6000_core *dev)
if (!ir)
return 0;
+ dprintk(2, "%s\n",__func__);
+
rc_unregister_device(ir->rc);
- if (ir->int_urb)
- tm6000_ir_int_stop(dev);
+ if (!ir->polling)
+ __tm6000_ir_int_stop(ir->rc);
+
+ tm6000_ir_stop(ir->rc);
+
+ /* Turn off the led */
+ tm6000_flash_led(dev, 0);
+ ir->pwled = 0;
+
kfree(ir);
dev->ir = NULL;
diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h
index 7f491b6..a38c251 100644
--- a/drivers/media/video/tm6000/tm6000-regs.h
+++ b/drivers/media/video/tm6000/tm6000-regs.h
@@ -284,19 +284,19 @@ enum {
/* ONLY for TM6010 */
#define TM6010_REQ07_RD8_IR 0x07, 0xd8
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_BSIZE 0x07, 0xd9
+#define TM6010_REQ07_RD9_IR_BSIZE 0x07, 0xd9
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_SEL 0x07, 0xda
+#define TM6010_REQ07_RDA_IR_WAKEUP_SEL 0x07, 0xda
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_ADD 0x07, 0xdb
+#define TM6010_REQ07_RDB_IR_WAKEUP_ADD 0x07, 0xdb
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER1 0x07, 0xdc
+#define TM6010_REQ07_RDC_IR_LEADER1 0x07, 0xdc
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER0 0x07, 0xdd
+#define TM6010_REQ07_RDD_IR_LEADER0 0x07, 0xdd
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT1 0x07, 0xde
+#define TM6010_REQ07_RDE_IR_PULSE_CNT1 0x07, 0xde
/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT0 0x07, 0xdf
+#define TM6010_REQ07_RDF_IR_PULSE_CNT0 0x07, 0xdf
/* ONLY for TM6010 */
#define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0
/* ONLY for TM6010 */
diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c
index 9a4145dc..9dc0831 100644
--- a/drivers/media/video/tm6000/tm6000-stds.c
+++ b/drivers/media/video/tm6000/tm6000-stds.c
@@ -361,82 +361,51 @@ static int tm6000_set_audio_std(struct tm6000_core *dev)
return 0;
}
- switch (tm6010_a_mode) {
+ /*
+ * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one
+ * audio standard for each V4L2_STD type.
+ */
+ if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) {
+ areg_05 |= 0x04;
+ } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) {
+ areg_05 |= 0x43;
+ } else if (dev->norm & V4L2_STD_MN) {
+ areg_05 |= 0x22;
+ } else switch (tm6010_a_mode) {
/* auto */
case 0:
- switch (dev->norm) {
- case V4L2_STD_NTSC_M_KR:
+ if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L)
areg_05 |= 0x00;
- break;
- case V4L2_STD_NTSC_M_JP:
- areg_05 |= 0x40;
- break;
- case V4L2_STD_NTSC_M:
- case V4L2_STD_PAL_M:
- case V4L2_STD_PAL_N:
- areg_05 |= 0x20;
- break;
- case V4L2_STD_PAL_Nc:
- areg_05 |= 0x60;
- break;
- case V4L2_STD_SECAM_L:
- areg_05 |= 0x00;
- break;
- case V4L2_STD_DK:
+ else /* Other PAL/SECAM standards */
areg_05 |= 0x10;
- break;
- }
break;
/* A2 */
case 1:
- switch (dev->norm) {
- case V4L2_STD_B:
- case V4L2_STD_GH:
- areg_05 = 0x05;
- break;
- case V4L2_STD_DK:
+ if (dev->norm & V4L2_STD_DK)
areg_05 = 0x09;
- break;
- }
+ else
+ areg_05 = 0x05;
break;
/* NICAM */
case 2:
- switch (dev->norm) {
- case V4L2_STD_B:
- case V4L2_STD_GH:
- areg_05 = 0x07;
- break;
- case V4L2_STD_DK:
+ if (dev->norm & V4L2_STD_DK) {
areg_05 = 0x06;
- break;
- case V4L2_STD_PAL_I:
+ } else if (dev->norm & V4L2_STD_PAL_I) {
areg_05 = 0x08;
- break;
- case V4L2_STD_SECAM_L:
+ } else if (dev->norm & V4L2_STD_SECAM_L) {
areg_05 = 0x0a;
areg_02 = 0x02;
- break;
+ } else {
+ areg_05 = 0x07;
}
nicam_flag = 1;
break;
/* other */
case 3:
- switch (dev->norm) {
- /* DK3_A2 */
- case V4L2_STD_DK:
+ if (dev->norm & V4L2_STD_DK) {
areg_05 = 0x0b;
- break;
- /* Korea */
- case V4L2_STD_NTSC_M_KR:
- areg_05 = 0x04;
- break;
- /* EIAJ */
- case V4L2_STD_NTSC_M_JP:
- areg_05 = 0x03;
- break;
- default:
+ } else {
areg_05 = 0x02;
- break;
}
break;
}
@@ -557,10 +526,16 @@ int tm6000_set_standard(struct tm6000_core *dev)
case TM6000_AMUX_ADC1:
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0x00, 0x0f);
+ /* Mux overflow workaround */
+ tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+ 0x10, 0xf0);
break;
case TM6000_AMUX_ADC2:
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0x08, 0x0f);
+ /* Mux overflow workaround */
+ tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+ 0x10, 0xf0);
break;
case TM6000_AMUX_SIF1:
reg_08_e2 |= 0x02;
@@ -570,6 +545,9 @@ int tm6000_set_standard(struct tm6000_core *dev)
tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0x02, 0x0f);
+ /* Mux overflow workaround */
+ tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+ 0x30, 0xf0);
break;
case TM6000_AMUX_SIF2:
reg_08_e2 |= 0x02;
@@ -579,6 +557,9 @@ int tm6000_set_standard(struct tm6000_core *dev)
tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
0x02, 0x0f);
+ /* Mux overflow workaround */
+ tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+ 0x30, 0xf0);
break;
default:
break;
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
index 1e5ace0..bc13db7 100644
--- a/drivers/media/video/tm6000/tm6000-video.c
+++ b/drivers/media/video/tm6000/tm6000-video.c
@@ -1605,16 +1605,25 @@ static int tm6000_release(struct file *file)
res_free(dev, fh);
if (!dev->users) {
- int err;
-
tm6000_uninit_isoc(dev);
+ /* Stop interrupt USB pipe */
+ tm6000_ir_int_stop(dev);
+
+ usb_reset_configuration(dev->udev);
+
+ if (dev->int_in.endp)
+ usb_set_interface(dev->udev,
+ dev->isoc_in.bInterfaceNumber, 2);
+ else
+ usb_set_interface(dev->udev,
+ dev->isoc_in.bInterfaceNumber, 0);
+
+ /* Start interrupt USB pipe */
+ tm6000_ir_int_start(dev);
+
if (!fh->radio)
videobuf_mmap_free(&fh->vb_vidq);
-
- err = tm6000_reset(dev);
- if (err < 0)
- dev_err(&vdev->dev, "reset failed: %d\n", err);
}
kfree(fh);
diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h
index 2777e51..27ba659 100644
--- a/drivers/media/video/tm6000/tm6000.h
+++ b/drivers/media/video/tm6000/tm6000.h
@@ -188,6 +188,9 @@ struct tm6000_core {
/* Device Capabilities*/
struct tm6000_capabilities caps;
+ /* Used to load alsa/dvb */
+ struct work_struct request_module_wk;
+
/* Tuner configuration */
int tuner_type; /* type of the tuner */
int tuner_addr; /* tuner address */
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 11cc980..4059ea17 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -326,6 +326,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
t->mode_mask = T_RADIO;
break;
case TUNER_PHILIPS_FMD1216ME_MK3:
+ case TUNER_PHILIPS_FMD1216MEX_MK3:
buffer[0] = 0x0b;
buffer[1] = 0xdc;
buffer[2] = 0x9c;
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c
index 926f039..dd26cac 100644
--- a/drivers/media/video/tvp514x.c
+++ b/drivers/media/video/tvp514x.c
@@ -52,7 +52,7 @@
#define LOCK_RETRY_DELAY (200)
/* Debug functions */
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 6abaa16..6be9910 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -703,21 +703,21 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
/* First tests should be against specific std */
if (std == V4L2_STD_ALL) {
- fmt = 0; /* Autodetect mode */
+ fmt = VIDEO_STD_AUTO_SWITCH_BIT; /* Autodetect mode */
} else if (std & V4L2_STD_NTSC_443) {
- fmt = 0xa;
+ fmt = VIDEO_STD_NTSC_4_43_BIT;
} else if (std & V4L2_STD_PAL_M) {
- fmt = 0x6;
+ fmt = VIDEO_STD_PAL_M_BIT;
} else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
- fmt = 0x8;
+ fmt = VIDEO_STD_PAL_COMBINATION_N_BIT;
} else {
/* Then, test against generic ones */
if (std & V4L2_STD_NTSC)
- fmt = 0x2;
+ fmt = VIDEO_STD_NTSC_MJ_BIT;
else if (std & V4L2_STD_PAL)
- fmt = 0x4;
+ fmt = VIDEO_STD_PAL_BDGHIN_BIT;
else if (std & V4L2_STD_SECAM)
- fmt = 0xc;
+ fmt = VIDEO_STD_SECAM_BIT;
}
v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt);
@@ -779,6 +779,70 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
+static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+{
+ int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
+
+ switch (val & 0x0F) {
+ case 0x01:
+ return V4L2_STD_NTSC;
+ case 0x03:
+ return V4L2_STD_PAL;
+ case 0x05:
+ return V4L2_STD_PAL_M;
+ case 0x07:
+ return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
+ case 0x09:
+ return V4L2_STD_NTSC_443;
+ case 0xb:
+ return V4L2_STD_SECAM;
+ default:
+ return V4L2_STD_UNKNOWN;
+ }
+}
+
+static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ if (index)
+ return -EINVAL;
+
+ *code = V4L2_MBUS_FMT_YUYV8_2X8;
+ return 0;
+}
+
+static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *f)
+{
+ struct tvp5150 *decoder = to_tvp5150(sd);
+ v4l2_std_id std;
+
+ if (f == NULL)
+ return -EINVAL;
+
+ tvp5150_reset(sd, 0);
+
+ /* Calculate height and width based on current standard */
+ if (decoder->norm == V4L2_STD_ALL)
+ std = tvp5150_read_std(sd);
+ else
+ std = decoder->norm;
+
+ f->width = 720;
+ if (std & V4L2_STD_525_60)
+ f->height = 480;
+ else
+ f->height = 576;
+
+ f->code = V4L2_MBUS_FMT_YUYV8_2X8;
+ f->field = V4L2_FIELD_SEQ_TB;
+ f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width,
+ f->height);
+ return 0;
+}
+
/****************************************************************************
I2C Command
****************************************************************************/
@@ -931,6 +995,9 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_routing = tvp5150_s_routing,
+ .enum_mbus_fmt = tvp5150_enum_mbus_fmt,
+ .s_mbus_fmt = tvp5150_mbus_fmt,
+ .try_mbus_fmt = tvp5150_mbus_fmt,
};
static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
index 7875e80..236c559 100644
--- a/drivers/media/video/tvp7002.c
+++ b/drivers/media/video/tvp7002.c
@@ -63,7 +63,7 @@ MODULE_LICENSE("GPL");
#define TVP7002_CL_MASK 0x0f
/* Debug functions */
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-2)");
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
index 9bbe617..65d065a 100644
--- a/drivers/media/video/upd64083.c
+++ b/drivers/media/video/upd64083.c
@@ -34,7 +34,7 @@ MODULE_DESCRIPTION("uPD64083 driver");
MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
MODULE_LICENSE("GPL");
-static int debug;
+static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index d7f9751..89fec02 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -110,42 +110,20 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap,
unsigned char addr;
int ret;
- if ((flags & I2C_M_TEN)) {
- /* a ten bit address */
- addr = 0xf0 | ((msg->addr >> 7) & 0x03);
- /* try extended address code... */
- ret = try_write_address(i2c_adap, addr, retries);
- if (ret != 1) {
- dev_err(&i2c_adap->dev,
- "died at extended address code, while writing\n");
- return -EREMOTEIO;
- }
- add[0] = addr;
- if (flags & I2C_M_RD) {
- /* okay, now switch into reading mode */
- addr |= 0x01;
- ret = try_read_address(i2c_adap, addr, retries);
- if (ret != 1) {
- dev_err(&i2c_adap->dev,
- "died at extended address code, while reading\n");
- return -EREMOTEIO;
- }
- }
- } else { /* normal 7bit address */
- addr = (msg->addr << 1);
- if (flags & I2C_M_RD)
- addr |= 1;
+ addr = (msg->addr << 1);
+ if (flags & I2C_M_RD)
+ addr |= 1;
- add[0] = addr;
- if (flags & I2C_M_RD)
- ret = try_read_address(i2c_adap, addr, retries);
- else
- ret = try_write_address(i2c_adap, addr, retries);
+ add[0] = addr;
+ if (flags & I2C_M_RD)
+ ret = try_read_address(i2c_adap, addr, retries);
+ else
+ ret = try_write_address(i2c_adap, addr, retries);
+
+ if (ret != 1)
+ return -EREMOTEIO;
- if (ret != 1)
- return -EREMOTEIO;
- }
return 0;
}
@@ -184,7 +162,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
static u32 functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
/* -----exported algorithm data: ------------------------------------- */
diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig
index 2956a76..6c197da 100644
--- a/drivers/media/video/uvc/Kconfig
+++ b/drivers/media/video/uvc/Kconfig
@@ -1,5 +1,6 @@
config USB_VIDEO_CLASS
tristate "USB Video Class (UVC)"
+ select VIDEOBUF2_VMALLOC
---help---
Support for the USB Video Class (UVC). Currently only video
input devices, such as webcams, are supported.
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile
index 2071ca8..c26d12f 100644
--- a/drivers/media/video/uvc/Makefile
+++ b/drivers/media/video/uvc/Makefile
@@ -1,5 +1,5 @@
uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
- uvc_status.o uvc_isight.o
+ uvc_status.o uvc_isight.o uvc_debugfs.o
ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
uvcvideo-objs += uvc_entity.o
endif
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 254d326..0efd3b1 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -878,8 +878,21 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
chain->dev->intfnum, ctrl->info.selector,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
ctrl->info.size);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ if (UVC_ENTITY_TYPE(ctrl->entity) !=
+ UVC_VC_EXTENSION_UNIT)
+ return ret;
+
+ /* GET_RES is mandatory for XU controls, but some
+ * cameras still choke on it. Ignore errors and set the
+ * resolution value to zero.
+ */
+ uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
+ "UVC non compliance - GET_RES failed on "
+ "an XU control. Enabling workaround.\n");
+ memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
+ ctrl->info.size);
+ }
}
ctrl->cached = 1;
@@ -1861,7 +1874,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
if (ncontrols == 0)
continue;
- entity->controls = kzalloc(ncontrols * sizeof(*ctrl),
+ entity->controls = kcalloc(ncontrols, sizeof(*ctrl),
GFP_KERNEL);
if (entity->controls == NULL)
return -ENOMEM;
diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/video/uvc/uvc_debugfs.c
new file mode 100644
index 0000000..14561a5
--- /dev/null
+++ b/drivers/media/video/uvc/uvc_debugfs.c
@@ -0,0 +1,136 @@
+/*
+ * uvc_debugfs.c -- USB Video Class driver - Debugging support
+ *
+ * Copyright (C) 2011
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.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/debugfs.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "uvcvideo.h"
+
+/* -----------------------------------------------------------------------------
+ * Statistics
+ */
+
+#define UVC_DEBUGFS_BUF_SIZE 1024
+
+struct uvc_debugfs_buffer {
+ size_t count;
+ char data[UVC_DEBUGFS_BUF_SIZE];
+};
+
+static int uvc_debugfs_stats_open(struct inode *inode, struct file *file)
+{
+ struct uvc_streaming *stream = inode->i_private;
+ struct uvc_debugfs_buffer *buf;
+
+ buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data));
+
+ file->private_data = buf;
+ return 0;
+}
+
+static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct uvc_debugfs_buffer *buf = file->private_data;
+
+ return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
+ buf->count);
+}
+
+static int uvc_debugfs_stats_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static const struct file_operations uvc_debugfs_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = uvc_debugfs_stats_open,
+ .llseek = no_llseek,
+ .read = uvc_debugfs_stats_read,
+ .release = uvc_debugfs_stats_release,
+};
+
+/* -----------------------------------------------------------------------------
+ * Global and stream initialization/cleanup
+ */
+
+static struct dentry *uvc_debugfs_root_dir;
+
+int uvc_debugfs_init_stream(struct uvc_streaming *stream)
+{
+ struct usb_device *udev = stream->dev->udev;
+ struct dentry *dent;
+ char dir_name[32];
+
+ if (uvc_debugfs_root_dir == NULL)
+ return -ENODEV;
+
+ sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum);
+
+ dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir);
+ if (IS_ERR_OR_NULL(dent)) {
+ uvc_printk(KERN_INFO, "Unable to create debugfs %s "
+ "directory.\n", dir_name);
+ return -ENODEV;
+ }
+
+ stream->debugfs_dir = dent;
+
+ dent = debugfs_create_file("stats", 0444, stream->debugfs_dir,
+ stream, &uvc_debugfs_stats_fops);
+ if (IS_ERR_OR_NULL(dent)) {
+ uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n");
+ uvc_debugfs_cleanup_stream(stream);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
+{
+ if (stream->debugfs_dir == NULL)
+ return;
+
+ debugfs_remove_recursive(stream->debugfs_dir);
+ stream->debugfs_dir = NULL;
+}
+
+int uvc_debugfs_init(void)
+{
+ struct dentry *dir;
+
+ dir = debugfs_create_dir("uvcvideo", usb_debug_root);
+ if (IS_ERR_OR_NULL(dir)) {
+ uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
+ return -ENODATA;
+ }
+
+ uvc_debugfs_root_dir = dir;
+ return 0;
+}
+
+void uvc_debugfs_cleanup(void)
+{
+ if (uvc_debugfs_root_dir != NULL)
+ debugfs_remove_recursive(uvc_debugfs_root_dir);
+}
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 656d4c9..a240d43 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1675,6 +1675,8 @@ static void uvc_unregister_video(struct uvc_device *dev)
video_unregister_device(stream->vdev);
stream->vdev = NULL;
+
+ uvc_debugfs_cleanup_stream(stream);
}
/* Decrement the stream count and call uvc_delete explicitly if there
@@ -1700,6 +1702,8 @@ static int uvc_register_video(struct uvc_device *dev,
return ret;
}
+ uvc_debugfs_init_stream(stream);
+
/* Register the device with V4L. */
vdev = video_device_alloc();
if (vdev == NULL) {
@@ -2033,6 +2037,15 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
* though they are compliant.
*/
static struct usb_device_id uvc_ids[] = {
+ /* LogiLink Wireless Webcam */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x0416,
+ .idProduct = 0xa91a,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_PROBE_MINMAX },
/* Genius eFace 2025 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2396,17 +2409,24 @@ struct uvc_driver uvc_driver = {
static int __init uvc_init(void)
{
- int result;
+ int ret;
+
+ uvc_debugfs_init();
- result = usb_register(&uvc_driver.driver);
- if (result == 0)
- printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
- return result;
+ ret = usb_register(&uvc_driver.driver);
+ if (ret < 0) {
+ uvc_debugfs_cleanup();
+ return ret;
+ }
+
+ printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
+ return 0;
}
static void __exit uvc_cleanup(void)
{
usb_deregister(&uvc_driver.driver);
+ uvc_debugfs_cleanup();
}
module_init(uvc_init);
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c
index 74bbe8f..8510e725 100644
--- a/drivers/media/video/uvc/uvc_isight.c
+++ b/drivers/media/video/uvc/uvc_isight.c
@@ -74,7 +74,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
* Empty buffers (bytesused == 0) don't trigger end of frame detection
* as it doesn't make sense to return an empty buffer.
*/
- if (is_header && buf->buf.bytesused != 0) {
+ if (is_header && buf->bytesused != 0) {
buf->state = UVC_BUF_STATE_DONE;
return -EAGAIN;
}
@@ -83,13 +83,13 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
* contain no data.
*/
if (!is_header) {
- maxlen = buf->buf.length - buf->buf.bytesused;
- mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ maxlen = buf->length - buf->bytesused;
+ mem = buf->mem + buf->bytesused;
nbytes = min(len, maxlen);
memcpy(mem, data, nbytes);
- buf->buf.bytesused += nbytes;
+ buf->bytesused += nbytes;
- if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
+ if (len > maxlen || buf->bytesused == buf->length) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete "
"(overflow).\n");
buf->state = UVC_BUF_STATE_DONE;
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 677691c..518f77d 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/list.h>
@@ -19,7 +20,7 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
-#include <linux/atomic.h>
+#include <media/videobuf2-vmalloc.h>
#include "uvcvideo.h"
@@ -29,467 +30,211 @@
* Video queues is initialized by uvc_queue_init(). The function performs
* basic initialization of the uvc_video_queue struct and never fails.
*
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- * The buffers are added to the main and irq queues. Both operations are
- * protected by the queue lock, and the later is protected by the irq
- * spinlock as well.
- *
- * The completion handler fetches a buffer from the irq queue and fills it
- * with video data. If no buffer is available (irq queue empty), the handler
- * returns immediately.
- *
- * When the buffer is full, the completion handler removes it from the irq
- * queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue.
- * At that point, any process waiting on the buffer will be woken up. If a
- * process tries to dequeue a buffer after it has been marked done, the
- * dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- * disconnected.
- *
- * When the device is disconnected, the kernel calls the completion handler
- * with an appropriate status code. The handler marks all buffers in the
- * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- * that any process waiting on a buffer gets woken up.
- *
- * Waking up up the first buffer on the irq list is not enough, as the
- * process waiting on the buffer might restart the dequeue operation
- * immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
*/
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
- int drop_corrupted)
-{
- mutex_init(&queue->mutex);
- spin_lock_init(&queue->irqlock);
- INIT_LIST_HEAD(&queue->mainqueue);
- INIT_LIST_HEAD(&queue->irqqueue);
- queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
- queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
*/
-static int __uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- unsigned int i;
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
- for (i = 0; i < queue->count; ++i) {
- if (queue->buffer[i].vma_use_count != 0)
- return -EBUSY;
- }
+ if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+ *nbuffers = UVC_MAX_VIDEO_BUFFERS;
- if (queue->count) {
- uvc_queue_cancel(queue, 0);
- INIT_LIST_HEAD(&queue->mainqueue);
- vfree(queue->mem);
- queue->count = 0;
- }
+ *nplanes = 1;
+
+ sizes[0] = stream->ctrl.dwMaxVideoFrameSize;
return 0;
}
-int uvc_free_buffers(struct uvc_video_queue *queue)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
- int ret;
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
- mutex_lock(&queue->mutex);
- ret = __uvc_free_buffers(queue);
- mutex_unlock(&queue->mutex);
+ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+ uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+ return -EINVAL;
+ }
- return ret;
-}
+ if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+ return -ENODEV;
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
- unsigned int buflength)
-{
- unsigned int bufsize = PAGE_ALIGN(buflength);
- unsigned int i;
- void *mem = NULL;
- int ret;
+ buf->state = UVC_BUF_STATE_QUEUED;
+ buf->error = 0;
+ buf->mem = vb2_plane_vaddr(vb, 0);
+ buf->length = vb2_plane_size(vb, 0);
+ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ buf->bytesused = 0;
+ else
+ buf->bytesused = vb2_get_plane_payload(vb, 0);
- if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
- nbuffers = UVC_MAX_VIDEO_BUFFERS;
+ return 0;
+}
- mutex_lock(&queue->mutex);
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ unsigned long flags;
- if ((ret = __uvc_free_buffers(queue)) < 0)
- goto done;
+ spin_lock_irqsave(&queue->irqlock, flags);
+ if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+ list_add_tail(&buf->queue, &queue->irqqueue);
+ } else {
+ /* If the device is disconnected return the buffer to userspace
+ * directly. The next QBUF call will fail with -ENODEV.
+ */
+ buf->state = UVC_BUF_STATE_ERROR;
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ }
- /* Bail out if no buffers should be allocated. */
- if (nbuffers == 0)
- goto done;
+ spin_unlock_irqrestore(&queue->irqlock, flags);
+}
- /* Decrement the number of buffers until allocation succeeds. */
- for (; nbuffers > 0; --nbuffers) {
- mem = vmalloc_32(nbuffers * bufsize);
- if (mem != NULL)
- break;
- }
+static int uvc_buffer_finish(struct vb2_buffer *vb)
+{
+ struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
+ struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
- if (mem == NULL) {
- ret = -ENOMEM;
- goto done;
- }
+ uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+ return 0;
+}
- for (i = 0; i < nbuffers; ++i) {
- memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
- queue->buffer[i].buf.index = i;
- queue->buffer[i].buf.m.offset = i * bufsize;
- queue->buffer[i].buf.length = buflength;
- queue->buffer[i].buf.type = queue->type;
- queue->buffer[i].buf.field = V4L2_FIELD_NONE;
- queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
- queue->buffer[i].buf.flags = 0;
- init_waitqueue_head(&queue->buffer[i].wait);
- }
+static struct vb2_ops uvc_queue_qops = {
+ .queue_setup = uvc_queue_setup,
+ .buf_prepare = uvc_buffer_prepare,
+ .buf_queue = uvc_buffer_queue,
+ .buf_finish = uvc_buffer_finish,
+};
- queue->mem = mem;
- queue->count = nbuffers;
- queue->buf_size = bufsize;
- ret = nbuffers;
+void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+ int drop_corrupted)
+{
+ queue->queue.type = type;
+ queue->queue.io_modes = VB2_MMAP;
+ queue->queue.drv_priv = queue;
+ queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+ queue->queue.ops = &uvc_queue_qops;
+ queue->queue.mem_ops = &vb2_vmalloc_memops;
+ vb2_queue_init(&queue->queue);
-done:
- mutex_unlock(&queue->mutex);
- return ret;
+ mutex_init(&queue->mutex);
+ spin_lock_init(&queue->irqlock);
+ INIT_LIST_HEAD(&queue->irqqueue);
+ queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
}
-/*
- * Check if buffers have been allocated.
+/* -----------------------------------------------------------------------------
+ * V4L2 queue operations
*/
-int uvc_queue_allocated(struct uvc_video_queue *queue)
+
+int uvc_alloc_buffers(struct uvc_video_queue *queue,
+ struct v4l2_requestbuffers *rb)
{
- int allocated;
+ int ret;
mutex_lock(&queue->mutex);
- allocated = queue->count != 0;
+ ret = vb2_reqbufs(&queue->queue, rb);
mutex_unlock(&queue->mutex);
- return allocated;
+ return ret ? ret : rb->count;
}
-static void __uvc_query_buffer(struct uvc_buffer *buf,
- struct v4l2_buffer *v4l2_buf)
+void uvc_free_buffers(struct uvc_video_queue *queue)
{
- memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
- if (buf->vma_use_count)
- v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
- switch (buf->state) {
- case UVC_BUF_STATE_ERROR:
- case UVC_BUF_STATE_DONE:
- v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
- break;
- case UVC_BUF_STATE_QUEUED:
- case UVC_BUF_STATE_ACTIVE:
- case UVC_BUF_STATE_READY:
- v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
- break;
- case UVC_BUF_STATE_IDLE:
- default:
- break;
- }
+ mutex_lock(&queue->mutex);
+ vb2_queue_release(&queue->queue);
+ mutex_unlock(&queue->mutex);
}
-int uvc_query_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf)
+int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
{
- int ret = 0;
+ int ret;
mutex_lock(&queue->mutex);
- if (v4l2_buf->index >= queue->count) {
- ret = -EINVAL;
- goto done;
- }
-
- __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
-
-done:
+ ret = vb2_querybuf(&queue->queue, buf);
mutex_unlock(&queue->mutex);
+
return ret;
}
-/*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
- */
-int uvc_queue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf)
+int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
{
- struct uvc_buffer *buf;
- unsigned long flags;
- int ret = 0;
-
- uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
-
- if (v4l2_buf->type != queue->type ||
- v4l2_buf->memory != V4L2_MEMORY_MMAP) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
- "and/or memory (%u).\n", v4l2_buf->type,
- v4l2_buf->memory);
- return -EINVAL;
- }
+ int ret;
mutex_lock(&queue->mutex);
- if (v4l2_buf->index >= queue->count) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
- ret = -EINVAL;
- goto done;
- }
-
- buf = &queue->buffer[v4l2_buf->index];
- if (buf->state != UVC_BUF_STATE_IDLE) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
- "(%u).\n", buf->state);
- ret = -EINVAL;
- goto done;
- }
-
- if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
- v4l2_buf->bytesused > buf->buf.length) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
- ret = -EINVAL;
- goto done;
- }
-
- spin_lock_irqsave(&queue->irqlock, flags);
- if (queue->flags & UVC_QUEUE_DISCONNECTED) {
- spin_unlock_irqrestore(&queue->irqlock, flags);
- ret = -ENODEV;
- goto done;
- }
- buf->state = UVC_BUF_STATE_QUEUED;
- if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- buf->buf.bytesused = 0;
- else
- buf->buf.bytesused = v4l2_buf->bytesused;
-
- list_add_tail(&buf->stream, &queue->mainqueue);
- list_add_tail(&buf->queue, &queue->irqqueue);
- spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
+ ret = vb2_qbuf(&queue->queue, buf);
mutex_unlock(&queue->mutex);
- return ret;
-}
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
- if (nonblocking) {
- return (buf->state != UVC_BUF_STATE_QUEUED &&
- buf->state != UVC_BUF_STATE_ACTIVE &&
- buf->state != UVC_BUF_STATE_READY)
- ? 0 : -EAGAIN;
- }
-
- return wait_event_interruptible(buf->wait,
- buf->state != UVC_BUF_STATE_QUEUED &&
- buf->state != UVC_BUF_STATE_ACTIVE &&
- buf->state != UVC_BUF_STATE_READY);
+ return ret;
}
-/*
- * Dequeue a video buffer. If nonblocking is false, block until a buffer is
- * available.
- */
-int uvc_dequeue_buffer(struct uvc_video_queue *queue,
- struct v4l2_buffer *v4l2_buf, int nonblocking)
+int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
+ int nonblocking)
{
- struct uvc_buffer *buf;
- int ret = 0;
-
- if (v4l2_buf->type != queue->type ||
- v4l2_buf->memory != V4L2_MEMORY_MMAP) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
- "and/or memory (%u).\n", v4l2_buf->type,
- v4l2_buf->memory);
- return -EINVAL;
- }
+ int ret;
mutex_lock(&queue->mutex);
- if (list_empty(&queue->mainqueue)) {
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
- ret = -EINVAL;
- goto done;
- }
-
- buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
- if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
- goto done;
-
- uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
- buf->buf.index, buf->state, buf->buf.bytesused);
-
- switch (buf->state) {
- case UVC_BUF_STATE_ERROR:
- uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
- "(transmission error).\n");
- ret = -EIO;
- case UVC_BUF_STATE_DONE:
- buf->state = UVC_BUF_STATE_IDLE;
- break;
-
- case UVC_BUF_STATE_IDLE:
- case UVC_BUF_STATE_QUEUED:
- case UVC_BUF_STATE_ACTIVE:
- case UVC_BUF_STATE_READY:
- default:
- uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
- "(driver bug?).\n", buf->state);
- ret = -EINVAL;
- goto done;
- }
-
- list_del(&buf->stream);
- __uvc_query_buffer(buf, v4l2_buf);
-
-done:
+ ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
mutex_unlock(&queue->mutex);
- return ret;
-}
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
- struct uvc_buffer *buffer = vma->vm_private_data;
- buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
- struct uvc_buffer *buffer = vma->vm_private_data;
- buffer->vma_use_count--;
+ return ret;
}
-static const struct vm_operations_struct uvc_vm_ops = {
- .open = uvc_vm_open,
- .close = uvc_vm_close,
-};
-
-/*
- * Memory-map a video buffer.
- *
- * This function implements video buffers memory mapping and is intended to be
- * used by the device mmap handler.
- */
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
- struct uvc_buffer *uninitialized_var(buffer);
- struct page *page;
- unsigned long addr, start, size;
- unsigned int i;
- int ret = 0;
-
- start = vma->vm_start;
- size = vma->vm_end - vma->vm_start;
+ int ret;
mutex_lock(&queue->mutex);
+ ret = vb2_mmap(&queue->queue, vma);
+ mutex_unlock(&queue->mutex);
- for (i = 0; i < queue->count; ++i) {
- buffer = &queue->buffer[i];
- if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
- break;
- }
-
- if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) {
- ret = -EINVAL;
- goto done;
- }
-
- /*
- * VM_IO marks the area as being an mmaped region for I/O to a
- * device. It also prevents the region from being core dumped.
- */
- vma->vm_flags |= VM_IO;
-
- addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-#ifdef CONFIG_MMU
- while (size > 0) {
- page = vmalloc_to_page((void *)addr);
- if ((ret = vm_insert_page(vma, start, page)) < 0)
- goto done;
-
- start += PAGE_SIZE;
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-#endif
+ return ret;
+}
- vma->vm_ops = &uvc_vm_ops;
- vma->vm_private_data = buffer;
- uvc_vm_open(vma);
+unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
+ poll_table *wait)
+{
+ unsigned int ret;
-done:
+ mutex_lock(&queue->mutex);
+ ret = vb2_poll(&queue->queue, file, wait);
mutex_unlock(&queue->mutex);
+
return ret;
}
-/*
- * Poll the video queue.
+/* -----------------------------------------------------------------------------
*
- * This function implements video queue polling and is intended to be used by
- * the device poll handler.
*/
-unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
- poll_table *wait)
+
+/*
+ * Check if buffers have been allocated.
+ */
+int uvc_queue_allocated(struct uvc_video_queue *queue)
{
- struct uvc_buffer *buf;
- unsigned int mask = 0;
+ int allocated;
mutex_lock(&queue->mutex);
- if (list_empty(&queue->mainqueue)) {
- mask |= POLLERR;
- goto done;
- }
- buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
- poll_wait(file, &buf->wait, wait);
- if (buf->state == UVC_BUF_STATE_DONE ||
- buf->state == UVC_BUF_STATE_ERROR) {
- if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- mask |= POLLIN | POLLRDNORM;
- else
- mask |= POLLOUT | POLLWRNORM;
- }
-
-done:
+ allocated = vb2_is_busy(&queue->queue);
mutex_unlock(&queue->mutex);
- return mask;
+
+ return allocated;
}
#ifndef CONFIG_MMU
@@ -515,7 +260,7 @@ unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
ret = -EINVAL;
goto done;
}
- ret = (unsigned long)queue->mem + buffer->buf.m.offset;
+ ret = (unsigned long)buf->mem;
done:
mutex_unlock(&queue->mutex);
return ret;
@@ -540,27 +285,24 @@ done:
*/
int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
- unsigned int i;
- int ret = 0;
+ unsigned long flags;
+ int ret;
mutex_lock(&queue->mutex);
if (enable) {
- if (uvc_queue_streaming(queue)) {
- ret = -EBUSY;
+ ret = vb2_streamon(&queue->queue, queue->queue.type);
+ if (ret < 0)
goto done;
- }
- queue->flags |= UVC_QUEUE_STREAMING;
+
queue->buf_used = 0;
} else {
- uvc_queue_cancel(queue, 0);
- INIT_LIST_HEAD(&queue->mainqueue);
-
- for (i = 0; i < queue->count; ++i) {
- queue->buffer[i].error = 0;
- queue->buffer[i].state = UVC_BUF_STATE_IDLE;
- }
+ ret = vb2_streamoff(&queue->queue, queue->queue.type);
+ if (ret < 0)
+ goto done;
- queue->flags &= ~UVC_QUEUE_STREAMING;
+ spin_lock_irqsave(&queue->irqlock, flags);
+ INIT_LIST_HEAD(&queue->irqqueue);
+ spin_unlock_irqrestore(&queue->irqlock, flags);
}
done:
@@ -591,12 +333,12 @@ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
- wake_up(&buf->wait);
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
}
/* This must be protected by the irqlock spinlock to avoid race
- * conditions between uvc_queue_buffer and the disconnection event that
+ * conditions between uvc_buffer_queue and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
- * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
+ * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED
* state outside the queue code.
*/
if (disconnect)
@@ -613,14 +355,12 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
buf->error = 0;
buf->state = UVC_BUF_STATE_QUEUED;
- buf->buf.bytesused = 0;
+ vb2_set_plane_payload(&buf->buf, 0, 0);
return buf;
}
spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
- buf->error = 0;
- buf->state = UVC_BUF_STATE_DONE;
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
@@ -628,7 +368,9 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
nextbuf = NULL;
spin_unlock_irqrestore(&queue->irqlock, flags);
- wake_up(&buf->wait);
+ buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
+ vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+
return nextbuf;
}
-
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index dadf11f..2ae4f88 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -58,6 +58,15 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
break;
case V4L2_CTRL_TYPE_MENU:
+ /* Prevent excessive memory consumption, as well as integer
+ * overflows.
+ */
+ if (xmap->menu_count == 0 ||
+ xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
+ ret = -EINVAL;
+ goto done;
+ }
+
size = xmap->menu_count * sizeof(*map->menu_info);
map->menu_info = kmalloc(size, GFP_KERNEL);
if (map->menu_info == NULL) {
@@ -513,10 +522,7 @@ static int uvc_v4l2_release(struct file *file)
/* Only free resources if this is a privileged handle. */
if (uvc_has_privileges(handle)) {
uvc_video_enable(stream, 0);
-
- if (uvc_free_buffers(&stream->queue) < 0)
- uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
- "free buffers.\n");
+ uvc_free_buffers(&stream->queue);
}
/* Release the file handle. */
@@ -914,19 +920,11 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
/* Buffers & streaming */
case VIDIOC_REQBUFS:
- {
- struct v4l2_requestbuffers *rb = arg;
-
- if (rb->type != stream->type ||
- rb->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
if ((ret = uvc_acquire_privileges(handle)) < 0)
return ret;
mutex_lock(&stream->mutex);
- ret = uvc_alloc_buffers(&stream->queue, rb->count,
- stream->ctrl.dwMaxVideoFrameSize);
+ ret = uvc_alloc_buffers(&stream->queue, arg);
mutex_unlock(&stream->mutex);
if (ret < 0)
return ret;
@@ -934,18 +932,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
if (ret == 0)
uvc_dismiss_privileges(handle);
- rb->count = ret;
ret = 0;
break;
- }
case VIDIOC_QUERYBUF:
{
struct v4l2_buffer *buf = arg;
- if (buf->type != stream->type)
- return -EINVAL;
-
if (!uvc_has_privileges(handle))
return -EBUSY;
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index b015e8e..c7e69b8 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -351,25 +351,553 @@ done:
return ret;
}
-int uvc_commit_video(struct uvc_streaming *stream,
- struct uvc_streaming_control *probe)
+static int uvc_commit_video(struct uvc_streaming *stream,
+ struct uvc_streaming_control *probe)
{
return uvc_set_video_ctrl(stream, probe, 0);
}
+/* -----------------------------------------------------------------------------
+ * Clocks and timestamps
+ */
+
+static void
+uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+ const __u8 *data, int len)
+{
+ struct uvc_clock_sample *sample;
+ unsigned int header_size;
+ bool has_pts = false;
+ bool has_scr = false;
+ unsigned long flags;
+ struct timespec ts;
+ u16 host_sof;
+ u16 dev_sof;
+
+ switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+ case UVC_STREAM_PTS | UVC_STREAM_SCR:
+ header_size = 12;
+ has_pts = true;
+ has_scr = true;
+ break;
+ case UVC_STREAM_PTS:
+ header_size = 6;
+ has_pts = true;
+ break;
+ case UVC_STREAM_SCR:
+ header_size = 8;
+ has_scr = true;
+ break;
+ default:
+ header_size = 2;
+ break;
+ }
+
+ /* Check for invalid headers. */
+ if (len < header_size)
+ return;
+
+ /* Extract the timestamps:
+ *
+ * - store the frame PTS in the buffer structure
+ * - if the SCR field is present, retrieve the host SOF counter and
+ * kernel timestamps and store them with the SCR STC and SOF fields
+ * in the ring buffer
+ */
+ if (has_pts && buf != NULL)
+ buf->pts = get_unaligned_le32(&data[2]);
+
+ if (!has_scr)
+ return;
+
+ /* To limit the amount of data, drop SCRs with an SOF identical to the
+ * previous one.
+ */
+ dev_sof = get_unaligned_le16(&data[header_size - 2]);
+ if (dev_sof == stream->clock.last_sof)
+ return;
+
+ stream->clock.last_sof = dev_sof;
+
+ host_sof = usb_get_current_frame_number(stream->dev->udev);
+ ktime_get_ts(&ts);
+
+ /* The UVC specification allows device implementations that can't obtain
+ * the USB frame number to keep their own frame counters as long as they
+ * match the size and frequency of the frame number associated with USB
+ * SOF tokens. The SOF values sent by such devices differ from the USB
+ * SOF tokens by a fixed offset that needs to be estimated and accounted
+ * for to make timestamp recovery as accurate as possible.
+ *
+ * The offset is estimated the first time a device SOF value is received
+ * as the difference between the host and device SOF values. As the two
+ * SOF values can differ slightly due to transmission delays, consider
+ * that the offset is null if the difference is not higher than 10 ms
+ * (negative differences can not happen and are thus considered as an
+ * offset). The video commit control wDelay field should be used to
+ * compute a dynamic threshold instead of using a fixed 10 ms value, but
+ * devices don't report reliable wDelay values.
+ *
+ * See uvc_video_clock_host_sof() for an explanation regarding why only
+ * the 8 LSBs of the delta are kept.
+ */
+ if (stream->clock.sof_offset == (u16)-1) {
+ u16 delta_sof = (host_sof - dev_sof) & 255;
+ if (delta_sof >= 10)
+ stream->clock.sof_offset = delta_sof;
+ else
+ stream->clock.sof_offset = 0;
+ }
+
+ dev_sof = (dev_sof + stream->clock.sof_offset) & 2047;
+
+ spin_lock_irqsave(&stream->clock.lock, flags);
+
+ sample = &stream->clock.samples[stream->clock.head];
+ sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
+ sample->dev_sof = dev_sof;
+ sample->host_sof = host_sof;
+ sample->host_ts = ts;
+
+ /* Update the sliding window head and count. */
+ stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
+
+ if (stream->clock.count < stream->clock.size)
+ stream->clock.count++;
+
+ spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
+static int uvc_video_clock_init(struct uvc_streaming *stream)
+{
+ struct uvc_clock *clock = &stream->clock;
+
+ spin_lock_init(&clock->lock);
+ clock->head = 0;
+ clock->count = 0;
+ clock->size = 32;
+ clock->last_sof = -1;
+ clock->sof_offset = -1;
+
+ clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
+ GFP_KERNEL);
+ if (clock->samples == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void uvc_video_clock_cleanup(struct uvc_streaming *stream)
+{
+ kfree(stream->clock.samples);
+ stream->clock.samples = NULL;
+}
+
+/*
+ * uvc_video_clock_host_sof - Return the host SOF value for a clock sample
+ *
+ * Host SOF counters reported by usb_get_current_frame_number() usually don't
+ * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame
+ * schedule window. They can be limited to 8, 9 or 10 bits depending on the host
+ * controller and its configuration.
+ *
+ * We thus need to recover the SOF value corresponding to the host frame number.
+ * As the device and host frame numbers are sampled in a short interval, the
+ * difference between their values should be equal to a small delta plus an
+ * integer multiple of 256 caused by the host frame number limited precision.
+ *
+ * To obtain the recovered host SOF value, compute the small delta by masking
+ * the high bits of the host frame counter and device SOF difference and add it
+ * to the device SOF value.
+ */
+static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
+{
+ /* The delta value can be negative. */
+ s8 delta_sof;
+
+ delta_sof = (sample->host_sof - sample->dev_sof) & 255;
+
+ return (sample->dev_sof + delta_sof) & 2047;
+}
+
+/*
+ * uvc_video_clock_update - Update the buffer timestamp
+ *
+ * This function converts the buffer PTS timestamp to the host clock domain by
+ * going through the USB SOF clock domain and stores the result in the V4L2
+ * buffer timestamp field.
+ *
+ * The relationship between the device clock and the host clock isn't known.
+ * However, the device and the host share the common USB SOF clock which can be
+ * used to recover that relationship.
+ *
+ * The relationship between the device clock and the USB SOF clock is considered
+ * to be linear over the clock samples sliding window and is given by
+ *
+ * SOF = m * PTS + p
+ *
+ * Several methods to compute the slope (m) and intercept (p) can be used. As
+ * the clock drift should be small compared to the sliding window size, we
+ * assume that the line that goes through the points at both ends of the window
+ * is a good approximation. Naming those points P1 and P2, we get
+ *
+ * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS
+ * + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)
+ *
+ * or
+ *
+ * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1)
+ *
+ * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * computed with
+ *
+ * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2)
+ *
+ * SOF values are coded on 11 bits by USB. We extend their precision with 16
+ * decimal bits, leading to a 11.16 coding.
+ *
+ * TODO: To avoid surprises with device clock values, PTS/STC timestamps should
+ * be normalized using the nominal device clock frequency reported through the
+ * UVC descriptors.
+ *
+ * Both the PTS/STC and SOF counters roll over, after a fixed but device
+ * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the
+ * sliding window size is smaller than the rollover period, differences computed
+ * on unsigned integers will produce the correct result. However, the p term in
+ * the linear relations will be miscomputed.
+ *
+ * To fix the issue, we subtract a constant from the PTS and STC values to bring
+ * PTS to half the 32 bit STC range. The sliding window STC values then fit into
+ * the 32 bit range without any rollover.
+ *
+ * Similarly, we add 2048 to the device SOF values to make sure that the SOF
+ * computed by (1) will never be smaller than 0. This offset is then compensated
+ * by adding 2048 to the SOF values used in (2). However, this doesn't prevent
+ * rollovers between (1) and (2): the SOF value computed by (1) can be slightly
+ * lower than 4096, and the host SOF counters can have rolled over to 2048. This
+ * case is handled by subtracting 2048 from the SOF value if it exceeds the host
+ * SOF value at the end of the sliding window.
+ *
+ * Finally we subtract a constant from the host timestamps to bring the first
+ * timestamp of the sliding window to 1s.
+ */
+void uvc_video_clock_update(struct uvc_streaming *stream,
+ struct v4l2_buffer *v4l2_buf,
+ struct uvc_buffer *buf)
+{
+ struct uvc_clock *clock = &stream->clock;
+ struct uvc_clock_sample *first;
+ struct uvc_clock_sample *last;
+ unsigned long flags;
+ struct timespec ts;
+ u32 delta_stc;
+ u32 y1, y2;
+ u32 x1, x2;
+ u32 mean;
+ u32 sof;
+ u32 div;
+ u32 rem;
+ u64 y;
+
+ spin_lock_irqsave(&clock->lock, flags);
+
+ if (clock->count < clock->size)
+ goto done;
+
+ first = &clock->samples[clock->head];
+ last = &clock->samples[(clock->head - 1) % clock->size];
+
+ /* First step, PTS to SOF conversion. */
+ delta_stc = buf->pts - (1UL << 31);
+ x1 = first->dev_stc - delta_stc;
+ x2 = last->dev_stc - delta_stc;
+ y1 = (first->dev_sof + 2048) << 16;
+ y2 = (last->dev_sof + 2048) << 16;
+
+ if (y2 < y1)
+ y2 += 2048 << 16;
+
+ y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2
+ - (u64)y2 * (u64)x1;
+ y = div_u64(y, x2 - x1);
+
+ sof = y;
+
+ uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
+ "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
+ stream->dev->name, buf->pts,
+ y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
+ sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+ x1, x2, y1, y2, clock->sof_offset);
+
+ /* Second step, SOF to host clock conversion. */
+ ts = timespec_sub(last->host_ts, first->host_ts);
+ x1 = (uvc_video_clock_host_sof(first) + 2048) << 16;
+ x2 = (uvc_video_clock_host_sof(last) + 2048) << 16;
+ y1 = NSEC_PER_SEC;
+ y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec;
+
+ if (x2 < x1)
+ x2 += 2048 << 16;
+
+ /* Interpolated and host SOF timestamps can wrap around at slightly
+ * different times. Handle this by adding or removing 2048 to or from
+ * the computed SOF value to keep it close to the SOF samples mean
+ * value.
+ */
+ mean = (x1 + x2) / 2;
+ if (mean - (1024 << 16) > sof)
+ sof += 2048 << 16;
+ else if (sof > mean + (1024 << 16))
+ sof -= 2048 << 16;
+
+ y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2
+ - (u64)y2 * (u64)x1;
+ y = div_u64(y, x2 - x1);
+
+ div = div_u64_rem(y, NSEC_PER_SEC, &rem);
+ ts.tv_sec = first->host_ts.tv_sec - 1 + div;
+ ts.tv_nsec = first->host_ts.tv_nsec + rem;
+ if (ts.tv_nsec >= NSEC_PER_SEC) {
+ ts.tv_sec++;
+ ts.tv_nsec -= NSEC_PER_SEC;
+ }
+
+ uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
+ "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+ stream->dev->name,
+ sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+ y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
+ v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec,
+ x1, first->host_sof, first->dev_sof,
+ x2, last->host_sof, last->dev_sof, y1, y2);
+
+ /* Update the V4L2 buffer. */
+ v4l2_buf->timestamp.tv_sec = ts.tv_sec;
+ v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+done:
+ spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
/* ------------------------------------------------------------------------
- * Video codecs
+ * Stream statistics
*/
-/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
-#define UVC_STREAM_EOH (1 << 7)
-#define UVC_STREAM_ERR (1 << 6)
-#define UVC_STREAM_STI (1 << 5)
-#define UVC_STREAM_RES (1 << 4)
-#define UVC_STREAM_SCR (1 << 3)
-#define UVC_STREAM_PTS (1 << 2)
-#define UVC_STREAM_EOF (1 << 1)
-#define UVC_STREAM_FID (1 << 0)
+static void uvc_video_stats_decode(struct uvc_streaming *stream,
+ const __u8 *data, int len)
+{
+ unsigned int header_size;
+ bool has_pts = false;
+ bool has_scr = false;
+ u16 uninitialized_var(scr_sof);
+ u32 uninitialized_var(scr_stc);
+ u32 uninitialized_var(pts);
+
+ if (stream->stats.stream.nb_frames == 0 &&
+ stream->stats.frame.nb_packets == 0)
+ ktime_get_ts(&stream->stats.stream.start_ts);
+
+ switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+ case UVC_STREAM_PTS | UVC_STREAM_SCR:
+ header_size = 12;
+ has_pts = true;
+ has_scr = true;
+ break;
+ case UVC_STREAM_PTS:
+ header_size = 6;
+ has_pts = true;
+ break;
+ case UVC_STREAM_SCR:
+ header_size = 8;
+ has_scr = true;
+ break;
+ default:
+ header_size = 2;
+ break;
+ }
+
+ /* Check for invalid headers. */
+ if (len < header_size || data[0] < header_size) {
+ stream->stats.frame.nb_invalid++;
+ return;
+ }
+
+ /* Extract the timestamps. */
+ if (has_pts)
+ pts = get_unaligned_le32(&data[2]);
+
+ if (has_scr) {
+ scr_stc = get_unaligned_le32(&data[header_size - 6]);
+ scr_sof = get_unaligned_le16(&data[header_size - 2]);
+ }
+
+ /* Is PTS constant through the whole frame ? */
+ if (has_pts && stream->stats.frame.nb_pts) {
+ if (stream->stats.frame.pts != pts) {
+ stream->stats.frame.nb_pts_diffs++;
+ stream->stats.frame.last_pts_diff =
+ stream->stats.frame.nb_packets;
+ }
+ }
+
+ if (has_pts) {
+ stream->stats.frame.nb_pts++;
+ stream->stats.frame.pts = pts;
+ }
+
+ /* Do all frames have a PTS in their first non-empty packet, or before
+ * their first empty packet ?
+ */
+ if (stream->stats.frame.size == 0) {
+ if (len > header_size)
+ stream->stats.frame.has_initial_pts = has_pts;
+ if (len == header_size && has_pts)
+ stream->stats.frame.has_early_pts = true;
+ }
+
+ /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */
+ if (has_scr && stream->stats.frame.nb_scr) {
+ if (stream->stats.frame.scr_stc != scr_stc)
+ stream->stats.frame.nb_scr_diffs++;
+ }
+
+ if (has_scr) {
+ /* Expand the SOF counter to 32 bits and store its value. */
+ if (stream->stats.stream.nb_frames > 0 ||
+ stream->stats.frame.nb_scr > 0)
+ stream->stats.stream.scr_sof_count +=
+ (scr_sof - stream->stats.stream.scr_sof) % 2048;
+ stream->stats.stream.scr_sof = scr_sof;
+
+ stream->stats.frame.nb_scr++;
+ stream->stats.frame.scr_stc = scr_stc;
+ stream->stats.frame.scr_sof = scr_sof;
+
+ if (scr_sof < stream->stats.stream.min_sof)
+ stream->stats.stream.min_sof = scr_sof;
+ if (scr_sof > stream->stats.stream.max_sof)
+ stream->stats.stream.max_sof = scr_sof;
+ }
+
+ /* Record the first non-empty packet number. */
+ if (stream->stats.frame.size == 0 && len > header_size)
+ stream->stats.frame.first_data = stream->stats.frame.nb_packets;
+
+ /* Update the frame size. */
+ stream->stats.frame.size += len - header_size;
+
+ /* Update the packets counters. */
+ stream->stats.frame.nb_packets++;
+ if (len > header_size)
+ stream->stats.frame.nb_empty++;
+
+ if (data[1] & UVC_STREAM_ERR)
+ stream->stats.frame.nb_errors++;
+}
+
+static void uvc_video_stats_update(struct uvc_streaming *stream)
+{
+ struct uvc_stats_frame *frame = &stream->stats.frame;
+
+ uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, "
+ "%u/%u/%u pts (%searly %sinitial), %u/%u scr, "
+ "last pts/stc/sof %u/%u/%u\n",
+ stream->sequence, frame->first_data,
+ frame->nb_packets - frame->nb_empty, frame->nb_packets,
+ frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts,
+ frame->has_early_pts ? "" : "!",
+ frame->has_initial_pts ? "" : "!",
+ frame->nb_scr_diffs, frame->nb_scr,
+ frame->pts, frame->scr_stc, frame->scr_sof);
+
+ stream->stats.stream.nb_frames++;
+ stream->stats.stream.nb_packets += stream->stats.frame.nb_packets;
+ stream->stats.stream.nb_empty += stream->stats.frame.nb_empty;
+ stream->stats.stream.nb_errors += stream->stats.frame.nb_errors;
+ stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid;
+
+ if (frame->has_early_pts)
+ stream->stats.stream.nb_pts_early++;
+ if (frame->has_initial_pts)
+ stream->stats.stream.nb_pts_initial++;
+ if (frame->last_pts_diff <= frame->first_data)
+ stream->stats.stream.nb_pts_constant++;
+ if (frame->nb_scr >= frame->nb_packets - frame->nb_empty)
+ stream->stats.stream.nb_scr_count_ok++;
+ if (frame->nb_scr_diffs + 1 == frame->nb_scr)
+ stream->stats.stream.nb_scr_diffs_ok++;
+
+ memset(&stream->stats.frame, 0, sizeof(stream->stats.frame));
+}
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+ size_t size)
+{
+ unsigned int scr_sof_freq;
+ unsigned int duration;
+ struct timespec ts;
+ size_t count = 0;
+
+ ts.tv_sec = stream->stats.stream.stop_ts.tv_sec
+ - stream->stats.stream.start_ts.tv_sec;
+ ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec
+ - stream->stats.stream.start_ts.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_sec--;
+ ts.tv_nsec += 1000000000;
+ }
+
+ /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF
+ * frequency this will not overflow before more than 1h.
+ */
+ duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+ if (duration != 0)
+ scr_sof_freq = stream->stats.stream.scr_sof_count * 1000
+ / duration;
+ else
+ scr_sof_freq = 0;
+
+ count += scnprintf(buf + count, size - count,
+ "frames: %u\npackets: %u\nempty: %u\n"
+ "errors: %u\ninvalid: %u\n",
+ stream->stats.stream.nb_frames,
+ stream->stats.stream.nb_packets,
+ stream->stats.stream.nb_empty,
+ stream->stats.stream.nb_errors,
+ stream->stats.stream.nb_invalid);
+ count += scnprintf(buf + count, size - count,
+ "pts: %u early, %u initial, %u ok\n",
+ stream->stats.stream.nb_pts_early,
+ stream->stats.stream.nb_pts_initial,
+ stream->stats.stream.nb_pts_constant);
+ count += scnprintf(buf + count, size - count,
+ "scr: %u count ok, %u diff ok\n",
+ stream->stats.stream.nb_scr_count_ok,
+ stream->stats.stream.nb_scr_diffs_ok);
+ count += scnprintf(buf + count, size - count,
+ "sof: %u <= sof <= %u, freq %u.%03u kHz\n",
+ stream->stats.stream.min_sof,
+ stream->stats.stream.max_sof,
+ scr_sof_freq / 1000, scr_sof_freq % 1000);
+
+ return count;
+}
+
+static void uvc_video_stats_start(struct uvc_streaming *stream)
+{
+ memset(&stream->stats, 0, sizeof(stream->stats));
+ stream->stats.stream.min_sof = 2048;
+}
+
+static void uvc_video_stats_stop(struct uvc_streaming *stream)
+{
+ ktime_get_ts(&stream->stats.stream.stop_ts);
+}
+
+/* ------------------------------------------------------------------------
+ * Video codecs
+ */
/* Video payload decoding is handled by uvc_video_decode_start(),
* uvc_video_decode_data() and uvc_video_decode_end().
@@ -416,14 +944,9 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
* - bHeaderLength value must be at least 2 bytes (see above)
* - bHeaderLength value can't be larger than the packet size.
*/
- if (len < 2 || data[0] < 2 || data[0] > len)
+ if (len < 2 || data[0] < 2 || data[0] > len) {
+ stream->stats.frame.nb_invalid++;
return -EINVAL;
-
- /* Skip payloads marked with the error bit ("error frames"). */
- if (data[1] & UVC_STREAM_ERR) {
- uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit "
- "set).\n");
- return -ENODATA;
}
fid = data[1] & UVC_STREAM_FID;
@@ -431,8 +954,14 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
/* Increase the sequence number regardless of any buffer states, so
* that discontinuous sequence numbers always indicate lost frames.
*/
- if (stream->last_fid != fid)
+ if (stream->last_fid != fid) {
stream->sequence++;
+ if (stream->sequence)
+ uvc_video_stats_update(stream);
+ }
+
+ uvc_video_clock_decode(stream, buf, data, len);
+ uvc_video_stats_decode(stream, data, len);
/* Store the payload FID bit and return immediately when the buffer is
* NULL.
@@ -442,6 +971,13 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
return -ENODATA;
}
+ /* Mark the buffer as bad if the error bit is set. */
+ if (data[1] & UVC_STREAM_ERR) {
+ uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit "
+ "set).\n");
+ buf->error = 1;
+ }
+
/* Synchronize to the input stream by waiting for the FID bit to be
* toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
* stream->last_fid is initialized to -1, so the first isochronous
@@ -467,9 +1003,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
else
ktime_get_real_ts(&ts);
- buf->buf.sequence = stream->sequence;
- buf->buf.timestamp.tv_sec = ts.tv_sec;
- buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ buf->buf.v4l2_buf.sequence = stream->sequence;
+ buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
+ buf->buf.v4l2_buf.timestamp.tv_usec =
+ ts.tv_nsec / NSEC_PER_USEC;
/* TODO: Handle PTS and SCR. */
buf->state = UVC_BUF_STATE_ACTIVE;
@@ -490,7 +1027,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
* avoids detecting end of frame conditions at FID toggling if the
* previous payload had the EOF bit set.
*/
- if (fid != stream->last_fid && buf->buf.bytesused != 0) {
+ if (fid != stream->last_fid && buf->bytesused != 0) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
"toggled).\n");
buf->state = UVC_BUF_STATE_READY;
@@ -505,7 +1042,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
static void uvc_video_decode_data(struct uvc_streaming *stream,
struct uvc_buffer *buf, const __u8 *data, int len)
{
- struct uvc_video_queue *queue = &stream->queue;
unsigned int maxlen, nbytes;
void *mem;
@@ -513,11 +1049,11 @@ static void uvc_video_decode_data(struct uvc_streaming *stream,
return;
/* Copy the video data to the buffer. */
- maxlen = buf->buf.length - buf->buf.bytesused;
- mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+ maxlen = buf->length - buf->bytesused;
+ mem = buf->mem + buf->bytesused;
nbytes = min((unsigned int)len, maxlen);
memcpy(mem, data, nbytes);
- buf->buf.bytesused += nbytes;
+ buf->bytesused += nbytes;
/* Complete the current frame if the buffer size was exceeded. */
if (len > maxlen) {
@@ -530,7 +1066,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream,
struct uvc_buffer *buf, const __u8 *data, int len)
{
/* Mark the buffer as done if the EOF marker is set. */
- if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) {
+ if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
if (data[0] == len)
uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
@@ -568,8 +1104,8 @@ static int uvc_video_encode_data(struct uvc_streaming *stream,
void *mem;
/* Copy video data to the URB buffer. */
- mem = queue->mem + buf->buf.m.offset + queue->buf_used;
- nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+ mem = buf->mem + queue->buf_used;
+ nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size,
nbytes);
memcpy(data, mem, nbytes);
@@ -624,7 +1160,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
urb->iso_frame_desc[i].actual_length);
if (buf->state == UVC_BUF_STATE_READY) {
- if (buf->buf.length != buf->buf.bytesused &&
+ if (buf->length != buf->bytesused &&
!(stream->cur_format->flags &
UVC_FMT_FLAG_COMPRESSED))
buf->error = 1;
@@ -724,12 +1260,12 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
stream->bulk.payload_size += ret;
len -= ret;
- if (buf->buf.bytesused == stream->queue.buf_used ||
+ if (buf->bytesused == stream->queue.buf_used ||
stream->bulk.payload_size == stream->bulk.max_payload_size) {
- if (buf->buf.bytesused == stream->queue.buf_used) {
+ if (buf->bytesused == stream->queue.buf_used) {
stream->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_READY;
- buf->buf.sequence = ++stream->sequence;
+ buf->buf.v4l2_buf.sequence = ++stream->sequence;
uvc_queue_next_buffer(&stream->queue, buf);
stream->last_fid ^= UVC_STREAM_FID;
}
@@ -870,6 +1406,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
struct urb *urb;
unsigned int i;
+ uvc_video_stats_stop(stream);
+
for (i = 0; i < UVC_URBS; ++i) {
urb = stream->urb[i];
if (urb == NULL)
@@ -882,6 +1420,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
if (free_buffers)
uvc_free_urb_buffers(stream);
+
+ uvc_video_clock_cleanup(stream);
}
/*
@@ -1009,6 +1549,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
stream->bulk.skip_payload = 0;
stream->bulk.payload_size = 0;
+ uvc_video_stats_start(stream);
+
+ ret = uvc_video_clock_init(stream);
+ if (ret < 0)
+ return ret;
+
if (intf->num_altsetting > 1) {
struct usb_host_endpoint *best_ep = NULL;
unsigned int best_psize = 3 * 1024;
@@ -1283,6 +1829,11 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
return ret;
}
- return uvc_init_video(stream, GFP_KERNEL);
-}
+ ret = uvc_init_video(stream, GFP_KERNEL);
+ if (ret < 0) {
+ usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+ uvc_queue_enable(&stream->queue, 0);
+ }
+ return ret;
+}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 4c1392e..67f88d8 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -13,6 +13,7 @@
#include <linux/videodev2.h>
#include <media/media-device.h>
#include <media/v4l2-device.h>
+#include <media/videobuf2-core.h>
/* --------------------------------------------------------------------------
* UVC constants
@@ -113,6 +114,7 @@
/* Maximum allowed number of control mappings per device */
#define UVC_MAX_CONTROL_MAPPINGS 1024
+#define UVC_MAX_CONTROL_MENU_ENTRIES 32
/* Devices quirks */
#define UVC_QUIRK_STATUS_INTERVAL 0x00000001
@@ -319,35 +321,30 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
- unsigned long vma_use_count;
- struct list_head stream;
-
- /* Touched by interrupt handler. */
- struct v4l2_buffer buf;
+ struct vb2_buffer buf;
struct list_head queue;
- wait_queue_head_t wait;
+
enum uvc_buffer_state state;
unsigned int error;
+
+ void *mem;
+ unsigned int length;
+ unsigned int bytesused;
+
+ u32 pts;
};
-#define UVC_QUEUE_STREAMING (1 << 0)
-#define UVC_QUEUE_DISCONNECTED (1 << 1)
-#define UVC_QUEUE_DROP_CORRUPTED (1 << 2)
+#define UVC_QUEUE_DISCONNECTED (1 << 0)
+#define UVC_QUEUE_DROP_CORRUPTED (1 << 1)
struct uvc_video_queue {
- enum v4l2_buf_type type;
+ struct vb2_queue queue;
+ struct mutex mutex; /* Protects queue */
- void *mem;
unsigned int flags;
-
- unsigned int count;
- unsigned int buf_size;
unsigned int buf_used;
- struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
- struct mutex mutex; /* protects buffers and mainqueue */
- spinlock_t irqlock; /* protects irqqueue */
- struct list_head mainqueue;
+ spinlock_t irqlock; /* Protects irqqueue */
struct list_head irqqueue;
};
@@ -362,6 +359,51 @@ struct uvc_video_chain {
struct mutex ctrl_mutex; /* Protects ctrl.info */
};
+struct uvc_stats_frame {
+ unsigned int size; /* Number of bytes captured */
+ unsigned int first_data; /* Index of the first non-empty packet */
+
+ unsigned int nb_packets; /* Number of packets */
+ unsigned int nb_empty; /* Number of empty packets */
+ unsigned int nb_invalid; /* Number of packets with an invalid header */
+ unsigned int nb_errors; /* Number of packets with the error bit set */
+
+ unsigned int nb_pts; /* Number of packets with a PTS timestamp */
+ unsigned int nb_pts_diffs; /* Number of PTS differences inside a frame */
+ unsigned int last_pts_diff; /* Index of the last PTS difference */
+ bool has_initial_pts; /* Whether the first non-empty packet has a PTS */
+ bool has_early_pts; /* Whether a PTS is present before the first non-empty packet */
+ u32 pts; /* PTS of the last packet */
+
+ unsigned int nb_scr; /* Number of packets with a SCR timestamp */
+ unsigned int nb_scr_diffs; /* Number of SCR.STC differences inside a frame */
+ u16 scr_sof; /* SCR.SOF of the last packet */
+ u32 scr_stc; /* SCR.STC of the last packet */
+};
+
+struct uvc_stats_stream {
+ struct timespec start_ts; /* Stream start timestamp */
+ struct timespec stop_ts; /* Stream stop timestamp */
+
+ unsigned int nb_frames; /* Number of frames */
+
+ unsigned int nb_packets; /* Number of packets */
+ unsigned int nb_empty; /* Number of empty packets */
+ unsigned int nb_invalid; /* Number of packets with an invalid header */
+ unsigned int nb_errors; /* Number of packets with the error bit set */
+
+ unsigned int nb_pts_constant; /* Number of frames with constant PTS */
+ unsigned int nb_pts_early; /* Number of frames with early PTS */
+ unsigned int nb_pts_initial; /* Number of frames with initial PTS */
+
+ unsigned int nb_scr_count_ok; /* Number of frames with at least one SCR per non empty packet */
+ unsigned int nb_scr_diffs_ok; /* Number of frames with varying SCR.STC */
+ unsigned int scr_sof_count; /* STC.SOF counter accumulated since stream start */
+ unsigned int scr_sof; /* STC.SOF of the last packet */
+ unsigned int min_sof; /* Minimum STC.SOF value */
+ unsigned int max_sof; /* Maximum STC.SOF value */
+};
+
struct uvc_streaming {
struct list_head list;
struct uvc_device *dev;
@@ -387,6 +429,7 @@ struct uvc_streaming {
*/
struct mutex mutex;
+ /* Buffers queue. */
unsigned int frozen : 1;
struct uvc_video_queue queue;
void (*decode) (struct urb *urb, struct uvc_streaming *video,
@@ -408,6 +451,32 @@ struct uvc_streaming {
__u32 sequence;
__u8 last_fid;
+
+ /* debugfs */
+ struct dentry *debugfs_dir;
+ struct {
+ struct uvc_stats_frame frame;
+ struct uvc_stats_stream stream;
+ } stats;
+
+ /* Timestamps support. */
+ struct uvc_clock {
+ struct uvc_clock_sample {
+ u32 dev_stc;
+ u16 dev_sof;
+ struct timespec host_ts;
+ u16 host_sof;
+ } *samples;
+
+ unsigned int head;
+ unsigned int count;
+ unsigned int size;
+
+ u16 last_sof;
+ u16 sof_offset;
+
+ spinlock_t lock;
+ } clock;
};
enum uvc_device_state {
@@ -479,9 +548,12 @@ struct uvc_driver {
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
#define UVC_TRACE_VIDEO (1 << 10)
+#define UVC_TRACE_STATS (1 << 11)
+#define UVC_TRACE_CLOCK (1 << 12)
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
+#define UVC_WARN_XU_GET_RES 2
extern unsigned int uvc_clock_param;
extern unsigned int uvc_no_drop_param;
@@ -516,8 +588,8 @@ extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
extern void uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type, int drop_corrupted);
extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
- unsigned int nbuffers, unsigned int buflength);
-extern int uvc_free_buffers(struct uvc_video_queue *queue);
+ struct v4l2_requestbuffers *rb);
+extern void uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_queue_buffer(struct uvc_video_queue *queue,
@@ -539,7 +611,7 @@ extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
extern int uvc_queue_allocated(struct uvc_video_queue *queue);
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
- return queue->flags & UVC_QUEUE_STREAMING;
+ return vb2_is_streaming(&queue->queue);
}
/* V4L2 interface */
@@ -556,10 +628,11 @@ extern int uvc_video_resume(struct uvc_streaming *stream, int reset);
extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
extern int uvc_probe_video(struct uvc_streaming *stream,
struct uvc_streaming_control *probe);
-extern int uvc_commit_video(struct uvc_streaming *stream,
- struct uvc_streaming_control *ctrl);
extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
__u8 intfnum, __u8 cs, void *data, __u16 size);
+void uvc_video_clock_update(struct uvc_streaming *stream,
+ struct v4l2_buffer *v4l2_buf,
+ struct uvc_buffer *buf);
/* Status */
extern int uvc_status_init(struct uvc_device *dev);
@@ -612,4 +685,13 @@ extern struct usb_host_endpoint *uvc_find_endpoint(
void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
struct uvc_buffer *buf);
+/* debugfs and statistics */
+int uvc_debugfs_init(void);
+void uvc_debugfs_cleanup(void);
+int uvc_debugfs_init_stream(struct uvc_streaming *stream);
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+ size_t size);
+
#endif
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index c68531b..af4419e 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -985,6 +985,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_CROPCAP:
case VIDIOC_G_CROP:
case VIDIOC_S_CROP:
+ case VIDIOC_G_SELECTION:
+ case VIDIOC_S_SELECTION:
case VIDIOC_G_JPEGCOMP:
case VIDIOC_S_JPEGCOMP:
case VIDIOC_QUERYSTD:
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 0f415da..da1f4c2 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -467,6 +467,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2";
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers";
case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers";
+ case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
/* MPEG controls */
/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -1108,8 +1109,8 @@ int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
INIT_LIST_HEAD(&hdl->ctrls);
INIT_LIST_HEAD(&hdl->ctrl_refs);
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
- hdl->buckets = kzalloc(sizeof(hdl->buckets[0]) * hdl->nr_of_buckets,
- GFP_KERNEL);
+ hdl->buckets = kcalloc(hdl->nr_of_buckets, sizeof(hdl->buckets[0]),
+ GFP_KERNEL);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
return hdl->error;
}
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index a5c9ed1..96e9615 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -146,10 +146,9 @@ static void v4l2_device_release(struct device *cd)
struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
mutex_lock(&videodev_lock);
- if (video_device[vdev->minor] != vdev) {
- mutex_unlock(&videodev_lock);
+ if (WARN_ON(video_device[vdev->minor] != vdev)) {
/* should not happen */
- WARN_ON(1);
+ mutex_unlock(&videodev_lock);
return;
}
@@ -168,7 +167,7 @@ static void v4l2_device_release(struct device *cd)
mutex_unlock(&videodev_lock);
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+ if (v4l2_dev && v4l2_dev->mdev &&
vdev->vfl_type != VFL_TYPE_SUBDEV)
media_device_unregister_entity(&vdev->entity);
#endif
@@ -556,8 +555,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
vdev->minor = -1;
/* the release callback MUST be present */
- WARN_ON(!vdev->release);
- if (!vdev->release)
+ if (WARN_ON(!vdev->release))
return -EINVAL;
/* v4l2_fh support */
@@ -703,8 +701,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
vdev->vfl_type != VFL_TYPE_SUBDEV) {
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
vdev->entity.name = vdev->name;
- vdev->entity.v4l.major = VIDEO_MAJOR;
- vdev->entity.v4l.minor = vdev->minor;
+ vdev->entity.info.v4l.major = VIDEO_MAJOR;
+ vdev->entity.info.v4l.minor = vdev->minor;
ret = media_device_register_entity(vdev->v4l2_dev->mdev,
&vdev->entity);
if (ret < 0)
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 0edd618..1f203b8 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -234,8 +234,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
goto clean_up;
}
#if defined(CONFIG_MEDIA_CONTROLLER)
- sd->entity.v4l.major = VIDEO_MAJOR;
- sd->entity.v4l.minor = vdev->minor;
+ sd->entity.info.v4l.major = VIDEO_MAJOR;
+ sd->entity.info.v4l.minor = vdev->minor;
#endif
sd->devnode = vdev;
}
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index e1da8fc..77feeb6 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -238,6 +238,8 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
[_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
[_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
+ [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION",
+ [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION",
[_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
[_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
[_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
@@ -1547,11 +1549,32 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_g_crop)
+ if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
- ret = ops->vidioc_g_crop(file, fh, p);
+
+ if (ops->vidioc_g_crop) {
+ ret = ops->vidioc_g_crop(file, fh, p);
+ } else {
+ /* simulate capture crop using selection api */
+ struct v4l2_selection s = {
+ .type = p->type,
+ };
+
+ /* crop means compose for output devices */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+ else
+ s.target = V4L2_SEL_TGT_CROP_ACTIVE;
+
+ ret = ops->vidioc_g_selection(file, fh, &s);
+
+ /* copying results to old structure on success */
+ if (!ret)
+ p->c = s.r;
+ }
+
if (!ret)
dbgrect(vfd, "", &p->c);
break;
@@ -1560,15 +1583,65 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_s_crop)
+ if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
break;
+
if (ret_prio) {
ret = ret_prio;
break;
}
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->c);
- ret = ops->vidioc_s_crop(file, fh, p);
+
+ if (ops->vidioc_s_crop) {
+ ret = ops->vidioc_s_crop(file, fh, p);
+ } else {
+ /* simulate capture crop using selection api */
+ struct v4l2_selection s = {
+ .type = p->type,
+ .r = p->c,
+ };
+
+ /* crop means compose for output devices */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+ else
+ s.target = V4L2_SEL_TGT_CROP_ACTIVE;
+
+ ret = ops->vidioc_s_selection(file, fh, &s);
+ }
+ break;
+ }
+ case VIDIOC_G_SELECTION:
+ {
+ struct v4l2_selection *p = arg;
+
+ if (!ops->vidioc_g_selection)
+ break;
+
+ dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+
+ ret = ops->vidioc_g_selection(file, fh, p);
+ if (!ret)
+ dbgrect(vfd, "", &p->r);
+ break;
+ }
+ case VIDIOC_S_SELECTION:
+ {
+ struct v4l2_selection *p = arg;
+
+ if (!ops->vidioc_s_selection)
+ break;
+
+ if (ret_prio) {
+ ret = ret_prio;
+ break;
+ }
+
+ dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
+ dbgrect(vfd, "", &p->r);
+
+ ret = ops->vidioc_s_selection(file, fh, p);
break;
}
case VIDIOC_CROPCAP:
@@ -1576,11 +1649,42 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_cropcap *p = arg;
/*FIXME: Should also show v4l2_fract pixelaspect */
- if (!ops->vidioc_cropcap)
+ if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
- ret = ops->vidioc_cropcap(file, fh, p);
+ if (ops->vidioc_cropcap) {
+ ret = ops->vidioc_cropcap(file, fh, p);
+ } else {
+ struct v4l2_selection s = { .type = p->type };
+
+ /* obtaining bounds */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+ else
+ s.target = V4L2_SEL_TGT_CROP_BOUNDS;
+
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ break;
+ p->bounds = s.r;
+
+ /* obtaining defrect */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+ else
+ s.target = V4L2_SEL_TGT_CROP_DEFAULT;
+
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ break;
+ p->defrect = s.r;
+
+ /* setting trivial pixelaspect */
+ p->pixelaspect.numerator = 1;
+ p->pixelaspect.denominator = 1;
+ }
+
if (!ret) {
dbgrect(vfd, "bounds ", &p->bounds);
dbgrect(vfd, "defrect ", &p->defrect);
@@ -2226,6 +2330,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
struct v4l2_ext_controls *ctrls = parg;
if (ctrls->count != 0) {
+ if (ctrls->count > V4L2_CID_MAX_CTRLS) {
+ ret = -EINVAL;
+ break;
+ }
*user_ptr = (void __user *)ctrls->controls;
*kernel_ptr = (void *)&ctrls->controls;
*array_size = sizeof(struct v4l2_ext_control)
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 65ade5f..41d118e 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -193,6 +193,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return v4l2_subdev_call(sd, core, s_register, p);
}
#endif
+
+ case VIDIOC_LOG_STATUS:
+ return v4l2_subdev_call(sd, core, log_status);
+
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
case VIDIOC_SUBDEV_G_FMT: {
struct v4l2_subdev_format *format = arg;
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c
index cbf13d0..20f7237 100644
--- a/drivers/media/video/via-camera.c
+++ b/drivers/media/video/via-camera.c
@@ -34,13 +34,13 @@ MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
MODULE_DESCRIPTION("VIA framebuffer-based camera controller driver");
MODULE_LICENSE("GPL");
-static int flip_image;
+static bool flip_image;
module_param(flip_image, bool, 0444);
MODULE_PARM_DESC(flip_image,
"If set, the sensor will be instructed to flip the image "
"vertically.");
-static int override_serial;
+static bool override_serial;
module_param(override_serial, bool, 0444);
MODULE_PARM_DESC(override_serial,
"The camera driver will normally refuse to load if "
@@ -156,14 +156,10 @@ static struct via_format {
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
},
- {
- .desc = "RGB 565",
- .pixelformat = V4L2_PIX_FMT_RGB565,
- .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
- .bpp = 2,
- },
/* RGB444 and Bayer should be doable, but have never been
- tested with this driver. */
+ tested with this driver. RGB565 seems to work at the default
+ resolution, but results in color corruption when being scaled by
+ viacam_set_scaled(), and is disabled as a result. */
};
#define N_VIA_FMTS ARRAY_SIZE(via_formats)
@@ -1504,14 +1500,4 @@ static struct platform_driver viacam_driver = {
.remove = viacam_remove,
};
-static int viacam_init(void)
-{
- return platform_driver_register(&viacam_driver);
-}
-module_init(viacam_init);
-
-static void viacam_exit(void)
-{
- platform_driver_unregister(&viacam_driver);
-}
-module_exit(viacam_exit);
+module_platform_driver(viacam_driver);
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index 3de7c7e..59cb54a 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -226,9 +226,10 @@ static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter,
}
/* register network adapter */
- dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
- if (dvb->net.dvbdev == NULL) {
- result = -ENOMEM;
+ result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx);
+ if (result < 0) {
+ printk(KERN_WARNING "%s: dvb_net_init failed (errno = %d)\n",
+ dvb->name, result);
goto fail_fe_conn;
}
return 0;
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 95a3f5e..2e8f1df 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -30,7 +30,7 @@ module_param(debug, int, 0644);
printk(KERN_DEBUG "vb2: " fmt, ## arg); \
} while (0)
-#define call_memop(q, plane, op, args...) \
+#define call_memop(q, op, args...) \
(((q)->mem_ops->op) ? \
((q)->mem_ops->op(args)) : 0)
@@ -52,7 +52,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
/* Allocate memory for all planes in this buffer */
for (plane = 0; plane < vb->num_planes; ++plane) {
- mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
+ mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
q->plane_sizes[plane]);
if (IS_ERR_OR_NULL(mem_priv))
goto free;
@@ -65,8 +65,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
return 0;
free:
/* Free already allocated memory if one of the allocations failed */
- for (; plane > 0; --plane)
- call_memop(q, plane, put, vb->planes[plane - 1].mem_priv);
+ for (; plane > 0; --plane) {
+ call_memop(q, put, vb->planes[plane - 1].mem_priv);
+ vb->planes[plane - 1].mem_priv = NULL;
+ }
return -ENOMEM;
}
@@ -80,10 +82,10 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
unsigned int plane;
for (plane = 0; plane < vb->num_planes; ++plane) {
- call_memop(q, plane, put, vb->planes[plane].mem_priv);
+ call_memop(q, put, vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
- dprintk(3, "Freed plane %d of buffer %d\n",
- plane, vb->v4l2_buf.index);
+ dprintk(3, "Freed plane %d of buffer %d\n", plane,
+ vb->v4l2_buf.index);
}
}
@@ -97,12 +99,9 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
unsigned int plane;
for (plane = 0; plane < vb->num_planes; ++plane) {
- void *mem_priv = vb->planes[plane].mem_priv;
-
- if (mem_priv) {
- call_memop(q, plane, put_userptr, mem_priv);
- vb->planes[plane].mem_priv = NULL;
- }
+ if (vb->planes[plane].mem_priv)
+ call_memop(q, put_userptr, vb->planes[plane].mem_priv);
+ vb->planes[plane].mem_priv = NULL;
}
}
@@ -305,7 +304,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
* case anyway. If num_users() returns more than 1,
* we are not the only user of the plane's memory.
*/
- if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1)
+ if (mem_priv && call_memop(q, num_users, mem_priv) > 1)
return true;
}
return false;
@@ -731,10 +730,10 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
{
struct vb2_queue *q = vb->vb2_queue;
- if (plane_no > vb->num_planes)
+ if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL;
- return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv);
+ return call_memop(q, vaddr, vb->planes[plane_no].mem_priv);
}
EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
@@ -754,10 +753,10 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
{
struct vb2_queue *q = vb->vb2_queue;
- if (plane_no > vb->num_planes)
+ if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
return NULL;
- return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv);
+ return call_memop(q, cookie, vb->planes[plane_no].mem_priv);
}
EXPORT_SYMBOL_GPL(vb2_plane_cookie);
@@ -883,7 +882,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Skip the plane if already verified */
- if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
+ if (vb->v4l2_planes[plane].m.userptr &&
+ vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
&& vb->v4l2_planes[plane].length == planes[plane].length)
continue;
@@ -898,27 +898,23 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
/* Release previously acquired memory if present */
if (vb->planes[plane].mem_priv)
- call_memop(q, plane, put_userptr,
- vb->planes[plane].mem_priv);
+ call_memop(q, put_userptr, vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
vb->v4l2_planes[plane].m.userptr = 0;
vb->v4l2_planes[plane].length = 0;
/* Acquire each plane's memory */
- if (q->mem_ops->get_userptr) {
- mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane],
- planes[plane].m.userptr,
- planes[plane].length,
- write);
- if (IS_ERR(mem_priv)) {
- dprintk(1, "qbuf: failed acquiring userspace "
+ mem_priv = call_memop(q, get_userptr, q->alloc_ctx[plane],
+ planes[plane].m.userptr,
+ planes[plane].length, write);
+ if (IS_ERR_OR_NULL(mem_priv)) {
+ dprintk(1, "qbuf: failed acquiring userspace "
"memory for plane %d\n", plane);
- ret = PTR_ERR(mem_priv);
- goto err;
- }
- vb->planes[plane].mem_priv = mem_priv;
+ ret = mem_priv ? PTR_ERR(mem_priv) : -EINVAL;
+ goto err;
}
+ vb->planes[plane].mem_priv = mem_priv;
}
/*
@@ -943,8 +939,7 @@ err:
/* In case of errors, release planes that were already acquired */
for (plane = 0; plane < vb->num_planes; ++plane) {
if (vb->planes[plane].mem_priv)
- call_memop(q, plane, put_userptr,
- vb->planes[plane].mem_priv);
+ call_memop(q, put_userptr, vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
vb->v4l2_planes[plane].m.userptr = 0;
vb->v4l2_planes[plane].length = 0;
@@ -1081,46 +1076,76 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf);
*/
int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
{
+ struct rw_semaphore *mmap_sem = NULL;
struct vb2_buffer *vb;
- int ret;
+ int ret = 0;
+
+ /*
+ * In case of user pointer buffers vb2 allocator needs to get direct
+ * access to userspace pages. This requires getting read access on
+ * mmap semaphore in the current process structure. The same
+ * semaphore is taken before calling mmap operation, while both mmap
+ * and qbuf are called by the driver or v4l2 core with driver's lock
+ * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in
+ * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core
+ * release driver's lock, takes mmap_sem and then takes again driver's
+ * lock.
+ *
+ * To avoid race with other vb2 calls, which might be called after
+ * releasing driver's lock, this operation is performed at the
+ * beggining of qbuf processing. This way the queue status is
+ * consistent after getting driver's lock back.
+ */
+ if (q->memory == V4L2_MEMORY_USERPTR) {
+ mmap_sem = &current->mm->mmap_sem;
+ call_qop(q, wait_prepare, q);
+ down_read(mmap_sem);
+ call_qop(q, wait_finish, q);
+ }
if (q->fileio) {
dprintk(1, "qbuf: file io in progress\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto unlock;
}
if (b->type != q->type) {
dprintk(1, "qbuf: invalid buffer type\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
if (b->index >= q->num_buffers) {
dprintk(1, "qbuf: buffer index out of range\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
vb = q->bufs[b->index];
if (NULL == vb) {
/* Should never happen */
dprintk(1, "qbuf: buffer is NULL\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
if (b->memory != q->memory) {
dprintk(1, "qbuf: invalid memory type\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
ret = __buf_prepare(vb, b);
if (ret)
- return ret;
+ goto unlock;
case VB2_BUF_STATE_PREPARED:
break;
default:
dprintk(1, "qbuf: buffer already in use\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
/*
@@ -1141,7 +1166,10 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
__fill_v4l2_buffer(vb, b);
dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
- return 0;
+unlock:
+ if (mmap_sem)
+ up_read(mmap_sem);
+ return ret;
}
EXPORT_SYMBOL_GPL(vb2_qbuf);
@@ -1521,7 +1549,6 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
{
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
- struct vb2_plane *vb_plane;
struct vb2_buffer *vb;
unsigned int buffer, plane;
int ret;
@@ -1558,9 +1585,8 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
return ret;
vb = q->bufs[buffer];
- vb_plane = &vb->planes[plane];
- ret = q->mem_ops->mmap(vb_plane->mem_priv, vma);
+ ret = call_memop(q, mmap, vb->planes[plane].mem_priv, vma);
if (ret)
return ret;
diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/video/videobuf2-dma-sg.c
index 3bad8b1..25c3b36 100644
--- a/drivers/media/video/videobuf2-dma-sg.c
+++ b/drivers/media/video/videobuf2-dma-sg.c
@@ -140,7 +140,6 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
if (!buf->pages)
goto userptr_fail_pages_array_alloc;
- down_read(&current->mm->mmap_sem);
num_pages_from_user = get_user_pages(current, current->mm,
vaddr & PAGE_MASK,
buf->sg_desc.num_pages,
@@ -148,7 +147,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
1, /* force */
buf->pages,
NULL);
- up_read(&current->mm->mmap_sem);
+
if (num_pages_from_user != buf->sg_desc.num_pages)
goto userptr_fail_get_user_pages;
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c
index 71a7a78..c41cb60 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -100,29 +100,26 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
unsigned long offset, start, end;
unsigned long this_pfn, prev_pfn;
dma_addr_t pa = 0;
- int ret = -EFAULT;
start = vaddr;
offset = start & ~PAGE_MASK;
end = start + size;
- down_read(&mm->mmap_sem);
vma = find_vma(mm, start);
if (vma == NULL || vma->vm_end < end)
- goto done;
+ return -EFAULT;
for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
- ret = follow_pfn(vma, start, &this_pfn);
+ int ret = follow_pfn(vma, start, &this_pfn);
if (ret)
- goto done;
+ return ret;
if (prev_pfn == 0)
pa = this_pfn << PAGE_SHIFT;
- else if (this_pfn != prev_pfn + 1) {
- ret = -EFAULT;
- goto done;
- }
+ else if (this_pfn != prev_pfn + 1)
+ return -EFAULT;
+
prev_pfn = this_pfn;
}
@@ -130,16 +127,11 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
* Memory is contigous, lock vma and return to the caller
*/
*res_vma = vb2_get_vma(vma);
- if (*res_vma == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- *res_pa = pa + offset;
- ret = 0;
+ if (*res_vma == NULL)
+ return -ENOMEM;
-done:
- up_read(&mm->mmap_sem);
- return ret;
+ *res_pa = pa + offset;
+ return 0;
}
EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c
index a3a8842..4e789a1 100644
--- a/drivers/media/video/videobuf2-vmalloc.c
+++ b/drivers/media/video/videobuf2-vmalloc.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -20,7 +21,10 @@
struct vb2_vmalloc_buf {
void *vaddr;
+ struct page **pages;
+ int write;
unsigned long size;
+ unsigned int n_pages;
atomic_t refcount;
struct vb2_vmarea_handler handler;
};
@@ -31,7 +35,7 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
{
struct vb2_vmalloc_buf *buf;
- buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
return NULL;
@@ -42,15 +46,12 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
buf->handler.arg = buf;
if (!buf->vaddr) {
- printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size);
+ pr_debug("vmalloc of size %ld failed\n", buf->size);
kfree(buf);
return NULL;
}
atomic_inc(&buf->refcount);
- printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n",
- buf->size, buf->vaddr);
-
return buf;
}
@@ -59,21 +60,84 @@ static void vb2_vmalloc_put(void *buf_priv)
struct vb2_vmalloc_buf *buf = buf_priv;
if (atomic_dec_and_test(&buf->refcount)) {
- printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n",
- __func__, buf->vaddr);
vfree(buf->vaddr);
kfree(buf);
}
}
-static void *vb2_vmalloc_vaddr(void *buf_priv)
+static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+ unsigned long size, int write)
+{
+ struct vb2_vmalloc_buf *buf;
+ unsigned long first, last;
+ int n_pages, offset;
+
+ buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->write = write;
+ offset = vaddr & ~PAGE_MASK;
+ buf->size = size;
+
+ first = vaddr >> PAGE_SHIFT;
+ last = (vaddr + size - 1) >> PAGE_SHIFT;
+ buf->n_pages = last - first + 1;
+ buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!buf->pages)
+ goto fail_pages_array_alloc;
+
+ /* current->mm->mmap_sem is taken by videobuf2 core */
+ n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK,
+ buf->n_pages, write, 1, /* force */
+ buf->pages, NULL);
+ if (n_pages != buf->n_pages)
+ goto fail_get_user_pages;
+
+ buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL);
+ if (!buf->vaddr)
+ goto fail_get_user_pages;
+
+ buf->vaddr += offset;
+ return buf;
+
+fail_get_user_pages:
+ pr_debug("get_user_pages requested/got: %d/%d]\n", n_pages,
+ buf->n_pages);
+ while (--n_pages >= 0)
+ put_page(buf->pages[n_pages]);
+ kfree(buf->pages);
+
+fail_pages_array_alloc:
+ kfree(buf);
+
+ return NULL;
+}
+
+static void vb2_vmalloc_put_userptr(void *buf_priv)
{
struct vb2_vmalloc_buf *buf = buf_priv;
+ unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK;
+ unsigned int i;
+
+ if (vaddr)
+ vm_unmap_ram((void *)vaddr, buf->n_pages);
+ for (i = 0; i < buf->n_pages; ++i) {
+ if (buf->write)
+ set_page_dirty_lock(buf->pages[i]);
+ put_page(buf->pages[i]);
+ }
+ kfree(buf->pages);
+ kfree(buf);
+}
- BUG_ON(!buf);
+static void *vb2_vmalloc_vaddr(void *buf_priv)
+{
+ struct vb2_vmalloc_buf *buf = buf_priv;
if (!buf->vaddr) {
- printk(KERN_ERR "Address of an unallocated plane requested\n");
+ pr_err("Address of an unallocated plane requested "
+ "or cannot map user pointer\n");
return NULL;
}
@@ -92,13 +156,13 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
int ret;
if (!buf) {
- printk(KERN_ERR "No memory to map\n");
+ pr_err("No memory to map\n");
return -EINVAL;
}
ret = remap_vmalloc_range(vma, buf->vaddr, 0);
if (ret) {
- printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret);
+ pr_err("Remapping vmalloc memory, error: %d\n", ret);
return ret;
}
@@ -121,6 +185,8 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
const struct vb2_mem_ops vb2_vmalloc_memops = {
.alloc = vb2_vmalloc_alloc,
.put = vb2_vmalloc_put,
+ .get_userptr = vb2_vmalloc_get_userptr,
+ .put_userptr = vb2_vmalloc_put_userptr,
.vaddr = vb2_vmalloc_vaddr,
.mmap = vb2_vmalloc_mmap,
.num_users = vb2_vmalloc_num_users,
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 52a0a37..4d7391e 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -708,7 +708,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb,
size, count);
/* allocate memory for table with virtual (page) addresses */
- fb->desc_table.virtual = (unsigned long *)
+ fb->desc_table.virtual =
kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
if (!fb->desc_table.virtual)
return -ENOMEM;
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
index e8a2784..e86173b 100644
--- a/drivers/media/video/zoran/zoran_device.c
+++ b/drivers/media/video/zoran/zoran_device.c
@@ -57,7 +57,7 @@
ZR36057_ISR_GIRQ1 | \
ZR36057_ISR_JPEGRepIRQ )
-static int lml33dpath; /* default = 0
+static bool lml33dpath; /* default = 0
* 1 will use digital path in capture
* mode instead of analog. It can be
* used for picture adjustments using
diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c
index 5e4f57c..f08546f 100644
--- a/drivers/media/video/zoran/zr36060.c
+++ b/drivers/media/video/zoran/zr36060.c
@@ -50,7 +50,7 @@
/* amount of chips attached via this driver */
static int zr36060_codecs;
-static int low_bitrate;
+static bool low_bitrate;
module_param(low_bitrate, bool, 0);
MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 6ce70e9..5319e9b 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -21,7 +21,7 @@
#define DRIVER_NAME "jmb38x_ms"
-static int no_dma;
+static bool no_dma;
module_param(no_dma, bool, 0644);
enum {
diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
index 668f5c6..29b2172 100644
--- a/drivers/memstick/host/r592.c
+++ b/drivers/memstick/host/r592.c
@@ -23,7 +23,7 @@
#include <linux/swab.h>
#include "r592.h"
-static int r592_enable_dma = 1;
+static bool r592_enable_dma = 1;
static int debug;
static const char *tpc_names[] = {
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index b7aacf4..6902b83 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -22,7 +22,7 @@
#define DRIVER_NAME "tifm_ms"
-static int no_dma;
+static bool no_dma;
module_param(no_dma, bool, 0644);
/*
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index e017dc8..f93dd95 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -12,51 +12,20 @@
#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>
-static inline int pm860x_read_device(struct i2c_client *i2c,
- int reg, int bytes, void *dest)
-{
- unsigned char data;
- int ret;
-
- data = (unsigned char)reg;
- ret = i2c_master_send(i2c, &data, 1);
- if (ret < 0)
- return ret;
-
- ret = i2c_master_recv(i2c, dest, bytes);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static inline int pm860x_write_device(struct i2c_client *i2c,
- int reg, int bytes, void *src)
-{
- unsigned char buf[bytes + 1];
- int ret;
-
- buf[0] = (unsigned char)reg;
- memcpy(&buf[1], src, bytes);
-
- ret = i2c_master_send(i2c, buf, bytes + 1);
- if (ret < 0)
- return ret;
- return 0;
-}
-
int pm860x_reg_read(struct i2c_client *i2c, int reg)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
- unsigned char data;
+ struct regmap *map = (i2c == chip->client) ? chip->regmap
+ : chip->regmap_companion;
+ unsigned int data;
int ret;
- mutex_lock(&chip->io_lock);
- ret = pm860x_read_device(i2c, reg, 1, &data);
- mutex_unlock(&chip->io_lock);
-
+ ret = regmap_read(map, reg, &data);
if (ret < 0)
return ret;
else
@@ -68,12 +37,11 @@ int pm860x_reg_write(struct i2c_client *i2c, int reg,
unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ struct regmap *map = (i2c == chip->client) ? chip->regmap
+ : chip->regmap_companion;
int ret;
- mutex_lock(&chip->io_lock);
- ret = pm860x_write_device(i2c, reg, 1, &data);
- mutex_unlock(&chip->io_lock);
-
+ ret = regmap_write(map, reg, data);
return ret;
}
EXPORT_SYMBOL(pm860x_reg_write);
@@ -82,12 +50,11 @@ int pm860x_bulk_read(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ struct regmap *map = (i2c == chip->client) ? chip->regmap
+ : chip->regmap_companion;
int ret;
- mutex_lock(&chip->io_lock);
- ret = pm860x_read_device(i2c, reg, count, buf);
- mutex_unlock(&chip->io_lock);
-
+ ret = regmap_raw_read(map, reg, buf, count);
return ret;
}
EXPORT_SYMBOL(pm860x_bulk_read);
@@ -96,12 +63,11 @@ int pm860x_bulk_write(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ struct regmap *map = (i2c == chip->client) ? chip->regmap
+ : chip->regmap_companion;
int ret;
- mutex_lock(&chip->io_lock);
- ret = pm860x_write_device(i2c, reg, count, buf);
- mutex_unlock(&chip->io_lock);
-
+ ret = regmap_raw_write(map, reg, buf, count);
return ret;
}
EXPORT_SYMBOL(pm860x_bulk_write);
@@ -110,39 +76,78 @@ int pm860x_set_bits(struct i2c_client *i2c, int reg,
unsigned char mask, unsigned char data)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
- unsigned char value;
+ struct regmap *map = (i2c == chip->client) ? chip->regmap
+ : chip->regmap_companion;
int ret;
- mutex_lock(&chip->io_lock);
- ret = pm860x_read_device(i2c, reg, 1, &value);
- if (ret < 0)
- goto out;
- value &= ~mask;
- value |= data;
- ret = pm860x_write_device(i2c, reg, 1, &value);
-out:
- mutex_unlock(&chip->io_lock);
+ ret = regmap_update_bits(map, reg, mask, data);
return ret;
}
EXPORT_SYMBOL(pm860x_set_bits);
+static int read_device(struct i2c_client *i2c, int reg,
+ int bytes, void *dest)
+{
+ 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},
+ };
+ int num = 1, ret = 0;
+
+ if (dest == NULL)
+ return -EINVAL;
+ msgbuf0[0] = (unsigned char)reg; /* command */
+ msg[1].len = bytes;
+
+ /* if data needs to read back, num should be 2 */
+ if (bytes > 0)
+ num = 2;
+ ret = adap->algo->master_xfer(adap, msg, num);
+ memcpy(dest, msgbuf1, bytes);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static int write_device(struct i2c_client *i2c, int reg,
+ int bytes, void *src)
+{
+ unsigned char buf[bytes + 1];
+ struct i2c_adapter *adap = i2c->adapter;
+ struct i2c_msg msg;
+ int ret;
+
+ buf[0] = (unsigned char)reg;
+ memcpy(&buf[1], src, bytes);
+ msg.addr = i2c->addr;
+ msg.flags = 0;
+ msg.len = bytes + 1;
+ msg.buf = buf;
+
+ ret = adap->algo->master_xfer(adap, &msg, 1);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
{
- struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
unsigned char data;
int ret;
- mutex_lock(&chip->io_lock);
- pm860x_write_device(i2c, 0xFA, 0, &zero);
- pm860x_write_device(i2c, 0xFB, 0, &zero);
- pm860x_write_device(i2c, 0xFF, 0, &zero);
- ret = pm860x_read_device(i2c, reg, 1, &data);
+ i2c_lock_adapter(i2c->adapter);
+ read_device(i2c, 0xFA, 0, &zero);
+ read_device(i2c, 0xFB, 0, &zero);
+ read_device(i2c, 0xFF, 0, &zero);
+ ret = read_device(i2c, reg, 1, &data);
if (ret >= 0)
ret = (int)data;
- pm860x_write_device(i2c, 0xFE, 0, &zero);
- pm860x_write_device(i2c, 0xFC, 0, &zero);
- mutex_unlock(&chip->io_lock);
+ read_device(i2c, 0xFE, 0, &zero);
+ read_device(i2c, 0xFC, 0, &zero);
+ i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_read);
@@ -150,18 +155,17 @@ EXPORT_SYMBOL(pm860x_page_reg_read);
int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
unsigned char data)
{
- struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
int ret;
- mutex_lock(&chip->io_lock);
- pm860x_write_device(i2c, 0xFA, 0, &zero);
- pm860x_write_device(i2c, 0xFB, 0, &zero);
- pm860x_write_device(i2c, 0xFF, 0, &zero);
- ret = pm860x_write_device(i2c, reg, 1, &data);
- pm860x_write_device(i2c, 0xFE, 0, &zero);
- pm860x_write_device(i2c, 0xFC, 0, &zero);
- mutex_unlock(&chip->io_lock);
+ i2c_lock_adapter(i2c->adapter);
+ read_device(i2c, 0xFA, 0, &zero);
+ read_device(i2c, 0xFB, 0, &zero);
+ read_device(i2c, 0xFF, 0, &zero);
+ ret = write_device(i2c, reg, 1, &data);
+ read_device(i2c, 0xFE, 0, &zero);
+ read_device(i2c, 0xFC, 0, &zero);
+ i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_write);
@@ -169,18 +173,17 @@ EXPORT_SYMBOL(pm860x_page_reg_write);
int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
- struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
- mutex_lock(&chip->io_lock);
- pm860x_write_device(i2c, 0xFA, 0, &zero);
- pm860x_write_device(i2c, 0xFB, 0, &zero);
- pm860x_write_device(i2c, 0xFF, 0, &zero);
- ret = pm860x_read_device(i2c, reg, count, buf);
- pm860x_write_device(i2c, 0xFE, 0, &zero);
- pm860x_write_device(i2c, 0xFC, 0, &zero);
- mutex_unlock(&chip->io_lock);
+ i2c_lock_adapter(i2c->adapter);
+ read_device(i2c, 0xfa, 0, &zero);
+ read_device(i2c, 0xfb, 0, &zero);
+ read_device(i2c, 0xff, 0, &zero);
+ ret = read_device(i2c, reg, count, buf);
+ read_device(i2c, 0xFE, 0, &zero);
+ read_device(i2c, 0xFC, 0, &zero);
+ i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_read);
@@ -188,18 +191,18 @@ EXPORT_SYMBOL(pm860x_page_bulk_read);
int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
int count, unsigned char *buf)
{
- struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero = 0;
int ret;
- mutex_lock(&chip->io_lock);
- pm860x_write_device(i2c, 0xFA, 0, &zero);
- pm860x_write_device(i2c, 0xFB, 0, &zero);
- pm860x_write_device(i2c, 0xFF, 0, &zero);
- ret = pm860x_write_device(i2c, reg, count, buf);
- pm860x_write_device(i2c, 0xFE, 0, &zero);
- pm860x_write_device(i2c, 0xFC, 0, &zero);
- mutex_unlock(&chip->io_lock);
+ i2c_lock_adapter(i2c->adapter);
+ read_device(i2c, 0xFA, 0, &zero);
+ read_device(i2c, 0xFB, 0, &zero);
+ read_device(i2c, 0xFF, 0, &zero);
+ ret = write_device(i2c, reg, count, buf);
+ read_device(i2c, 0xFE, 0, &zero);
+ read_device(i2c, 0xFC, 0, &zero);
+ i2c_unlock_adapter(i2c->adapter);
+ i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_write);
@@ -207,25 +210,24 @@ EXPORT_SYMBOL(pm860x_page_bulk_write);
int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
unsigned char mask, unsigned char data)
{
- struct pm860x_chip *chip = i2c_get_clientdata(i2c);
unsigned char zero;
unsigned char value;
int ret;
- mutex_lock(&chip->io_lock);
- pm860x_write_device(i2c, 0xFA, 0, &zero);
- pm860x_write_device(i2c, 0xFB, 0, &zero);
- pm860x_write_device(i2c, 0xFF, 0, &zero);
- ret = pm860x_read_device(i2c, reg, 1, &value);
+ i2c_lock_adapter(i2c->adapter);
+ read_device(i2c, 0xFA, 0, &zero);
+ read_device(i2c, 0xFB, 0, &zero);
+ read_device(i2c, 0xFF, 0, &zero);
+ ret = read_device(i2c, reg, 1, &value);
if (ret < 0)
goto out;
value &= ~mask;
value |= data;
- ret = pm860x_write_device(i2c, reg, 1, &value);
+ ret = write_device(i2c, reg, 1, &value);
out:
- pm860x_write_device(i2c, 0xFE, 0, &zero);
- pm860x_write_device(i2c, 0xFC, 0, &zero);
- mutex_unlock(&chip->io_lock);
+ read_device(i2c, 0xFE, 0, &zero);
+ read_device(i2c, 0xFC, 0, &zero);
+ i2c_unlock_adapter(i2c->adapter);
return ret;
}
EXPORT_SYMBOL(pm860x_page_set_bits);
@@ -257,11 +259,17 @@ static int verify_addr(struct i2c_client *i2c)
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__);
@@ -273,10 +281,17 @@ static int __devinit pm860x_probe(struct i2c_client *client,
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;
- mutex_init(&chip->io_lock);
dev_set_drvdata(chip->dev, chip);
/*
@@ -290,6 +305,14 @@ static int __devinit pm860x_probe(struct i2c_client *client,
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);
}
@@ -302,7 +325,11 @@ static int __devexit pm860x_remove(struct i2c_client *client)
struct pm860x_chip *chip = i2c_get_clientdata(client);
pm860x_device_exit(chip);
- i2c_unregister_device(chip->companion);
+ if (chip->companion) {
+ regmap_exit(chip->regmap_companion);
+ i2c_unregister_device(chip->companion);
+ }
+ regmap_exit(chip->regmap);
kfree(chip);
return 0;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c8322ee..cd13e9f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -12,6 +12,7 @@ config MFD_CORE
config MFD_88PM860X
bool "Support Marvell 88PM8606/88PM8607"
depends on I2C=y && GENERIC_HARDIRQS
+ select REGMAP_I2C
select MFD_CORE
help
This supports for Marvell 88PM8606/88PM8607 Power Management IC.
@@ -199,7 +200,7 @@ config MENELAUS
config TWL4030_CORE
bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
- depends on I2C=y && GENERIC_HARDIRQS
+ depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN
help
Say yes here if you have TWL4030 / TWL6030 family chip on your board.
This core driver provides register access and IRQ handling
@@ -257,7 +258,7 @@ config TWL6040_CORE
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
- depends on I2C=y && GENERIC_HARDIRQS
+ depends on (I2C=y || SPI_MASTER=y) && GENERIC_HARDIRQS
select MFD_CORE
help
Support for the STMPE family of I/O Expanders from
@@ -278,6 +279,23 @@ config MFD_STMPE
Keypad: stmpe-keypad
Touchscreen: stmpe-ts
+menu "STMPE Interface Drivers"
+depends on MFD_STMPE
+
+config STMPE_I2C
+ bool "STMPE I2C Inteface"
+ depends on I2C=y
+ default y
+ help
+ This is used to enable I2C interface of STMPE
+
+config STMPE_SPI
+ bool "STMPE SPI Inteface"
+ depends on SPI_MASTER
+ help
+ This is used to enable SPI interface of STMPE
+endmenu
+
config MFD_TC3589X
bool "Support Toshiba TC35892 and variants"
depends on I2C=y && GENERIC_HARDIRQS
@@ -311,7 +329,7 @@ config MFD_TC6387XB
config MFD_TC6393XB
bool "Support Toshiba TC6393XB"
- depends on GPIOLIB && ARM
+ depends on GPIOLIB && ARM && HAVE_CLK
select MFD_CORE
select MFD_TMIO
help
@@ -399,6 +417,17 @@ config MFD_MAX8998
additional drivers must be enabled in order to use the functionality
of the device.
+config MFD_S5M_CORE
+ bool "SAMSUNG S5M Series Support"
+ depends on I2C=y && GENERIC_HARDIRQS
+ select MFD_CORE
+ select REGMAP_I2C
+ help
+ Support for the Samsung Electronics S5M MFD series.
+ This driver provies common support for accessing the device,
+ additional drivers must be enabled in order to use the functionality
+ of the device
+
config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400"
select MFD_CORE
@@ -505,6 +534,7 @@ config MFD_WM8994
bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
depends on I2C=y && GENERIC_HARDIRQS
help
The WM8994 is a highly integrated hi-fi CODEC designed for
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d5f5743..b953bab 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o
+obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
+obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
@@ -31,7 +33,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
-obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
+obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o wm8994-regmap.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
@@ -109,3 +111,4 @@ obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
+obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 02c4201..3aa36eb 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -407,13 +407,13 @@ static int aat2870_i2c_probe(struct i2c_client *client,
aat2870->init(aat2870);
if (aat2870->en_pin >= 0) {
- ret = gpio_request(aat2870->en_pin, "aat2870-en");
+ ret = gpio_request_one(aat2870->en_pin, GPIOF_OUT_INIT_HIGH,
+ "aat2870-en");
if (ret < 0) {
dev_err(&client->dev,
"Failed to request GPIO %d\n", aat2870->en_pin);
goto out_kfree;
}
- gpio_direction_output(aat2870->en_pin, 1);
}
aat2870_enable(aat2870);
@@ -468,9 +468,10 @@ static int aat2870_i2c_remove(struct i2c_client *client)
return 0;
}
-#ifdef CONFIG_PM
-static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int aat2870_i2c_suspend(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
aat2870_disable(aat2870);
@@ -478,8 +479,9 @@ static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
return 0;
}
-static int aat2870_i2c_resume(struct i2c_client *client)
+static int aat2870_i2c_resume(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
struct aat2870_register *reg = NULL;
int i;
@@ -495,12 +497,12 @@ static int aat2870_i2c_resume(struct i2c_client *client)
return 0;
}
-#else
-#define aat2870_i2c_suspend NULL
-#define aat2870_i2c_resume NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(aat2870_pm_ops, aat2870_i2c_suspend,
+ aat2870_i2c_resume);
-static struct i2c_device_id aat2870_i2c_id_table[] = {
+static const struct i2c_device_id aat2870_i2c_id_table[] = {
{ "aat2870", 0 },
{ }
};
@@ -510,11 +512,10 @@ static struct i2c_driver aat2870_i2c_driver = {
.driver = {
.name = "aat2870",
.owner = THIS_MODULE,
+ .pm = &aat2870_pm_ops,
},
.probe = aat2870_i2c_probe,
.remove = aat2870_i2c_remove,
- .suspend = aat2870_i2c_suspend,
- .resume = aat2870_i2c_resume,
.id_table = aat2870_i2c_id_table,
};
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c
index ec10629..bd56a76 100644
--- a/drivers/mfd/ab5500-core.c
+++ b/drivers/mfd/ab5500-core.c
@@ -22,8 +22,8 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/random.h>
-#include <linux/mfd/ab5500/ab5500.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab5500.h>
#include <linux/list.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c
index b7b2d348..7200694 100644
--- a/drivers/mfd/ab5500-debugfs.c
+++ b/drivers/mfd/ab5500-debugfs.c
@@ -7,8 +7,8 @@
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#include <linux/mfd/ab5500/ab5500.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab5500.h>
#include <linux/uaccess.h>
#include "ab5500-core.h"
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index d3d572b..53e2a80 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -17,7 +17,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/ab8500.h>
/*
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index dedb7f6..9a0211a 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
static u32 debug_bank;
static u32 debug_address;
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index e985d17..c39fc71 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -18,9 +18,9 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/list.h>
-#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500/gpadc.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-gpadc.h>
/*
* GPADC register offsets
diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c
index 9be541c..087fecd 100644
--- a/drivers/mfd/ab8500-i2c.c
+++ b/drivers/mfd/ab8500-i2c.c
@@ -10,7 +10,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/db8500-prcmu.h>
static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index f20feef..c28d4eb1 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -7,9 +7,9 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500/sysctrl.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-sysctrl.h>
static struct device *sysctrl_dev;
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 155fa04..315fef5 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -172,14 +172,14 @@ static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static struct pci_device_id cs5535_mfd_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(cs5535_mfd_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, cs5535_mfd_pci_tbl);
-static struct pci_driver cs5535_mfd_drv = {
+static struct pci_driver cs5535_mfd_driver = {
.name = DRV_NAME,
.id_table = cs5535_mfd_pci_tbl,
.probe = cs5535_mfd_probe,
@@ -188,12 +188,12 @@ static struct pci_driver cs5535_mfd_drv = {
static int __init cs5535_mfd_init(void)
{
- return pci_register_driver(&cs5535_mfd_drv);
+ return pci_register_driver(&cs5535_mfd_driver);
}
static void __exit cs5535_mfd_exit(void)
{
- pci_unregister_driver(&cs5535_mfd_drv);
+ pci_unregister_driver(&cs5535_mfd_driver);
}
module_init(cs5535_mfd_init);
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 8ad88da..7710227 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -308,8 +308,7 @@ static int add_children(struct i2c_client *client)
for (i = 0; i < ARRAY_SIZE(config_inputs); i++) {
int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset;
- gpio_request(gpio, config_inputs[i].label);
- gpio_direction_input(gpio);
+ gpio_request_one(gpio, GPIOF_IN, config_inputs[i].label);
/* make it easy for userspace to see these */
gpio_export(gpio, false);
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 97c2776..b76657e 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -485,17 +485,7 @@ static struct platform_driver intel_msic_driver = {
},
};
-static int __init intel_msic_init(void)
-{
- return platform_driver_register(&intel_msic_driver);
-}
-module_init(intel_msic_init);
-
-static void __exit intel_msic_exit(void)
-{
- platform_driver_unregister(&intel_msic_driver);
-}
-module_exit(intel_msic_exit);
+module_platform_driver(intel_msic_driver);
MODULE_DESCRIPTION("Driver for Intel MSIC");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 5c2a06a..a9223ed 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -33,7 +33,7 @@
/* Module Parameters */
static unsigned int num_modules = CMODIO_MAX_MODULES;
-static unsigned char *modules[CMODIO_MAX_MODULES] = {
+static char *modules[CMODIO_MAX_MODULES] = {
"empty", "empty", "empty", "empty",
};
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index ef39528..87662a1 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = {
},
};
-const struct mfd_cell jz4740_adc_cells[] = {
+static struct mfd_cell jz4740_adc_cells[] = {
{
.id = 0,
.name = "jz4740-hwmon",
@@ -338,17 +338,7 @@ static struct platform_driver jz4740_adc_driver = {
},
};
-static int __init jz4740_adc_init(void)
-{
- return platform_driver_register(&jz4740_adc_driver);
-}
-module_init(jz4740_adc_init);
-
-static void __exit jz4740_adc_exit(void)
-{
- platform_driver_unregister(&jz4740_adc_driver);
-}
-module_exit(jz4740_adc_exit);
+module_platform_driver(jz4740_adc_driver);
MODULE_DESCRIPTION("JZ4740 SoC ADC driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index ea1169b..abc4213 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -74,7 +74,7 @@ static struct mfd_cell tunnelcreek_cells[] = {
},
};
-static struct pci_device_id lpc_sch_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
{ 0, }
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index e1e59c9..ca881ef 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -210,21 +210,6 @@ static struct max8925_irq_data max8925_irqs[] = {
.mask_reg = MAX8925_CHG_IRQ1_MASK,
.offs = 1 << 2,
},
- [MAX8925_IRQ_VCHG_USB_OVP] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 3,
- },
- [MAX8925_IRQ_VCHG_USB_F] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 4,
- },
- [MAX8925_IRQ_VCHG_USB_R] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 5,
- },
[MAX8925_IRQ_VCHG_THM_OK_R] = {
.reg = MAX8925_CHG_IRQ2,
.mask_reg = MAX8925_CHG_IRQ2_MASK,
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index 0219115..d9e4b36 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -161,6 +161,8 @@ static int __devinit max8925_probe(struct i2c_client *client,
chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
i2c_set_clientdata(chip->adc, chip);
+ device_init_wakeup(&client->dev, 1);
+
max8925_device_init(chip, pdata);
return 0;
@@ -177,10 +179,35 @@ static int __devexit max8925_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int max8925_suspend(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct max8925_chip *chip = i2c_get_clientdata(client);
+
+ if (device_may_wakeup(dev) && chip->wakeup_flag)
+ enable_irq_wake(chip->core_irq);
+ return 0;
+}
+
+static int max8925_resume(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct max8925_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(max8925_pm_ops, max8925_suspend, max8925_resume);
+
static struct i2c_driver max8925_driver = {
.driver = {
.name = "max8925",
.owner = THIS_MODULE,
+ .pm = &max8925_pm_ops,
},
.probe = max8925_probe,
.remove = __devexit_p(max8925_remove),
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 5be53ae..cb83a7a 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -43,7 +43,8 @@ static struct mfd_cell max8997_devs[] = {
{ .name = "max8997-battery", },
{ .name = "max8997-haptic", },
{ .name = "max8997-muic", },
- { .name = "max8997-flash", },
+ { .name = "max8997-led", .id = 1 },
+ { .name = "max8997-led", .id = 2 },
};
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index de4096a..6ef56d2 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -176,6 +176,8 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
goto err;
+ device_init_wakeup(max8998->dev, max8998->wakeup);
+
return ret;
err:
@@ -210,7 +212,7 @@ static int max8998_suspend(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
- if (max8998->wakeup)
+ if (device_may_wakeup(dev))
irq_set_irq_wake(max8998->irq, 1);
return 0;
}
@@ -220,7 +222,7 @@ static int max8998_resume(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
- if (max8998->wakeup)
+ if (device_may_wakeup(dev))
irq_set_irq_wake(max8998->irq, 0);
/*
* In LP3974, if IRQ registers are not "read & clear"
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index e9619ac..7122386 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -18,11 +18,15 @@
#include <linux/spi/spi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mc13xxx.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
struct mc13xxx {
struct spi_device *spidev;
struct mutex lock;
int irq;
+ int flags;
irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
void *irqdata[MC13XXX_NUM_IRQ];
@@ -550,10 +554,7 @@ static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
{
- struct mc13xxx_platform_data *pdata =
- dev_get_platdata(&mc13xxx->spidev->dev);
-
- return pdata->flags;
+ return mc13xxx->flags;
}
EXPORT_SYMBOL(mc13xxx_get_flags);
@@ -615,13 +616,13 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
break;
case MC13XXX_ADC_MODE_SINGLE_CHAN:
- adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+ adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
adc1 |= MC13XXX_ADC1_RAND;
break;
case MC13XXX_ADC_MODE_MULT_CHAN:
- adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+ adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
break;
@@ -696,17 +697,67 @@ static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
}
+#ifdef CONFIG_OF
+static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
+{
+ struct device_node *np = mc13xxx->spidev->dev.of_node;
+
+ if (!np)
+ return -ENODEV;
+
+ if (of_get_property(np, "fsl,mc13xxx-uses-adc", NULL))
+ mc13xxx->flags |= MC13XXX_USE_ADC;
+
+ if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL))
+ mc13xxx->flags |= MC13XXX_USE_CODEC;
+
+ if (of_get_property(np, "fsl,mc13xxx-uses-rtc", NULL))
+ mc13xxx->flags |= MC13XXX_USE_RTC;
+
+ if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL))
+ mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
+
+ return 0;
+}
+#else
+static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
+{
+ return -ENODEV;
+}
+#endif
+
+static const struct spi_device_id mc13xxx_device_id[] = {
+ {
+ .name = "mc13783",
+ .driver_data = MC13XXX_ID_MC13783,
+ }, {
+ .name = "mc13892",
+ .driver_data = MC13XXX_ID_MC13892,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
+
+static const struct of_device_id mc13xxx_dt_ids[] = {
+ { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, },
+ { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids);
+
static int mc13xxx_probe(struct spi_device *spi)
{
+ const struct of_device_id *of_id;
+ struct spi_driver *sdrv = to_spi_driver(spi->dev.driver);
struct mc13xxx *mc13xxx;
struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
enum mc13xxx_id id;
int ret;
- if (!pdata) {
- dev_err(&spi->dev, "invalid platform data\n");
- return -EINVAL;
- }
+ of_id = of_match_device(mc13xxx_dt_ids, &spi->dev);
+ if (of_id)
+ sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data];
mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
if (!mc13xxx)
@@ -749,28 +800,33 @@ err_revision:
mc13xxx_unlock(mc13xxx);
- if (pdata->flags & MC13XXX_USE_ADC)
+ if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
+ mc13xxx->flags = pdata->flags;
+
+ if (mc13xxx->flags & MC13XXX_USE_ADC)
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
- if (pdata->flags & MC13XXX_USE_CODEC)
+ if (mc13xxx->flags & MC13XXX_USE_CODEC)
mc13xxx_add_subdevice(mc13xxx, "%s-codec");
- mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
- &pdata->regulators, sizeof(pdata->regulators));
-
- if (pdata->flags & MC13XXX_USE_RTC)
+ if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
- if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
+ if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
mc13xxx_add_subdevice(mc13xxx, "%s-ts");
- if (pdata->leds)
+ if (pdata) {
+ mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
+ &pdata->regulators, sizeof(pdata->regulators));
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
pdata->leds, sizeof(*pdata->leds));
-
- if (pdata->buttons)
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
pdata->buttons, sizeof(*pdata->buttons));
+ } else {
+ mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
+ mc13xxx_add_subdevice(mc13xxx, "%s-led");
+ mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
+ }
return 0;
}
@@ -788,25 +844,12 @@ static int __devexit mc13xxx_remove(struct spi_device *spi)
return 0;
}
-static const struct spi_device_id mc13xxx_device_id[] = {
- {
- .name = "mc13783",
- .driver_data = MC13XXX_ID_MC13783,
- }, {
- .name = "mc13892",
- .driver_data = MC13XXX_ID_MC13892,
- }, {
- /* sentinel */
- }
-};
-MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
-
static struct spi_driver mc13xxx_driver = {
.id_table = mc13xxx_device_id,
.driver = {
.name = "mc13xxx",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_probe,
.remove = __devexit_p(mc13xxx_remove),
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 84815f9..63be60b 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -26,9 +26,35 @@
#define to_mcp(d) container_of(d, struct mcp, attached_device)
#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
+static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id,
+ const char *codec)
+{
+ while (id->name[0]) {
+ if (strcmp(codec, id->name) == 0)
+ return id;
+ id++;
+ }
+ return NULL;
+}
+
+const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp)
+{
+ const struct mcp_driver *driver =
+ to_mcp_driver(mcp->attached_device.driver);
+
+ return mcp_match_id(driver->id_table, mcp->codec);
+}
+EXPORT_SYMBOL(mcp_get_device_id);
+
static int mcp_bus_match(struct device *dev, struct device_driver *drv)
{
- return 1;
+ const struct mcp *mcp = to_mcp(dev);
+ const struct mcp_driver *driver = to_mcp_driver(drv);
+
+ if (driver->id_table)
+ return !!mcp_match_id(driver->id_table, mcp->codec);
+
+ return 0;
}
static int mcp_bus_probe(struct device *dev)
@@ -74,9 +100,18 @@ static int mcp_bus_resume(struct device *dev)
return ret;
}
+static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct mcp *mcp = to_mcp(dev);
+
+ add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec);
+ return 0;
+}
+
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
+ .uevent = mcp_bus_uevent,
.probe = mcp_bus_probe,
.remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
@@ -212,9 +247,14 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
}
EXPORT_SYMBOL(mcp_host_alloc);
-int mcp_host_register(struct mcp *mcp)
+int mcp_host_register(struct mcp *mcp, void *pdata)
{
+ if (!mcp->codec)
+ return -EINVAL;
+
+ mcp->attached_device.platform_data = pdata;
dev_set_name(&mcp->attached_device, "mcp0");
+ request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec);
return device_register(&mcp->attached_device);
}
EXPORT_SYMBOL(mcp_host_register);
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 2dab02d..9adc2eb 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -19,6 +19,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/mcp.h>
+#include <linux/io.h>
#include <mach/dma.h>
#include <mach/hardware.h>
@@ -26,12 +27,19 @@
#include <asm/system.h>
#include <mach/mcp.h>
-#include <mach/assabet.h>
-
+/* Register offsets */
+#define MCCR0 0x00
+#define MCDR0 0x08
+#define MCDR1 0x0C
+#define MCDR2 0x10
+#define MCSR 0x18
+#define MCCR1 0x00
struct mcp_sa11x0 {
- u32 mccr0;
- u32 mccr1;
+ u32 mccr0;
+ u32 mccr1;
+ unsigned char *mccr0_base;
+ unsigned char *mccr1_base;
};
#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
@@ -39,25 +47,25 @@ struct mcp_sa11x0 {
static void
mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
{
- unsigned int mccr0;
+ struct mcp_sa11x0 *priv = priv(mcp);
divisor /= 32;
- mccr0 = Ser4MCCR0 & ~0x00007f00;
- mccr0 |= divisor << 8;
- Ser4MCCR0 = mccr0;
+ priv->mccr0 &= ~0x00007f00;
+ priv->mccr0 |= divisor << 8;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
static void
mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
{
- unsigned int mccr0;
+ struct mcp_sa11x0 *priv = priv(mcp);
divisor /= 32;
- mccr0 = Ser4MCCR0 & ~0x0000007f;
- mccr0 |= divisor;
- Ser4MCCR0 = mccr0;
+ priv->mccr0 &= ~0x0000007f;
+ priv->mccr0 |= divisor;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
/*
@@ -71,12 +79,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
{
int ret = -ETIME;
int i;
+ u32 mcpreg;
+ struct mcp_sa11x0 *priv = priv(mcp);
- Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
+ mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff);
+ __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- if (Ser4MCSR & MCSR_CWC) {
+ mcpreg = __raw_readl(priv->mccr0_base + MCSR);
+ if (mcpreg & MCSR_CWC) {
ret = 0;
break;
}
@@ -97,13 +109,18 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
{
int ret = -ETIME;
int i;
+ u32 mcpreg;
+ struct mcp_sa11x0 *priv = priv(mcp);
- Ser4MCDR2 = reg << 17 | MCDR2_Rd;
+ mcpreg = reg << 17 | MCDR2_Rd;
+ __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- if (Ser4MCSR & MCSR_CRC) {
- ret = Ser4MCDR2 & 0xffff;
+ mcpreg = __raw_readl(priv->mccr0_base + MCSR);
+ if (mcpreg & MCSR_CRC) {
+ ret = __raw_readl(priv->mccr0_base + MCDR2)
+ & 0xffff;
break;
}
}
@@ -116,13 +133,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
static void mcp_sa11x0_enable(struct mcp *mcp)
{
- Ser4MCSR = -1;
- Ser4MCCR0 |= MCCR0_MCE;
+ struct mcp_sa11x0 *priv = priv(mcp);
+
+ __raw_writel(-1, priv->mccr0_base + MCSR);
+ priv->mccr0 |= MCCR0_MCE;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
static void mcp_sa11x0_disable(struct mcp *mcp)
{
- Ser4MCCR0 &= ~MCCR0_MCE;
+ struct mcp_sa11x0 *priv = priv(mcp);
+
+ priv->mccr0 &= ~MCCR0_MCE;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
}
/*
@@ -142,50 +165,69 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
struct mcp_plat_data *data = pdev->dev.platform_data;
struct mcp *mcp;
int ret;
+ struct mcp_sa11x0 *priv;
+ struct resource *res_mem0, *res_mem1;
+ u32 size0, size1;
if (!data)
return -ENODEV;
- if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
+ if (!data->codec)
+ return -ENODEV;
+
+ res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem0)
+ return -ENODEV;
+ size0 = res_mem0->end - res_mem0->start + 1;
+
+ res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res_mem1)
+ return -ENODEV;
+ size1 = res_mem1->end - res_mem1->start + 1;
+
+ if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp"))
return -EBUSY;
+ if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) {
+ ret = -EBUSY;
+ goto release;
+ }
+
mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
if (!mcp) {
ret = -ENOMEM;
- goto release;
+ goto release2;
}
+ priv = priv(mcp);
+
mcp->owner = THIS_MODULE;
mcp->ops = &mcp_sa11x0;
mcp->sclk_rate = data->sclk_rate;
- mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
- mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
- mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
- mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
- mcp->gpio_base = data->gpio_base;
+ mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0)
+ + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
+ mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0)
+ + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
+ mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1)
+ + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
+ mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1)
+ + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
+ mcp->codec = data->codec;
platform_set_drvdata(pdev, mcp);
- if (machine_is_assabet()) {
- ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
- }
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
/*
* Initialise device. Note that we initially
* set the sampling rate to minimum.
*/
- Ser4MCSR = -1;
- Ser4MCCR1 = data->mccr1;
- Ser4MCCR0 = data->mccr0 | 0x7f7f;
+ priv->mccr0_base = ioremap(res_mem0->start, size0);
+ priv->mccr1_base = ioremap(res_mem1->start, size1);
+
+ __raw_writel(-1, priv->mccr0_base + MCSR);
+ priv->mccr1 = data->mccr1;
+ priv->mccr0 = data->mccr0 | 0x7f7f;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
/*
* Calculate the read/write timeout (us) from the bit clock
@@ -195,36 +237,53 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
mcp->sclk_rate;
- ret = mcp_host_register(mcp);
+ ret = mcp_host_register(mcp, data->codec_pdata);
if (ret == 0)
goto out;
+ release2:
+ release_mem_region(res_mem1->start, size1);
release:
- release_mem_region(0x80060000, 0x60);
+ release_mem_region(res_mem0->start, size0);
platform_set_drvdata(pdev, NULL);
out:
return ret;
}
-static int mcp_sa11x0_remove(struct platform_device *dev)
+static int mcp_sa11x0_remove(struct platform_device *pdev)
{
- struct mcp *mcp = platform_get_drvdata(dev);
+ struct mcp *mcp = platform_get_drvdata(pdev);
+ struct mcp_sa11x0 *priv = priv(mcp);
+ struct resource *res_mem;
+ u32 size;
- platform_set_drvdata(dev, NULL);
+ platform_set_drvdata(pdev, NULL);
mcp_host_unregister(mcp);
- release_mem_region(0x80060000, 0x60);
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res_mem) {
+ size = res_mem->end - res_mem->start + 1;
+ release_mem_region(res_mem->start, size);
+ }
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_mem) {
+ size = res_mem->end - res_mem->start + 1;
+ release_mem_region(res_mem->start, size);
+ }
+ iounmap(priv->mccr0_base);
+ iounmap(priv->mccr1_base);
return 0;
}
static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
{
struct mcp *mcp = platform_get_drvdata(dev);
+ struct mcp_sa11x0 *priv = priv(mcp);
+ u32 mccr0;
- priv(mcp)->mccr0 = Ser4MCCR0;
- priv(mcp)->mccr1 = Ser4MCCR1;
- Ser4MCCR0 &= ~MCCR0_MCE;
+ mccr0 = priv->mccr0 & ~MCCR0_MCE;
+ __raw_writel(mccr0, priv->mccr0_base + MCCR0);
return 0;
}
@@ -232,9 +291,10 @@ static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
static int mcp_sa11x0_resume(struct platform_device *dev)
{
struct mcp *mcp = platform_get_drvdata(dev);
+ struct mcp_sa11x0 *priv = priv(mcp);
- Ser4MCCR1 = priv(mcp)->mccr1;
- Ser4MCCR0 = priv(mcp)->mccr0;
+ __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
return 0;
}
@@ -251,24 +311,14 @@ static struct platform_driver mcp_sa11x0_driver = {
.resume = mcp_sa11x0_resume,
.driver = {
.name = "sa11x0-mcp",
+ .owner = THIS_MODULE,
},
};
/*
* This needs re-working
*/
-static int __init mcp_sa11x0_init(void)
-{
- return platform_driver_register(&mcp_sa11x0_driver);
-}
-
-static void __exit mcp_sa11x0_exit(void)
-{
- platform_driver_unregister(&mcp_sa11x0_driver);
-}
-
-module_init(mcp_sa11x0_init);
-module_exit(mcp_sa11x0_exit);
+module_platform_driver(mcp_sa11x0_driver);
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 3f565ef..68ac2c5 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -503,19 +503,13 @@ static void omap_usbhs_init(struct device *dev)
spin_lock_irqsave(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
- gpio_request(pdata->ehci_data->reset_gpio_port[0],
- "USB1 PHY reset");
- gpio_direction_output
- (pdata->ehci_data->reset_gpio_port[0], 0);
- }
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+ gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
+ GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) {
- gpio_request(pdata->ehci_data->reset_gpio_port[1],
- "USB2 PHY reset");
- gpio_direction_output
- (pdata->ehci_data->reset_gpio_port[1], 0);
- }
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+ gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
+ GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
/* Hold the PHY in RESET for enough time till DIR is high */
udelay(10);
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index aed0d2a..3927c17 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -249,17 +249,7 @@ static struct platform_driver pcf50633_adc_driver = {
.remove = __devexit_p(pcf50633_adc_remove),
};
-static int __init pcf50633_adc_init(void)
-{
- return platform_driver_register(&pcf50633_adc_driver);
-}
-module_init(pcf50633_adc_init);
-
-static void __exit pcf50633_adc_exit(void)
-{
- platform_driver_unregister(&pcf50633_adc_driver);
-}
-module_exit(pcf50633_adc_exit);
+module_platform_driver(pcf50633_adc_driver);
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
MODULE_DESCRIPTION("PCF50633 adc driver");
diff --git a/drivers/mfd/s5m-core.c b/drivers/mfd/s5m-core.c
new file mode 100644
index 0000000..e075c11
--- /dev/null
+++ b/drivers/mfd/s5m-core.c
@@ -0,0 +1,176 @@
+/*
+ * s5m87xx.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+#include <linux/mfd/s5m87xx/s5m-pmic.h>
+#include <linux/mfd/s5m87xx/s5m-rtc.h>
+#include <linux/regmap.h>
+
+static struct mfd_cell s5m87xx_devs[] = {
+ {
+ .name = "s5m8767-pmic",
+ }, {
+ .name = "s5m-rtc",
+ },
+};
+
+int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, void *dest)
+{
+ return regmap_read(s5m87xx->regmap, reg, dest);
+}
+EXPORT_SYMBOL_GPL(s5m_reg_read);
+
+int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ return regmap_bulk_read(s5m87xx->regmap, reg, buf, count);;
+}
+EXPORT_SYMBOL_GPL(s5m_bulk_read);
+
+int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value)
+{
+ return regmap_write(s5m87xx->regmap, reg, value);
+}
+EXPORT_SYMBOL_GPL(s5m_reg_write);
+
+int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ return regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
+}
+EXPORT_SYMBOL_GPL(s5m_bulk_write);
+
+int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask)
+{
+ return regmap_update_bits(s5m87xx->regmap, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(s5m_reg_update);
+
+static struct regmap_config s5m_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int s5m87xx_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct s5m_platform_data *pdata = i2c->dev.platform_data;
+ struct s5m87xx_dev *s5m87xx;
+ int ret = 0;
+ int error;
+
+ s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
+ if (s5m87xx == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, s5m87xx);
+ s5m87xx->dev = &i2c->dev;
+ s5m87xx->i2c = i2c;
+ s5m87xx->irq = i2c->irq;
+ s5m87xx->type = id->driver_data;
+
+ if (pdata) {
+ s5m87xx->device_type = pdata->device_type;
+ s5m87xx->ono = pdata->ono;
+ s5m87xx->irq_base = pdata->irq_base;
+ s5m87xx->wakeup = pdata->wakeup;
+ }
+
+ s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
+ if (IS_ERR(s5m87xx->regmap)) {
+ error = PTR_ERR(s5m87xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ error);
+ goto err;
+ }
+
+ s5m87xx->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
+ i2c_set_clientdata(s5m87xx->rtc, s5m87xx);
+
+ if (pdata->cfg_pmic_irq)
+ pdata->cfg_pmic_irq();
+
+ s5m_irq_init(s5m87xx);
+
+ pm_runtime_set_active(s5m87xx->dev);
+
+ ret = mfd_add_devices(s5m87xx->dev, -1,
+ s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
+ NULL, 0);
+
+ if (ret < 0)
+ goto err;
+
+ return ret;
+
+err:
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+ return ret;
+}
+
+static int s5m87xx_i2c_remove(struct i2c_client *i2c)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+ return 0;
+}
+
+static const struct i2c_device_id s5m87xx_i2c_id[] = {
+ { "s5m87xx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, s5m87xx_i2c_id);
+
+static struct i2c_driver s5m87xx_i2c_driver = {
+ .driver = {
+ .name = "s5m87xx",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5m87xx_i2c_probe,
+ .remove = s5m87xx_i2c_remove,
+ .id_table = s5m87xx_i2c_id,
+};
+
+static int __init s5m87xx_i2c_init(void)
+{
+ return i2c_add_driver(&s5m87xx_i2c_driver);
+}
+
+subsys_initcall(s5m87xx_i2c_init);
+
+static void __exit s5m87xx_i2c_exit(void)
+{
+ i2c_del_driver(&s5m87xx_i2c_driver);
+}
+module_exit(s5m87xx_i2c_exit);
+
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("Core support for the S5M MFD");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/s5m-irq.c b/drivers/mfd/s5m-irq.c
new file mode 100644
index 0000000..de76dfb
--- /dev/null
+++ b/drivers/mfd/s5m-irq.c
@@ -0,0 +1,487 @@
+/*
+ * s5m-irq.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.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/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+
+struct s5m_irq_data {
+ int reg;
+ int mask;
+};
+
+static struct s5m_irq_data s5m8767_irqs[] = {
+ [S5M8767_IRQ_PWRR] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_PWRR_MASK,
+ },
+ [S5M8767_IRQ_PWRF] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_PWRF_MASK,
+ },
+ [S5M8767_IRQ_PWR1S] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_PWR1S_MASK,
+ },
+ [S5M8767_IRQ_JIGR] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_JIGR_MASK,
+ },
+ [S5M8767_IRQ_JIGF] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_JIGF_MASK,
+ },
+ [S5M8767_IRQ_LOWBAT2] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_LOWBAT2_MASK,
+ },
+ [S5M8767_IRQ_LOWBAT1] = {
+ .reg = 1,
+ .mask = S5M8767_IRQ_LOWBAT1_MASK,
+ },
+ [S5M8767_IRQ_MRB] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_MRB_MASK,
+ },
+ [S5M8767_IRQ_DVSOK2] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_DVSOK2_MASK,
+ },
+ [S5M8767_IRQ_DVSOK3] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_DVSOK3_MASK,
+ },
+ [S5M8767_IRQ_DVSOK4] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_DVSOK4_MASK,
+ },
+ [S5M8767_IRQ_RTC60S] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_RTC60S_MASK,
+ },
+ [S5M8767_IRQ_RTCA1] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_RTCA1_MASK,
+ },
+ [S5M8767_IRQ_RTCA2] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_RTCA2_MASK,
+ },
+ [S5M8767_IRQ_SMPL] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_SMPL_MASK,
+ },
+ [S5M8767_IRQ_RTC1S] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_RTC1S_MASK,
+ },
+ [S5M8767_IRQ_WTSR] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_WTSR_MASK,
+ },
+};
+
+static struct s5m_irq_data s5m8763_irqs[] = {
+ [S5M8763_IRQ_DCINF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_DCINF_MASK,
+ },
+ [S5M8763_IRQ_DCINR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_DCINR_MASK,
+ },
+ [S5M8763_IRQ_JIGF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_JIGF_MASK,
+ },
+ [S5M8763_IRQ_JIGR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_JIGR_MASK,
+ },
+ [S5M8763_IRQ_PWRONF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_PWRONF_MASK,
+ },
+ [S5M8763_IRQ_PWRONR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_PWRONR_MASK,
+ },
+ [S5M8763_IRQ_WTSREVNT] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_WTSREVNT_MASK,
+ },
+ [S5M8763_IRQ_SMPLEVNT] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_SMPLEVNT_MASK,
+ },
+ [S5M8763_IRQ_ALARM1] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_ALARM1_MASK,
+ },
+ [S5M8763_IRQ_ALARM0] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_ALARM0_MASK,
+ },
+ [S5M8763_IRQ_ONKEY1S] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_ONKEY1S_MASK,
+ },
+ [S5M8763_IRQ_TOPOFFR] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_TOPOFFR_MASK,
+ },
+ [S5M8763_IRQ_DCINOVPR] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_DCINOVPR_MASK,
+ },
+ [S5M8763_IRQ_CHGRSTF] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_CHGRSTF_MASK,
+ },
+ [S5M8763_IRQ_DONER] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_DONER_MASK,
+ },
+ [S5M8763_IRQ_CHGFAULT] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_CHGFAULT_MASK,
+ },
+ [S5M8763_IRQ_LOBAT1] = {
+ .reg = 4,
+ .mask = S5M8763_IRQ_LOBAT1_MASK,
+ },
+ [S5M8763_IRQ_LOBAT2] = {
+ .reg = 4,
+ .mask = S5M8763_IRQ_LOBAT2_MASK,
+ },
+};
+
+static inline struct s5m_irq_data *
+irq_to_s5m8767_irq(struct s5m87xx_dev *s5m87xx, int irq)
+{
+ return &s5m8767_irqs[irq - s5m87xx->irq_base];
+}
+
+static void s5m8767_irq_lock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&s5m87xx->irqlock);
+}
+
+static void s5m8767_irq_sync_unlock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
+ if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
+ s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
+ s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
+ s5m87xx->irq_masks_cur[i]);
+ }
+ }
+
+ mutex_unlock(&s5m87xx->irqlock);
+}
+
+static void s5m8767_irq_unmask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
+}
+
+static void s5m8767_irq_mask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+}
+
+static struct irq_chip s5m8767_irq_chip = {
+ .name = "s5m8767",
+ .irq_bus_lock = s5m8767_irq_lock,
+ .irq_bus_sync_unlock = s5m8767_irq_sync_unlock,
+ .irq_mask = s5m8767_irq_mask,
+ .irq_unmask = s5m8767_irq_unmask,
+};
+
+static inline struct s5m_irq_data *
+irq_to_s5m8763_irq(struct s5m87xx_dev *s5m87xx, int irq)
+{
+ return &s5m8763_irqs[irq - s5m87xx->irq_base];
+}
+
+static void s5m8763_irq_lock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&s5m87xx->irqlock);
+}
+
+static void s5m8763_irq_sync_unlock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
+ if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
+ s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
+ s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
+ s5m87xx->irq_masks_cur[i]);
+ }
+ }
+
+ mutex_unlock(&s5m87xx->irqlock);
+}
+
+static void s5m8763_irq_unmask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
+}
+
+static void s5m8763_irq_mask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+}
+
+static struct irq_chip s5m8763_irq_chip = {
+ .name = "s5m8763",
+ .irq_bus_lock = s5m8763_irq_lock,
+ .irq_bus_sync_unlock = s5m8763_irq_sync_unlock,
+ .irq_mask = s5m8763_irq_mask,
+ .irq_unmask = s5m8763_irq_unmask,
+};
+
+
+static irqreturn_t s5m8767_irq_thread(int irq, void *data)
+{
+ struct s5m87xx_dev *s5m87xx = data;
+ u8 irq_reg[NUM_IRQ_REGS-1];
+ int ret;
+ int i;
+
+
+ ret = s5m_bulk_read(s5m87xx, S5M8767_REG_INT1,
+ NUM_IRQ_REGS - 1, irq_reg);
+ if (ret < 0) {
+ dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < NUM_IRQ_REGS - 1; i++)
+ irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
+
+ for (i = 0; i < S5M8767_IRQ_NR; i++) {
+ if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
+ handle_nested_irq(s5m87xx->irq_base + i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t s5m8763_irq_thread(int irq, void *data)
+{
+ struct s5m87xx_dev *s5m87xx = data;
+ u8 irq_reg[NUM_IRQ_REGS];
+ int ret;
+ int i;
+
+ ret = s5m_bulk_read(s5m87xx, S5M8763_REG_IRQ1,
+ NUM_IRQ_REGS, irq_reg);
+ if (ret < 0) {
+ dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < NUM_IRQ_REGS; i++)
+ irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
+
+ for (i = 0; i < S5M8763_IRQ_NR; i++) {
+ if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
+ handle_nested_irq(s5m87xx->irq_base + i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
+{
+ if (s5m87xx->irq && s5m87xx->irq_base){
+ switch (s5m87xx->device_type) {
+ case S5M8763X:
+ s5m8763_irq_thread(s5m87xx->irq_base, s5m87xx);
+ break;
+ case S5M8767X:
+ s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
+ break;
+ default:
+ break;
+
+ }
+ }
+ return 0;
+}
+
+int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
+{
+ int i;
+ int cur_irq;
+ int ret = 0;
+ int type = s5m87xx->device_type;
+
+ if (!s5m87xx->irq) {
+ dev_warn(s5m87xx->dev,
+ "No interrupt specified, no interrupts\n");
+ s5m87xx->irq_base = 0;
+ return 0;
+ }
+
+ if (!s5m87xx->irq_base) {
+ dev_err(s5m87xx->dev,
+ "No interrupt base specified, no interrupts\n");
+ return 0;
+ }
+
+ mutex_init(&s5m87xx->irqlock);
+
+ switch (type) {
+ case S5M8763X:
+ for (i = 0; i < NUM_IRQ_REGS; i++) {
+ s5m87xx->irq_masks_cur[i] = 0xff;
+ s5m87xx->irq_masks_cache[i] = 0xff;
+ s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
+ 0xff);
+ }
+
+ s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM1, 0xff);
+ s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM2, 0xff);
+
+ for (i = 0; i < S5M8763_IRQ_NR; i++) {
+ cur_irq = i + s5m87xx->irq_base;
+ irq_set_chip_data(cur_irq, s5m87xx);
+ irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ irq_set_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(s5m87xx->irq, NULL,
+ s5m8763_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "s5m87xx-irq", s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+ break;
+ case S5M8767X:
+ for (i = 0; i < NUM_IRQ_REGS - 1; i++) {
+ s5m87xx->irq_masks_cur[i] = 0xff;
+ s5m87xx->irq_masks_cache[i] = 0xff;
+ s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
+ 0xff);
+ }
+ for (i = 0; i < S5M8767_IRQ_NR; i++) {
+ cur_irq = i + s5m87xx->irq_base;
+ irq_set_chip_data(cur_irq, s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev,
+ "Failed to irq_set_chip_data %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+
+ irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ irq_set_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(s5m87xx->irq, NULL,
+ s5m8767_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "s5m87xx-irq", s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!s5m87xx->ono)
+ return 0;
+
+ switch (type) {
+ case S5M8763X:
+ ret = request_threaded_irq(s5m87xx->ono, NULL,
+ s5m8763_irq_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "s5m87xx-ono",
+ s5m87xx);
+ break;
+ case S5M8767X:
+ ret = request_threaded_irq(s5m87xx->ono, NULL,
+ s5m8767_irq_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
+ break;
+ default:
+ break;
+ }
+
+ if (ret)
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->ono, ret);
+
+ return 0;
+}
+
+void s5m_irq_exit(struct s5m87xx_dev *s5m87xx)
+{
+ if (s5m87xx->ono)
+ free_irq(s5m87xx->ono, s5m87xx);
+
+ if (s5m87xx->irq)
+ free_irq(s5m87xx->irq, s5m87xx);
+}
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index df3702c..f4d8611 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1720,7 +1720,7 @@ static int sm501_plat_remove(struct platform_device *dev)
return 0;
}
-static struct pci_device_id sm501_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = {
{ 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
new file mode 100644
index 0000000..373f423
--- /dev/null
+++ b/drivers/mfd/stmpe-i2c.c
@@ -0,0 +1,109 @@
+/*
+ * ST Microelectronics MFD: stmpe's i2c client specific driver
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Copyright (C) ST Microelectronics SA 2011
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * Author: Viresh Kumar <viresh.kumar@st.com> for ST Microelectronics
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include "stmpe.h"
+
+static int i2c_reg_read(struct stmpe *stmpe, u8 reg)
+{
+ struct i2c_client *i2c = stmpe->client;
+
+ return i2c_smbus_read_byte_data(i2c, reg);
+}
+
+static int i2c_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
+{
+ struct i2c_client *i2c = stmpe->client;
+
+ return i2c_smbus_write_byte_data(i2c, reg, val);
+}
+
+static int i2c_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
+{
+ struct i2c_client *i2c = stmpe->client;
+
+ return i2c_smbus_read_i2c_block_data(i2c, reg, length, values);
+}
+
+static int i2c_block_write(struct stmpe *stmpe, u8 reg, u8 length,
+ const u8 *values)
+{
+ struct i2c_client *i2c = stmpe->client;
+
+ return i2c_smbus_write_i2c_block_data(i2c, reg, length, values);
+}
+
+static struct stmpe_client_info i2c_ci = {
+ .read_byte = i2c_reg_read,
+ .write_byte = i2c_reg_write,
+ .read_block = i2c_block_read,
+ .write_block = i2c_block_write,
+};
+
+static int __devinit
+stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ i2c_ci.data = (void *)id;
+ i2c_ci.irq = i2c->irq;
+ i2c_ci.client = i2c;
+ i2c_ci.dev = &i2c->dev;
+
+ return stmpe_probe(&i2c_ci, id->driver_data);
+}
+
+static int __devexit stmpe_i2c_remove(struct i2c_client *i2c)
+{
+ struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
+
+ return stmpe_remove(stmpe);
+}
+
+static const struct i2c_device_id stmpe_i2c_id[] = {
+ { "stmpe610", STMPE610 },
+ { "stmpe801", STMPE801 },
+ { "stmpe811", STMPE811 },
+ { "stmpe1601", STMPE1601 },
+ { "stmpe2401", STMPE2401 },
+ { "stmpe2403", STMPE2403 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, stmpe_id);
+
+static struct i2c_driver stmpe_i2c_driver = {
+ .driver.name = "stmpe-i2c",
+ .driver.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .driver.pm = &stmpe_dev_pm_ops,
+#endif
+ .probe = stmpe_i2c_probe,
+ .remove = __devexit_p(stmpe_i2c_remove),
+ .id_table = stmpe_i2c_id,
+};
+
+static int __init stmpe_init(void)
+{
+ return i2c_add_driver(&stmpe_i2c_driver);
+}
+subsys_initcall(stmpe_init);
+
+static void __exit stmpe_exit(void)
+{
+ i2c_del_driver(&stmpe_i2c_driver);
+}
+module_exit(stmpe_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver");
+MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
new file mode 100644
index 0000000..b58c43c
--- /dev/null
+++ b/drivers/mfd/stmpe-spi.c
@@ -0,0 +1,150 @@
+/*
+ * ST Microelectronics MFD: stmpe's spi client specific driver
+ *
+ * Copyright (C) ST Microelectronics SA 2011
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Viresh Kumar <viresh.kumar@st.com> for ST Microelectronics
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include "stmpe.h"
+
+#define READ_CMD (1 << 7)
+
+static int spi_reg_read(struct stmpe *stmpe, u8 reg)
+{
+ struct spi_device *spi = stmpe->client;
+ int status = spi_w8r16(spi, reg | READ_CMD);
+
+ return (status < 0) ? status : status >> 8;
+}
+
+static int spi_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
+{
+ struct spi_device *spi = stmpe->client;
+ u16 cmd = (val << 8) | reg;
+
+ return spi_write(spi, (const u8 *)&cmd, 2);
+}
+
+static int spi_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
+{
+ int ret, i;
+
+ for (i = 0; i < length; i++) {
+ ret = spi_reg_read(stmpe, reg + i);
+ if (ret < 0)
+ return ret;
+ *(values + i) = ret;
+ }
+
+ return 0;
+}
+
+static int spi_block_write(struct stmpe *stmpe, u8 reg, u8 length,
+ const u8 *values)
+{
+ int ret = 0, i;
+
+ for (i = length; i > 0; i--, reg++) {
+ ret = spi_reg_write(stmpe, reg, *(values + i - 1));
+ if (ret < 0)
+ return ret;
+ }
+
+ return ret;
+}
+
+static void spi_init(struct stmpe *stmpe)
+{
+ struct spi_device *spi = stmpe->client;
+
+ spi->bits_per_word = 8;
+
+ /* This register is only present for stmpe811 */
+ if (stmpe->variant->id_val == 0x0811)
+ spi_reg_write(stmpe, STMPE811_REG_SPI_CFG, spi->mode);
+
+ if (spi_setup(spi) < 0)
+ dev_dbg(&spi->dev, "spi_setup failed\n");
+}
+
+static struct stmpe_client_info spi_ci = {
+ .read_byte = spi_reg_read,
+ .write_byte = spi_reg_write,
+ .read_block = spi_block_read,
+ .write_block = spi_block_write,
+ .init = spi_init,
+};
+
+static int __devinit
+stmpe_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ /* don't exceed max specified rate - 1MHz - Limitation of STMPE */
+ if (spi->max_speed_hz > 1000000) {
+ dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+ (spi->max_speed_hz/1000));
+ return -EINVAL;
+ }
+
+ spi_ci.irq = spi->irq;
+ spi_ci.client = spi;
+ spi_ci.dev = &spi->dev;
+
+ return stmpe_probe(&spi_ci, id->driver_data);
+}
+
+static int __devexit stmpe_spi_remove(struct spi_device *spi)
+{
+ struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
+
+ return stmpe_remove(stmpe);
+}
+
+static const struct spi_device_id stmpe_spi_id[] = {
+ { "stmpe610", STMPE610 },
+ { "stmpe801", STMPE801 },
+ { "stmpe811", STMPE811 },
+ { "stmpe1601", STMPE1601 },
+ { "stmpe2401", STMPE2401 },
+ { "stmpe2403", STMPE2403 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, stmpe_id);
+
+static struct spi_driver stmpe_spi_driver = {
+ .driver = {
+ .name = "stmpe-spi",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &stmpe_dev_pm_ops,
+#endif
+ },
+ .probe = stmpe_spi_probe,
+ .remove = __devexit_p(stmpe_spi_remove),
+ .id_table = stmpe_spi_id,
+};
+
+static int __init stmpe_init(void)
+{
+ return spi_register_driver(&stmpe_spi_driver);
+}
+subsys_initcall(stmpe_init);
+
+static void __exit stmpe_exit(void)
+{
+ spi_unregister_driver(&stmpe_spi_driver);
+}
+module_exit(stmpe_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver");
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 2963689c..e07947e 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -1,18 +1,20 @@
/*
+ * ST Microelectronics MFD: stmpe's driver
+ *
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License, version 2
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
+#include <linux/gpio.h>
+#include <linux/export.h>
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/pm.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/stmpe.h>
#include "stmpe.h"
static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
@@ -29,10 +31,9 @@ static int __stmpe_reg_read(struct stmpe *stmpe, u8 reg)
{
int ret;
- ret = i2c_smbus_read_byte_data(stmpe->i2c, reg);
+ ret = stmpe->ci->read_byte(stmpe, reg);
if (ret < 0)
- dev_err(stmpe->dev, "failed to read reg %#x: %d\n",
- reg, ret);
+ dev_err(stmpe->dev, "failed to read reg %#x: %d\n", reg, ret);
dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret);
@@ -45,10 +46,9 @@ static int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val);
- ret = i2c_smbus_write_byte_data(stmpe->i2c, reg, val);
+ ret = stmpe->ci->write_byte(stmpe, reg, val);
if (ret < 0)
- dev_err(stmpe->dev, "failed to write reg %#x: %d\n",
- reg, ret);
+ dev_err(stmpe->dev, "failed to write reg %#x: %d\n", reg, ret);
return ret;
}
@@ -72,10 +72,9 @@ static int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length,
{
int ret;
- ret = i2c_smbus_read_i2c_block_data(stmpe->i2c, reg, length, values);
+ ret = stmpe->ci->read_block(stmpe, reg, length, values);
if (ret < 0)
- dev_err(stmpe->dev, "failed to read regs %#x: %d\n",
- reg, ret);
+ dev_err(stmpe->dev, "failed to read regs %#x: %d\n", reg, ret);
dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret);
stmpe_dump_bytes("stmpe rd: ", values, length);
@@ -91,11 +90,9 @@ static int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length);
stmpe_dump_bytes("stmpe wr: ", values, length);
- ret = i2c_smbus_write_i2c_block_data(stmpe->i2c, reg, length,
- values);
+ ret = stmpe->ci->write_block(stmpe, reg, length, values);
if (ret < 0)
- dev_err(stmpe->dev, "failed to write regs %#x: %d\n",
- reg, ret);
+ dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret);
return ret;
}
@@ -245,12 +242,14 @@ int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block)
u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB];
int af_bits = variant->af_bits;
int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8);
- int afperreg = 8 / af_bits;
int mask = (1 << af_bits) - 1;
u8 regs[numregs];
- int af;
- int ret;
+ int af, afperreg, ret;
+
+ if (!variant->get_altfunc)
+ return 0;
+ afperreg = 8 / af_bits;
mutex_lock(&stmpe->lock);
ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
@@ -325,7 +324,51 @@ static struct mfd_cell stmpe_keypad_cell = {
};
/*
- * Touchscreen (STMPE811)
+ * STMPE801
+ */
+static const u8 stmpe801_regs[] = {
+ [STMPE_IDX_CHIP_ID] = STMPE801_REG_CHIP_ID,
+ [STMPE_IDX_ICR_LSB] = STMPE801_REG_SYS_CTRL,
+ [STMPE_IDX_GPMR_LSB] = STMPE801_REG_GPIO_MP_STA,
+ [STMPE_IDX_GPSR_LSB] = STMPE801_REG_GPIO_SET_PIN,
+ [STMPE_IDX_GPCR_LSB] = STMPE801_REG_GPIO_SET_PIN,
+ [STMPE_IDX_GPDR_LSB] = STMPE801_REG_GPIO_DIR,
+ [STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN,
+ [STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA,
+
+};
+
+static struct stmpe_variant_block stmpe801_blocks[] = {
+ {
+ .cell = &stmpe_gpio_cell,
+ .irq = 0,
+ .block = STMPE_BLOCK_GPIO,
+ },
+};
+
+static int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
+ bool enable)
+{
+ if (blocks & STMPE_BLOCK_GPIO)
+ return 0;
+ else
+ return -EINVAL;
+}
+
+static struct stmpe_variant_info stmpe801 = {
+ .name = "stmpe801",
+ .id_val = STMPE801_ID,
+ .id_mask = 0xffff,
+ .num_gpios = 8,
+ .regs = stmpe801_regs,
+ .blocks = stmpe801_blocks,
+ .num_blocks = ARRAY_SIZE(stmpe801_blocks),
+ .num_irqs = STMPE801_NR_INTERNAL_IRQS,
+ .enable = stmpe801_enable,
+};
+
+/*
+ * Touchscreen (STMPE811 or STMPE610)
*/
static struct resource stmpe_ts_resources[] = {
@@ -350,7 +393,7 @@ static struct mfd_cell stmpe_ts_cell = {
};
/*
- * STMPE811
+ * STMPE811 or STMPE610
*/
static const u8 stmpe811_regs[] = {
@@ -421,6 +464,21 @@ static struct stmpe_variant_info stmpe811 = {
.get_altfunc = stmpe811_get_altfunc,
};
+/* Similar to 811, except number of gpios */
+static struct stmpe_variant_info stmpe610 = {
+ .name = "stmpe610",
+ .id_val = 0x0811,
+ .id_mask = 0xffff,
+ .num_gpios = 6,
+ .af_bits = 1,
+ .regs = stmpe811_regs,
+ .blocks = stmpe811_blocks,
+ .num_blocks = ARRAY_SIZE(stmpe811_blocks),
+ .num_irqs = STMPE811_NR_INTERNAL_IRQS,
+ .enable = stmpe811_enable,
+ .get_altfunc = stmpe811_get_altfunc,
+};
+
/*
* STMPE1601
*/
@@ -655,6 +713,8 @@ static struct stmpe_variant_info stmpe2403 = {
};
static struct stmpe_variant_info *stmpe_variant_info[] = {
+ [STMPE610] = &stmpe610,
+ [STMPE801] = &stmpe801,
[STMPE811] = &stmpe811,
[STMPE1601] = &stmpe1601,
[STMPE2401] = &stmpe2401,
@@ -671,6 +731,11 @@ static irqreturn_t stmpe_irq(int irq, void *data)
int ret;
int i;
+ if (variant->id_val == STMPE801_ID) {
+ handle_nested_irq(stmpe->irq_base);
+ return IRQ_HANDLED;
+ }
+
ret = stmpe_block_read(stmpe, israddr, num, isr);
if (ret < 0)
return IRQ_NONE;
@@ -757,14 +822,17 @@ static struct irq_chip stmpe_irq_chip = {
static int __devinit stmpe_irq_init(struct stmpe *stmpe)
{
+ struct irq_chip *chip = NULL;
int num_irqs = stmpe->variant->num_irqs;
int base = stmpe->irq_base;
int irq;
+ if (stmpe->variant->id_val != STMPE801_ID)
+ chip = &stmpe_irq_chip;
+
for (irq = base; irq < base + num_irqs; irq++) {
irq_set_chip_data(irq, stmpe);
- irq_set_chip_and_handler(irq, &stmpe_irq_chip,
- handle_edge_irq);
+ irq_set_chip_and_handler(irq, chip, handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
@@ -796,7 +864,7 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
unsigned int irq_trigger = stmpe->pdata->irq_trigger;
int autosleep_timeout = stmpe->pdata->autosleep_timeout;
struct stmpe_variant_info *variant = stmpe->variant;
- u8 icr = STMPE_ICR_LSB_GIM;
+ u8 icr;
unsigned int id;
u8 data[2];
int ret;
@@ -819,16 +887,32 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
if (ret)
return ret;
- if (irq_trigger == IRQF_TRIGGER_FALLING ||
- irq_trigger == IRQF_TRIGGER_RISING)
- icr |= STMPE_ICR_LSB_EDGE;
+ if (id == STMPE801_ID)
+ icr = STMPE801_REG_SYS_CTRL_INT_EN;
+ else
+ icr = STMPE_ICR_LSB_GIM;
+
+ /* STMPE801 doesn't support Edge interrupts */
+ if (id != STMPE801_ID) {
+ if (irq_trigger == IRQF_TRIGGER_FALLING ||
+ irq_trigger == IRQF_TRIGGER_RISING)
+ icr |= STMPE_ICR_LSB_EDGE;
+ }
if (irq_trigger == IRQF_TRIGGER_RISING ||
- irq_trigger == IRQF_TRIGGER_HIGH)
- icr |= STMPE_ICR_LSB_HIGH;
+ irq_trigger == IRQF_TRIGGER_HIGH) {
+ if (id == STMPE801_ID)
+ icr |= STMPE801_REG_SYS_CTRL_INT_HI;
+ else
+ icr |= STMPE_ICR_LSB_HIGH;
+ }
- if (stmpe->pdata->irq_invert_polarity)
- icr ^= STMPE_ICR_LSB_HIGH;
+ if (stmpe->pdata->irq_invert_polarity) {
+ if (id == STMPE801_ID)
+ icr ^= STMPE801_REG_SYS_CTRL_INT_HI;
+ else
+ icr ^= STMPE_ICR_LSB_HIGH;
+ }
if (stmpe->pdata->autosleep) {
ret = stmpe_autosleep(stmpe, autosleep_timeout);
@@ -873,32 +957,10 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
return ret;
}
-#ifdef CONFIG_PM
-static int stmpe_suspend(struct device *dev)
-{
- struct i2c_client *i2c = to_i2c_client(dev);
-
- if (device_may_wakeup(&i2c->dev))
- enable_irq_wake(i2c->irq);
-
- return 0;
-}
-
-static int stmpe_resume(struct device *dev)
-{
- struct i2c_client *i2c = to_i2c_client(dev);
-
- if (device_may_wakeup(&i2c->dev))
- disable_irq_wake(i2c->irq);
-
- return 0;
-}
-#endif
-
-static int __devinit stmpe_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+/* Called from client specific probe routines */
+int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
{
- struct stmpe_platform_data *pdata = i2c->dev.platform_data;
+ struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
struct stmpe *stmpe;
int ret;
@@ -912,30 +974,43 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
mutex_init(&stmpe->irq_lock);
mutex_init(&stmpe->lock);
- stmpe->dev = &i2c->dev;
- stmpe->i2c = i2c;
-
+ stmpe->dev = ci->dev;
+ stmpe->client = ci->client;
stmpe->pdata = pdata;
stmpe->irq_base = pdata->irq_base;
-
- stmpe->partnum = id->driver_data;
- stmpe->variant = stmpe_variant_info[stmpe->partnum];
+ stmpe->ci = ci;
+ stmpe->partnum = partnum;
+ stmpe->variant = stmpe_variant_info[partnum];
stmpe->regs = stmpe->variant->regs;
stmpe->num_gpios = stmpe->variant->num_gpios;
+ dev_set_drvdata(stmpe->dev, stmpe);
- i2c_set_clientdata(i2c, stmpe);
+ if (ci->init)
+ ci->init(stmpe);
+
+ if (pdata->irq_over_gpio) {
+ ret = gpio_request_one(pdata->irq_gpio, GPIOF_DIR_IN, "stmpe");
+ if (ret) {
+ dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
+ ret);
+ goto out_free;
+ }
+
+ stmpe->irq = gpio_to_irq(pdata->irq_gpio);
+ } else {
+ stmpe->irq = ci->irq;
+ }
ret = stmpe_chip_init(stmpe);
if (ret)
- goto out_free;
+ goto free_gpio;
ret = stmpe_irq_init(stmpe);
if (ret)
- goto out_free;
+ goto free_gpio;
- ret = request_threaded_irq(stmpe->i2c->irq, NULL, stmpe_irq,
- pdata->irq_trigger | IRQF_ONESHOT,
- "stmpe", stmpe);
+ ret = request_threaded_irq(stmpe->irq, NULL, stmpe_irq,
+ pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe);
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n", ret);
goto out_removeirq;
@@ -951,67 +1026,55 @@ static int __devinit stmpe_probe(struct i2c_client *i2c,
out_removedevs:
mfd_remove_devices(stmpe->dev);
- free_irq(stmpe->i2c->irq, stmpe);
+ free_irq(stmpe->irq, stmpe);
out_removeirq:
stmpe_irq_remove(stmpe);
+free_gpio:
+ if (pdata->irq_over_gpio)
+ gpio_free(pdata->irq_gpio);
out_free:
kfree(stmpe);
return ret;
}
-static int __devexit stmpe_remove(struct i2c_client *client)
+int stmpe_remove(struct stmpe *stmpe)
{
- struct stmpe *stmpe = i2c_get_clientdata(client);
-
mfd_remove_devices(stmpe->dev);
- free_irq(stmpe->i2c->irq, stmpe);
+ free_irq(stmpe->irq, stmpe);
stmpe_irq_remove(stmpe);
+ if (stmpe->pdata->irq_over_gpio)
+ gpio_free(stmpe->pdata->irq_gpio);
+
kfree(stmpe);
return 0;
}
-static const struct i2c_device_id stmpe_id[] = {
- { "stmpe811", STMPE811 },
- { "stmpe1601", STMPE1601 },
- { "stmpe2401", STMPE2401 },
- { "stmpe2403", STMPE2403 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, stmpe_id);
-
#ifdef CONFIG_PM
-static const struct dev_pm_ops stmpe_dev_pm_ops = {
- .suspend = stmpe_suspend,
- .resume = stmpe_resume,
-};
-#endif
+static int stmpe_suspend(struct device *dev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(dev);
-static struct i2c_driver stmpe_driver = {
- .driver.name = "stmpe",
- .driver.owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .driver.pm = &stmpe_dev_pm_ops,
-#endif
- .probe = stmpe_probe,
- .remove = __devexit_p(stmpe_remove),
- .id_table = stmpe_id,
-};
+ if (device_may_wakeup(dev))
+ enable_irq_wake(stmpe->irq);
-static int __init stmpe_init(void)
-{
- return i2c_add_driver(&stmpe_driver);
+ return 0;
}
-subsys_initcall(stmpe_init);
-static void __exit stmpe_exit(void)
+static int stmpe_resume(struct device *dev)
{
- i2c_del_driver(&stmpe_driver);
+ struct stmpe *stmpe = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(stmpe->irq);
+
+ return 0;
}
-module_exit(stmpe_exit);
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("STMPE MFD core driver");
-MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
+const struct dev_pm_ops stmpe_dev_pm_ops = {
+ .suspend = stmpe_suspend,
+ .resume = stmpe_resume,
+};
+#endif
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index e4ee3895..7b8e13f 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -8,6 +8,14 @@
#ifndef __STMPE_H
#define __STMPE_H
+#include <linux/device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/printk.h>
+#include <linux/types.h>
+
+extern const struct dev_pm_ops stmpe_dev_pm_ops;
+
#ifdef STMPE_DUMP_BYTES
static inline void stmpe_dump_bytes(const char *str, const void *buf,
size_t len)
@@ -67,11 +75,55 @@ struct stmpe_variant_info {
int (*enable_autosleep)(struct stmpe *stmpe, int autosleep_timeout);
};
+/**
+ * struct stmpe_client_info - i2c or spi specific routines/info
+ * @data: client specific data
+ * @read_byte: read single byte
+ * @write_byte: write single byte
+ * @read_block: read block or multiple bytes
+ * @write_block: write block or multiple bytes
+ * @init: client init routine, called during probe
+ */
+struct stmpe_client_info {
+ void *data;
+ int irq;
+ void *client;
+ struct device *dev;
+ int (*read_byte)(struct stmpe *stmpe, u8 reg);
+ int (*write_byte)(struct stmpe *stmpe, u8 reg, u8 val);
+ int (*read_block)(struct stmpe *stmpe, u8 reg, u8 len, u8 *values);
+ int (*write_block)(struct stmpe *stmpe, u8 reg, u8 len,
+ const u8 *values);
+ void (*init)(struct stmpe *stmpe);
+};
+
+int stmpe_probe(struct stmpe_client_info *ci, int partnum);
+int stmpe_remove(struct stmpe *stmpe);
+
#define STMPE_ICR_LSB_HIGH (1 << 2)
#define STMPE_ICR_LSB_EDGE (1 << 1)
#define STMPE_ICR_LSB_GIM (1 << 0)
/*
+ * STMPE801
+ */
+#define STMPE801_ID 0x0108
+#define STMPE801_NR_INTERNAL_IRQS 1
+
+#define STMPE801_REG_CHIP_ID 0x00
+#define STMPE801_REG_VERSION_ID 0x02
+#define STMPE801_REG_SYS_CTRL 0x04
+#define STMPE801_REG_GPIO_INT_EN 0x08
+#define STMPE801_REG_GPIO_INT_STA 0x09
+#define STMPE801_REG_GPIO_MP_STA 0x10
+#define STMPE801_REG_GPIO_SET_PIN 0x11
+#define STMPE801_REG_GPIO_DIR 0x12
+
+#define STMPE801_REG_SYS_CTRL_RESET (1 << 7)
+#define STMPE801_REG_SYS_CTRL_INT_EN (1 << 2)
+#define STMPE801_REG_SYS_CTRL_INT_HI (1 << 0)
+
+/*
* STMPE811
*/
@@ -87,6 +139,7 @@ struct stmpe_variant_info {
#define STMPE811_REG_CHIP_ID 0x00
#define STMPE811_REG_SYS_CTRL2 0x04
+#define STMPE811_REG_SPI_CFG 0x08
#define STMPE811_REG_INT_CTRL 0x09
#define STMPE811_REG_INT_EN 0x0A
#define STMPE811_REG_INT_STA 0x0B
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index 91ad21e..2d9e879 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -442,21 +442,7 @@ static struct platform_driver t7l66xb_platform_driver = {
/*--------------------------------------------------------------------------*/
-static int __init t7l66xb_init(void)
-{
- int retval = 0;
-
- retval = platform_driver_register(&t7l66xb_platform_driver);
- return retval;
-}
-
-static void __exit t7l66xb_exit(void)
-{
- platform_driver_unregister(&t7l66xb_platform_driver);
-}
-
-module_init(t7l66xb_init);
-module_exit(t7l66xb_exit);
+module_platform_driver(t7l66xb_platform_driver);
MODULE_DESCRIPTION("Toshiba T7L66XB core driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 71bc835..d20a284 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -234,19 +234,7 @@ static struct platform_driver tc6387xb_platform_driver = {
.resume = tc6387xb_resume,
};
-
-static int __init tc6387xb_init(void)
-{
- return platform_driver_register(&tc6387xb_platform_driver);
-}
-
-static void __exit tc6387xb_exit(void)
-{
- platform_driver_unregister(&tc6387xb_platform_driver);
-}
-
-module_init(tc6387xb_init);
-module_exit(tc6387xb_exit);
+module_platform_driver(tc6387xb_platform_driver);
MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index af9ab0e..4fb0e6c 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -458,17 +458,7 @@ static struct platform_driver ti_ssp_driver = {
}
};
-static int __init ti_ssp_init(void)
-{
- return platform_driver_register(&ti_ssp_driver);
-}
-module_init(ti_ssp_init);
-
-static void __exit ti_ssp_exit(void)
-{
- platform_driver_unregister(&ti_ssp_driver);
-}
-module_exit(ti_ssp_exit);
+module_platform_driver(ti_ssp_driver);
MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
MODULE_AUTHOR("Cyril Chemparathy");
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index 02d6569..0ba26fb 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -857,7 +857,7 @@ static void __devexit timb_remove(struct pci_dev *dev)
kfree(priv);
}
-static struct pci_device_id timberdale_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
{ 0 }
};
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c
index a56be93..95c0d79 100644
--- a/drivers/mfd/tps65910-irq.c
+++ b/drivers/mfd/tps65910-irq.c
@@ -215,6 +215,7 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
int tps65910_irq_exit(struct tps65910 *tps65910)
{
- free_irq(tps65910->chip_irq, tps65910);
+ if (tps65910->chip_irq)
+ free_irq(tps65910->chip_irq, tps65910);
return 0;
}
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index c1da84b..01cf501 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -172,15 +172,12 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
- ret = tps65910_irq_init(tps65910, init_data->irq, init_data);
- if (ret < 0)
- goto err;
+ tps65910_irq_init(tps65910, init_data->irq, init_data);
kfree(init_data);
return ret;
err:
- mfd_remove_devices(tps65910->dev);
kfree(tps65910);
kfree(init_data);
return ret;
@@ -190,8 +187,8 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
- mfd_remove_devices(tps65910->dev);
tps65910_irq_exit(tps65910);
+ mfd_remove_devices(tps65910->dev);
kfree(tps65910);
return 0;
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index 6d71e0d..27d3302 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -111,7 +111,6 @@ static int __devexit tps65912_spi_remove(struct spi_device *spi)
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = tps65912_spi_probe,
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 61e70cf..e04e04d 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -34,6 +34,11 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
#include <linux/regulator/machine.h>
@@ -144,6 +149,9 @@
#define TWL_MODULE_LAST TWL4030_MODULE_LAST
+#define TWL4030_NR_IRQS 8
+#define TWL6030_NR_IRQS 20
+
/* Base Address defns for twl4030_map[] */
/* subchip/slave 0 - USB ID */
@@ -255,6 +263,7 @@ struct twl_client {
static struct twl_client twl_modules[TWL_NUM_SLAVES];
+static struct irq_domain domain;
/* mapping the module id to slave id and base address */
struct twl_mapping {
@@ -1183,14 +1192,48 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
int status;
unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data;
+ struct device_node *node = client->dev.of_node;
u8 temp;
int ret = 0;
+ int nr_irqs = TWL4030_NR_IRQS;
+
+ if ((id->driver_data) & TWL6030_CLASS)
+ nr_irqs = TWL6030_NR_IRQS;
+
+ if (node && !pdata) {
+ /*
+ * XXX: Temporary pdata until the information is correctly
+ * retrieved by every TWL modules from DT.
+ */
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct twl4030_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ }
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
return -EINVAL;
}
+ status = irq_alloc_descs(-1, pdata->irq_base, nr_irqs, 0);
+ if (IS_ERR_VALUE(status)) {
+ dev_err(&client->dev, "Fail to allocate IRQ descs\n");
+ return status;
+ }
+
+ pdata->irq_base = status;
+ pdata->irq_end = pdata->irq_base + nr_irqs;
+
+ domain.irq_base = pdata->irq_base;
+ domain.nr_irq = nr_irqs;
+#ifdef CONFIG_OF_IRQ
+ domain.of_node = of_node_get(node);
+ domain.ops = &irq_domain_simple_ops;
+#endif
+ irq_domain_add(&domain);
+
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
return -EIO;
@@ -1270,7 +1313,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
- status = add_children(pdata, id->driver_data);
+#ifdef CONFIG_OF_DEVICE
+ if (node)
+ status = of_platform_populate(node, NULL, NULL, &client->dev);
+ else
+#endif
+ status = add_children(pdata, id->driver_data);
+
fail:
if (status < 0)
twl_remove(client);
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index ae51ab5..838ce4e 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -261,17 +261,7 @@ static struct platform_driver twl4030_audio_driver = {
},
};
-static int __devinit twl4030_audio_init(void)
-{
- return platform_driver_register(&twl4030_audio_driver);
-}
-module_init(twl4030_audio_init);
-
-static void __devexit twl4030_audio_exit(void)
-{
- platform_driver_unregister(&twl4030_audio_driver);
-}
-module_exit(twl4030_audio_exit);
+module_platform_driver(twl4030_audio_driver);
MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 29f11e0..b69bb51 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -492,7 +492,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
u8 bytes[4];
} imr;
- /* byte[0] gets overwriten as we write ... */
+ /* byte[0] gets overwritten as we write ... */
imr.word = cpu_to_le32(agent->imr << 8);
agent->imr_change_pending = false;
@@ -667,6 +667,7 @@ int twl4030_sih_setup(int module)
irq_set_chip_data(irq, agent);
irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
handle_edge_irq);
+ irq_set_nested_thread(irq, 1);
activate_irq(irq);
}
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 834f824..456ecb5 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -807,19 +807,7 @@ static struct platform_driver twl4030_madc_driver = {
},
};
-static int __init twl4030_madc_init(void)
-{
- return platform_driver_register(&twl4030_madc_driver);
-}
-
-module_init(twl4030_madc_init);
-
-static void __exit twl4030_madc_exit(void)
-{
- platform_driver_unregister(&twl4030_madc_driver);
-}
-
-module_exit(twl4030_madc_exit);
+module_platform_driver(twl4030_madc_driver);
MODULE_DESCRIPTION("TWL4030 ADC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index a764676..d905f51 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -34,7 +34,8 @@
static u8 twl4030_start_script_address = 0x2b;
#define PWR_P1_SW_EVENTS 0x10
-#define PWR_DEVOFF (1<<0)
+#define PWR_DEVOFF (1 << 0)
+#define SEQ_OFFSYNC (1 << 0)
#define PHY_TO_OFF_PM_MASTER(p) (p - 0x36)
#define PHY_TO_OFF_PM_RECEIVER(p) (p - 0x5b)
@@ -511,12 +512,27 @@ int twl4030_remove_script(u8 flags)
return err;
}
+/*
+ * In master mode, start the power off sequence.
+ * After a successful execution, TWL shuts down the power to the SoC
+ * and all peripherals connected to it.
+ */
+void twl4030_power_off(void)
+{
+ int err;
+
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF,
+ TWL4030_PM_MASTER_P1_SW_EVENTS);
+ if (err)
+ pr_err("TWL4030 Unable to power off\n");
+}
+
void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
int i;
struct twl4030_resconfig *resconfig;
- u8 address = twl4030_start_script_address;
+ u8 val, address = twl4030_start_script_address;
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
TWL4030_PM_MASTER_KEY_CFG1,
@@ -548,6 +564,28 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
}
}
+ /* Board has to be wired properly to use this feature */
+ if (twl4030_scripts->use_poweroff && !pm_power_off) {
+ /* Default for SEQ_OFFSYNC is set, lets ensure this */
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
+ TWL4030_PM_MASTER_CFG_P123_TRANSITION);
+ if (err) {
+ pr_warning("TWL4030 Unable to read registers\n");
+
+ } else if (!(val & SEQ_OFFSYNC)) {
+ val |= SEQ_OFFSYNC;
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
+ TWL4030_PM_MASTER_CFG_P123_TRANSITION);
+ if (err) {
+ pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
+ goto relock;
+ }
+ }
+
+ pm_power_off = twl4030_power_off;
+ }
+
+relock:
err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index 268f80f..dda8629 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -509,13 +509,10 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
twl6040->audpwron = -EINVAL;
if (gpio_is_valid(twl6040->audpwron)) {
- ret = gpio_request(twl6040->audpwron, "audpwron");
+ ret = gpio_request_one(twl6040->audpwron, GPIOF_OUT_INIT_LOW,
+ "audpwron");
if (ret)
goto gpio1_err;
-
- ret = gpio_direction_output(twl6040->audpwron, 0);
- if (ret)
- goto gpio2_err;
}
/* codec interrupt */
@@ -619,18 +616,7 @@ static struct platform_driver twl6040_driver = {
},
};
-static int __devinit twl6040_init(void)
-{
- return platform_driver_register(&twl6040_driver);
-}
-module_init(twl6040_init);
-
-static void __devexit twl6040_exit(void)
-{
- platform_driver_unregister(&twl6040_driver);
-}
-
-module_exit(twl6040_exit);
+module_platform_driver(twl6040_driver);
MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index b281217..91c4f25 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -36,6 +36,15 @@ static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
+static struct mcp_device_id ucb1x00_id[] = {
+ { "ucb1x00", 0 }, /* auto-detection */
+ { "ucb1200", UCB_ID_1200 },
+ { "ucb1300", UCB_ID_1300 },
+ { "tc35143", UCB_ID_TC35143 },
+ { }
+};
+MODULE_DEVICE_TABLE(mcp, ucb1x00_id);
+
/**
* ucb1x00_io_set_dir - set IO direction
* @ucb: UCB1x00 structure describing chip
@@ -527,17 +536,33 @@ static struct class ucb1x00_class = {
static int ucb1x00_probe(struct mcp *mcp)
{
+ const struct mcp_device_id *mid;
struct ucb1x00 *ucb;
struct ucb1x00_driver *drv;
+ struct ucb1x00_plat_data *pdata;
unsigned int id;
int ret = -ENODEV;
int temp;
mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
+ mid = mcp_get_device_id(mcp);
- if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
- printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
+ if (mid && mid->driver_data) {
+ if (id != mid->driver_data) {
+ printk(KERN_WARNING "%s wrong ID %04x found: %04x\n",
+ mid->name, (unsigned int) mid->driver_data, id);
+ goto err_disable;
+ }
+ } else {
+ mid = &ucb1x00_id[1];
+ while (mid->driver_data) {
+ if (id == mid->driver_data)
+ break;
+ mid++;
+ }
+ printk(KERN_WARNING "%s ID not found: %04x\n",
+ ucb1x00_id[0].name, id);
goto err_disable;
}
@@ -546,28 +571,28 @@ static int ucb1x00_probe(struct mcp *mcp)
if (!ucb)
goto err_disable;
-
+ pdata = mcp->attached_device.platform_data;
ucb->dev.class = &ucb1x00_class;
ucb->dev.parent = &mcp->attached_device;
- dev_set_name(&ucb->dev, "ucb1x00");
+ dev_set_name(&ucb->dev, mid->name);
spin_lock_init(&ucb->lock);
spin_lock_init(&ucb->io_lock);
sema_init(&ucb->adc_sem, 1);
- ucb->id = id;
+ ucb->id = mid;
ucb->mcp = mcp;
ucb->irq = ucb1x00_detect_irq(ucb);
if (ucb->irq == NO_IRQ) {
- printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
+ printk(KERN_ERR "%s: IRQ probe failed\n", mid->name);
ret = -ENODEV;
goto err_free;
}
ucb->gpio.base = -1;
- if (mcp->gpio_base != 0) {
+ if (pdata && (pdata->gpio_base >= 0)) {
ucb->gpio.label = dev_name(&ucb->dev);
- ucb->gpio.base = mcp->gpio_base;
+ ucb->gpio.base = pdata->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
@@ -580,10 +605,10 @@ static int ucb1x00_probe(struct mcp *mcp)
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
- "UCB1x00", ucb);
+ mid->name, ucb);
if (ret) {
- printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
- ucb->irq, ret);
+ printk(KERN_ERR "%s: unable to grab irq%d: %d\n",
+ mid->name, ucb->irq, ret);
goto err_gpio;
}
@@ -705,6 +730,7 @@ static struct mcp_driver ucb1x00_driver = {
.remove = ucb1x00_remove,
.suspend = ucb1x00_suspend,
.resume = ucb1x00_resume,
+ .id_table = ucb1x00_id,
};
static int __init ucb1x00_init(void)
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 38ffbd5..40ec3c1 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -382,7 +382,7 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
idev->name = "Touchscreen panel";
- idev->id.product = ts->ucb->id;
+ idev->id.product = ts->ucb->id->driver_data;
idev->open = ucb1x00_ts_open;
idev->close = ucb1x00_ts_close;
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
index d698703..b73cc15 100644
--- a/drivers/mfd/vx855.c
+++ b/drivers/mfd/vx855.c
@@ -118,7 +118,7 @@ static void __devexit vx855_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-static struct pci_device_id vx855_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
{ 0, }
};
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 0a2b8d4..f5e54fa 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -559,6 +559,8 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
buf[i], reg + i, reg + i);
ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
+ if (ret != 0)
+ return ret;
}
return 0;
@@ -1875,7 +1877,6 @@ err_irq:
err_regmap:
mfd_remove_devices(wm831x->dev);
regmap_exit(wm831x->regmap);
- kfree(wm831x);
return ret;
}
@@ -1887,7 +1888,6 @@ void wm831x_device_exit(struct wm831x *wm831x)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x);
regmap_exit(wm831x->regmap);
- kfree(wm831x);
}
int wm831x_device_suspend(struct wm831x *wm831x)
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index ac8da1d..cb15609 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -30,7 +30,7 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
struct wm831x *wm831x;
int ret;
- wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
return -ENOMEM;
@@ -42,7 +42,6 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(wm831x->regmap);
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
ret);
- kfree(wm831x);
return ret;
}
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index f4747a4..bec4d05 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -325,11 +325,6 @@ static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data)
return WM831X_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
}
-static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data)
-{
- return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
-}
-
static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
int irq)
{
@@ -477,8 +472,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD);
if (primary & WM831X_TCHDATA_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA);
- if (primary & (WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT))
- goto out;
+ primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
int offset = wm831x_irqs[i].reg - 1;
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 8d6a9a9..62ef325 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -30,7 +30,7 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
type = (enum wm831x_parent)id->driver_data;
- wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
+ wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
return -ENOMEM;
@@ -45,7 +45,6 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
ret = PTR_ERR(wm831x->regmap);
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
ret);
- kfree(wm831x);
return ret;
}
@@ -95,7 +94,6 @@ MODULE_DEVICE_TABLE(spi, wm831x_spi_id);
static struct spi_driver wm831x_spi_driver = {
.driver = {
.name = "wm831x",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &wm831x_spi_pm,
},
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index e81cc31..dd1caaa 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -573,6 +573,8 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
u16 id1, id2, mask_rev;
u16 cust_id, mode, chip_rev;
+ dev_set_drvdata(wm8350->dev, wm8350);
+
/* get WM8350 revision and config mode */
ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
if (ret != 0) {
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 5fe5de1..d955faa 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -63,7 +63,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
struct wm8350 *wm8350;
int ret = 0;
- wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
+ wm8350 = devm_kzalloc(&i2c->dev, sizeof(struct wm8350), GFP_KERNEL);
if (wm8350 == NULL)
return -ENOMEM;
@@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
return ret;
err:
- kfree(wm8350);
return ret;
}
@@ -89,7 +88,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
wm8350_device_exit(wm8350);
- kfree(wm8350);
return 0;
}
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 62b4626..2204893 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -344,7 +344,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
struct wm8400 *wm8400;
int ret;
- wm8400 = kzalloc(sizeof(struct wm8400), GFP_KERNEL);
+ wm8400 = devm_kzalloc(&i2c->dev, sizeof(struct wm8400), GFP_KERNEL);
if (wm8400 == NULL) {
ret = -ENOMEM;
goto err;
@@ -353,7 +353,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
wm8400->regmap = regmap_init_i2c(i2c, &wm8400_regmap_config);
if (IS_ERR(wm8400->regmap)) {
ret = PTR_ERR(wm8400->regmap);
- goto struct_err;
+ goto err;
}
wm8400->dev = &i2c->dev;
@@ -367,8 +367,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
map_err:
regmap_exit(wm8400->regmap);
-struct_err:
- kfree(wm8400);
err:
return ret;
}
@@ -379,7 +377,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c)
wm8400_release(wm8400);
regmap_exit(wm8400->regmap);
- kfree(wm8400);
return 0;
}
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 61894fc..f117e7f 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -28,11 +28,7 @@
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/registers.h>
-static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
- int bytes, void *dest)
-{
- return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
-}
+#include "wm8994.h"
/**
* wm8994_reg_read: Read a single WM8994 register.
@@ -68,12 +64,6 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
return regmap_bulk_read(wm8994->regmap, reg, buf, count);
}
-static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
- int bytes, const void *src)
-{
- return regmap_raw_write(wm8994->regmap, reg, src, bytes);
-}
-
/**
* wm8994_reg_write: Write a single WM8994 register.
*
@@ -252,6 +242,20 @@ static int wm8994_suspend(struct device *dev)
break;
}
+ switch (wm8994->type) {
+ case WM1811:
+ ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read jackdet: %d\n", ret);
+ } else if (ret & WM1811_JACKDET_MODE_MASK) {
+ dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Disable LDO pulldowns while the device is suspended if we
* don't know that something will be driving them. */
if (!wm8994->ldo_ena_always_driven)
@@ -259,25 +263,14 @@ static int wm8994_suspend(struct device *dev)
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
- /* GPIO configuration state is saved here since we may be configuring
- * the GPIO alternate functions even if we're not using the gpiolib
- * driver for them.
- */
- ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
- &wm8994->gpio_regs);
- if (ret < 0)
- dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
-
- /* For similar reasons we also stash the regulator states */
- ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
- &wm8994->ldo_regs);
- if (ret < 0)
- dev_err(dev, "Failed to save LDO registers: %d\n", ret);
-
/* Explicitly put the device into reset in case regulators
* don't get disabled in order to ensure consistent restart.
*/
- wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);
+ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+ wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
+
+ regcache_cache_only(wm8994->regmap, true);
+ regcache_mark_dirty(wm8994->regmap);
wm8994->suspended = true;
@@ -294,7 +287,7 @@ static int wm8994_suspend(struct device *dev)
static int wm8994_resume(struct device *dev)
{
struct wm8994 *wm8994 = dev_get_drvdata(dev);
- int ret, i;
+ int ret;
/* We may have lied to the PM core about suspending */
if (!wm8994->suspended)
@@ -307,27 +300,13 @@ static int wm8994_resume(struct device *dev)
return ret;
}
- /* Write register at a time as we use the cache on the CPU so store
- * it in native endian.
- */
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- ret = wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK
- + i, wm8994->irq_masks_cur[i]);
- if (ret < 0)
- dev_err(dev, "Failed to restore interrupt masks: %d\n",
- ret);
+ regcache_cache_only(wm8994->regmap, false);
+ ret = regcache_sync(wm8994->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
+ goto err_enable;
}
- ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
- &wm8994->ldo_regs);
- if (ret < 0)
- dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
-
- ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
- &wm8994->gpio_regs);
- if (ret < 0)
- dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
-
/* Disable LDO pulldowns while the device is active */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
@@ -336,6 +315,11 @@ static int wm8994_resume(struct device *dev)
wm8994->suspended = false;
return 0;
+
+err_enable:
+ regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
+
+ return ret;
}
#endif
@@ -361,19 +345,16 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
-static struct regmap_config wm8994_regmap_config = {
- .reg_bits = 16,
- .val_bits = 16,
-};
-
/*
* Instantiate the generic non-control parts of the device.
*/
static int wm8994_device_init(struct wm8994 *wm8994, int irq)
{
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ struct regmap_config *regmap_config;
const char *devname;
int ret, i;
+ int pulls = 0;
dev_set_drvdata(wm8994->dev, wm8994);
@@ -402,9 +383,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err_regmap;
}
- wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
- wm8994->num_supplies,
- GFP_KERNEL);
+ wm8994->supplies = devm_kzalloc(wm8994->dev,
+ sizeof(struct regulator_bulk_data) *
+ wm8994->num_supplies, GFP_KERNEL);
if (!wm8994->supplies) {
ret = -ENOMEM;
goto err_regmap;
@@ -432,7 +413,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
wm8994->supplies);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
- goto err_supplies;
+ goto err_regmap;
}
ret = regulator_bulk_enable(wm8994->num_supplies,
@@ -482,25 +463,54 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
ret);
goto err_enable;
}
+ wm8994->revision = ret;
switch (wm8994->type) {
case WM8994:
- switch (ret) {
+ switch (wm8994->revision) {
case 0:
case 1:
dev_warn(wm8994->dev,
"revision %c not fully supported\n",
- 'A' + ret);
+ 'A' + wm8994->revision);
break;
default:
break;
}
break;
+ case WM1811:
+ /* Revision C did not change the relevant layer */
+ if (wm8994->revision > 1)
+ wm8994->revision++;
+ break;
default:
break;
}
- dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret);
+ dev_info(wm8994->dev, "%s revision %c\n", devname,
+ 'A' + wm8994->revision);
+
+ switch (wm8994->type) {
+ case WM1811:
+ regmap_config = &wm1811_regmap_config;
+ break;
+ case WM8994:
+ regmap_config = &wm8994_regmap_config;
+ break;
+ case WM8958:
+ regmap_config = &wm8958_regmap_config;
+ break;
+ default:
+ dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
+ return -EINVAL;
+ }
+
+ ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
+ ret);
+ return ret;
+ }
if (pdata) {
wm8994->irq_base = pdata->irq_base;
@@ -516,12 +526,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
}
wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+
+ if (pdata->spkmode_pu)
+ pulls |= WM8994_SPKMODE_PU;
}
- /* Disable LDO pulldowns while the device is active */
+ /* Disable unneeded pulls */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
- WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
- 0);
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |
+ WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,
+ pulls);
/* In some system designs where the regulators are not in use,
* we can achieve a small reduction in leakage currents by
@@ -560,12 +574,9 @@ err_enable:
wm8994->supplies);
err_get:
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-err_supplies:
- kfree(wm8994->supplies);
err_regmap:
regmap_exit(wm8994->regmap);
mfd_remove_devices(wm8994->dev);
- kfree(wm8994);
return ret;
}
@@ -577,18 +588,24 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
regulator_bulk_disable(wm8994->num_supplies,
wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
- kfree(wm8994->supplies);
regmap_exit(wm8994->regmap);
- kfree(wm8994);
}
+static const struct of_device_id wm8994_of_match[] = {
+ { .compatible = "wlf,wm1811", },
+ { .compatible = "wlf,wm8994", },
+ { .compatible = "wlf,wm8958", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8994_of_match);
+
static int wm8994_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
int ret;
- wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
+ wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
if (wm8994 == NULL)
return -ENOMEM;
@@ -597,12 +614,11 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994->irq = i2c->irq;
wm8994->type = id->driver_data;
- wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
+ wm8994->regmap = regmap_init_i2c(i2c, &wm8994_base_regmap_config);
if (IS_ERR(wm8994->regmap)) {
ret = PTR_ERR(wm8994->regmap);
dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
ret);
- kfree(wm8994);
return ret;
}
@@ -620,6 +636,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id wm8994_i2c_id[] = {
{ "wm1811", WM1811 },
+ { "wm1811a", WM1811 },
{ "wm8994", WM8994 },
{ "wm8958", WM8958 },
{ }
@@ -634,6 +651,7 @@ static struct i2c_driver wm8994_i2c_driver = {
.name = "wm8994",
.owner = THIS_MODULE,
.pm = &wm8994_pm_ops,
+ .of_match_table = wm8994_of_match,
},
.probe = wm8994_i2c_probe,
.remove = wm8994_i2c_remove,
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index d682f7b..46b20c4 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -18,248 +18,127 @@
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
+#include <linux/regmap.h>
#include <linux/mfd/wm8994/core.h>
#include <linux/mfd/wm8994/registers.h>
#include <linux/delay.h>
-struct wm8994_irq_data {
- int reg;
- int mask;
-};
-
-static struct wm8994_irq_data wm8994_irqs[] = {
+static struct regmap_irq wm8994_irqs[] = {
[WM8994_IRQ_TEMP_SHUT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_TEMP_SHUT_EINT,
},
[WM8994_IRQ_MIC1_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC1_DET_EINT,
},
[WM8994_IRQ_MIC1_SHRT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC1_SHRT_EINT,
},
[WM8994_IRQ_MIC2_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC2_DET_EINT,
},
[WM8994_IRQ_MIC2_SHRT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC2_SHRT_EINT,
},
[WM8994_IRQ_FLL1_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FLL1_LOCK_EINT,
},
[WM8994_IRQ_FLL2_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FLL2_LOCK_EINT,
},
[WM8994_IRQ_SRC1_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_SRC1_LOCK_EINT,
},
[WM8994_IRQ_SRC2_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_SRC2_LOCK_EINT,
},
[WM8994_IRQ_AIF1DRC1_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF1DRC1_SIG_DET,
},
[WM8994_IRQ_AIF1DRC2_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF1DRC2_SIG_DET_EINT,
},
[WM8994_IRQ_AIF2DRC_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF2DRC_SIG_DET_EINT,
},
[WM8994_IRQ_FIFOS_ERR] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FIFOS_ERR_EINT,
},
[WM8994_IRQ_WSEQ_DONE] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_WSEQ_DONE_EINT,
},
[WM8994_IRQ_DCS_DONE] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_DCS_DONE_EINT,
},
[WM8994_IRQ_TEMP_WARN] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_TEMP_WARN_EINT,
},
[WM8994_IRQ_GPIO(1)] = {
- .reg = 1,
.mask = WM8994_GP1_EINT,
},
[WM8994_IRQ_GPIO(2)] = {
- .reg = 1,
.mask = WM8994_GP2_EINT,
},
[WM8994_IRQ_GPIO(3)] = {
- .reg = 1,
.mask = WM8994_GP3_EINT,
},
[WM8994_IRQ_GPIO(4)] = {
- .reg = 1,
.mask = WM8994_GP4_EINT,
},
[WM8994_IRQ_GPIO(5)] = {
- .reg = 1,
.mask = WM8994_GP5_EINT,
},
[WM8994_IRQ_GPIO(6)] = {
- .reg = 1,
.mask = WM8994_GP6_EINT,
},
[WM8994_IRQ_GPIO(7)] = {
- .reg = 1,
.mask = WM8994_GP7_EINT,
},
[WM8994_IRQ_GPIO(8)] = {
- .reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(9)] = {
- .reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(10)] = {
- .reg = 1,
.mask = WM8994_GP10_EINT,
},
[WM8994_IRQ_GPIO(11)] = {
- .reg = 1,
.mask = WM8994_GP11_EINT,
},
};
-static inline int irq_data_to_status_reg(struct wm8994_irq_data *irq_data)
-{
- return WM8994_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
-}
-
-static inline int irq_data_to_mask_reg(struct wm8994_irq_data *irq_data)
-{
- return WM8994_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
-}
-
-static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
- int irq)
-{
- return &wm8994_irqs[irq - wm8994->irq_base];
-}
-
-static void wm8994_irq_lock(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
-
- mutex_lock(&wm8994->irq_lock);
-}
-
-static void wm8994_irq_sync_unlock(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- /* If there's been a change in the mask write it back
- * to the hardware. */
- if (wm8994->irq_masks_cur[i] != wm8994->irq_masks_cache[i]) {
- wm8994->irq_masks_cache[i] = wm8994->irq_masks_cur[i];
- wm8994_reg_write(wm8994,
- WM8994_INTERRUPT_STATUS_1_MASK + i,
- wm8994->irq_masks_cur[i]);
- }
- }
-
- mutex_unlock(&wm8994->irq_lock);
-}
-
-static void wm8994_irq_enable(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
- data->irq);
-
- wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
-}
-
-static void wm8994_irq_disable(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
- data->irq);
-
- wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
-}
+static struct regmap_irq_chip wm8994_irq_chip = {
+ .name = "wm8994",
+ .irqs = wm8994_irqs,
+ .num_irqs = ARRAY_SIZE(wm8994_irqs),
-static struct irq_chip wm8994_irq_chip = {
- .name = "wm8994",
- .irq_bus_lock = wm8994_irq_lock,
- .irq_bus_sync_unlock = wm8994_irq_sync_unlock,
- .irq_disable = wm8994_irq_disable,
- .irq_enable = wm8994_irq_enable,
+ .num_regs = 2,
+ .status_base = WM8994_INTERRUPT_STATUS_1,
+ .mask_base = WM8994_INTERRUPT_STATUS_1_MASK,
+ .ack_base = WM8994_INTERRUPT_STATUS_1,
};
-/* The processing of the primary interrupt occurs in a thread so that
- * we can interact with the device over I2C or SPI. */
-static irqreturn_t wm8994_irq_thread(int irq, void *data)
-{
- struct wm8994 *wm8994 = data;
- unsigned int i;
- u16 status[WM8994_NUM_IRQ_REGS];
- int ret;
-
- ret = wm8994_bulk_read(wm8994, WM8994_INTERRUPT_STATUS_1,
- WM8994_NUM_IRQ_REGS, status);
- if (ret < 0) {
- dev_err(wm8994->dev, "Failed to read interrupt status: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- /* Bit swap and apply masking */
- for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) {
- status[i] = be16_to_cpu(status[i]);
- status[i] &= ~wm8994->irq_masks_cur[i];
- }
-
- /* Ack any unmasked IRQs */
- for (i = 0; i < ARRAY_SIZE(status); i++) {
- if (status[i])
- wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1 + i,
- status[i]);
- }
-
- /* Report */
- for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
- if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
- handle_nested_irq(wm8994->irq_base + i);
- }
-
- return IRQ_HANDLED;
-}
-
int wm8994_irq_init(struct wm8994 *wm8994)
{
- int i, cur_irq, ret;
-
- mutex_init(&wm8994->irq_lock);
-
- /* Mask the individual interrupt sources */
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- wm8994->irq_masks_cur[i] = 0xffff;
- wm8994->irq_masks_cache[i] = 0xffff;
- wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK + i,
- 0xffff);
- }
+ int ret;
if (!wm8994->irq) {
dev_warn(wm8994->dev,
@@ -274,30 +153,12 @@ int wm8994_irq_init(struct wm8994 *wm8994)
return 0;
}
- /* Register them with genirq */
- for (cur_irq = wm8994->irq_base;
- cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
- cur_irq++) {
- irq_set_chip_data(cur_irq, wm8994);
- irq_set_chip_and_handler(cur_irq, &wm8994_irq_chip,
- handle_edge_irq);
- irq_set_nested_thread(cur_irq, 1);
-
- /* ARM needs us to explicitly flag the IRQ as valid
- * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
-#else
- irq_set_noprobe(cur_irq);
-#endif
- }
-
- ret = request_threaded_irq(wm8994->irq, NULL, wm8994_irq_thread,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "wm8994", wm8994);
+ ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ wm8994->irq_base, &wm8994_irq_chip,
+ &wm8994->irq_data);
if (ret != 0) {
- dev_err(wm8994->dev, "Failed to request IRQ %d: %d\n",
- wm8994->irq, ret);
+ dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
}
@@ -309,6 +170,5 @@ int wm8994_irq_init(struct wm8994 *wm8994)
void wm8994_irq_exit(struct wm8994 *wm8994)
{
- if (wm8994->irq)
- free_irq(wm8994->irq, wm8994);
+ regmap_del_irq_chip(wm8994->irq, wm8994->irq_data);
}
diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c
new file mode 100644
index 0000000..c598ae6
--- /dev/null
+++ b/drivers/mfd/wm8994-regmap.c
@@ -0,0 +1,1238 @@
+/*
+ * wm8994-regmap.c -- Register map data for WM8994 series devices
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/registers.h>
+#include <linux/regmap.h>
+
+#include "wm8994.h"
+
+static struct reg_default wm1811_defaults[] = {
+ { 0x0000, 0x1811 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0003 }, /* R60 - LDO 2 */
+ { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */
+ { 0x003E, 0x0039 }, /* R62 - MICBIAS2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */
+ { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */
+ { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */
+ { 0x00D2, 0x0000 }, /* R210 - Mic Detect 3 */
+ { 0x0100, 0x0100 }, /* R256 - Chip Revision */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0212, 0x0000 }, /* R530 - Rate Status */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0226, 0x0000 }, /* R550 - FLL1 EFS 1 */
+ { 0x0227, 0x0006 }, /* R551 - FLL1 EFS 2 */
+ { 0x0240, 0x0000 }, /* R576 - FLL2Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2Control (5) */
+ { 0x0246, 0x0000 }, /* R582 - FLL2 EFS 1 */
+ { 0x0247, 0x0006 }, /* R583 - FLL2 EFS 2 */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4050 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0318, 0x0003 }, /* R792 - AIF2TX Control */
+ { 0x0320, 0x0040 }, /* R800 - AIF3 Control (1) */
+ { 0x0321, 0x0000 }, /* R801 - AIF3 Control (2) */
+ { 0x0322, 0x0000 }, /* R802 - AIF3DAC Data */
+ { 0x0323, 0x0000 }, /* R803 - AIF3ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0530, 0x0068 }, /* R1328 - AIF2 DAC Noise Gate */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0594, 0x0000 }, /* R1428 - AIF2 EQ Band 1 C */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - AIF2ADC Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - AIF2ADC Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - AIF2ADC Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - AIF2TX Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - AIF2TX Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - Pull Control (MCLK2) */
+ { 0x0702, 0xA101 }, /* R1794 - Pull Control (BCLK2) */
+ { 0x0703, 0xA101 }, /* R1795 - Pull Control (DACLRCLK2) */
+ { 0x0704, 0xA101 }, /* R1796 - Pull Control (DACDAT2) */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */
+ { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */
+ { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+};
+
+static struct reg_default wm8994_defaults[] = {
+ { 0x0000, 0x8994 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0000 }, /* R57 - AntiPOP (2) */
+ { 0x003A, 0x0000 }, /* R58 - MICBIAS */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0003 }, /* R60 - LDO 2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */
+ { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x0100, 0x0003 }, /* R256 - Chip Revision */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0212, 0x0000 }, /* R530 - Rate Status */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0240, 0x0000 }, /* R576 - FLL2 Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2 Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2 Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2 Control (5) */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4050 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0404, 0x00C0 }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x0405, 0x00C0 }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x0406, 0x00C0 }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x0407, 0x00C0 }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - DAC2 Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - DAC2 Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - GPIO 2 */
+ { 0x0702, 0xA101 }, /* R1794 - GPIO 3 */
+ { 0x0703, 0xA101 }, /* R1795 - GPIO 4 */
+ { 0x0704, 0xA101 }, /* R1796 - GPIO 5 */
+ { 0x0705, 0xA101 }, /* R1797 - GPIO 6 */
+ { 0x0706, 0xA101 }, /* R1798 - GPIO 7 */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */
+ { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */
+ { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+};
+
+static struct reg_default wm8958_defaults[] = {
+ { 0x0000, 0x8958 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0005 }, /* R60 - LDO 2 */
+ { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */
+ { 0x003E, 0x0039 }, /* R62 - MICBIAS2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */
+ { 0x00D0, 0x5600 }, /* R208 - Mic Detect 1 */
+ { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0226, 0x0000 }, /* R550 - FLL1 EFS 1 */
+ { 0x0227, 0x0006 }, /* R551 - FLL1 EFS 2 */
+ { 0x0240, 0x0000 }, /* R576 - FLL2Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2Control (5) */
+ { 0x0246, 0x0000 }, /* R582 - FLL2 EFS 1 */
+ { 0x0247, 0x0006 }, /* R583 - FLL2 EFS 2 */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4053 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0320, 0x0040 }, /* R800 - AIF3 Control (1) */
+ { 0x0321, 0x0000 }, /* R801 - AIF3 Control (2) */
+ { 0x0322, 0x0000 }, /* R802 - AIF3DAC Data */
+ { 0x0323, 0x0000 }, /* R803 - AIF3ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0404, 0x00C0 }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x0405, 0x00C0 }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x0406, 0x00C0 }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x0407, 0x00C0 }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0431, 0x0068 }, /* R1073 - AIF1 DAC2 Noise Gate */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x04B4, 0x0000 }, /* R1204 - AIF1 DAC2EQ Band 1 C */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0530, 0x0068 }, /* R1328 - AIF2 DAC Noise Gate */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0594, 0x0000 }, /* R1428 - AIF2 EQ Band 1 C */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - DAC2 Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - DAC2 Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - Pull Control (MCLK2) */
+ { 0x0702, 0xA101 }, /* R1794 - Pull Control (BCLK2) */
+ { 0x0703, 0xA101 }, /* R1795 - Pull Control (DACLRCLK2) */
+ { 0x0704, 0xA101 }, /* R1796 - Pull Control (DACDAT2) */
+ { 0x0705, 0xA101 }, /* R1797 - GPIO 6 */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xFFEF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+ { 0x0900, 0x1C00 }, /* R2304 - DSP2_Program */
+ { 0x0901, 0x0000 }, /* R2305 - DSP2_Config */
+ { 0x0A0D, 0x0000 }, /* R2573 - DSP2_ExecControl */
+ { 0x2400, 0x003F }, /* R9216 - MBC Band 1 K (1) */
+ { 0x2401, 0x8BD8 }, /* R9217 - MBC Band 1 K (2) */
+ { 0x2402, 0x0032 }, /* R9218 - MBC Band 1 N1 (1) */
+ { 0x2403, 0xF52D }, /* R9219 - MBC Band 1 N1 (2) */
+ { 0x2404, 0x0065 }, /* R9220 - MBC Band 1 N2 (1) */
+ { 0x2405, 0xAC8C }, /* R9221 - MBC Band 1 N2 (2) */
+ { 0x2406, 0x006B }, /* R9222 - MBC Band 1 N3 (1) */
+ { 0x2407, 0xE087 }, /* R9223 - MBC Band 1 N3 (2) */
+ { 0x2408, 0x0072 }, /* R9224 - MBC Band 1 N4 (1) */
+ { 0x2409, 0x1483 }, /* R9225 - MBC Band 1 N4 (2) */
+ { 0x240A, 0x0072 }, /* R9226 - MBC Band 1 N5 (1) */
+ { 0x240B, 0x1483 }, /* R9227 - MBC Band 1 N5 (2) */
+ { 0x240C, 0x0043 }, /* R9228 - MBC Band 1 X1 (1) */
+ { 0x240D, 0x3525 }, /* R9229 - MBC Band 1 X1 (2) */
+ { 0x240E, 0x0006 }, /* R9230 - MBC Band 1 X2 (1) */
+ { 0x240F, 0x6A4A }, /* R9231 - MBC Band 1 X2 (2) */
+ { 0x2410, 0x0043 }, /* R9232 - MBC Band 1 X3 (1) */
+ { 0x2411, 0x6079 }, /* R9233 - MBC Band 1 X3 (2) */
+ { 0x2412, 0x000C }, /* R9234 - MBC Band 1 Attack (1) */
+ { 0x2413, 0xCCCD }, /* R9235 - MBC Band 1 Attack (2) */
+ { 0x2414, 0x0000 }, /* R9236 - MBC Band 1 Decay (1) */
+ { 0x2415, 0x0800 }, /* R9237 - MBC Band 1 Decay (2) */
+ { 0x2416, 0x003F }, /* R9238 - MBC Band 2 K (1) */
+ { 0x2417, 0x8BD8 }, /* R9239 - MBC Band 2 K (2) */
+ { 0x2418, 0x0032 }, /* R9240 - MBC Band 2 N1 (1) */
+ { 0x2419, 0xF52D }, /* R9241 - MBC Band 2 N1 (2) */
+ { 0x241A, 0x0065 }, /* R9242 - MBC Band 2 N2 (1) */
+ { 0x241B, 0xAC8C }, /* R9243 - MBC Band 2 N2 (2) */
+ { 0x241C, 0x006B }, /* R9244 - MBC Band 2 N3 (1) */
+ { 0x241D, 0xE087 }, /* R9245 - MBC Band 2 N3 (2) */
+ { 0x241E, 0x0072 }, /* R9246 - MBC Band 2 N4 (1) */
+ { 0x241F, 0x1483 }, /* R9247 - MBC Band 2 N4 (2) */
+ { 0x2420, 0x0072 }, /* R9248 - MBC Band 2 N5 (1) */
+ { 0x2421, 0x1483 }, /* R9249 - MBC Band 2 N5 (2) */
+ { 0x2422, 0x0043 }, /* R9250 - MBC Band 2 X1 (1) */
+ { 0x2423, 0x3525 }, /* R9251 - MBC Band 2 X1 (2) */
+ { 0x2424, 0x0006 }, /* R9252 - MBC Band 2 X2 (1) */
+ { 0x2425, 0x6A4A }, /* R9253 - MBC Band 2 X2 (2) */
+ { 0x2426, 0x0043 }, /* R9254 - MBC Band 2 X3 (1) */
+ { 0x2427, 0x6079 }, /* R9255 - MBC Band 2 X3 (2) */
+ { 0x2428, 0x000C }, /* R9256 - MBC Band 2 Attack (1) */
+ { 0x2429, 0xCCCD }, /* R9257 - MBC Band 2 Attack (2) */
+ { 0x242A, 0x0000 }, /* R9258 - MBC Band 2 Decay (1) */
+ { 0x242B, 0x0800 }, /* R9259 - MBC Band 2 Decay (2) */
+ { 0x242C, 0x005A }, /* R9260 - MBC_B2_PG2 (1) */
+ { 0x242D, 0x7EFA }, /* R9261 - MBC_B2_PG2 (2) */
+ { 0x242E, 0x005A }, /* R9262 - MBC_B1_PG2 (1) */
+ { 0x242F, 0x7EFA }, /* R9263 - MBC_B1_PG2 (2) */
+ { 0x2600, 0x00A7 }, /* R9728 - MBC Crossover (1) */
+ { 0x2601, 0x0D1C }, /* R9729 - MBC Crossover (2) */
+ { 0x2602, 0x0083 }, /* R9730 - MBC HPF (1) */
+ { 0x2603, 0x98AD }, /* R9731 - MBC HPF (2) */
+ { 0x2606, 0x0008 }, /* R9734 - MBC LPF (1) */
+ { 0x2607, 0xE7A2 }, /* R9735 - MBC LPF (2) */
+ { 0x260A, 0x0055 }, /* R9738 - MBC RMS Limit (1) */
+ { 0x260B, 0x8C4B }, /* R9739 - MBC RMS Limit (2) */
+};
+
+static bool wm1811_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_POWER_MANAGEMENT_1:
+ case WM8994_POWER_MANAGEMENT_2:
+ case WM8994_POWER_MANAGEMENT_3:
+ case WM8994_POWER_MANAGEMENT_4:
+ case WM8994_POWER_MANAGEMENT_5:
+ case WM8994_POWER_MANAGEMENT_6:
+ case WM8994_INPUT_MIXER_1:
+ case WM8994_LEFT_LINE_INPUT_1_2_VOLUME:
+ case WM8994_LEFT_LINE_INPUT_3_4_VOLUME:
+ case WM8994_RIGHT_LINE_INPUT_1_2_VOLUME:
+ case WM8994_RIGHT_LINE_INPUT_3_4_VOLUME:
+ case WM8994_LEFT_OUTPUT_VOLUME:
+ case WM8994_RIGHT_OUTPUT_VOLUME:
+ case WM8994_LINE_OUTPUTS_VOLUME:
+ case WM8994_HPOUT2_VOLUME:
+ case WM8994_LEFT_OPGA_VOLUME:
+ case WM8994_RIGHT_OPGA_VOLUME:
+ case WM8994_SPKMIXL_ATTENUATION:
+ case WM8994_SPKMIXR_ATTENUATION:
+ case WM8994_SPKOUT_MIXERS:
+ case WM8994_CLASSD:
+ case WM8994_SPEAKER_VOLUME_LEFT:
+ case WM8994_SPEAKER_VOLUME_RIGHT:
+ case WM8994_INPUT_MIXER_2:
+ case WM8994_INPUT_MIXER_3:
+ case WM8994_INPUT_MIXER_4:
+ case WM8994_INPUT_MIXER_5:
+ case WM8994_INPUT_MIXER_6:
+ case WM8994_OUTPUT_MIXER_1:
+ case WM8994_OUTPUT_MIXER_2:
+ case WM8994_OUTPUT_MIXER_3:
+ case WM8994_OUTPUT_MIXER_4:
+ case WM8994_OUTPUT_MIXER_5:
+ case WM8994_OUTPUT_MIXER_6:
+ case WM8994_HPOUT2_MIXER:
+ case WM8994_LINE_MIXER_1:
+ case WM8994_LINE_MIXER_2:
+ case WM8994_SPEAKER_MIXER:
+ case WM8994_ADDITIONAL_CONTROL:
+ case WM8994_ANTIPOP_1:
+ case WM8994_ANTIPOP_2:
+ case WM8994_LDO_1:
+ case WM8994_LDO_2:
+ case WM8958_MICBIAS1:
+ case WM8958_MICBIAS2:
+ case WM8994_CHARGE_PUMP_1:
+ case WM8958_CHARGE_PUMP_2:
+ case WM8994_CLASS_W_1:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_2:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_DC_SERVO_4:
+ case WM8994_ANALOGUE_HP_1:
+ case WM8958_MIC_DETECT_1:
+ case WM8958_MIC_DETECT_2:
+ case WM8958_MIC_DETECT_3:
+ case WM8994_CHIP_REVISION:
+ case WM8994_CONTROL_INTERFACE:
+ case WM8994_AIF1_CLOCKING_1:
+ case WM8994_AIF1_CLOCKING_2:
+ case WM8994_AIF2_CLOCKING_1:
+ case WM8994_AIF2_CLOCKING_2:
+ case WM8994_CLOCKING_1:
+ case WM8994_CLOCKING_2:
+ case WM8994_AIF1_RATE:
+ case WM8994_AIF2_RATE:
+ case WM8994_RATE_STATUS:
+ case WM8994_FLL1_CONTROL_1:
+ case WM8994_FLL1_CONTROL_2:
+ case WM8994_FLL1_CONTROL_3:
+ case WM8994_FLL1_CONTROL_4:
+ case WM8994_FLL1_CONTROL_5:
+ case WM8958_FLL1_EFS_1:
+ case WM8958_FLL1_EFS_2:
+ case WM8994_FLL2_CONTROL_1:
+ case WM8994_FLL2_CONTROL_2:
+ case WM8994_FLL2_CONTROL_3:
+ case WM8994_FLL2_CONTROL_4:
+ case WM8994_FLL2_CONTROL_5:
+ case WM8958_FLL2_EFS_1:
+ case WM8958_FLL2_EFS_2:
+ case WM8994_AIF1_CONTROL_1:
+ case WM8994_AIF1_CONTROL_2:
+ case WM8994_AIF1_MASTER_SLAVE:
+ case WM8994_AIF1_BCLK:
+ case WM8994_AIF1ADC_LRCLK:
+ case WM8994_AIF1DAC_LRCLK:
+ case WM8994_AIF1DAC_DATA:
+ case WM8994_AIF1ADC_DATA:
+ case WM8994_AIF2_CONTROL_1:
+ case WM8994_AIF2_CONTROL_2:
+ case WM8994_AIF2_MASTER_SLAVE:
+ case WM8994_AIF2_BCLK:
+ case WM8994_AIF2ADC_LRCLK:
+ case WM8994_AIF2DAC_LRCLK:
+ case WM8994_AIF2DAC_DATA:
+ case WM8994_AIF2ADC_DATA:
+ case WM1811_AIF2TX_CONTROL:
+ case WM8958_AIF3_CONTROL_1:
+ case WM8958_AIF3_CONTROL_2:
+ case WM8958_AIF3DAC_DATA:
+ case WM8958_AIF3ADC_DATA:
+ case WM8994_AIF1_ADC1_LEFT_VOLUME:
+ case WM8994_AIF1_ADC1_RIGHT_VOLUME:
+ case WM8994_AIF1_DAC1_LEFT_VOLUME:
+ case WM8994_AIF1_DAC1_RIGHT_VOLUME:
+ case WM8994_AIF1_ADC1_FILTERS:
+ case WM8994_AIF1_DAC1_FILTERS_1:
+ case WM8994_AIF1_DAC1_FILTERS_2:
+ case WM8958_AIF1_DAC1_NOISE_GATE:
+ case WM8994_AIF1_DRC1_1:
+ case WM8994_AIF1_DRC1_2:
+ case WM8994_AIF1_DRC1_3:
+ case WM8994_AIF1_DRC1_4:
+ case WM8994_AIF1_DRC1_5:
+ case WM8994_AIF1_DAC1_EQ_GAINS_1:
+ case WM8994_AIF1_DAC1_EQ_GAINS_2:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_C:
+ case WM8994_AIF2_ADC_LEFT_VOLUME:
+ case WM8994_AIF2_ADC_RIGHT_VOLUME:
+ case WM8994_AIF2_DAC_LEFT_VOLUME:
+ case WM8994_AIF2_DAC_RIGHT_VOLUME:
+ case WM8994_AIF2_ADC_FILTERS:
+ case WM8994_AIF2_DAC_FILTERS_1:
+ case WM8994_AIF2_DAC_FILTERS_2:
+ case WM8958_AIF2_DAC_NOISE_GATE:
+ case WM8994_AIF2_DRC_1:
+ case WM8994_AIF2_DRC_2:
+ case WM8994_AIF2_DRC_3:
+ case WM8994_AIF2_DRC_4:
+ case WM8994_AIF2_DRC_5:
+ case WM8994_AIF2_EQ_GAINS_1:
+ case WM8994_AIF2_EQ_GAINS_2:
+ case WM8994_AIF2_EQ_BAND_1_A:
+ case WM8994_AIF2_EQ_BAND_1_B:
+ case WM8994_AIF2_EQ_BAND_1_PG:
+ case WM8994_AIF2_EQ_BAND_2_A:
+ case WM8994_AIF2_EQ_BAND_2_B:
+ case WM8994_AIF2_EQ_BAND_2_C:
+ case WM8994_AIF2_EQ_BAND_2_PG:
+ case WM8994_AIF2_EQ_BAND_3_A:
+ case WM8994_AIF2_EQ_BAND_3_B:
+ case WM8994_AIF2_EQ_BAND_3_C:
+ case WM8994_AIF2_EQ_BAND_3_PG:
+ case WM8994_AIF2_EQ_BAND_4_A:
+ case WM8994_AIF2_EQ_BAND_4_B:
+ case WM8994_AIF2_EQ_BAND_4_C:
+ case WM8994_AIF2_EQ_BAND_4_PG:
+ case WM8994_AIF2_EQ_BAND_5_A:
+ case WM8994_AIF2_EQ_BAND_5_B:
+ case WM8994_AIF2_EQ_BAND_5_PG:
+ case WM8994_AIF2_EQ_BAND_1_C:
+ case WM8994_DAC1_MIXER_VOLUMES:
+ case WM8994_DAC1_LEFT_MIXER_ROUTING:
+ case WM8994_DAC1_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC2_MIXER_VOLUMES:
+ case WM8994_DAC2_LEFT_MIXER_ROUTING:
+ case WM8994_DAC2_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC1_LEFT_VOLUME:
+ case WM8994_DAC1_RIGHT_VOLUME:
+ case WM8994_DAC2_LEFT_VOLUME:
+ case WM8994_DAC2_RIGHT_VOLUME:
+ case WM8994_DAC_SOFTMUTE:
+ case WM8994_OVERSAMPLING:
+ case WM8994_SIDETONE:
+ case WM8994_GPIO_1:
+ case WM8994_GPIO_2:
+ case WM8994_GPIO_3:
+ case WM8994_GPIO_4:
+ case WM8994_GPIO_5:
+ case WM8994_GPIO_6:
+ case WM8994_GPIO_8:
+ case WM8994_GPIO_9:
+ case WM8994_GPIO_10:
+ case WM8994_GPIO_11:
+ case WM8994_PULL_CONTROL_1:
+ case WM8994_PULL_CONTROL_2:
+ case WM8994_INTERRUPT_STATUS_1:
+ case WM8994_INTERRUPT_STATUS_2:
+ case WM8994_INTERRUPT_RAW_STATUS_2:
+ case WM8994_INTERRUPT_STATUS_1_MASK:
+ case WM8994_INTERRUPT_STATUS_2_MASK:
+ case WM8994_INTERRUPT_CONTROL:
+ case WM8994_IRQ_DEBOUNCE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8994_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_WRITE_SEQUENCER_CTRL_1:
+ case WM8994_WRITE_SEQUENCER_CTRL_2:
+ case WM8994_AIF1_ADC2_LEFT_VOLUME:
+ case WM8994_AIF1_ADC2_RIGHT_VOLUME:
+ case WM8994_AIF1_DAC2_LEFT_VOLUME:
+ case WM8994_AIF1_DAC2_RIGHT_VOLUME:
+ case WM8994_AIF1_ADC2_FILTERS:
+ case WM8994_AIF1_DAC2_FILTERS_1:
+ case WM8994_AIF1_DAC2_FILTERS_2:
+ case WM8958_AIF1_DAC2_NOISE_GATE:
+ case WM8994_AIF1_DRC2_1:
+ case WM8994_AIF1_DRC2_2:
+ case WM8994_AIF1_DRC2_3:
+ case WM8994_AIF1_DRC2_4:
+ case WM8994_AIF1_DRC2_5:
+ case WM8994_AIF1_DAC2_EQ_GAINS_1:
+ case WM8994_AIF1_DAC2_EQ_GAINS_2:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_C:
+ case WM8994_DAC2_MIXER_VOLUMES:
+ case WM8994_DAC2_LEFT_MIXER_ROUTING:
+ case WM8994_DAC2_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC2_LEFT_VOLUME:
+ case WM8994_DAC2_RIGHT_VOLUME:
+ return true;
+ default:
+ return wm1811_readable_register(dev, reg);
+ }
+}
+
+static bool wm8958_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8958_DSP2_PROGRAM:
+ case WM8958_DSP2_CONFIG:
+ case WM8958_DSP2_MAGICNUM:
+ case WM8958_DSP2_RELEASEYEAR:
+ case WM8958_DSP2_RELEASEMONTHDAY:
+ case WM8958_DSP2_RELEASETIME:
+ case WM8958_DSP2_VERMAJMIN:
+ case WM8958_DSP2_VERBUILD:
+ case WM8958_DSP2_TESTREG:
+ case WM8958_DSP2_XORREG:
+ case WM8958_DSP2_SHIFTMAXX:
+ case WM8958_DSP2_SHIFTMAXY:
+ case WM8958_DSP2_SHIFTMAXZ:
+ case WM8958_DSP2_SHIFTMAXEXTLO:
+ case WM8958_DSP2_AESSELECT:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_DSP2_SAMPLEBREAK:
+ case WM8958_DSP2_COUNTBREAK:
+ case WM8958_DSP2_INTSTATUS:
+ case WM8958_DSP2_EVENTSTATUS:
+ case WM8958_DSP2_INTMASK:
+ case WM8958_DSP2_CONFIGDWIDTH:
+ case WM8958_DSP2_CONFIGINSTR:
+ case WM8958_DSP2_CONFIGDMEM:
+ case WM8958_DSP2_CONFIGDELAYS:
+ case WM8958_DSP2_CONFIGNUMIO:
+ case WM8958_DSP2_CONFIGEXTDEPTH:
+ case WM8958_DSP2_CONFIGMULTIPLIER:
+ case WM8958_DSP2_CONFIGCTRLDWIDTH:
+ case WM8958_DSP2_CONFIGPIPELINE:
+ case WM8958_DSP2_SHIFTMAXEXTHI:
+ case WM8958_DSP2_SWVERSIONREG:
+ case WM8958_DSP2_CONFIGXMEM:
+ case WM8958_DSP2_CONFIGYMEM:
+ case WM8958_DSP2_CONFIGZMEM:
+ case WM8958_FW_BUILD_1:
+ case WM8958_FW_BUILD_0:
+ case WM8958_FW_ID_1:
+ case WM8958_FW_ID_0:
+ case WM8958_FW_MAJOR_1:
+ case WM8958_FW_MAJOR_0:
+ case WM8958_FW_MINOR_1:
+ case WM8958_FW_MINOR_0:
+ case WM8958_FW_PATCH_1:
+ case WM8958_FW_PATCH_0:
+ case WM8958_MBC_BAND_1_K_1:
+ case WM8958_MBC_BAND_1_K_2:
+ case WM8958_MBC_BAND_1_N1_1:
+ case WM8958_MBC_BAND_1_N1_2:
+ case WM8958_MBC_BAND_1_N2_1:
+ case WM8958_MBC_BAND_1_N2_2:
+ case WM8958_MBC_BAND_1_N3_1:
+ case WM8958_MBC_BAND_1_N3_2:
+ case WM8958_MBC_BAND_1_N4_1:
+ case WM8958_MBC_BAND_1_N4_2:
+ case WM8958_MBC_BAND_1_N5_1:
+ case WM8958_MBC_BAND_1_N5_2:
+ case WM8958_MBC_BAND_1_X1_1:
+ case WM8958_MBC_BAND_1_X1_2:
+ case WM8958_MBC_BAND_1_X2_1:
+ case WM8958_MBC_BAND_1_X2_2:
+ case WM8958_MBC_BAND_1_X3_1:
+ case WM8958_MBC_BAND_1_X3_2:
+ case WM8958_MBC_BAND_1_ATTACK_1:
+ case WM8958_MBC_BAND_1_ATTACK_2:
+ case WM8958_MBC_BAND_1_DECAY_1:
+ case WM8958_MBC_BAND_1_DECAY_2:
+ case WM8958_MBC_BAND_2_K_1:
+ case WM8958_MBC_BAND_2_K_2:
+ case WM8958_MBC_BAND_2_N1_1:
+ case WM8958_MBC_BAND_2_N1_2:
+ case WM8958_MBC_BAND_2_N2_1:
+ case WM8958_MBC_BAND_2_N2_2:
+ case WM8958_MBC_BAND_2_N3_1:
+ case WM8958_MBC_BAND_2_N3_2:
+ case WM8958_MBC_BAND_2_N4_1:
+ case WM8958_MBC_BAND_2_N4_2:
+ case WM8958_MBC_BAND_2_N5_1:
+ case WM8958_MBC_BAND_2_N5_2:
+ case WM8958_MBC_BAND_2_X1_1:
+ case WM8958_MBC_BAND_2_X1_2:
+ case WM8958_MBC_BAND_2_X2_1:
+ case WM8958_MBC_BAND_2_X2_2:
+ case WM8958_MBC_BAND_2_X3_1:
+ case WM8958_MBC_BAND_2_X3_2:
+ case WM8958_MBC_BAND_2_ATTACK_1:
+ case WM8958_MBC_BAND_2_ATTACK_2:
+ case WM8958_MBC_BAND_2_DECAY_1:
+ case WM8958_MBC_BAND_2_DECAY_2:
+ case WM8958_MBC_B2_PG2_1:
+ case WM8958_MBC_B2_PG2_2:
+ case WM8958_MBC_B1_PG2_1:
+ case WM8958_MBC_B1_PG2_2:
+ case WM8958_MBC_CROSSOVER_1:
+ case WM8958_MBC_CROSSOVER_2:
+ case WM8958_MBC_HPF_1:
+ case WM8958_MBC_HPF_2:
+ case WM8958_MBC_LPF_1:
+ case WM8958_MBC_LPF_2:
+ case WM8958_MBC_RMS_LIMIT_1:
+ case WM8958_MBC_RMS_LIMIT_2:
+ return true;
+ default:
+ return wm8994_readable_register(dev, reg);
+ }
+}
+
+static bool wm8994_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_RATE_STATUS:
+ case WM8958_MIC_DETECT_3:
+ case WM8994_DC_SERVO_4E:
+ case WM8994_CHIP_REVISION:
+ case WM8994_INTERRUPT_STATUS_1:
+ case WM8994_INTERRUPT_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm1811_volatile_register(struct device *dev, unsigned int reg)
+{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
+
+ switch (reg) {
+ case WM8994_GPIO_6:
+ if (wm8994->revision > 1)
+ return true;
+ else
+ return false;
+ default:
+ return wm8994_volatile_register(dev, reg);
+ }
+}
+
+static bool wm8958_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8958_DSP2_MAGICNUM:
+ case WM8958_DSP2_RELEASEYEAR:
+ case WM8958_DSP2_RELEASEMONTHDAY:
+ case WM8958_DSP2_RELEASETIME:
+ case WM8958_DSP2_VERMAJMIN:
+ case WM8958_DSP2_VERBUILD:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_DSP2_SWVERSIONREG:
+ case WM8958_DSP2_CONFIGXMEM:
+ case WM8958_DSP2_CONFIGYMEM:
+ case WM8958_DSP2_CONFIGZMEM:
+ case WM8958_FW_BUILD_1:
+ case WM8958_FW_BUILD_0:
+ case WM8958_FW_ID_1:
+ case WM8958_FW_ID_0:
+ case WM8958_FW_MAJOR_1:
+ case WM8958_FW_MAJOR_0:
+ case WM8958_FW_MINOR_1:
+ case WM8958_FW_MINOR_0:
+ case WM8958_FW_PATCH_1:
+ case WM8958_FW_PATCH_0:
+ return true;
+ default:
+ return wm8994_volatile_register(dev, reg);
+ }
+}
+
+struct regmap_config wm1811_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm1811_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm1811_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm1811_volatile_register,
+ .readable_reg = wm1811_readable_register,
+};
+
+struct regmap_config wm8994_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm8994_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8994_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm8994_volatile_register,
+ .readable_reg = wm8994_readable_register,
+};
+
+struct regmap_config wm8958_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm8958_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8958_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm8958_volatile_register,
+ .readable_reg = wm8958_readable_register,
+};
+
+struct regmap_config wm8994_base_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+};
diff --git a/drivers/mfd/wm8994.h b/drivers/mfd/wm8994.h
new file mode 100644
index 0000000..6f39a84
--- /dev/null
+++ b/drivers/mfd/wm8994.h
@@ -0,0 +1,25 @@
+/*
+ * wm8994.h -- WM8994 MFD internals
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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 __MFD_WM8994_H__
+#define __MFD_WM8994_H__
+
+#include <linux/regmap.h>
+
+extern struct regmap_config wm1811_regmap_config;
+extern struct regmap_config wm8994_regmap_config;
+extern struct regmap_config wm8958_regmap_config;
+extern struct regmap_config wm8994_base_regmap_config;
+
+#endif
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5664696..6a1a092 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -500,6 +500,14 @@ config USB_SWITCH_FSA9480
stereo and mono audio, video, microphone and UART data to use
a common connector port.
+config MAX8997_MUIC
+ tristate "MAX8997 MUIC Support"
+ depends on MFD_MAX8997
+ help
+ If you say yes here you get support for the MUIC device of
+ Maxim MAX8997 PMIC.
+ The MAX8997 MUIC is a USB port accessory detector and switch.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b26495a..3e1d801 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -48,3 +48,4 @@ obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
+obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o
diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c
index 2208a9d..d7a9aa1 100644
--- a/drivers/misc/ab8500-pwm.c
+++ b/drivers/misc/ab8500-pwm.c
@@ -8,8 +8,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/pwm.h>
-#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/module.h>
/*
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c
index eb5cd28..a2d25e4 100644
--- a/drivers/misc/carma/carma-fpga-program.c
+++ b/drivers/misc/carma/carma-fpga-program.c
@@ -513,7 +513,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
* transaction, and then put it under external control
*/
memset(&config, 0, sizeof(config));
- config.direction = DMA_TO_DEVICE;
+ config.direction = DMA_MEM_TO_DEV;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
config.dst_maxburst = fpga_fifo_size(priv->regs) / 2 / 4;
ret = chan->device->device_control(chan, DMA_SLAVE_CONFIG,
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
index b1f4563..701eb60 100644
--- a/drivers/misc/iwmc3200top/main.c
+++ b/drivers/misc/iwmc3200top/main.c
@@ -376,20 +376,20 @@ static int blocks;
module_param(blocks, int, 0604);
MODULE_PARM_DESC(blocks, "max_blocks_to_send");
-static int dump;
+static bool dump;
module_param(dump, bool, 0604);
MODULE_PARM_DESC(dump, "dump_hex_content");
-static int jump = 1;
+static bool jump = 1;
module_param(jump, bool, 0604);
-static int direct = 1;
+static bool direct = 1;
module_param(direct, bool, 0604);
-static int checksum = 1;
+static bool checksum = 1;
module_param(checksum, bool, 0604);
-static int fw_download = 1;
+static bool fw_download = 1;
module_param(fw_download, bool, 0604);
static int block_size = IWMC_SDIO_BLK_SIZE;
@@ -398,7 +398,7 @@ module_param(block_size, int, 0404);
static int download_trans_blks = IWMC_DEFAULT_TR_BLK;
module_param(download_trans_blks, int, 0604);
-static int rubbish_barker;
+static bool rubbish_barker;
module_param(rubbish_barker, bool, 0604);
#ifdef CONFIG_IWMC3200TOP_DEBUG
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
index 29d12a7..a981e2a 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -111,6 +111,8 @@ static struct kernel_param_ops param_ops_axis = {
.get = param_get_int,
};
+#define param_check_axis(name, p) param_check_int(name, p)
+
module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
diff --git a/drivers/misc/max8997-muic.c b/drivers/misc/max8997-muic.c
new file mode 100644
index 0000000..d74ef41
--- /dev/null
+++ b/drivers/misc/max8997-muic.c
@@ -0,0 +1,505 @@
+/*
+ * max8997-muic.c - MAX8997 muic driver for the Maxim 8997
+ *
+ * Copyright (C) 2011 Samsung Electrnoics
+ * Donggeun Kim <dg77.kim@samsung.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/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/kobject.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+/* MAX8997-MUIC STATUS1 register */
+#define STATUS1_ADC_SHIFT 0
+#define STATUS1_ADCLOW_SHIFT 5
+#define STATUS1_ADCERR_SHIFT 6
+#define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT)
+#define STATUS1_ADCLOW_MASK (0x1 << STATUS1_ADCLOW_SHIFT)
+#define STATUS1_ADCERR_MASK (0x1 << STATUS1_ADCERR_SHIFT)
+
+/* MAX8997-MUIC STATUS2 register */
+#define STATUS2_CHGTYP_SHIFT 0
+#define STATUS2_CHGDETRUN_SHIFT 3
+#define STATUS2_DCDTMR_SHIFT 4
+#define STATUS2_DBCHG_SHIFT 5
+#define STATUS2_VBVOLT_SHIFT 6
+#define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT)
+#define STATUS2_CHGDETRUN_MASK (0x1 << STATUS2_CHGDETRUN_SHIFT)
+#define STATUS2_DCDTMR_MASK (0x1 << STATUS2_DCDTMR_SHIFT)
+#define STATUS2_DBCHG_MASK (0x1 << STATUS2_DBCHG_SHIFT)
+#define STATUS2_VBVOLT_MASK (0x1 << STATUS2_VBVOLT_SHIFT)
+
+/* MAX8997-MUIC STATUS3 register */
+#define STATUS3_OVP_SHIFT 2
+#define STATUS3_OVP_MASK (0x1 << STATUS3_OVP_SHIFT)
+
+/* MAX8997-MUIC CONTROL1 register */
+#define COMN1SW_SHIFT 0
+#define COMP2SW_SHIFT 3
+#define COMN1SW_MASK (0x7 << COMN1SW_SHIFT)
+#define COMP2SW_MASK (0x7 << COMP2SW_SHIFT)
+#define SW_MASK (COMP2SW_MASK | COMN1SW_MASK)
+
+#define MAX8997_SW_USB ((1 << COMP2SW_SHIFT) | (1 << COMN1SW_SHIFT))
+#define MAX8997_SW_AUDIO ((2 << COMP2SW_SHIFT) | (2 << COMN1SW_SHIFT))
+#define MAX8997_SW_UART ((3 << COMP2SW_SHIFT) | (3 << COMN1SW_SHIFT))
+#define MAX8997_SW_OPEN ((0 << COMP2SW_SHIFT) | (0 << COMN1SW_SHIFT))
+
+#define MAX8997_ADC_GROUND 0x00
+#define MAX8997_ADC_MHL 0x01
+#define MAX8997_ADC_JIG_USB_1 0x18
+#define MAX8997_ADC_JIG_USB_2 0x19
+#define MAX8997_ADC_DESKDOCK 0x1a
+#define MAX8997_ADC_JIG_UART 0x1c
+#define MAX8997_ADC_CARDOCK 0x1d
+#define MAX8997_ADC_OPEN 0x1f
+
+struct max8997_muic_irq {
+ unsigned int irq;
+ const char *name;
+};
+
+static struct max8997_muic_irq muic_irqs[] = {
+ { MAX8997_MUICIRQ_ADCError, "muic-ADC_error" },
+ { MAX8997_MUICIRQ_ADCLow, "muic-ADC_low" },
+ { MAX8997_MUICIRQ_ADC, "muic-ADC" },
+ { MAX8997_MUICIRQ_VBVolt, "muic-VB_voltage" },
+ { MAX8997_MUICIRQ_DBChg, "muic-DB_charger" },
+ { MAX8997_MUICIRQ_DCDTmr, "muic-DCD_timer" },
+ { MAX8997_MUICIRQ_ChgDetRun, "muic-CDR_status" },
+ { MAX8997_MUICIRQ_ChgTyp, "muic-charger_type" },
+ { MAX8997_MUICIRQ_OVP, "muic-over_voltage" },
+};
+
+struct max8997_muic_info {
+ struct device *dev;
+ struct max8997_dev *iodev;
+ struct i2c_client *muic;
+ struct max8997_muic_platform_data *muic_pdata;
+
+ int irq;
+ struct work_struct irq_work;
+
+ enum max8997_muic_charger_type pre_charger_type;
+ int pre_adc;
+
+ struct mutex mutex;
+};
+
+static int max8997_muic_handle_usb(struct max8997_muic_info *info,
+ enum max8997_muic_usb_type usb_type, bool attached)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+ int ret = 0;
+
+ if (usb_type == MAX8997_USB_HOST) {
+ /* switch to USB */
+ ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
+ attached ? MAX8997_SW_USB : MAX8997_SW_OPEN,
+ SW_MASK);
+ if (ret) {
+ dev_err(info->dev, "failed to update muic register\n");
+ goto out;
+ }
+ }
+
+ if (mdata->usb_callback)
+ mdata->usb_callback(usb_type, attached);
+out:
+ return ret;
+}
+
+static void max8997_muic_handle_mhl(struct max8997_muic_info *info,
+ bool attached)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+
+ if (mdata->mhl_callback)
+ mdata->mhl_callback(attached);
+}
+
+static int max8997_muic_handle_dock(struct max8997_muic_info *info,
+ int adc, bool attached)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+ int ret = 0;
+
+ /* switch to AUDIO */
+ ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
+ attached ? MAX8997_SW_AUDIO : MAX8997_SW_OPEN,
+ SW_MASK);
+ if (ret) {
+ dev_err(info->dev, "failed to update muic register\n");
+ goto out;
+ }
+
+ switch (adc) {
+ case MAX8997_ADC_DESKDOCK:
+ if (mdata->deskdock_callback)
+ mdata->deskdock_callback(attached);
+ break;
+ case MAX8997_ADC_CARDOCK:
+ if (mdata->cardock_callback)
+ mdata->cardock_callback(attached);
+ break;
+ default:
+ break;
+ }
+out:
+ return ret;
+}
+
+static int max8997_muic_handle_jig_uart(struct max8997_muic_info *info,
+ bool attached)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+ int ret = 0;
+
+ /* switch to UART */
+ ret = max8997_update_reg(info->muic, MAX8997_MUIC_REG_CONTROL1,
+ attached ? MAX8997_SW_UART : MAX8997_SW_OPEN,
+ SW_MASK);
+ if (ret) {
+ dev_err(info->dev, "failed to update muic register\n");
+ goto out;
+ }
+
+ if (mdata->uart_callback)
+ mdata->uart_callback(attached);
+out:
+ return ret;
+}
+
+static int max8997_muic_handle_adc_detach(struct max8997_muic_info *info)
+{
+ int ret = 0;
+
+ switch (info->pre_adc) {
+ case MAX8997_ADC_GROUND:
+ ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, false);
+ break;
+ case MAX8997_ADC_MHL:
+ max8997_muic_handle_mhl(info, false);
+ break;
+ case MAX8997_ADC_JIG_USB_1:
+ case MAX8997_ADC_JIG_USB_2:
+ ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, false);
+ break;
+ case MAX8997_ADC_DESKDOCK:
+ case MAX8997_ADC_CARDOCK:
+ ret = max8997_muic_handle_dock(info, info->pre_adc, false);
+ break;
+ case MAX8997_ADC_JIG_UART:
+ ret = max8997_muic_handle_jig_uart(info, false);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int max8997_muic_handle_adc(struct max8997_muic_info *info, int adc)
+{
+ int ret = 0;
+
+ switch (adc) {
+ case MAX8997_ADC_GROUND:
+ ret = max8997_muic_handle_usb(info, MAX8997_USB_HOST, true);
+ break;
+ case MAX8997_ADC_MHL:
+ max8997_muic_handle_mhl(info, true);
+ break;
+ case MAX8997_ADC_JIG_USB_1:
+ case MAX8997_ADC_JIG_USB_2:
+ ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, true);
+ break;
+ case MAX8997_ADC_DESKDOCK:
+ case MAX8997_ADC_CARDOCK:
+ ret = max8997_muic_handle_dock(info, adc, true);
+ break;
+ case MAX8997_ADC_JIG_UART:
+ ret = max8997_muic_handle_jig_uart(info, true);
+ break;
+ case MAX8997_ADC_OPEN:
+ ret = max8997_muic_handle_adc_detach(info);
+ break;
+ default:
+ break;
+ }
+
+ info->pre_adc = adc;
+
+ return ret;
+}
+
+static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
+ enum max8997_muic_charger_type charger_type)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+ u8 adc;
+ int ret;
+
+ ret = max8997_read_reg(info->muic, MAX8997_MUIC_REG_STATUS1, &adc);
+ if (ret) {
+ dev_err(info->dev, "failed to read muic register\n");
+ goto out;
+ }
+
+ switch (charger_type) {
+ case MAX8997_CHARGER_TYPE_NONE:
+ if (mdata->charger_callback)
+ mdata->charger_callback(false, charger_type);
+ if (info->pre_charger_type == MAX8997_CHARGER_TYPE_USB) {
+ max8997_muic_handle_usb(info,
+ MAX8997_USB_DEVICE, false);
+ }
+ break;
+ case MAX8997_CHARGER_TYPE_USB:
+ if ((adc & STATUS1_ADC_MASK) == MAX8997_ADC_OPEN) {
+ max8997_muic_handle_usb(info,
+ MAX8997_USB_DEVICE, true);
+ }
+ if (mdata->charger_callback)
+ mdata->charger_callback(true, charger_type);
+ break;
+ case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
+ case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
+ case MAX8997_CHARGER_TYPE_500MA:
+ case MAX8997_CHARGER_TYPE_1A:
+ if (mdata->charger_callback)
+ mdata->charger_callback(true, charger_type);
+ break;
+ default:
+ break;
+ }
+
+ info->pre_charger_type = charger_type;
+out:
+ return ret;
+}
+
+static void max8997_muic_irq_work(struct work_struct *work)
+{
+ struct max8997_muic_info *info = container_of(work,
+ struct max8997_muic_info, irq_work);
+ struct max8997_platform_data *pdata =
+ dev_get_platdata(info->iodev->dev);
+ u8 status[3];
+ u8 adc, chg_type;
+
+ int irq_type = info->irq - pdata->irq_base;
+ int ret;
+
+ mutex_lock(&info->mutex);
+
+ ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
+ 3, status);
+ if (ret) {
+ dev_err(info->dev, "failed to read muic register\n");
+ mutex_unlock(&info->mutex);
+ return;
+ }
+
+ dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__,
+ status[0], status[1]);
+
+ switch (irq_type) {
+ case MAX8997_MUICIRQ_ADC:
+ adc = status[0] & STATUS1_ADC_MASK;
+ adc >>= STATUS1_ADC_SHIFT;
+
+ max8997_muic_handle_adc(info, adc);
+ break;
+ case MAX8997_MUICIRQ_ChgTyp:
+ chg_type = status[1] & STATUS2_CHGTYP_MASK;
+ chg_type >>= STATUS2_CHGTYP_SHIFT;
+
+ max8997_muic_handle_charger_type(info, chg_type);
+ break;
+ default:
+ dev_info(info->dev, "misc interrupt: %s occurred\n",
+ muic_irqs[irq_type].name);
+ break;
+ }
+
+ mutex_unlock(&info->mutex);
+
+ return;
+}
+
+static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
+{
+ struct max8997_muic_info *info = data;
+
+ dev_dbg(info->dev, "irq:%d\n", irq);
+ info->irq = irq;
+
+ schedule_work(&info->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void max8997_muic_detect_dev(struct max8997_muic_info *info)
+{
+ int ret;
+ u8 status[2], adc, chg_type;
+
+ ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
+ 2, status);
+ if (ret) {
+ dev_err(info->dev, "failed to read muic register\n");
+ return;
+ }
+
+ dev_info(info->dev, "STATUS1:0x%x, STATUS2:0x%x\n",
+ status[0], status[1]);
+
+ adc = status[0] & STATUS1_ADC_MASK;
+ adc >>= STATUS1_ADC_SHIFT;
+
+ chg_type = status[1] & STATUS2_CHGTYP_MASK;
+ chg_type >>= STATUS2_CHGTYP_SHIFT;
+
+ max8997_muic_handle_adc(info, adc);
+ max8997_muic_handle_charger_type(info, chg_type);
+}
+
+static void max8997_initialize_device(struct max8997_muic_info *info)
+{
+ struct max8997_muic_platform_data *mdata = info->muic_pdata;
+ int i;
+
+ for (i = 0; i < mdata->num_init_data; i++) {
+ max8997_write_reg(info->muic, mdata->init_data[i].addr,
+ mdata->init_data[i].data);
+ }
+}
+
+static int __devinit max8997_muic_probe(struct platform_device *pdev)
+{
+ struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct max8997_muic_info *info;
+ int ret, i;
+
+ info = kzalloc(sizeof(struct max8997_muic_info), GFP_KERNEL);
+ if (!info) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
+
+ if (!pdata->muic_pdata) {
+ dev_err(&pdev->dev, "failed to get platform_data\n");
+ ret = -EINVAL;
+ goto err_pdata;
+ }
+ info->muic_pdata = pdata->muic_pdata;
+
+ info->dev = &pdev->dev;
+ info->iodev = iodev;
+ info->muic = iodev->muic;
+
+ platform_set_drvdata(pdev, info);
+ mutex_init(&info->mutex);
+
+ INIT_WORK(&info->irq_work, max8997_muic_irq_work);
+
+ for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
+ struct max8997_muic_irq *muic_irq = &muic_irqs[i];
+
+ ret = request_threaded_irq(pdata->irq_base + muic_irq->irq,
+ NULL, max8997_muic_irq_handler,
+ 0, muic_irq->name,
+ info);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed: irq request (IRQ: %d,"
+ " error :%d)\n",
+ muic_irq->irq, ret);
+
+ for (i = i - 1; i >= 0; i--)
+ free_irq(muic_irq->irq, info);
+
+ goto err_irq;
+ }
+ }
+
+ /* Initialize registers according to platform data */
+ max8997_initialize_device(info);
+
+ /* Initial device detection */
+ max8997_muic_detect_dev(info);
+
+ return ret;
+
+err_irq:
+err_pdata:
+ kfree(info);
+err_kfree:
+ return ret;
+}
+
+static int __devexit max8997_muic_remove(struct platform_device *pdev)
+{
+ struct max8997_muic_info *info = platform_get_drvdata(pdev);
+ struct max8997_platform_data *pdata =
+ dev_get_platdata(info->iodev->dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
+ free_irq(pdata->irq_base + muic_irqs[i].irq, info);
+ cancel_work_sync(&info->irq_work);
+
+ kfree(info);
+
+ return 0;
+}
+
+static struct platform_driver max8997_muic_driver = {
+ .driver = {
+ .name = "max8997-muic",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8997_muic_probe,
+ .remove = __devexit_p(max8997_muic_remove),
+};
+
+static int __init max8997_muic_init(void)
+{
+ return platform_driver_register(&max8997_muic_driver);
+}
+module_init(max8997_muic_init);
+
+static void __exit max8997_muic_exit(void)
+{
+ platform_driver_unregister(&max8997_muic_driver);
+}
+module_exit(max8997_muic_exit);
+
+MODULE_DESCRIPTION("Maxim MAX8997 MUIC driver");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 12eef39..400756e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -6,5 +6,4 @@ subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG
obj-$(CONFIG_MMC) += core/
obj-$(CONFIG_MMC) += card/
-obj-$(CONFIG_MMC) += host/
-
+obj-$(subst m,y,$(CONFIG_MMC)) += host/
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 1e0e27c..0cad48a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -107,6 +107,8 @@ struct mmc_blk_data {
*/
unsigned int part_curr;
struct device_attribute force_ro;
+ struct device_attribute power_ro_lock;
+ int area_type;
};
static DEFINE_MUTEX(open_lock);
@@ -119,6 +121,7 @@ enum mmc_blk_status {
MMC_BLK_ABORT,
MMC_BLK_DATA_ERR,
MMC_BLK_ECC_ERR,
+ MMC_BLK_NOMEDIUM,
};
module_param(perdev_minors, int, 0444);
@@ -165,6 +168,70 @@ static void mmc_blk_put(struct mmc_blk_data *md)
mutex_unlock(&open_lock);
}
+static ssize_t power_ro_lock_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+ struct mmc_card *card = md->queue.card;
+ int locked = 0;
+
+ if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
+ locked = 2;
+ else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
+ locked = 1;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
+
+ return ret;
+}
+
+static ssize_t power_ro_lock_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ struct mmc_blk_data *md, *part_md;
+ struct mmc_card *card;
+ unsigned long set;
+
+ if (kstrtoul(buf, 0, &set))
+ return -EINVAL;
+
+ if (set != 1)
+ return count;
+
+ md = mmc_blk_get(dev_to_disk(dev));
+ card = md->queue.card;
+
+ mmc_claim_host(card->host);
+
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
+ card->ext_csd.boot_ro_lock |
+ EXT_CSD_BOOT_WP_B_PWR_WP_EN,
+ card->ext_csd.part_time);
+ if (ret)
+ pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
+ else
+ card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
+
+ mmc_release_host(card->host);
+
+ if (!ret) {
+ pr_info("%s: Locking boot partition ro until next power on\n",
+ md->disk->disk_name);
+ set_disk_ro(md->disk, 1);
+
+ list_for_each_entry(part_md, &md->part, part)
+ if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
+ pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
+ set_disk_ro(part_md->disk, 1);
+ }
+ }
+
+ mmc_blk_put(md);
+ return count;
+}
+
static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -266,6 +333,9 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
goto idata_err;
}
+ if (!idata->buf_bytes)
+ return idata;
+
idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
if (!idata->buf) {
err = -ENOMEM;
@@ -312,25 +382,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
if (IS_ERR(idata))
return PTR_ERR(idata);
- cmd.opcode = idata->ic.opcode;
- cmd.arg = idata->ic.arg;
- cmd.flags = idata->ic.flags;
-
- data.sg = &sg;
- data.sg_len = 1;
- data.blksz = idata->ic.blksz;
- data.blocks = idata->ic.blocks;
-
- sg_init_one(data.sg, idata->buf, idata->buf_bytes);
-
- if (idata->ic.write_flag)
- data.flags = MMC_DATA_WRITE;
- else
- data.flags = MMC_DATA_READ;
-
- mrq.cmd = &cmd;
- mrq.data = &data;
-
md = mmc_blk_get(bdev->bd_disk);
if (!md) {
err = -EINVAL;
@@ -343,6 +394,48 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_done;
}
+ cmd.opcode = idata->ic.opcode;
+ cmd.arg = idata->ic.arg;
+ cmd.flags = idata->ic.flags;
+
+ if (idata->buf_bytes) {
+ data.sg = &sg;
+ data.sg_len = 1;
+ data.blksz = idata->ic.blksz;
+ data.blocks = idata->ic.blocks;
+
+ sg_init_one(data.sg, idata->buf, idata->buf_bytes);
+
+ if (idata->ic.write_flag)
+ data.flags = MMC_DATA_WRITE;
+ else
+ data.flags = MMC_DATA_READ;
+
+ /* data.flags must already be set before doing this. */
+ mmc_set_data_timeout(&data, card);
+
+ /* Allow overriding the timeout_ns for empirical tuning. */
+ if (idata->ic.data_timeout_ns)
+ data.timeout_ns = idata->ic.data_timeout_ns;
+
+ if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+ /*
+ * Pretend this is a data transfer and rely on the
+ * host driver to compute timeout. When all host
+ * drivers support cmd.cmd_timeout for R1B, this
+ * can be changed to:
+ *
+ * mrq.data = NULL;
+ * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
+ */
+ data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
+ }
+
+ mrq.data = &data;
+ }
+
+ mrq.cmd = &cmd;
+
mmc_claim_host(card->host);
if (idata->ic.is_acmd) {
@@ -351,24 +444,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_rel_host;
}
- /* data.flags must already be set before doing this. */
- mmc_set_data_timeout(&data, card);
- /* Allow overriding the timeout_ns for empirical tuning. */
- if (idata->ic.data_timeout_ns)
- data.timeout_ns = idata->ic.data_timeout_ns;
-
- if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
- /*
- * Pretend this is a data transfer and rely on the host driver
- * to compute timeout. When all host drivers support
- * cmd.cmd_timeout for R1B, this can be changed to:
- *
- * mrq.data = NULL;
- * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
- */
- data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
- }
-
mmc_wait_for_req(card->host, &mrq);
if (cmd.error) {
@@ -565,6 +640,7 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
return err;
}
+#define ERR_NOMEDIUM 3
#define ERR_RETRY 2
#define ERR_ABORT 1
#define ERR_CONTINUE 0
@@ -632,6 +708,9 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
u32 status, stop_status = 0;
int err, retry;
+ if (mmc_card_removed(card))
+ return ERR_NOMEDIUM;
+
/*
* Try to get card status which indicates both the card state
* and why there was no response. If the first attempt fails,
@@ -648,8 +727,12 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
}
/* We couldn't get a response from the card. Give up. */
- if (err)
+ if (err) {
+ /* Check if the card is removed */
+ if (mmc_detect_card_removed(card->host))
+ return ERR_NOMEDIUM;
return ERR_ABORT;
+ }
/* Flag ECC errors */
if ((status & R1_CARD_ECC_FAILED) ||
@@ -922,6 +1005,8 @@ static int mmc_blk_err_check(struct mmc_card *card,
return MMC_BLK_RETRY;
case ERR_ABORT:
return MMC_BLK_ABORT;
+ case ERR_NOMEDIUM:
+ return MMC_BLK_NOMEDIUM;
case ERR_CONTINUE:
break;
}
@@ -1255,6 +1340,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
if (!ret)
goto start_new_req;
break;
+ case MMC_BLK_NOMEDIUM:
+ goto cmd_abort;
}
if (ret) {
@@ -1271,6 +1358,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
cmd_abort:
spin_lock_irq(&md->lock);
+ if (mmc_card_removed(card))
+ req->cmd_flags |= REQ_QUIET;
while (ret)
ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
spin_unlock_irq(&md->lock);
@@ -1339,7 +1428,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct device *parent,
sector_t size,
bool default_ro,
- const char *subname)
+ const char *subname,
+ int area_type)
{
struct mmc_blk_data *md;
int devidx, ret;
@@ -1364,11 +1454,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
if (!subname) {
md->name_idx = find_first_zero_bit(name_use, max_devices);
__set_bit(md->name_idx, name_use);
- }
- else
+ } else
md->name_idx = ((struct mmc_blk_data *)
dev_to_disk(parent)->private_data)->name_idx;
+ md->area_type = area_type;
+
/*
* Set the read-only status based on the supported commands
* and the write protect switch.
@@ -1462,7 +1553,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
size = card->csd.capacity << (card->csd.read_blkbits - 9);
}
- md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL);
+ md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
+ MMC_BLK_DATA_AREA_MAIN);
return md;
}
@@ -1471,13 +1563,14 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
unsigned int part_type,
sector_t size,
bool default_ro,
- const char *subname)
+ const char *subname,
+ int area_type)
{
char cap_str[10];
struct mmc_blk_data *part_md;
part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
- subname);
+ subname, area_type);
if (IS_ERR(part_md))
return PTR_ERR(part_md);
part_md->part_type = part_type;
@@ -1510,7 +1603,8 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
card->part[idx].part_cfg,
card->part[idx].size >> 9,
card->part[idx].force_ro,
- card->part[idx].name);
+ card->part[idx].name,
+ card->part[idx].area_type);
if (ret)
return ret;
}
@@ -1539,9 +1633,16 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
static void mmc_blk_remove_req(struct mmc_blk_data *md)
{
+ struct mmc_card *card;
+
if (md) {
+ card = md->queue.card;
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable)
+ device_remove_file(disk_to_dev(md->disk),
+ &md->power_ro_lock);
/* Stop new requests from getting into the queue */
del_gendisk(md->disk);
@@ -1570,6 +1671,7 @@ static void mmc_blk_remove_parts(struct mmc_card *card,
static int mmc_add_disk(struct mmc_blk_data *md)
{
int ret;
+ struct mmc_card *card = md->queue.card;
add_disk(md->disk);
md->force_ro.show = force_ro_show;
@@ -1579,18 +1681,53 @@ static int mmc_add_disk(struct mmc_blk_data *md)
md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
if (ret)
- del_gendisk(md->disk);
+ goto force_ro_fail;
+
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable) {
+ mode_t mode;
+
+ if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
+ mode = S_IRUGO;
+ else
+ mode = S_IRUGO | S_IWUSR;
+
+ md->power_ro_lock.show = power_ro_lock_show;
+ md->power_ro_lock.store = power_ro_lock_store;
+ md->power_ro_lock.attr.mode = mode;
+ md->power_ro_lock.attr.name =
+ "ro_lock_until_next_power_on";
+ ret = device_create_file(disk_to_dev(md->disk),
+ &md->power_ro_lock);
+ if (ret)
+ goto power_ro_lock_fail;
+ }
+ return ret;
+
+power_ro_lock_fail:
+ device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+force_ro_fail:
+ del_gendisk(md->disk);
return ret;
}
+#define CID_MANFID_SANDISK 0x2
+#define CID_MANFID_TOSHIBA 0x11
+#define CID_MANFID_MICRON 0x13
+
static const struct mmc_fixup blk_fixups[] =
{
- MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
- MMC_FIXUP("SEM04G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
- MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
- MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
- MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
+ MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
+ MMC_QUIRK_INAND_CMD38),
+ MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
+ MMC_QUIRK_INAND_CMD38),
+ MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
+ MMC_QUIRK_INAND_CMD38),
+ MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
+ MMC_QUIRK_INAND_CMD38),
+ MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
+ MMC_QUIRK_INAND_CMD38),
/*
* Some MMC cards experience performance degradation with CMD23
@@ -1600,18 +1737,18 @@ static const struct mmc_fixup blk_fixups[] =
*
* N.B. This doesn't affect SD cards.
*/
- MMC_FIXUP("MMC08G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_BLK_NO_CMD23),
- MMC_FIXUP("MMC16G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_BLK_NO_CMD23),
- MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_BLK_NO_CMD23),
/*
* Some Micron MMC cards needs longer data read timeout than
* indicated in CSD.
*/
- MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc,
+ MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
MMC_QUIRK_LONG_READ_TIME),
END_FIXUP
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index e99bdc1..759714e 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -1581,6 +1581,7 @@ static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
t->max_segs = test->card->host->max_segs;
t->max_seg_sz = test->card->host->max_seg_size;
+ t->max_seg_sz -= t->max_seg_sz % 512;
t->max_tfr = t->max_sz;
if (t->max_tfr >> 9 > test->card->host->max_blk_count)
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dcad59c..2517547 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -29,6 +29,8 @@
*/
static int mmc_prep_request(struct request_queue *q, struct request *req)
{
+ struct mmc_queue *mq = q->queuedata;
+
/*
* We only like normal block requests and discards.
*/
@@ -37,6 +39,9 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
return BLKPREP_KILL;
}
+ if (mq && mmc_card_removed(mq->card))
+ return BLKPREP_KILL;
+
req->cmd_flags |= REQ_DONTPREP;
return BLKPREP_OK;
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 6395019..dca4428 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \
mmc.o mmc_ops.o sd.o sd_ops.o \
sdio.o sdio_ops.o sdio_bus.o \
sdio_cis.o sdio_io.o sdio_irq.o \
- quirks.o
+ quirks.o cd-gpio.o
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 6be4924..5d011a3 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -303,10 +303,11 @@ int mmc_add_card(struct mmc_card *card)
mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
- printk(KERN_INFO "%s: new %s%s%s card at address %04x\n",
+ pr_info("%s: new %s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
- mmc_sd_card_uhs(card) ? "ultra high speed " :
+ mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
+ (mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "",
type, card->rca);
}
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
new file mode 100644
index 0000000..082202a
--- /dev/null
+++ b/drivers/mmc/core/cd-gpio.c
@@ -0,0 +1,74 @@
+/*
+ * Generic GPIO card-detect helper
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/mmc/host.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct mmc_cd_gpio {
+ unsigned int gpio;
+ char label[0];
+};
+
+static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
+{
+ /* Schedule a card detection after a debounce timeout */
+ mmc_detect_change(dev_id, msecs_to_jiffies(100));
+ return IRQ_HANDLED;
+}
+
+int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
+ unsigned int irq, unsigned long flags)
+{
+ size_t len = strlen(dev_name(host->parent)) + 4;
+ struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
+ int ret;
+
+ if (!cd)
+ return -ENOMEM;
+
+ snprintf(cd->label, len, "%s cd", dev_name(host->parent));
+
+ ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
+ if (ret < 0)
+ goto egpioreq;
+
+ ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
+ flags, cd->label, host);
+ if (ret < 0)
+ goto eirqreq;
+
+ cd->gpio = gpio;
+ host->hotplug.irq = irq;
+ host->hotplug.handler_priv = cd;
+
+ return 0;
+
+eirqreq:
+ gpio_free(gpio);
+egpioreq:
+ kfree(cd);
+ return ret;
+}
+EXPORT_SYMBOL(mmc_cd_gpio_request);
+
+void mmc_cd_gpio_free(struct mmc_host *host)
+{
+ struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
+
+ free_irq(host->hotplug.irq, host);
+ gpio_free(cd->gpio);
+ kfree(cd);
+}
+EXPORT_SYMBOL(mmc_cd_gpio_free);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 950b97d..f545a3e 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -48,7 +48,7 @@ static struct workqueue_struct *workqueue;
* performance cost, and for other reasons may not always be desired.
* So we allow it it to be disabled.
*/
-int use_spi_crc = 1;
+bool use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);
/*
@@ -58,9 +58,9 @@ module_param(use_spi_crc, bool, 0);
* overridden if necessary.
*/
#ifdef CONFIG_MMC_UNSAFE_RESUME
-int mmc_assume_removable;
+bool mmc_assume_removable;
#else
-int mmc_assume_removable = 1;
+bool mmc_assume_removable = 1;
#endif
EXPORT_SYMBOL(mmc_assume_removable);
module_param_named(removable, mmc_assume_removable, bool, 0644);
@@ -140,7 +140,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
cmd->retries = 0;
}
- if (err && cmd->retries) {
+ if (err && cmd->retries && !mmc_card_removed(host->card)) {
/*
* Request starter must handle retries - see
* mmc_wait_for_req_done().
@@ -247,6 +247,11 @@ static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
init_completion(&mrq->completion);
mrq->done = mmc_wait_done;
+ if (mmc_card_removed(host->card)) {
+ mrq->cmd->error = -ENOMEDIUM;
+ complete(&mrq->completion);
+ return;
+ }
mmc_start_request(host, mrq);
}
@@ -259,7 +264,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
wait_for_completion(&mrq->completion);
cmd = mrq->cmd;
- if (!cmd->error || !cmd->retries)
+ if (!cmd->error || !cmd->retries ||
+ mmc_card_removed(host->card))
break;
pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
@@ -1456,7 +1462,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
WARN_ON(host->removed);
spin_unlock_irqrestore(&host->lock, flags);
#endif
-
+ host->detect_change = 1;
mmc_schedule_delayed_work(&host->detect, delay);
}
@@ -2049,6 +2055,43 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
return -EIO;
}
+int _mmc_detect_card_removed(struct mmc_host *host)
+{
+ int ret;
+
+ if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
+ return 0;
+
+ if (!host->card || mmc_card_removed(host->card))
+ return 1;
+
+ ret = host->bus_ops->alive(host);
+ if (ret) {
+ mmc_card_set_removed(host->card);
+ pr_debug("%s: card remove detected\n", mmc_hostname(host));
+ }
+
+ return ret;
+}
+
+int mmc_detect_card_removed(struct mmc_host *host)
+{
+ struct mmc_card *card = host->card;
+
+ WARN_ON(!host->claimed);
+ /*
+ * The card will be considered unchanged unless we have been asked to
+ * detect a change or host requires polling to provide card detection.
+ */
+ if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL))
+ return mmc_card_removed(card);
+
+ host->detect_change = 0;
+
+ return _mmc_detect_card_removed(host);
+}
+EXPORT_SYMBOL(mmc_detect_card_removed);
+
void mmc_rescan(struct work_struct *work)
{
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
@@ -2069,6 +2112,8 @@ void mmc_rescan(struct work_struct *work)
&& !(host->caps & MMC_CAP_NONREMOVABLE))
host->bus_ops->detect(host);
+ host->detect_change = 0;
+
/*
* Let mmc_bus_put() free the bus/bus_ops if we've found that
* the card is no longer present.
@@ -2130,6 +2175,7 @@ void mmc_stop_host(struct mmc_host *host)
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
+ /* Calling bus_ops->remove() with a claimed host can deadlock */
if (host->bus_ops->remove)
host->bus_ops->remove(host);
@@ -2201,6 +2247,9 @@ int mmc_card_awake(struct mmc_host *host)
{
int err = -ENOSYS;
+ if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
+ return 0;
+
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
@@ -2216,6 +2265,9 @@ int mmc_card_sleep(struct mmc_host *host)
{
int err = -ENOSYS;
+ if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
+ return 0;
+
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
@@ -2270,6 +2322,7 @@ EXPORT_SYMBOL(mmc_flush_cache);
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
struct mmc_card *card = host->card;
+ unsigned int timeout;
int err = 0;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
@@ -2280,16 +2333,18 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
- if (card->ext_csd.cache_ctrl ^ enable)
+ if (card->ext_csd.cache_ctrl ^ enable) {
+ timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_CACHE_CTRL, enable, 0);
- if (err)
- pr_err("%s: cache %s error %d\n",
- mmc_hostname(card->host),
- enable ? "on" : "off",
- err);
- else
- card->ext_csd.cache_ctrl = enable;
+ EXT_CSD_CACHE_CTRL, enable, timeout);
+ if (err)
+ pr_err("%s: cache %s error %d\n",
+ mmc_hostname(card->host),
+ enable ? "on" : "off",
+ err);
+ else
+ card->ext_csd.cache_ctrl = enable;
+ }
}
return err;
@@ -2310,7 +2365,13 @@ int mmc_suspend_host(struct mmc_host *host)
cancel_delayed_work(&host->disable);
cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();
- err = mmc_cache_ctrl(host, 0);
+ if (mmc_try_claim_host(host)) {
+ err = mmc_cache_ctrl(host, 0);
+ mmc_do_release_host(host);
+ } else {
+ err = -EBUSY;
+ }
+
if (err)
goto out;
@@ -2338,7 +2399,9 @@ int mmc_suspend_host(struct mmc_host *host)
if (err == -ENOSYS || !host->bus_ops->resume) {
/*
* We simply "remove" the card in this case.
- * It will be redetected on resume.
+ * It will be redetected on resume. (Calling
+ * bus_ops->remove() with a claimed host can
+ * deadlock.)
*/
if (host->bus_ops->remove)
host->bus_ops->remove(host);
@@ -2431,11 +2494,11 @@ int mmc_pm_notify(struct notifier_block *notify_block,
if (!host->bus_ops || host->bus_ops->suspend)
break;
- mmc_claim_host(host);
-
+ /* Calling bus_ops->remove() with a claimed host can deadlock */
if (host->bus_ops->remove)
host->bus_ops->remove(host);
+ mmc_claim_host(host);
mmc_detach_bus(host);
mmc_power_off(host);
mmc_release_host(host);
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 14664f1..3bdafbc 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -24,6 +24,7 @@ struct mmc_bus_ops {
int (*resume)(struct mmc_host *);
int (*power_save)(struct mmc_host *);
int (*power_restore)(struct mmc_host *);
+ int (*alive)(struct mmc_host *);
};
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
@@ -59,12 +60,14 @@ void mmc_rescan(struct work_struct *work);
void mmc_start_host(struct mmc_host *host);
void mmc_stop_host(struct mmc_host *host);
+int _mmc_detect_card_removed(struct mmc_host *host);
+
int mmc_attach_mmc(struct mmc_host *host);
int mmc_attach_sd(struct mmc_host *host);
int mmc_attach_sdio(struct mmc_host *host);
/* Module parameters */
-extern int use_spi_crc;
+extern bool use_spi_crc;
/* Debugfs information for hosts and cards */
void mmc_add_host_debugfs(struct mmc_host *host);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 3923880..9ab5b17 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -57,6 +57,8 @@ static int mmc_ios_show(struct seq_file *s, void *data)
const char *str;
seq_printf(s, "clock:\t\t%u Hz\n", ios->clock);
+ if (host->actual_clock)
+ seq_printf(s, "actual clock:\t%u Hz\n", host->actual_clock);
seq_printf(s, "vdd:\t\t%u ", ios->vdd);
if ((1 << ios->vdd) & MMC_VDD_165_195)
seq_printf(s, "(1.65 - 1.95 V)\n");
@@ -133,6 +135,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_UHS_DDR50:
str = "sd uhs DDR50";
break;
+ case MMC_TIMING_MMC_HS200:
+ str = "mmc high-speed SDR200";
+ break;
default:
str = "invalid";
break;
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index d31c78b..30055f2 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -54,6 +54,27 @@ static DEFINE_IDR(mmc_host_idr);
static DEFINE_SPINLOCK(mmc_host_lock);
#ifdef CONFIG_MMC_CLKGATE
+static ssize_t clkgate_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay);
+}
+
+static ssize_t clkgate_delay_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ unsigned long flags, value;
+
+ if (kstrtoul(buf, 0, &value))
+ return -EINVAL;
+
+ spin_lock_irqsave(&host->clk_lock, flags);
+ host->clkgate_delay = value;
+ spin_unlock_irqrestore(&host->clk_lock, flags);
+ return count;
+}
/*
* Enabling clock gating will make the core call out to the host
@@ -114,7 +135,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
static void mmc_host_clk_gate_work(struct work_struct *work)
{
struct mmc_host *host = container_of(work, struct mmc_host,
- clk_gate_work);
+ clk_gate_work.work);
mmc_host_clk_gate_delayed(host);
}
@@ -131,6 +152,8 @@ void mmc_host_clk_hold(struct mmc_host *host)
{
unsigned long flags;
+ /* cancel any clock gating work scheduled by mmc_host_clk_release() */
+ cancel_delayed_work_sync(&host->clk_gate_work);
mutex_lock(&host->clk_gate_mutex);
spin_lock_irqsave(&host->clk_lock, flags);
if (host->clk_gated) {
@@ -180,7 +203,8 @@ void mmc_host_clk_release(struct mmc_host *host)
host->clk_requests--;
if (mmc_host_may_gate_card(host->card) &&
!host->clk_requests)
- queue_work(system_nrt_wq, &host->clk_gate_work);
+ queue_delayed_work(system_nrt_wq, &host->clk_gate_work,
+ msecs_to_jiffies(host->clkgate_delay));
spin_unlock_irqrestore(&host->clk_lock, flags);
}
@@ -213,8 +237,13 @@ static inline void mmc_host_clk_init(struct mmc_host *host)
host->clk_requests = 0;
/* Hold MCI clock for 8 cycles by default */
host->clk_delay = 8;
+ /*
+ * Default clock gating delay is 200ms.
+ * This value can be tuned by writing into sysfs entry.
+ */
+ host->clkgate_delay = 200;
host->clk_gated = false;
- INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
+ INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
spin_lock_init(&host->clk_lock);
mutex_init(&host->clk_gate_mutex);
}
@@ -229,7 +258,7 @@ static inline void mmc_host_clk_exit(struct mmc_host *host)
* Wait for any outstanding gate and then make sure we're
* ungated before exiting.
*/
- if (cancel_work_sync(&host->clk_gate_work))
+ if (cancel_delayed_work_sync(&host->clk_gate_work))
mmc_host_clk_gate_delayed(host);
if (host->clk_gated)
mmc_host_clk_hold(host);
@@ -237,6 +266,17 @@ static inline void mmc_host_clk_exit(struct mmc_host *host)
WARN_ON(host->clk_requests > 1);
}
+static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)
+{
+ host->clkgate_delay_attr.show = clkgate_delay_show;
+ host->clkgate_delay_attr.store = clkgate_delay_store;
+ sysfs_attr_init(&host->clkgate_delay_attr.attr);
+ host->clkgate_delay_attr.attr.name = "clkgate_delay";
+ host->clkgate_delay_attr.attr.mode = S_IRUGO | S_IWUSR;
+ if (device_create_file(&host->class_dev, &host->clkgate_delay_attr))
+ pr_err("%s: Failed to create clkgate_delay sysfs entry\n",
+ mmc_hostname(host));
+}
#else
static inline void mmc_host_clk_init(struct mmc_host *host)
@@ -247,6 +287,10 @@ static inline void mmc_host_clk_exit(struct mmc_host *host)
{
}
+static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)
+{
+}
+
#endif
/**
@@ -335,6 +379,7 @@ int mmc_add_host(struct mmc_host *host)
#ifdef CONFIG_DEBUG_FS
mmc_add_host_debugfs(host);
#endif
+ mmc_host_clk_sysfs_init(host);
mmc_start_host(host);
register_pm_notifier(&host->pm_notify);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index d240427..59b9ba5 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -286,6 +286,27 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
}
card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
+ case EXT_CSD_CARD_TYPE_SDR_ALL:
+ case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
+ case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
+ case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
+ card->ext_csd.hs_max_dtr = 200000000;
+ card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
+ break;
+ case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
+ case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
+ case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
+ case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
+ card->ext_csd.hs_max_dtr = 200000000;
+ card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
+ break;
+ case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
+ case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
+ case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
+ case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
+ card->ext_csd.hs_max_dtr = 200000000;
+ card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
+ break;
case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
EXT_CSD_CARD_TYPE_26:
card->ext_csd.hs_max_dtr = 52000000;
@@ -348,7 +369,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
mmc_part_add(card, part_size,
EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
- "boot%d", idx, true);
+ "boot%d", idx, true,
+ MMC_BLK_DATA_AREA_BOOT);
}
}
}
@@ -435,7 +457,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
hc_wp_grp_sz);
mmc_part_add(card, part_size << 19,
EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
- "gp%d", idx, false);
+ "gp%d", idx, false,
+ MMC_BLK_DATA_AREA_GP);
}
}
card->ext_csd.sec_trim_mult =
@@ -446,6 +469,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
card->ext_csd.trim_timeout = 300 *
ext_csd[EXT_CSD_TRIM_MULT];
+
+ /*
+ * Note that the call to mmc_part_add above defaults to read
+ * only. If this default assumption is changed, the call must
+ * take into account the value of boot_locked below.
+ */
+ card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP];
+ card->ext_csd.boot_ro_lockable = true;
}
if (card->ext_csd.rev >= 5) {
@@ -690,6 +721,79 @@ static int mmc_select_powerclass(struct mmc_card *card,
}
/*
+ * Selects the desired buswidth and switch to the HS200 mode
+ * if bus width set without error
+ */
+static int mmc_select_hs200(struct mmc_card *card)
+{
+ int idx, err = 0;
+ struct mmc_host *host;
+ static unsigned ext_csd_bits[] = {
+ EXT_CSD_BUS_WIDTH_4,
+ EXT_CSD_BUS_WIDTH_8,
+ };
+ static unsigned bus_widths[] = {
+ MMC_BUS_WIDTH_4,
+ MMC_BUS_WIDTH_8,
+ };
+
+ BUG_ON(!card);
+
+ host = card->host;
+
+ if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
+ host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+ if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0))
+ err = mmc_set_signal_voltage(host,
+ MMC_SIGNAL_VOLTAGE_180, 0);
+
+ /* If fails try again during next card power cycle */
+ if (err)
+ goto err;
+
+ idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
+
+ /*
+ * Unlike SD, MMC cards dont have a configuration register to notify
+ * supported bus width. So bus test command should be run to identify
+ * the supported bus width or compare the ext csd values of current
+ * bus width and ext csd values of 1 bit mode read earlier.
+ */
+ for (; idx >= 0; idx--) {
+
+ /*
+ * Host is capable of 8bit transfer, then switch
+ * the device to work in 8bit transfer mode. If the
+ * mmc switch command returns error then switch to
+ * 4bit transfer mode. On success set the corresponding
+ * bus width on the host.
+ */
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ ext_csd_bits[idx],
+ card->ext_csd.generic_cmd6_time);
+ if (err)
+ continue;
+
+ mmc_set_bus_width(card->host, bus_widths[idx]);
+
+ if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
+ err = mmc_compare_ext_csds(card, bus_widths[idx]);
+ else
+ err = mmc_bus_test(card, bus_widths[idx]);
+ if (!err)
+ break;
+ }
+
+ /* switch to HS200 mode if bus width set successfully */
+ if (!err)
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 2, 0);
+err:
+ return err;
+}
+
+/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
@@ -895,11 +999,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
/*
* Activate high speed (if supported)
*/
- if ((card->ext_csd.hs_max_dtr != 0) &&
- (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1,
- card->ext_csd.generic_cmd6_time);
+ if (card->ext_csd.hs_max_dtr != 0) {
+ err = 0;
+ if (card->ext_csd.hs_max_dtr > 52000000 &&
+ host->caps2 & MMC_CAP2_HS200)
+ err = mmc_select_hs200(card);
+ else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 1, 0);
+
if (err && err != -EBADMSG)
goto free_card;
@@ -908,8 +1016,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
mmc_hostname(card->host));
err = 0;
} else {
- mmc_card_set_highspeed(card);
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ if (card->ext_csd.hs_max_dtr > 52000000 &&
+ host->caps2 & MMC_CAP2_HS200) {
+ mmc_card_set_hs200(card);
+ mmc_set_timing(card->host,
+ MMC_TIMING_MMC_HS200);
+ } else {
+ mmc_card_set_highspeed(card);
+ mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+ }
}
}
@@ -934,7 +1049,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
*/
max_dtr = (unsigned int)-1;
- if (mmc_card_highspeed(card)) {
+ if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
if (max_dtr > card->ext_csd.hs_max_dtr)
max_dtr = card->ext_csd.hs_max_dtr;
} else if (max_dtr > card->csd.max_dtr) {
@@ -960,9 +1075,48 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * Indicate HS200 SDR mode (if supported).
+ */
+ if (mmc_card_hs200(card)) {
+ u32 ext_csd_bits;
+ u32 bus_width = card->host->ios.bus_width;
+
+ /*
+ * For devices supporting HS200 mode, the bus width has
+ * to be set before executing the tuning function. If
+ * set before tuning, then device will respond with CRC
+ * errors for responses on CMD line. So for HS200 the
+ * sequence will be
+ * 1. set bus width 4bit / 8 bit (1 bit not supported)
+ * 2. switch to HS200 mode
+ * 3. set the clock to > 52Mhz <=200MHz and
+ * 4. execute tuning for HS200
+ */
+ if ((host->caps2 & MMC_CAP2_HS200) &&
+ card->host->ops->execute_tuning)
+ err = card->host->ops->execute_tuning(card->host,
+ MMC_SEND_TUNING_BLOCK_HS200);
+ if (err) {
+ pr_warning("%s: tuning execution failed\n",
+ mmc_hostname(card->host));
+ goto err;
+ }
+
+ ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+ EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
+ err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
+ if (err) {
+ pr_err("%s: power class selection to bus width %d failed\n",
+ mmc_hostname(card->host), 1 << bus_width);
+ goto err;
+ }
+ }
+
+ /*
* Activate wide bus and DDR (if supported).
*/
- if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
+ if (!mmc_card_hs200(card) &&
+ (card->csd.mmca_vsn >= CSD_SPEC_VER_3) &&
(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
static unsigned ext_csd_bits[][2] = {
{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
@@ -1048,7 +1202,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
*
* WARNING: eMMC rules are NOT the same as SD DDR
*/
- if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
+ if (ddr == MMC_1_2V_DDR_MODE) {
err = mmc_set_signal_voltage(host,
MMC_SIGNAL_VOLTAGE_120, 0);
if (err)
@@ -1067,14 +1221,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
card->ext_csd.cache_size > 0) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_CACHE_CTRL, 1, 0);
+ EXT_CSD_CACHE_CTRL, 1,
+ card->ext_csd.generic_cmd6_time);
if (err && err != -EBADMSG)
goto free_card;
/*
* Only if no error, cache is turned on successfully.
*/
- card->ext_csd.cache_ctrl = err ? 0 : 1;
+ if (err) {
+ pr_warning("%s: Cache is supported, "
+ "but failed to turn on (%d)\n",
+ mmc_hostname(card->host), err);
+ card->ext_csd.cache_ctrl = 0;
+ err = 0;
+ } else {
+ card->ext_csd.cache_ctrl = 1;
+ }
}
if (!oldcard)
@@ -1105,6 +1268,14 @@ static void mmc_remove(struct mmc_host *host)
}
/*
+ * Card detection - card is alive.
+ */
+static int mmc_alive(struct mmc_host *host)
+{
+ return mmc_send_status(host->card, NULL);
+}
+
+/*
* Card detection callback from host.
*/
static void mmc_detect(struct mmc_host *host)
@@ -1119,7 +1290,7 @@ static void mmc_detect(struct mmc_host *host)
/*
* Just check if our card has been removed.
*/
- err = mmc_send_status(host->card, NULL);
+ err = _mmc_detect_card_removed(host);
mmc_release_host(host);
@@ -1224,6 +1395,7 @@ static const struct mmc_bus_ops mmc_ops = {
.suspend = NULL,
.resume = NULL,
.power_restore = mmc_power_restore,
+ .alive = mmc_alive,
};
static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -1234,6 +1406,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
.suspend = mmc_suspend,
.resume = mmc_resume,
.power_restore = mmc_power_restore,
+ .alive = mmc_alive,
};
static void mmc_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index f2a05ea..c63ad03 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -307,8 +307,8 @@ static int mmc_read_switch(struct mmc_card *card)
goto out;
}
- if (status[13] & UHS_SDR50_BUS_SPEED)
- card->sw_caps.hs_max_dtr = 50000000;
+ if (status[13] & SD_MODE_HIGH_SPEED)
+ card->sw_caps.hs_max_dtr = HIGH_SPEED_MAX_DTR;
if (card->scr.sda_spec3) {
card->sw_caps.sd3_bus_mode = status[13];
@@ -661,7 +661,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
/* SPI mode doesn't define CMD19 */
if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
- err = card->host->ops->execute_tuning(card->host);
+ err = card->host->ops->execute_tuning(card->host,
+ MMC_SEND_TUNING_BLOCK);
out:
kfree(status);
@@ -960,7 +961,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
goto free_card;
/* Card is an ultra-high-speed card */
- mmc_sd_card_set_uhs(card);
+ mmc_card_set_uhs(card);
/*
* Since initialization is now complete, enable preset
@@ -1019,6 +1020,14 @@ static void mmc_sd_remove(struct mmc_host *host)
}
/*
+ * Card detection - card is alive.
+ */
+static int mmc_sd_alive(struct mmc_host *host)
+{
+ return mmc_send_status(host->card, NULL);
+}
+
+/*
* Card detection callback from host.
*/
static void mmc_sd_detect(struct mmc_host *host)
@@ -1033,7 +1042,7 @@ static void mmc_sd_detect(struct mmc_host *host)
/*
* Just check if our card has been removed.
*/
- err = mmc_send_status(host->card, NULL);
+ err = _mmc_detect_card_removed(host);
mmc_release_host(host);
@@ -1102,6 +1111,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
.suspend = NULL,
.resume = NULL,
.power_restore = mmc_sd_power_restore,
+ .alive = mmc_sd_alive,
};
static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
@@ -1110,6 +1120,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
.suspend = mmc_sd_suspend,
.resume = mmc_sd_resume,
.power_restore = mmc_sd_power_restore,
+ .alive = mmc_sd_alive,
};
static void mmc_sd_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 3ab565e..bd7bacc 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -14,6 +14,7 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
@@ -102,6 +103,7 @@ static int sdio_read_cccr(struct mmc_card *card)
int ret;
int cccr_vsn;
unsigned char data;
+ unsigned char speed;
memset(&card->cccr, 0, sizeof(struct sdio_cccr));
@@ -140,12 +142,60 @@ static int sdio_read_cccr(struct mmc_card *card)
}
if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
- ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data);
+ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
if (ret)
goto out;
- if (data & SDIO_SPEED_SHS)
- card->cccr.high_speed = 1;
+ card->scr.sda_spec3 = 0;
+ card->sw_caps.sd3_bus_mode = 0;
+ card->sw_caps.sd3_drv_type = 0;
+ if (cccr_vsn >= SDIO_CCCR_REV_3_00) {
+ card->scr.sda_spec3 = 1;
+ ret = mmc_io_rw_direct(card, 0, 0,
+ SDIO_CCCR_UHS, 0, &data);
+ if (ret)
+ goto out;
+
+ if (card->host->caps &
+ (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_DDR50)) {
+ if (data & SDIO_UHS_DDR50)
+ card->sw_caps.sd3_bus_mode
+ |= SD_MODE_UHS_DDR50;
+
+ if (data & SDIO_UHS_SDR50)
+ card->sw_caps.sd3_bus_mode
+ |= SD_MODE_UHS_SDR50;
+
+ if (data & SDIO_UHS_SDR104)
+ card->sw_caps.sd3_bus_mode
+ |= SD_MODE_UHS_SDR104;
+ }
+
+ ret = mmc_io_rw_direct(card, 0, 0,
+ SDIO_CCCR_DRIVE_STRENGTH, 0, &data);
+ if (ret)
+ goto out;
+
+ if (data & SDIO_DRIVE_SDTA)
+ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_A;
+ if (data & SDIO_DRIVE_SDTC)
+ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C;
+ if (data & SDIO_DRIVE_SDTD)
+ card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D;
+ }
+
+ /* if no uhs mode ensure we check for high speed */
+ if (!card->sw_caps.sd3_bus_mode) {
+ if (speed & SDIO_SPEED_SHS) {
+ card->cccr.high_speed = 1;
+ card->sw_caps.hs_max_dtr = 50000000;
+ } else {
+ card->cccr.high_speed = 0;
+ card->sw_caps.hs_max_dtr = 25000000;
+ }
+ }
}
out:
@@ -327,6 +377,194 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
return max_dtr;
}
+static unsigned char host_drive_to_sdio_drive(int host_strength)
+{
+ switch (host_strength) {
+ case MMC_SET_DRIVER_TYPE_A:
+ return SDIO_DTSx_SET_TYPE_A;
+ case MMC_SET_DRIVER_TYPE_B:
+ return SDIO_DTSx_SET_TYPE_B;
+ case MMC_SET_DRIVER_TYPE_C:
+ return SDIO_DTSx_SET_TYPE_C;
+ case MMC_SET_DRIVER_TYPE_D:
+ return SDIO_DTSx_SET_TYPE_D;
+ default:
+ return SDIO_DTSx_SET_TYPE_B;
+ }
+}
+
+static void sdio_select_driver_type(struct mmc_card *card)
+{
+ int host_drv_type = SD_DRIVER_TYPE_B;
+ int card_drv_type = SD_DRIVER_TYPE_B;
+ int drive_strength;
+ unsigned char card_strength;
+ int err;
+
+ /*
+ * If the host doesn't support any of the Driver Types A,C or D,
+ * or there is no board specific handler then default Driver
+ * Type B is used.
+ */
+ if (!(card->host->caps &
+ (MMC_CAP_DRIVER_TYPE_A |
+ MMC_CAP_DRIVER_TYPE_C |
+ MMC_CAP_DRIVER_TYPE_D)))
+ return;
+
+ if (!card->host->ops->select_drive_strength)
+ return;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
+ host_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
+ host_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
+ host_drv_type |= SD_DRIVER_TYPE_D;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
+ card_drv_type |= SD_DRIVER_TYPE_A;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
+ card_drv_type |= SD_DRIVER_TYPE_C;
+
+ if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
+ card_drv_type |= SD_DRIVER_TYPE_D;
+
+ /*
+ * The drive strength that the hardware can support
+ * depends on the board design. Pass the appropriate
+ * information and let the hardware specific code
+ * return what is possible given the options
+ */
+ drive_strength = card->host->ops->select_drive_strength(
+ card->sw_caps.uhs_max_dtr,
+ host_drv_type, card_drv_type);
+
+ /* if error just use default for drive strength B */
+ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_DRIVE_STRENGTH, 0,
+ &card_strength);
+ if (err)
+ return;
+
+ card_strength &= ~(SDIO_DRIVE_DTSx_MASK<<SDIO_DRIVE_DTSx_SHIFT);
+ card_strength |= host_drive_to_sdio_drive(drive_strength);
+
+ err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_DRIVE_STRENGTH,
+ card_strength, NULL);
+
+ /* if error default to drive strength B */
+ if (!err)
+ mmc_set_driver_type(card->host, drive_strength);
+}
+
+
+static int sdio_set_bus_speed_mode(struct mmc_card *card)
+{
+ unsigned int bus_speed, timing;
+ int err;
+ unsigned char speed;
+
+ /*
+ * If the host doesn't support any of the UHS-I modes, fallback on
+ * default speed.
+ */
+ if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50)))
+ return 0;
+
+ bus_speed = SDIO_SPEED_SDR12;
+ timing = MMC_TIMING_UHS_SDR12;
+ if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
+ bus_speed = SDIO_SPEED_SDR104;
+ timing = MMC_TIMING_UHS_SDR104;
+ card->sw_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR;
+ } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
+ bus_speed = SDIO_SPEED_DDR50;
+ timing = MMC_TIMING_UHS_DDR50;
+ card->sw_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
+ SD_MODE_UHS_SDR50)) {
+ bus_speed = SDIO_SPEED_SDR50;
+ timing = MMC_TIMING_UHS_SDR50;
+ card->sw_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
+ bus_speed = SDIO_SPEED_SDR25;
+ timing = MMC_TIMING_UHS_SDR25;
+ card->sw_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR;
+ } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
+ SD_MODE_UHS_SDR12)) {
+ bus_speed = SDIO_SPEED_SDR12;
+ timing = MMC_TIMING_UHS_SDR12;
+ card->sw_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR;
+ }
+
+ err = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
+ if (err)
+ return err;
+
+ speed &= ~SDIO_SPEED_BSS_MASK;
+ speed |= bus_speed;
+ err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
+ if (err)
+ return err;
+
+ if (bus_speed) {
+ mmc_set_timing(card->host, timing);
+ mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr);
+ }
+
+ return 0;
+}
+
+/*
+ * UHS-I specific initialization procedure
+ */
+static int mmc_sdio_init_uhs_card(struct mmc_card *card)
+{
+ int err;
+
+ if (!card->scr.sda_spec3)
+ return 0;
+
+ /*
+ * Switch to wider bus (if supported).
+ */
+ if (card->host->caps & MMC_CAP_4_BIT_DATA) {
+ err = sdio_enable_4bit_bus(card);
+ if (err > 0) {
+ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+ err = 0;
+ }
+ }
+
+ /* Set the driver strength for the card */
+ sdio_select_driver_type(card);
+
+ /* Set bus speed mode of the card */
+ err = sdio_set_bus_speed_mode(card);
+ if (err)
+ goto out;
+
+ /* Initialize and start re-tuning timer */
+ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
+ err = card->host->ops->execute_tuning(card->host,
+ MMC_SEND_TUNING_BLOCK);
+
+out:
+
+ return err;
+}
+
/*
* Handle the detection and initialisation of a card.
*
@@ -394,6 +632,30 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
host->ops->init_card(host, card);
/*
+ * If the host and card support UHS-I mode request the card
+ * to switch to 1.8V signaling level. No 1.8v signalling if
+ * UHS mode is not enabled to maintain compatibilty and some
+ * systems that claim 1.8v signalling in fact do not support
+ * it.
+ */
+ if ((ocr & R4_18V_PRESENT) &&
+ (host->caps &
+ (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
+ MMC_CAP_UHS_DDR50))) {
+ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
+ true);
+ if (err) {
+ ocr &= ~R4_18V_PRESENT;
+ host->ocr &= ~R4_18V_PRESENT;
+ }
+ err = 0;
+ } else {
+ ocr &= ~R4_18V_PRESENT;
+ host->ocr &= ~R4_18V_PRESENT;
+ }
+
+ /*
* For native busses: set card RCA and quit open drain mode.
*/
if (!powered_resume && !mmc_host_is_spi(host)) {
@@ -492,29 +754,39 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
if (err)
goto remove;
- /*
- * Switch to high-speed (if supported).
- */
- err = sdio_enable_hs(card);
- if (err > 0)
- mmc_sd_go_highspeed(card);
- else if (err)
- goto remove;
+ /* Initialization sequence for UHS-I cards */
+ /* Only if card supports 1.8v and UHS signaling */
+ if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) {
+ err = mmc_sdio_init_uhs_card(card);
+ if (err)
+ goto remove;
- /*
- * Change to the card's maximum speed.
- */
- mmc_set_clock(host, mmc_sdio_get_max_clock(card));
+ /* Card is an ultra-high-speed card */
+ mmc_card_set_uhs(card);
+ } else {
+ /*
+ * Switch to high-speed (if supported).
+ */
+ err = sdio_enable_hs(card);
+ if (err > 0)
+ mmc_sd_go_highspeed(card);
+ else if (err)
+ goto remove;
- /*
- * Switch to wider bus (if supported).
- */
- err = sdio_enable_4bit_bus(card);
- if (err > 0)
- mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
- else if (err)
- goto remove;
+ /*
+ * Change to the card's maximum speed.
+ */
+ mmc_set_clock(host, mmc_sdio_get_max_clock(card));
+ /*
+ * Switch to wider bus (if supported).
+ */
+ err = sdio_enable_4bit_bus(card);
+ if (err > 0)
+ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+ else if (err)
+ goto remove;
+ }
finish:
if (!oldcard)
host->card = card;
@@ -550,6 +822,14 @@ static void mmc_sdio_remove(struct mmc_host *host)
}
/*
+ * Card detection - card is alive.
+ */
+static int mmc_sdio_alive(struct mmc_host *host)
+{
+ return mmc_select_card(host->card);
+}
+
+/*
* Card detection callback from host.
*/
static void mmc_sdio_detect(struct mmc_host *host)
@@ -571,7 +851,7 @@ static void mmc_sdio_detect(struct mmc_host *host)
/*
* Just check if our card has been removed.
*/
- err = mmc_select_card(host->card);
+ err = _mmc_detect_card_removed(host);
mmc_release_host(host);
@@ -749,6 +1029,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = {
.suspend = mmc_sdio_suspend,
.resume = mmc_sdio_resume,
.power_restore = mmc_sdio_power_restore,
+ .alive = mmc_sdio_alive,
};
@@ -797,8 +1078,17 @@ int mmc_attach_sdio(struct mmc_host *host)
* Detect and init the card.
*/
err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
- if (err)
- goto err;
+ if (err) {
+ if (err == -EAGAIN) {
+ /*
+ * Retry initialization with S18R set to 0.
+ */
+ host->ocr &= ~R4_18V_PRESENT;
+ err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
+ }
+ if (err)
+ goto err;
+ }
card = host->card;
/*
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index b1f3168..8f6f5ac 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -196,6 +196,9 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
else
mval = min(mval, func->max_blksize);
+ if (mmc_card_broken_byte_mode_512(func->card))
+ return min(mval, 511u);
+
return min(mval, 512u); /* maximum size for byte mode */
}
@@ -314,7 +317,7 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
func->card->host->max_seg_size / func->cur_blksize);
max_blocks = min(max_blocks, 511u);
- while (remainder > func->cur_blksize) {
+ while (remainder >= func->cur_blksize) {
unsigned blocks;
blocks = remainder / func->cur_blksize;
@@ -339,8 +342,9 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
while (remainder > 0) {
size = min(remainder, sdio_max_byte_size(func));
+ /* Indicate byte mode by setting "blocks" = 0 */
ret = mmc_io_rw_extended(func->card, write, func->num, addr,
- incr_addr, buf, 1, size);
+ incr_addr, buf, 0, size);
if (ret)
return ret;
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index b0517cc..d29e206 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -128,8 +128,6 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
BUG_ON(!card);
BUG_ON(fn > 7);
- BUG_ON(blocks == 1 && blksz > 512);
- WARN_ON(blocks == 0);
WARN_ON(blksz == 0);
/* sanity check */
@@ -144,22 +142,20 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
cmd.arg |= fn << 28;
cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
cmd.arg |= addr << 9;
- if (blocks == 1 && blksz < 512)
- cmd.arg |= blksz; /* byte mode */
- else if (blocks == 1 && blksz == 512 &&
- !(mmc_card_broken_byte_mode_512(card)))
- cmd.arg |= 0; /* byte mode, 0==512 */
+ if (blocks == 0)
+ cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
else
cmd.arg |= 0x08000000 | blocks; /* block mode */
cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
data.blksz = blksz;
- data.blocks = blocks;
+ /* Code in host drivers/fwk assumes that "blocks" always is >=1 */
+ data.blocks = blocks ? blocks : 1;
data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
data.sg = &sg;
data.sg_len = 1;
- sg_init_one(&sg, buf, blksz * blocks);
+ sg_init_one(&sg, buf, data.blksz * data.blocks);
mmc_set_data_timeout(&data, card);
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index b4b83f3..745f8fc 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
+obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o
obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index f437c3e..947faa5 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -236,7 +236,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
sg = &data->sg[i];
- sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
amount = min(size, sg->length);
size -= amount;
@@ -252,7 +252,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
dmabuf = (unsigned *)tmpv;
}
- kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+ kunmap_atomic(sgbuffer);
if (size == 0)
break;
@@ -302,7 +302,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
sg = &data->sg[i];
- sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
amount = min(size, sg->length);
size -= amount;
@@ -318,7 +318,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
}
flush_kernel_dcache_page(sg_page(sg));
- kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+ kunmap_atomic(sgbuffer);
data->bytes_xfered += amount;
if (size == 0)
break;
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index a7ee502..fcfe1eb 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -823,6 +823,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
struct scatterlist *sg;
unsigned int i;
enum dma_data_direction direction;
+ enum dma_transfer_direction slave_dirn;
unsigned int sglen;
u32 iflags;
@@ -860,16 +861,19 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
if (host->caps.has_dma)
atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
- if (data->flags & MMC_DATA_READ)
+ if (data->flags & MMC_DATA_READ) {
direction = DMA_FROM_DEVICE;
- else
+ slave_dirn = DMA_DEV_TO_MEM;
+ } else {
direction = DMA_TO_DEVICE;
+ slave_dirn = DMA_MEM_TO_DEV;
+ }
sglen = dma_map_sg(chan->device->dev, data->sg,
data->sg_len, direction);
desc = chan->device->device_prep_slave_sg(chan,
- data->sg, sglen, direction,
+ data->sg, sglen, slave_dirn,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
goto unmap_exit;
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 5d3b9ae..dbd0c8a 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -153,6 +153,7 @@ static inline int has_dbdma(void)
{
switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1200:
+ case ALCHEMY_CPU_AU1300:
return 1;
default:
return 0;
@@ -768,11 +769,15 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
config2 = au_readl(HOST_CONFIG2(host));
switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ config2 |= SD_CONFIG2_BB;
+ break;
case MMC_BUS_WIDTH_4:
+ config2 &= ~SD_CONFIG2_BB;
config2 |= SD_CONFIG2_WB;
break;
case MMC_BUS_WIDTH_1:
- config2 &= ~SD_CONFIG2_WB;
+ config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
break;
}
au_writel(config2, HOST_CONFIG2(host));
@@ -943,7 +948,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
struct mmc_host *mmc;
struct au1xmmc_host *host;
struct resource *r;
- int ret;
+ int ret, iflag;
mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
if (!mmc) {
@@ -982,37 +987,43 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no IRQ defined\n");
goto out3;
}
-
host->irq = r->start;
- /* IRQ is shared among both SD controllers */
- ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
- DRIVER_NAME, host);
- if (ret) {
- dev_err(&pdev->dev, "cannot grab IRQ\n");
- goto out3;
- }
mmc->ops = &au1xmmc_ops;
mmc->f_min = 450000;
mmc->f_max = 24000000;
+ mmc->max_blk_size = 2048;
+ mmc->max_blk_count = 512;
+
+ mmc->ocr_avail = AU1XMMC_OCR;
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+ mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
+
+ iflag = IRQF_SHARED; /* Au1100/Au1200: one int for both ctrls */
+
switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1100:
mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE;
- mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
break;
case ALCHEMY_CPU_AU1200:
mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
- mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
+ break;
+ case ALCHEMY_CPU_AU1300:
+ iflag = 0; /* nothing is shared */
+ mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
+ mmc->f_max = 52000000;
+ if (host->ioarea->start == AU1100_SD0_PHYS_ADDR)
+ mmc->caps |= MMC_CAP_8_BIT_DATA;
break;
}
- mmc->max_blk_size = 2048;
- mmc->max_blk_count = 512;
-
- mmc->ocr_avail = AU1XMMC_OCR;
- mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+ ret = request_irq(host->irq, au1xmmc_irq, iflag, DRIVER_NAME, host);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot grab IRQ\n");
+ goto out3;
+ }
host->status = HOST_S_IDLE;
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index 0371bf5..0366617 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -627,17 +627,7 @@ static struct platform_driver sdh_driver = {
},
};
-static int __init sdh_init(void)
-{
- return platform_driver_register(&sdh_driver);
-}
-module_init(sdh_init);
-
-static void __exit sdh_exit(void)
-{
- platform_driver_unregister(&sdh_driver);
-}
-module_exit(sdh_exit);
+module_platform_driver(sdh_driver);
MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver");
MODULE_AUTHOR("Cliff Cai, Roy Huang");
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index ce2a47b..83693fd 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -780,18 +780,7 @@ static struct platform_driver cb710_mmc_driver = {
#endif
};
-static int __init cb710_mmc_init_module(void)
-{
- return platform_driver_register(&cb710_mmc_driver);
-}
-
-static void __exit cb710_mmc_cleanup_module(void)
-{
- platform_driver_unregister(&cb710_mmc_driver);
-}
-
-module_init(cb710_mmc_init_module);
-module_exit(cb710_mmc_cleanup_module);
+module_platform_driver(cb710_mmc_driver);
MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
MODULE_DESCRIPTION("ENE CB710 memory card reader driver - MMC/SD part");
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 3aaeb08..0e34279 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -588,11 +588,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
mci_writel(host, CTYPE, (slot->ctype << slot->id));
}
-static void dw_mci_start_request(struct dw_mci *host,
- struct dw_mci_slot *slot)
+static void __dw_mci_start_request(struct dw_mci *host,
+ struct dw_mci_slot *slot,
+ struct mmc_command *cmd)
{
struct mmc_request *mrq;
- struct mmc_command *cmd;
struct mmc_data *data;
u32 cmdflags;
@@ -610,14 +610,13 @@ static void dw_mci_start_request(struct dw_mci *host,
host->completed_events = 0;
host->data_status = 0;
- data = mrq->data;
+ data = cmd->data;
if (data) {
dw_mci_set_timeout(host);
mci_writel(host, BYTCNT, data->blksz*data->blocks);
mci_writel(host, BLKSIZ, data->blksz);
}
- cmd = mrq->cmd;
cmdflags = dw_mci_prepare_command(slot->mmc, cmd);
/* this is the first command, send the initialization clock */
@@ -635,6 +634,16 @@ static void dw_mci_start_request(struct dw_mci *host,
host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
}
+static void dw_mci_start_request(struct dw_mci *host,
+ struct dw_mci_slot *slot)
+{
+ struct mmc_request *mrq = slot->mrq;
+ struct mmc_command *cmd;
+
+ cmd = mrq->sbc ? mrq->sbc : mrq->cmd;
+ __dw_mci_start_request(host, slot, cmd);
+}
+
/* must be called with host->lock held */
static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot,
struct mmc_request *mrq)
@@ -698,12 +707,15 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
}
+ regs = mci_readl(slot->host, UHS_REG);
+
/* DDR mode set */
- if (ios->timing == MMC_TIMING_UHS_DDR50) {
- regs = mci_readl(slot->host, UHS_REG);
+ if (ios->timing == MMC_TIMING_UHS_DDR50)
regs |= (0x1 << slot->id) << 16;
- mci_writel(slot->host, UHS_REG, regs);
- }
+ else
+ regs &= ~(0x1 << slot->id) << 16;
+
+ mci_writel(slot->host, UHS_REG, regs);
if (ios->clock) {
/*
@@ -889,7 +901,14 @@ static void dw_mci_tasklet_func(unsigned long priv)
cmd = host->cmd;
host->cmd = NULL;
set_bit(EVENT_CMD_COMPLETE, &host->completed_events);
- dw_mci_command_complete(host, host->mrq->cmd);
+ dw_mci_command_complete(host, cmd);
+ if (cmd == host->mrq->sbc && !cmd->error) {
+ prev_state = state = STATE_SENDING_CMD;
+ __dw_mci_start_request(host, host->cur_slot,
+ host->mrq->cmd);
+ goto unlock;
+ }
+
if (!host->mrq->data || cmd->error) {
dw_mci_request_end(host, host->mrq);
goto unlock;
@@ -967,6 +986,12 @@ static void dw_mci_tasklet_func(unsigned long priv)
goto unlock;
}
+ if (host->mrq->sbc && !data->error) {
+ data->stop->error = 0;
+ dw_mci_request_end(host, host->mrq);
+ goto unlock;
+ }
+
prev_state = state = STATE_SENDING_STOP;
if (!data->error)
send_stop_cmd(host, data);
@@ -1678,8 +1703,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
if (host->pdata->caps)
mmc->caps = host->pdata->caps;
- else
- mmc->caps = 0;
+
+ if (host->pdata->caps2)
+ mmc->caps2 = host->pdata->caps2;
if (host->pdata->get_bus_wd)
if (host->pdata->get_bus_wd(slot->id) >= 4)
@@ -1923,7 +1949,7 @@ static int dw_mci_probe(struct platform_device *pdev)
* should put it in the platform data.
*/
fifo_size = mci_readl(host, FIFOTH);
- fifo_size = 1 + ((fifo_size >> 16) & 0x7ff);
+ fifo_size = 1 + ((fifo_size >> 16) & 0xfff);
} else {
fifo_size = host->pdata->fifo_depth;
}
@@ -2062,14 +2088,14 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
/*
* TODO: we should probably disable the clock to the card in the suspend path.
*/
-static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
+static int dw_mci_suspend(struct device *dev)
{
int i, ret;
- struct dw_mci *host = platform_get_drvdata(pdev);
+ struct dw_mci *host = dev_get_drvdata(dev);
for (i = 0; i < host->num_slots; i++) {
struct dw_mci_slot *slot = host->slot[i];
@@ -2092,10 +2118,10 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
return 0;
}
-static int dw_mci_resume(struct platform_device *pdev)
+static int dw_mci_resume(struct device *dev)
{
int i, ret;
- struct dw_mci *host = platform_get_drvdata(pdev);
+ struct dw_mci *host = dev_get_drvdata(dev);
if (host->vmmc)
regulator_enable(host->vmmc);
@@ -2103,7 +2129,7 @@ static int dw_mci_resume(struct platform_device *pdev)
if (host->dma_ops->init)
host->dma_ops->init(host);
- if (!mci_wait_reset(&pdev->dev, host)) {
+ if (!mci_wait_reset(dev, host)) {
ret = -ENODEV;
return ret;
}
@@ -2131,14 +2157,15 @@ static int dw_mci_resume(struct platform_device *pdev)
#else
#define dw_mci_suspend NULL
#define dw_mci_resume NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(dw_mci_pmops, dw_mci_suspend, dw_mci_resume);
static struct platform_driver dw_mci_driver = {
.remove = __exit_p(dw_mci_remove),
- .suspend = dw_mci_suspend,
- .resume = dw_mci_resume,
.driver = {
.name = "dw_mmc",
+ .pm = &dw_mci_pmops,
},
};
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 72c071f..df392a1 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -126,7 +126,7 @@
#define SDMMC_CMD_RESP_EXP BIT(6)
#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
/* Status register defines */
-#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF)
+#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF)
/* Internal DMAC interrupt defines */
#define SDMMC_IDMAC_INT_AI BIT(9)
#define SDMMC_IDMAC_INT_NI BIT(8)
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 74218ad..c8852a8 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -1012,17 +1012,7 @@ static struct platform_driver jz4740_mmc_driver = {
},
};
-static int __init jz4740_mmc_init(void)
-{
- return platform_driver_register(&jz4740_mmc_driver);
-}
-module_init(jz4740_mmc_init);
-
-static void __exit jz4740_mmc_exit(void)
-{
- platform_driver_unregister(&jz4740_mmc_driver);
-}
-module_exit(jz4740_mmc_exit);
+module_platform_driver(jz4740_mmc_driver);
MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 92946b8..273306c 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1525,7 +1525,6 @@ static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
static struct spi_driver mmc_spi_driver = {
.driver = {
.name = "mmc_spi",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
.of_match_table = mmc_spi_of_match_table,
},
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index fa8dd2f..0d955ff 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -374,6 +374,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
struct dma_chan *chan;
struct dma_device *device;
struct dma_async_tx_descriptor *desc;
+ enum dma_data_direction buffer_dirn;
int nr_sg;
/* Check if next job is already prepared */
@@ -387,10 +388,12 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
}
if (data->flags & MMC_DATA_READ) {
- conf.direction = DMA_FROM_DEVICE;
+ conf.direction = DMA_DEV_TO_MEM;
+ buffer_dirn = DMA_FROM_DEVICE;
chan = host->dma_rx_channel;
} else {
- conf.direction = DMA_TO_DEVICE;
+ conf.direction = DMA_MEM_TO_DEV;
+ buffer_dirn = DMA_TO_DEVICE;
chan = host->dma_tx_channel;
}
@@ -403,7 +406,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
return -EINVAL;
device = chan->device;
- nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction);
+ nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
if (nr_sg == 0)
return -EINVAL;
@@ -426,7 +429,7 @@ static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
unmap_exit:
if (!next)
dmaengine_terminate_all(chan);
- dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+ dma_unmap_sg(device->dev, data->sg, data->sg_len, buffer_dirn);
return -ENOMEM;
}
@@ -1245,6 +1248,7 @@ static int __devinit mmci_probe(struct amba_device *dev,
if (host->vcc == NULL)
mmc->ocr_avail = plat->ocr_mask;
mmc->caps = plat->capabilities;
+ mmc->caps2 = plat->capabilities2;
/*
* We can do SGIO
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 80d8eb1..1d14cda 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -689,8 +689,8 @@ msmsdcc_pio_irq(int irq, void *dev_id)
/* Map the current scatter buffer */
local_irq_save(flags);
- buffer = kmap_atomic(sg_page(host->pio.sg),
- KM_BIO_SRC_IRQ) + host->pio.sg->offset;
+ buffer = kmap_atomic(sg_page(host->pio.sg))
+ + host->pio.sg->offset;
buffer += host->pio.sg_off;
remain = host->pio.sg->length - host->pio.sg_off;
len = 0;
@@ -700,7 +700,7 @@ msmsdcc_pio_irq(int irq, void *dev_id)
len = msmsdcc_pio_write(host, buffer, remain, status);
/* Unmap the buffer */
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+ kunmap_atomic(buffer);
local_irq_restore(flags);
host->pio.sg_off += len;
@@ -1480,18 +1480,7 @@ static struct platform_driver msmsdcc_driver = {
},
};
-static int __init msmsdcc_init(void)
-{
- return platform_driver_register(&msmsdcc_driver);
-}
-
-static void __exit msmsdcc_exit(void)
-{
- platform_driver_unregister(&msmsdcc_driver);
-}
-
-module_init(msmsdcc_init);
-module_exit(msmsdcc_exit);
+module_platform_driver(msmsdcc_driver);
MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 8e0fbe9..4184b79 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -218,6 +218,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
unsigned int blksz = data->blksz;
unsigned int datasize = nob * blksz;
struct scatterlist *sg;
+ enum dma_transfer_direction slave_dirn;
int i, nents;
if (data->flags & MMC_DATA_STREAM)
@@ -240,10 +241,13 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
}
}
- if (data->flags & MMC_DATA_READ)
+ if (data->flags & MMC_DATA_READ) {
host->dma_dir = DMA_FROM_DEVICE;
- else
+ slave_dirn = DMA_DEV_TO_MEM;
+ } else {
host->dma_dir = DMA_TO_DEVICE;
+ slave_dirn = DMA_MEM_TO_DEV;
+ }
nents = dma_map_sg(host->dma->device->dev, data->sg,
data->sg_len, host->dma_dir);
@@ -251,7 +255,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
return -EINVAL;
host->desc = host->dma->device->device_prep_slave_sg(host->dma,
- data->sg, data->sg_len, host->dma_dir,
+ data->sg, data->sg_len, slave_dirn,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!host->desc) {
@@ -1047,18 +1051,7 @@ static struct platform_driver mxcmci_driver = {
}
};
-static int __init mxcmci_init(void)
-{
- return platform_driver_register(&mxcmci_driver);
-}
-
-static void __exit mxcmci_exit(void)
-{
- platform_driver_unregister(&mxcmci_driver);
-}
-
-module_init(mxcmci_init);
-module_exit(mxcmci_exit);
+module_platform_driver(mxcmci_driver);
MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 973011f..382c835 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -154,6 +154,7 @@ struct mxs_mmc_host {
struct dma_chan *dmach;
struct mxs_dma_data dma_data;
unsigned int dma_dir;
+ enum dma_transfer_direction slave_dirn;
u32 ssp_pio_words[SSP_PIO_NUM];
unsigned int version;
@@ -324,7 +325,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
}
desc = host->dmach->device->device_prep_slave_sg(host->dmach,
- sgl, sg_len, host->dma_dir, append);
+ sgl, sg_len, host->slave_dirn, append);
if (desc) {
desc->callback = mxs_mmc_dma_irq_callback;
desc->callback_param = host;
@@ -356,6 +357,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
+ host->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
if (!desc)
goto out;
@@ -395,6 +397,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
+ host->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
if (!desc)
goto out;
@@ -433,6 +436,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
int i;
unsigned short dma_data_dir, timeout;
+ enum dma_transfer_direction slave_dirn;
unsigned int data_size = 0, log2_blksz;
unsigned int blocks = data->blocks;
@@ -448,9 +452,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
if (data->flags & MMC_DATA_WRITE) {
dma_data_dir = DMA_TO_DEVICE;
+ slave_dirn = DMA_MEM_TO_DEV;
read = 0;
} else {
dma_data_dir = DMA_FROM_DEVICE;
+ slave_dirn = DMA_DEV_TO_MEM;
read = BM_SSP_CTRL0_READ;
}
@@ -510,6 +516,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
host->ssp_pio_words[1] = cmd0;
host->ssp_pio_words[2] = cmd1;
host->dma_dir = DMA_NONE;
+ host->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
if (!desc)
goto out;
@@ -518,6 +525,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
WARN_ON(host->data != NULL);
host->data = data;
host->dma_dir = dma_data_dir;
+ host->slave_dirn = slave_dirn;
desc = mxs_mmc_prep_dma(host, 1);
if (!desc)
goto out;
@@ -855,18 +863,7 @@ static struct platform_driver mxs_mmc_driver = {
},
};
-static int __init mxs_mmc_init(void)
-{
- return platform_driver_register(&mxs_mmc_driver);
-}
-
-static void __exit mxs_mmc_exit(void)
-{
- platform_driver_unregister(&mxs_mmc_driver);
-}
-
-module_init(mxs_mmc_init);
-module_exit(mxs_mmc_exit);
+module_platform_driver(mxs_mmc_driver);
MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
MODULE_AUTHOR("Freescale Semiconductor");
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index d1fb561..fd0c661 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -24,7 +24,6 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
-#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/clk.h>
#include <linux/mmc/host.h>
@@ -120,7 +119,6 @@
#define MMC_AUTOSUSPEND_DELAY 100
#define MMC_TIMEOUT_MS 20
-#define OMAP_MMC_MASTER_CLOCK 96000000
#define OMAP_MMC_MIN_CLOCK 400000
#define OMAP_MMC_MAX_CLOCK 52000000
#define DRIVER_NAME "omap_hsmmc"
@@ -163,7 +161,6 @@ struct omap_hsmmc_host {
*/
struct regulator *vcc;
struct regulator *vcc_aux;
- struct work_struct mmc_carddetect_work;
void __iomem *base;
resource_size_t mapbase;
spinlock_t irq_lock; /* Prevent races with irq handler */
@@ -598,12 +595,12 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
}
/* Calculate divisor for the given clock frequency */
-static u16 calc_divisor(struct mmc_ios *ios)
+static u16 calc_divisor(struct omap_hsmmc_host *host, struct mmc_ios *ios)
{
u16 dsor = 0;
if (ios->clock) {
- dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock);
+ dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock);
if (dsor > 250)
dsor = 250;
}
@@ -623,7 +620,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
regval = OMAP_HSMMC_READ(host->base, SYSCTL);
regval = regval & ~(CLKD_MASK | DTO_MASK);
- regval = regval | (calc_divisor(ios) << 6) | (DTO << 16);
+ regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
OMAP_HSMMC_WRITE(host->base, SYSCTL,
OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
@@ -1280,17 +1277,16 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
}
/*
- * Work Item to notify the core about card insertion/removal
+ * irq handler to notify the core about card insertion/removal
*/
-static void omap_hsmmc_detect(struct work_struct *work)
+static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id)
{
- struct omap_hsmmc_host *host =
- container_of(work, struct omap_hsmmc_host, mmc_carddetect_work);
+ struct omap_hsmmc_host *host = dev_id;
struct omap_mmc_slot_data *slot = &mmc_slot(host);
int carddetect;
if (host->suspended)
- return;
+ return IRQ_HANDLED;
sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
@@ -1305,19 +1301,6 @@ static void omap_hsmmc_detect(struct work_struct *work)
mmc_detect_change(host->mmc, (HZ * 200) / 1000);
else
mmc_detect_change(host->mmc, (HZ * 50) / 1000);
-}
-
-/*
- * ISR for handling card insertion and removal
- */
-static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id)
-{
- struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id;
-
- if (host->suspended)
- return IRQ_HANDLED;
- schedule_work(&host->mmc_carddetect_work);
-
return IRQ_HANDLED;
}
@@ -1919,7 +1902,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
host->next_data.cookie = 1;
platform_set_drvdata(pdev, host);
- INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect);
mmc->ops = &omap_hsmmc_ops;
@@ -2049,10 +2031,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
/* Request IRQ for card detect */
if ((mmc_slot(host).card_detect_irq)) {
- ret = request_irq(mmc_slot(host).card_detect_irq,
- omap_hsmmc_cd_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- mmc_hostname(mmc), host);
+ ret = request_threaded_irq(mmc_slot(host).card_detect_irq,
+ NULL,
+ omap_hsmmc_detect,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ mmc_hostname(mmc), host);
if (ret) {
dev_dbg(mmc_dev(host->mmc),
"Unable to grab MMC CD IRQ\n");
@@ -2131,7 +2114,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
free_irq(host->irq, host);
if (mmc_slot(host).card_detect_irq)
free_irq(mmc_slot(host).card_detect_irq, host);
- flush_work_sync(&host->mmc_carddetect_work);
pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev);
@@ -2178,7 +2160,6 @@ static int omap_hsmmc_suspend(struct device *dev)
return ret;
}
}
- cancel_work_sync(&host->mmc_carddetect_work);
ret = mmc_suspend_host(host->mmc);
if (ret) {
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index fc4356e..cb2dc0e 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -872,18 +872,7 @@ static struct platform_driver pxamci_driver = {
},
};
-static int __init pxamci_init(void)
-{
- return platform_driver_register(&pxamci_driver);
-}
-
-static void __exit pxamci_exit(void)
-{
- platform_driver_unregister(&pxamci_driver);
-}
-
-module_init(pxamci_init);
-module_exit(pxamci_exit);
+module_platform_driver(pxamci_driver);
MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 720f993..1bcfd6d 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1914,18 +1914,7 @@ static struct platform_driver s3cmci_driver = {
.shutdown = s3cmci_shutdown,
};
-static int __init s3cmci_init(void)
-{
- return platform_driver_register(&s3cmci_driver);
-}
-
-static void __exit s3cmci_exit(void)
-{
- platform_driver_unregister(&s3cmci_driver);
-}
-
-module_init(s3cmci_init);
-module_exit(s3cmci_exit);
+module_platform_driver(s3cmci_driver);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index b4257e7..28a8708 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -115,17 +115,7 @@ static struct platform_driver sdhci_cns3xxx_driver = {
.remove = __devexit_p(sdhci_cns3xxx_remove),
};
-static int __init sdhci_cns3xxx_init(void)
-{
- return platform_driver_register(&sdhci_cns3xxx_driver);
-}
-module_init(sdhci_cns3xxx_init);
-
-static void __exit sdhci_cns3xxx_exit(void)
-{
- platform_driver_unregister(&sdhci_cns3xxx_driver);
-}
-module_exit(sdhci_cns3xxx_exit);
+module_platform_driver(sdhci_cns3xxx_driver);
MODULE_DESCRIPTION("SDHCI driver for CNS3xxx");
MODULE_AUTHOR("Scott Shu, "
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index a81312c..46fd1fd 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -88,17 +88,7 @@ static struct platform_driver sdhci_dove_driver = {
.remove = __devexit_p(sdhci_dove_remove),
};
-static int __init sdhci_dove_init(void)
-{
- return platform_driver_register(&sdhci_dove_driver);
-}
-module_init(sdhci_dove_init);
-
-static void __exit sdhci_dove_exit(void)
-{
- platform_driver_unregister(&sdhci_dove_driver);
-}
-module_exit(sdhci_dove_exit);
+module_platform_driver(sdhci_dove_driver);
MODULE_DESCRIPTION("SDHCI driver for Dove");
MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 38ebc4e..d601e41 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -606,17 +606,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.remove = __devexit_p(sdhci_esdhc_imx_remove),
};
-static int __init sdhci_esdhc_imx_init(void)
-{
- return platform_driver_register(&sdhci_esdhc_imx_driver);
-}
-module_init(sdhci_esdhc_imx_init);
-
-static void __exit sdhci_esdhc_imx_exit(void)
-{
- platform_driver_unregister(&sdhci_esdhc_imx_driver);
-}
-module_exit(sdhci_esdhc_imx_exit);
+module_platform_driver(sdhci_esdhc_imx_driver);
MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index c3b08f1..b97b2f5 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -73,7 +73,7 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
| (div << ESDHC_DIVIDER_SHIFT)
| (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- mdelay(100);
+ mdelay(1);
out:
host->clock = clock;
}
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 01e5f62..ff4adc0 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -131,17 +131,7 @@ static struct platform_driver sdhci_esdhc_driver = {
.remove = __devexit_p(sdhci_esdhc_remove),
};
-static int __init sdhci_esdhc_init(void)
-{
- return platform_driver_register(&sdhci_esdhc_driver);
-}
-module_init(sdhci_esdhc_init);
-
-static void __exit sdhci_esdhc_exit(void)
-{
- platform_driver_unregister(&sdhci_esdhc_driver);
-}
-module_exit(sdhci_esdhc_exit);
+module_platform_driver(sdhci_esdhc_driver);
MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC");
MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 3619adc..0ce088a 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -93,17 +93,7 @@ static struct platform_driver sdhci_hlwd_driver = {
.remove = __devexit_p(sdhci_hlwd_remove),
};
-static int __init sdhci_hlwd_init(void)
-{
- return platform_driver_register(&sdhci_hlwd_driver);
-}
-module_init(sdhci_hlwd_init);
-
-static void __exit sdhci_hlwd_exit(void)
-{
- platform_driver_unregister(&sdhci_hlwd_driver);
-}
-module_exit(sdhci_hlwd_exit);
+module_platform_driver(sdhci_hlwd_driver);
MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver");
MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz");
diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c
new file mode 100644
index 0000000..a611217
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pci-data.c
@@ -0,0 +1,5 @@
+#include <linux/module.h>
+#include <linux/mmc/sdhci-pci-data.h>
+
+struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
+EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 6878a946..7165e6a 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -23,8 +23,8 @@
#include <linux/scatterlist.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/sfi.h>
#include <linux/pm_runtime.h>
+#include <linux/mmc/sdhci-pci-data.h>
#include "sdhci.h"
@@ -61,6 +61,7 @@ struct sdhci_pci_fixes {
struct sdhci_pci_slot {
struct sdhci_pci_chip *chip;
struct sdhci_host *host;
+ struct sdhci_pci_data *data;
int pci_bar;
int rst_n_gpio;
@@ -171,32 +172,9 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
return 0;
}
-/* Medfield eMMC hardware reset GPIOs */
-static int mfd_emmc0_rst_gpio = -EINVAL;
-static int mfd_emmc1_rst_gpio = -EINVAL;
-
-static int mfd_emmc_gpio_parse(struct sfi_table_header *table)
-{
- struct sfi_table_simple *sb = (struct sfi_table_simple *)table;
- struct sfi_gpio_table_entry *entry;
- int i, num;
-
- num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
- entry = (struct sfi_gpio_table_entry *)sb->pentry;
-
- for (i = 0; i < num; i++, entry++) {
- if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN))
- mfd_emmc0_rst_gpio = entry->pin_no;
- else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN))
- mfd_emmc1_rst_gpio = entry->pin_no;
- }
-
- return 0;
-}
-
#ifdef CONFIG_PM_RUNTIME
-static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
+static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id)
{
struct sdhci_pci_slot *slot = dev_id;
struct sdhci_host *host = slot->host;
@@ -205,15 +183,16 @@ static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#define MFLD_SD_CD_PIN 69
-
-static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
+static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)
{
- int err, irq, gpio = MFLD_SD_CD_PIN;
+ int err, irq, gpio = slot->cd_gpio;
slot->cd_gpio = -EINVAL;
slot->cd_irq = -EINVAL;
+ if (!gpio_is_valid(gpio))
+ return;
+
err = gpio_request(gpio, "sd_cd");
if (err < 0)
goto out;
@@ -226,72 +205,53 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
if (irq < 0)
goto out_free;
- err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING |
+ err = request_irq(irq, sdhci_pci_sd_cd, IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING, "sd_cd", slot);
if (err)
goto out_free;
slot->cd_gpio = gpio;
slot->cd_irq = irq;
- slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION;
- return 0;
+ return;
out_free:
gpio_free(gpio);
out:
dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n");
- return 0;
}
-static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead)
+static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)
{
if (slot->cd_irq >= 0)
free_irq(slot->cd_irq, slot);
- gpio_free(slot->cd_gpio);
+ if (gpio_is_valid(slot->cd_gpio))
+ gpio_free(slot->cd_gpio);
}
#else
-#define mfd_sd_probe_slot NULL
-#define mfd_sd_remove_slot NULL
+static inline void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)
+{
+}
+
+static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)
+{
+}
#endif
static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
- const char *name = NULL;
- int gpio = -EINVAL;
-
- sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse);
-
- switch (slot->chip->pdev->device) {
- case PCI_DEVICE_ID_INTEL_MFD_EMMC0:
- gpio = mfd_emmc0_rst_gpio;
- name = "eMMC0_reset";
- break;
- case PCI_DEVICE_ID_INTEL_MFD_EMMC1:
- gpio = mfd_emmc1_rst_gpio;
- name = "eMMC1_reset";
- break;
- }
-
- if (!gpio_request(gpio, name)) {
- gpio_direction_output(gpio, 1);
- slot->rst_n_gpio = gpio;
- slot->host->mmc->caps |= MMC_CAP_HW_RESET;
- }
-
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
-
slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;
-
return 0;
}
-static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead)
+static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot)
{
- gpio_free(slot->rst_n_gpio);
+ slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD;
+ return 0;
}
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
@@ -307,20 +267,18 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.allow_runtime_pm = true,
- .probe_slot = mfd_sd_probe_slot,
- .remove_slot = mfd_sd_remove_slot,
};
static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.allow_runtime_pm = true,
+ .probe_slot = mfd_sdio_probe_slot,
};
static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.allow_runtime_pm = true,
.probe_slot = mfd_emmc_probe_slot,
- .remove_slot = mfd_emmc_remove_slot,
};
/* O2Micro extra registers */
@@ -1012,11 +970,8 @@ static int sdhci_pci_suspend(struct device *dev)
ret = sdhci_suspend_host(slot->host);
- if (ret) {
- for (i--; i >= 0; i--)
- sdhci_resume_host(chip->slots[i]->host);
- return ret;
- }
+ if (ret)
+ goto err_pci_suspend;
slot_pm_flags = slot->host->mmc->pm_flags;
if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
@@ -1027,11 +982,8 @@ static int sdhci_pci_suspend(struct device *dev)
if (chip->fixes && chip->fixes->suspend) {
ret = chip->fixes->suspend(chip);
- if (ret) {
- for (i = chip->num_slots - 1; i >= 0; i--)
- sdhci_resume_host(chip->slots[i]->host);
- return ret;
- }
+ if (ret)
+ goto err_pci_suspend;
}
pci_save_state(pdev);
@@ -1048,6 +1000,11 @@ static int sdhci_pci_suspend(struct device *dev)
}
return 0;
+
+err_pci_suspend:
+ while (--i >= 0)
+ sdhci_resume_host(chip->slots[i]->host);
+ return ret;
}
static int sdhci_pci_resume(struct device *dev)
@@ -1113,23 +1070,22 @@ static int sdhci_pci_runtime_suspend(struct device *dev)
ret = sdhci_runtime_suspend_host(slot->host);
- if (ret) {
- for (i--; i >= 0; i--)
- sdhci_runtime_resume_host(chip->slots[i]->host);
- return ret;
- }
+ if (ret)
+ goto err_pci_runtime_suspend;
}
if (chip->fixes && chip->fixes->suspend) {
ret = chip->fixes->suspend(chip);
- if (ret) {
- for (i = chip->num_slots - 1; i >= 0; i--)
- sdhci_runtime_resume_host(chip->slots[i]->host);
- return ret;
- }
+ if (ret)
+ goto err_pci_runtime_suspend;
}
return 0;
+
+err_pci_runtime_suspend:
+ while (--i >= 0)
+ sdhci_runtime_resume_host(chip->slots[i]->host);
+ return ret;
}
static int sdhci_pci_runtime_resume(struct device *dev)
@@ -1190,11 +1146,12 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
\*****************************************************************************/
static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
- struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
+ struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
+ int slotno)
{
struct sdhci_pci_slot *slot;
struct sdhci_host *host;
- int ret;
+ int ret, bar = first_bar + slotno;
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
@@ -1228,6 +1185,23 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
slot->host = host;
slot->pci_bar = bar;
slot->rst_n_gpio = -EINVAL;
+ slot->cd_gpio = -EINVAL;
+
+ /* Retrieve platform data if there is any */
+ if (*sdhci_pci_get_data)
+ slot->data = sdhci_pci_get_data(pdev, slotno);
+
+ if (slot->data) {
+ if (slot->data->setup) {
+ ret = slot->data->setup(slot->data);
+ if (ret) {
+ dev_err(&pdev->dev, "platform setup failed\n");
+ goto free;
+ }
+ }
+ slot->rst_n_gpio = slot->data->rst_n_gpio;
+ slot->cd_gpio = slot->data->cd_gpio;
+ }
host->hw_name = "PCI";
host->ops = &sdhci_pci_ops;
@@ -1238,7 +1212,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
if (ret) {
dev_err(&pdev->dev, "cannot request region\n");
- goto free;
+ goto cleanup;
}
host->ioaddr = pci_ioremap_bar(pdev, bar);
@@ -1254,15 +1228,30 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
goto unmap;
}
+ if (gpio_is_valid(slot->rst_n_gpio)) {
+ if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) {
+ gpio_direction_output(slot->rst_n_gpio, 1);
+ slot->host->mmc->caps |= MMC_CAP_HW_RESET;
+ } else {
+ dev_warn(&pdev->dev, "failed to request rst_n_gpio\n");
+ slot->rst_n_gpio = -EINVAL;
+ }
+ }
+
host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
ret = sdhci_add_host(host);
if (ret)
goto remove;
+ sdhci_pci_add_own_cd(slot);
+
return slot;
remove:
+ if (gpio_is_valid(slot->rst_n_gpio))
+ gpio_free(slot->rst_n_gpio);
+
if (chip->fixes && chip->fixes->remove_slot)
chip->fixes->remove_slot(slot, 0);
@@ -1272,6 +1261,10 @@ unmap:
release:
pci_release_region(pdev, bar);
+cleanup:
+ if (slot->data && slot->data->cleanup)
+ slot->data->cleanup(slot->data);
+
free:
sdhci_free_host(host);
@@ -1283,6 +1276,8 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
int dead;
u32 scratch;
+ sdhci_pci_remove_own_cd(slot);
+
dead = 0;
scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
if (scratch == (u32)-1)
@@ -1290,9 +1285,15 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
sdhci_remove_host(slot->host, dead);
+ if (gpio_is_valid(slot->rst_n_gpio))
+ gpio_free(slot->rst_n_gpio);
+
if (slot->chip->fixes && slot->chip->fixes->remove_slot)
slot->chip->fixes->remove_slot(slot, dead);
+ if (slot->data && slot->data->cleanup)
+ slot->data->cleanup(slot->data);
+
pci_release_region(slot->chip->pdev, slot->pci_bar);
sdhci_free_host(slot->host);
@@ -1379,7 +1380,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
slots = chip->num_slots; /* Quirk may have changed this */
for (i = 0; i < slots; i++) {
- slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
+ slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
if (IS_ERR(slot)) {
for (i--; i >= 0; i--)
sdhci_pci_remove_slot(chip->slots[i]);
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 7a039c3..dbb75bf 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -223,18 +223,8 @@ static struct platform_driver sdhci_pxav2_driver = {
.probe = sdhci_pxav2_probe,
.remove = __devexit_p(sdhci_pxav2_remove),
};
-static int __init sdhci_pxav2_init(void)
-{
- return platform_driver_register(&sdhci_pxav2_driver);
-}
-
-static void __exit sdhci_pxav2_exit(void)
-{
- platform_driver_unregister(&sdhci_pxav2_driver);
-}
-module_init(sdhci_pxav2_init);
-module_exit(sdhci_pxav2_exit);
+module_platform_driver(sdhci_pxav2_driver);
MODULE_DESCRIPTION("SDHCI driver for pxav2");
MODULE_AUTHOR("Marvell International Ltd.");
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index 15673a7..f296956 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -269,18 +269,8 @@ static struct platform_driver sdhci_pxav3_driver = {
.probe = sdhci_pxav3_probe,
.remove = __devexit_p(sdhci_pxav3_remove),
};
-static int __init sdhci_pxav3_init(void)
-{
- return platform_driver_register(&sdhci_pxav3_driver);
-}
-
-static void __exit sdhci_pxav3_exit(void)
-{
- platform_driver_unregister(&sdhci_pxav3_driver);
-}
-module_init(sdhci_pxav3_init);
-module_exit(sdhci_pxav3_exit);
+module_platform_driver(sdhci_pxav3_driver);
MODULE_DESCRIPTION("SDHCI driver for pxav3");
MODULE_AUTHOR("Marvell International Ltd.");
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 9a20d1f..1af756e 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -80,7 +80,7 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host)
tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
- writel(tmp, host->ioaddr + 0x80);
+ writel(tmp, host->ioaddr + S3C_SDHCI_CONTROL2);
}
}
@@ -521,6 +521,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (pdata->host_caps)
host->mmc->caps |= pdata->host_caps;
+ if (pdata->pm_caps)
+ host->mmc->pm_caps |= pdata->pm_caps;
+
host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE);
@@ -654,18 +657,7 @@ static struct platform_driver sdhci_s3c_driver = {
},
};
-static int __init sdhci_s3c_init(void)
-{
- return platform_driver_register(&sdhci_s3c_driver);
-}
-
-static void __exit sdhci_s3c_exit(void)
-{
- platform_driver_unregister(&sdhci_s3c_driver);
-}
-
-module_init(sdhci_s3c_init);
-module_exit(sdhci_s3c_exit);
+module_platform_driver(sdhci_s3c_driver);
MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 63cc8b6..b7f8b33 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -21,6 +21,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-spear.h>
@@ -271,26 +272,54 @@ static int __devexit sdhci_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int sdhci_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct spear_sdhci *sdhci = dev_get_platdata(dev);
+ int ret;
+
+ ret = sdhci_suspend_host(host);
+ if (!ret)
+ clk_disable(sdhci->clk);
+
+ return ret;
+}
+
+static int sdhci_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct spear_sdhci *sdhci = dev_get_platdata(dev);
+ int ret;
+
+ ret = clk_enable(sdhci->clk);
+ if (ret) {
+ dev_dbg(dev, "Resume: Error enabling clock\n");
+ return ret;
+ }
+
+ return sdhci_resume_host(host);
+}
+
+const struct dev_pm_ops sdhci_pm_ops = {
+ .suspend = sdhci_suspend,
+ .resume = sdhci_resume,
+};
+#endif
+
static struct platform_driver sdhci_driver = {
.driver = {
.name = "sdhci",
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &sdhci_pm_ops,
+#endif
},
.probe = sdhci_probe,
.remove = __devexit_p(sdhci_remove),
};
-static int __init sdhci_init(void)
-{
- return platform_driver_register(&sdhci_driver);
-}
-module_init(sdhci_init);
-
-static void __exit sdhci_exit(void)
-{
- platform_driver_unregister(&sdhci_driver);
-}
-module_exit(sdhci_exit);
+module_platform_driver(sdhci_driver);
MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver");
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e2e18d3..78a36eb 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -324,17 +324,7 @@ static struct platform_driver sdhci_tegra_driver = {
.remove = __devexit_p(sdhci_tegra_remove),
};
-static int __init sdhci_tegra_init(void)
-{
- return platform_driver_register(&sdhci_tegra_driver);
-}
-module_init(sdhci_tegra_init);
-
-static void __exit sdhci_tegra_exit(void)
-{
- platform_driver_unregister(&sdhci_tegra_driver);
-}
-module_exit(sdhci_tegra_exit);
+module_platform_driver(sdhci_tegra_driver);
MODULE_DESCRIPTION("SDHCI driver for Tegra");
MODULE_AUTHOR(" Google, Inc.");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 19ed580..8d66706 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *);
static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
static void sdhci_finish_command(struct sdhci_host *);
-static int sdhci_execute_tuning(struct mmc_host *mmc);
+static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
static void sdhci_tuning_timer(unsigned long data);
#ifdef CONFIG_PM_RUNTIME
@@ -146,10 +146,8 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{
u32 present, irqs;
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- return;
-
- if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION)
+ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
+ !mmc_card_is_removable(host->mmc))
return;
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
@@ -214,6 +212,11 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
+
+ if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+ if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
+ host->ops->enable_dma(host);
+ }
}
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
@@ -423,12 +426,12 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
{
local_irq_save(*flags);
- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ return kmap_atomic(sg_page(sg)) + sg->offset;
}
static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
{
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+ kunmap_atomic(buffer);
local_irq_restore(*flags);
}
@@ -1016,7 +1019,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
flags |= SDHCI_CMD_INDEX;
/* CMD19 is special in that the Data Present Select should be set */
- if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK))
+ if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK ||
+ cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
flags |= SDHCI_CMD_DATA;
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
@@ -1066,12 +1070,15 @@ static void sdhci_finish_command(struct sdhci_host *host)
static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
int div = 0; /* Initialized for compiler warning */
+ int real_div = div, clk_mul = 1;
u16 clk = 0;
unsigned long timeout;
- if (clock == host->clock)
+ if (clock && clock == host->clock)
return;
+ host->mmc->actual_clock = 0;
+
if (host->ops->set_clock) {
host->ops->set_clock(host, clock);
if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
@@ -1109,6 +1116,8 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
* Control register.
*/
clk = SDHCI_PROG_CLOCK_MODE;
+ real_div = div;
+ clk_mul = host->clk_mul;
div--;
}
} else {
@@ -1122,6 +1131,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
break;
}
}
+ real_div = div;
div >>= 1;
}
} else {
@@ -1130,9 +1140,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
if ((host->max_clk / div) <= clock)
break;
}
+ real_div = div;
div >>= 1;
}
+ if (real_div)
+ host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
+
clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
@@ -1160,7 +1174,7 @@ out:
host->clock = clock;
}
-static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
{
u8 pwr = 0;
@@ -1183,13 +1197,13 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
}
if (host->pwr == pwr)
- return;
+ return -1;
host->pwr = pwr;
if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- return;
+ return 0;
}
/*
@@ -1216,6 +1230,8 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
*/
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
mdelay(10);
+
+ return power;
}
/*****************************************************************************\
@@ -1277,7 +1293,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
if ((host->flags & SDHCI_NEEDS_RETUNING) &&
!(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
spin_unlock_irqrestore(&host->lock, flags);
- sdhci_execute_tuning(mmc);
+ sdhci_execute_tuning(mmc, mrq->cmd->opcode);
spin_lock_irqsave(&host->lock, flags);
/* Restore original mmc_request structure */
@@ -1297,12 +1313,17 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
{
unsigned long flags;
+ int vdd_bit = -1;
u8 ctrl;
spin_lock_irqsave(&host->lock, flags);
- if (host->flags & SDHCI_DEVICE_DEAD)
- goto out;
+ if (host->flags & SDHCI_DEVICE_DEAD) {
+ spin_unlock_irqrestore(&host->lock, flags);
+ if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
+ mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+ return;
+ }
/*
* Reset the chip on each power off.
@@ -1316,9 +1337,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
sdhci_set_clock(host, ios->clock);
if (ios->power_mode == MMC_POWER_OFF)
- sdhci_set_power(host, -1);
+ vdd_bit = sdhci_set_power(host, -1);
else
- sdhci_set_power(host, ios->vdd);
+ vdd_bit = sdhci_set_power(host, ios->vdd);
+
+ if (host->vmmc && vdd_bit != -1) {
+ spin_unlock_irqrestore(&host->lock, flags);
+ mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
+ spin_lock_irqsave(&host->lock, flags);
+ }
if (host->ops->platform_send_init_74_clocks)
host->ops->platform_send_init_74_clocks(host, ios->power_mode);
@@ -1361,11 +1388,11 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
unsigned int clock;
/* In case of UHS-I modes, set High Speed Enable */
- if ((ios->timing == MMC_TIMING_UHS_SDR50) ||
+ if ((ios->timing == MMC_TIMING_MMC_HS200) ||
+ (ios->timing == MMC_TIMING_UHS_SDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
- (ios->timing == MMC_TIMING_UHS_SDR25) ||
- (ios->timing == MMC_TIMING_UHS_SDR12))
+ (ios->timing == MMC_TIMING_UHS_SDR25))
ctrl |= SDHCI_CTRL_HISPD;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -1415,7 +1442,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- if (ios->timing == MMC_TIMING_UHS_SDR12)
+ if (ios->timing == MMC_TIMING_MMC_HS200)
+ ctrl_2 |= SDHCI_CTRL_HS_SDR200;
+ else if (ios->timing == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
else if (ios->timing == MMC_TIMING_UHS_SDR25)
ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
@@ -1443,7 +1472,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
-out:
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
}
@@ -1663,7 +1691,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
return err;
}
-static int sdhci_execute_tuning(struct mmc_host *mmc)
+static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host;
u16 ctrl;
@@ -1671,6 +1699,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
int tuning_loop_counter = MAX_TUNING_LOOP;
unsigned long timeout;
int err = 0;
+ bool requires_tuning_nonuhs = false;
host = mmc_priv(mmc);
@@ -1681,13 +1710,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/*
- * Host Controller needs tuning only in case of SDR104 mode
- * and for SDR50 mode when Use Tuning for SDR50 is set in
+ * The Host Controller needs tuning only in case of SDR104 mode
+ * and for SDR50 mode when Use Tuning for SDR50 is set in the
* Capabilities register.
+ * If the Host Controller supports the HS200 mode then the
+ * tuning function has to be executed.
*/
+ if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+ (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
+ host->flags & SDHCI_HS200_NEEDS_TUNING))
+ requires_tuning_nonuhs = true;
+
if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
- (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
- (host->flags & SDHCI_SDR50_NEEDS_TUNING)))
+ requires_tuning_nonuhs)
ctrl |= SDHCI_CTRL_EXEC_TUNING;
else {
spin_unlock(&host->lock);
@@ -1723,7 +1758,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
if (!tuning_loop_counter && !timeout)
break;
- cmd.opcode = MMC_SEND_TUNING_BLOCK;
+ cmd.opcode = opcode;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
cmd.retries = 0;
@@ -1738,7 +1773,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
* block to the Host Controller. So we set the block size
* to 64 here.
*/
- sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
+ if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
+ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
+ SDHCI_BLOCK_SIZE);
+ else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
+ SDHCI_BLOCK_SIZE);
+ } else {
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
+ SDHCI_BLOCK_SIZE);
+ }
/*
* The tuning block is sent by the card to the host controller.
@@ -2121,12 +2166,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { }
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
+ u32 command;
BUG_ON(intmask == 0);
/* CMD19 generates _only_ Buffer Read Ready interrupt */
if (intmask & SDHCI_INT_DATA_AVAIL) {
- if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) ==
- MMC_SEND_TUNING_BLOCK) {
+ command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
+ if (command == MMC_SEND_TUNING_BLOCK ||
+ command == MMC_SEND_TUNING_BLOCK_HS200) {
host->tuning_done = 1;
wake_up(&host->buf_ready_int);
return;
@@ -2330,26 +2377,33 @@ out:
int sdhci_suspend_host(struct sdhci_host *host)
{
int ret;
+ bool has_tuning_timer;
sdhci_disable_card_detection(host);
/* Disable tuning since we are suspending */
- if (host->version >= SDHCI_SPEC_300 && host->tuning_count &&
- host->tuning_mode == SDHCI_TUNING_MODE_1) {
+ has_tuning_timer = host->version >= SDHCI_SPEC_300 &&
+ host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1;
+ if (has_tuning_timer) {
+ del_timer_sync(&host->tuning_timer);
host->flags &= ~SDHCI_NEEDS_RETUNING;
- mod_timer(&host->tuning_timer, jiffies +
- host->tuning_count * HZ);
}
ret = mmc_suspend_host(host->mmc);
- if (ret)
+ if (ret) {
+ if (has_tuning_timer) {
+ host->flags |= SDHCI_NEEDS_RETUNING;
+ mod_timer(&host->tuning_timer, jiffies +
+ host->tuning_count * HZ);
+ }
+
+ sdhci_enable_card_detection(host);
+
return ret;
+ }
free_irq(host->irq, host);
- if (host->vmmc)
- ret = regulator_disable(host->vmmc);
-
return ret;
}
@@ -2359,12 +2413,6 @@ int sdhci_resume_host(struct sdhci_host *host)
{
int ret;
- if (host->vmmc) {
- int ret = regulator_enable(host->vmmc);
- if (ret)
- return ret;
- }
-
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
if (host->ops->enable_dma)
host->ops->enable_dma(host);
@@ -2727,10 +2775,14 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps[1] & SDHCI_SUPPORT_DDR50)
mmc->caps |= MMC_CAP_UHS_DDR50;
- /* Does the host needs tuning for SDR50? */
+ /* Does the host need tuning for SDR50? */
if (caps[1] & SDHCI_USE_SDR50_TUNING)
host->flags |= SDHCI_SDR50_NEEDS_TUNING;
+ /* Does the host need tuning for HS200? */
+ if (mmc->caps2 & MMC_CAP2_HS200)
+ host->flags |= SDHCI_HS200_NEEDS_TUNING;
+
/* Driver Type(s) (A, C, D) supported by the host */
if (caps[1] & SDHCI_DRIVER_TYPE_A)
mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
@@ -2926,8 +2978,6 @@ int sdhci_add_host(struct sdhci_host *host)
if (IS_ERR(host->vmmc)) {
pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
host->vmmc = NULL;
- } else {
- regulator_enable(host->vmmc);
}
sdhci_init(host, 0);
@@ -3016,10 +3066,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->finish_tasklet);
- if (host->vmmc) {
- regulator_disable(host->vmmc);
+ if (host->vmmc)
regulator_put(host->vmmc);
- }
kfree(host->adma_desc);
kfree(host->align_buffer);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index a04d4d0..ad265b9 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -158,6 +158,7 @@
#define SDHCI_CTRL_UHS_SDR50 0x0002
#define SDHCI_CTRL_UHS_SDR104 0x0003
#define SDHCI_CTRL_UHS_DDR50 0x0004
+#define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */
#define SDHCI_CTRL_VDD_180 0x0008
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d5505f3..f5d8b53 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -16,6 +16,33 @@
*
*/
+/*
+ * The MMCIF driver is now processing MMC requests asynchronously, according
+ * to the Linux MMC API requirement.
+ *
+ * The MMCIF driver processes MMC requests in up to 3 stages: command, optional
+ * data, and optional stop. To achieve asynchronous processing each of these
+ * stages is split into two halves: a top and a bottom half. The top half
+ * initialises the hardware, installs a timeout handler to handle completion
+ * timeouts, and returns. In case of the command stage this immediately returns
+ * control to the caller, leaving all further processing to run asynchronously.
+ * All further request processing is performed by the bottom halves.
+ *
+ * The bottom half further consists of a "hard" IRQ handler, an IRQ handler
+ * thread, a DMA completion callback, if DMA is used, a timeout work, and
+ * request- and stage-specific handler methods.
+ *
+ * Each bottom half run begins with either a hardware interrupt, a DMA callback
+ * invocation, or a timeout work run. In case of an error or a successful
+ * processing completion, the MMC core is informed and the request processing is
+ * finished. In case processing has to continue, i.e., if data has to be read
+ * from or written to the card, or if a stop command has to be sent, the next
+ * top half is called, which performs the necessary hardware handling and
+ * reschedules the timeout work. This returns the driver state machine into the
+ * bottom half waiting state.
+ */
+
+#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -123,6 +150,11 @@
#define MASK_MRBSYTO (1 << 1)
#define MASK_MRSPTO (1 << 0)
+#define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \
+ MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \
+ MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
+ MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
+
/* CE_HOST_STS1 */
#define STS1_CMDSEQ (1 << 31)
@@ -162,9 +194,21 @@ enum mmcif_state {
STATE_IOS,
};
+enum mmcif_wait_for {
+ MMCIF_WAIT_FOR_REQUEST,
+ MMCIF_WAIT_FOR_CMD,
+ MMCIF_WAIT_FOR_MREAD,
+ MMCIF_WAIT_FOR_MWRITE,
+ MMCIF_WAIT_FOR_READ,
+ MMCIF_WAIT_FOR_WRITE,
+ MMCIF_WAIT_FOR_READ_END,
+ MMCIF_WAIT_FOR_WRITE_END,
+ MMCIF_WAIT_FOR_STOP,
+};
+
struct sh_mmcif_host {
struct mmc_host *mmc;
- struct mmc_data *data;
+ struct mmc_request *mrq;
struct platform_device *pd;
struct sh_dmae_slave dma_slave_tx;
struct sh_dmae_slave dma_slave_rx;
@@ -172,11 +216,17 @@ struct sh_mmcif_host {
unsigned int clk;
int bus_width;
bool sd_error;
+ bool dying;
long timeout;
void __iomem *addr;
- struct completion intr_wait;
+ u32 *pio_ptr;
+ spinlock_t lock; /* protect sh_mmcif_host::state */
enum mmcif_state state;
- spinlock_t lock;
+ enum mmcif_wait_for wait_for;
+ struct delayed_work timeout_work;
+ size_t blocksize;
+ int sg_idx;
+ int sg_blkidx;
bool power;
bool card_present;
@@ -202,19 +252,21 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
static void mmcif_dma_complete(void *arg)
{
struct sh_mmcif_host *host = arg;
+ struct mmc_data *data = host->mrq->data;
+
dev_dbg(&host->pd->dev, "Command completed\n");
- if (WARN(!host->data, "%s: NULL data in DMA completion!\n",
+ if (WARN(!data, "%s: NULL data in DMA completion!\n",
dev_name(&host->pd->dev)))
return;
- if (host->data->flags & MMC_DATA_READ)
+ if (data->flags & MMC_DATA_READ)
dma_unmap_sg(host->chan_rx->device->dev,
- host->data->sg, host->data->sg_len,
+ data->sg, data->sg_len,
DMA_FROM_DEVICE);
else
dma_unmap_sg(host->chan_tx->device->dev,
- host->data->sg, host->data->sg_len,
+ data->sg, data->sg_len,
DMA_TO_DEVICE);
complete(&host->dma_complete);
@@ -222,18 +274,19 @@ static void mmcif_dma_complete(void *arg)
static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
{
- struct scatterlist *sg = host->data->sg;
+ struct mmc_data *data = host->mrq->data;
+ struct scatterlist *sg = data->sg;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_rx;
dma_cookie_t cookie = -EINVAL;
int ret;
- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+ ret = dma_map_sg(chan->device->dev, sg, data->sg_len,
DMA_FROM_DEVICE);
if (ret > 0) {
host->dma_active = true;
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
- DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (desc) {
@@ -244,7 +297,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
dma_async_issue_pending(chan);
}
dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
- __func__, host->data->sg_len, ret, cookie);
+ __func__, data->sg_len, ret, cookie);
if (!desc) {
/* DMA failed, fall back to PIO */
@@ -265,23 +318,24 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
}
dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
- desc, cookie, host->data->sg_len);
+ desc, cookie, data->sg_len);
}
static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
{
- struct scatterlist *sg = host->data->sg;
+ struct mmc_data *data = host->mrq->data;
+ struct scatterlist *sg = data->sg;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *chan = host->chan_tx;
dma_cookie_t cookie = -EINVAL;
int ret;
- ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+ ret = dma_map_sg(chan->device->dev, sg, data->sg_len,
DMA_TO_DEVICE);
if (ret > 0) {
host->dma_active = true;
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
- DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
}
if (desc) {
@@ -292,7 +346,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
dma_async_issue_pending(chan);
}
dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
- __func__, host->data->sg_len, ret, cookie);
+ __func__, data->sg_len, ret, cookie);
if (!desc) {
/* DMA failed, fall back to PIO */
@@ -399,7 +453,7 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
else
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
- (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16));
+ ((fls(host->clk / clk) - 1) << 16));
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
}
@@ -421,7 +475,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
{
u32 state1, state2;
- int ret, timeout = 10000000;
+ int ret, timeout;
host->sd_error = false;
@@ -433,155 +487,212 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
if (state1 & STS1_CMDSEQ) {
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK);
sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK);
- while (1) {
- timeout--;
- if (timeout < 0) {
- dev_err(&host->pd->dev,
- "Forceed end of command sequence timeout err\n");
- return -EIO;
- }
+ for (timeout = 10000000; timeout; timeout--) {
if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1)
- & STS1_CMDSEQ))
+ & STS1_CMDSEQ))
break;
mdelay(1);
}
+ if (!timeout) {
+ dev_err(&host->pd->dev,
+ "Forced end of command sequence timeout err\n");
+ return -EIO;
+ }
sh_mmcif_sync_reset(host);
dev_dbg(&host->pd->dev, "Forced end of command sequence\n");
return -EIO;
}
if (state2 & STS2_CRC_ERR) {
- dev_dbg(&host->pd->dev, ": Happened CRC error\n");
+ dev_dbg(&host->pd->dev, ": CRC error\n");
ret = -EIO;
} else if (state2 & STS2_TIMEOUT_ERR) {
- dev_dbg(&host->pd->dev, ": Happened Timeout error\n");
+ dev_dbg(&host->pd->dev, ": Timeout\n");
ret = -ETIMEDOUT;
} else {
- dev_dbg(&host->pd->dev, ": Happened End/Index error\n");
+ dev_dbg(&host->pd->dev, ": End/Index error\n");
ret = -EIO;
}
return ret;
}
-static int sh_mmcif_single_read(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p)
{
- struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, *p = sg_virt(data->sg);
+ struct mmc_data *data = host->mrq->data;
+
+ host->sg_blkidx += host->blocksize;
+
+ /* data->sg->length must be a multiple of host->blocksize? */
+ BUG_ON(host->sg_blkidx > data->sg->length);
+
+ if (host->sg_blkidx == data->sg->length) {
+ host->sg_blkidx = 0;
+ if (++host->sg_idx < data->sg_len)
+ host->pio_ptr = sg_virt(++data->sg);
+ } else {
+ host->pio_ptr = p;
+ }
+
+ if (host->sg_idx == data->sg_len)
+ return false;
+
+ return true;
+}
+
+static void sh_mmcif_single_read(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
+{
+ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK) + 3;
+
+ host->wait_for = MMCIF_WAIT_FOR_READ;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf read enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
- for (i = 0; i < blocksize / 4; i++)
+}
+
+static bool sh_mmcif_read_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = sg_virt(data->sg);
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ for (i = 0; i < host->blocksize / 4; i++)
*p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
/* buffer read end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
+ host->wait_for = MMCIF_WAIT_FOR_READ_END;
- return 0;
+ return true;
}
-static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static void sh_mmcif_multi_read(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, j, sec, *p;
-
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
- MMCIF_CE_BLOCK_SET);
- for (j = 0; j < data->sg_len; j++) {
- p = sg_virt(data->sg);
- for (sec = 0; sec < data->sg->length / blocksize; sec++) {
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
- /* buf read enable */
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
-
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- for (i = 0; i < blocksize / 4; i++)
- *p++ = sh_mmcif_readl(host->addr,
- MMCIF_CE_DATA);
- }
- if (j < data->sg_len - 1)
- data->sg++;
+
+ if (!data->sg_len || !data->sg->length)
+ return;
+
+ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK;
+
+ host->wait_for = MMCIF_WAIT_FOR_MREAD;
+ host->sg_idx = 0;
+ host->sg_blkidx = 0;
+ host->pio_ptr = sg_virt(data->sg);
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
+}
+
+static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = host->pio_ptr;
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
}
- return 0;
+
+ BUG_ON(!data->sg->length);
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA);
+
+ if (!sh_mmcif_next_block(host, p))
+ return false;
+
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
+
+ return true;
}
-static int sh_mmcif_single_write(struct sh_mmcif_host *host,
+static void sh_mmcif_single_write(struct sh_mmcif_host *host,
struct mmc_request *mrq)
{
- struct mmc_data *data = mrq->data;
- long time;
- u32 blocksize, i, *p = sg_virt(data->sg);
+ host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK) + 3;
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+ host->wait_for = MMCIF_WAIT_FOR_WRITE;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf write enable */
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- blocksize = (BLOCK_SIZE_MASK &
- sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3;
- for (i = 0; i < blocksize / 4; i++)
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+}
+
+static bool sh_mmcif_write_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = sg_virt(data->sg);
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
+ }
+
+ for (i = 0; i < host->blocksize / 4; i++)
sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
/* buffer write end */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
+ host->wait_for = MMCIF_WAIT_FOR_WRITE_END;
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
-
- return 0;
+ return true;
}
-static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
- struct mmc_request *mrq)
+static void sh_mmcif_multi_write(struct sh_mmcif_host *host,
+ struct mmc_request *mrq)
{
struct mmc_data *data = mrq->data;
- long time;
- u32 i, sec, j, blocksize, *p;
- blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr,
- MMCIF_CE_BLOCK_SET);
+ if (!data->sg_len || !data->sg->length)
+ return;
- for (j = 0; j < data->sg_len; j++) {
- p = sg_virt(data->sg);
- for (sec = 0; sec < data->sg->length / blocksize; sec++) {
- sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
- /* buf write enable*/
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
+ host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) &
+ BLOCK_SIZE_MASK;
- if (time <= 0 || host->sd_error)
- return sh_mmcif_error_manage(host);
+ host->wait_for = MMCIF_WAIT_FOR_MWRITE;
+ host->sg_idx = 0;
+ host->sg_blkidx = 0;
+ host->pio_ptr = sg_virt(data->sg);
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+}
- for (i = 0; i < blocksize / 4; i++)
- sh_mmcif_writel(host->addr,
- MMCIF_CE_DATA, *p++);
- }
- if (j < data->sg_len - 1)
- data->sg++;
+static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
+{
+ struct mmc_data *data = host->mrq->data;
+ u32 *p = host->pio_ptr;
+ int i;
+
+ if (host->sd_error) {
+ data->error = sh_mmcif_error_manage(host);
+ return false;
}
- return 0;
+
+ BUG_ON(!data->sg->length);
+
+ for (i = 0; i < host->blocksize / 4; i++)
+ sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++);
+
+ if (!sh_mmcif_next_block(host, p))
+ return false;
+
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
+
+ return true;
}
static void sh_mmcif_get_response(struct sh_mmcif_host *host,
@@ -603,8 +714,11 @@ static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
}
static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
- struct mmc_request *mrq, struct mmc_command *cmd, u32 opc)
+ struct mmc_request *mrq)
{
+ struct mmc_data *data = mrq->data;
+ struct mmc_command *cmd = mrq->cmd;
+ u32 opc = cmd->opcode;
u32 tmp = 0;
/* Response Type check */
@@ -636,7 +750,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
break;
}
/* WDAT / DATW */
- if (host->data) {
+ if (data) {
tmp |= CMD_SET_WDAT;
switch (host->bus_width) {
case MMC_BUS_WIDTH_1:
@@ -660,7 +774,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) {
tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET,
- mrq->data->blocks << 16);
+ data->blocks << 16);
}
/* RIDXC[1:0] check bits */
if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID ||
@@ -674,68 +788,60 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
opc == MMC_SEND_CSD || opc == MMC_SEND_CID)
tmp |= CMD_SET_CRC7C_INTERNAL;
- return opc = ((opc << 24) | tmp);
+ return (opc << 24) | tmp;
}
static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
- struct mmc_request *mrq, u32 opc)
+ struct mmc_request *mrq, u32 opc)
{
- int ret;
-
switch (opc) {
case MMC_READ_MULTIPLE_BLOCK:
- ret = sh_mmcif_multi_read(host, mrq);
- break;
+ sh_mmcif_multi_read(host, mrq);
+ return 0;
case MMC_WRITE_MULTIPLE_BLOCK:
- ret = sh_mmcif_multi_write(host, mrq);
- break;
+ sh_mmcif_multi_write(host, mrq);
+ return 0;
case MMC_WRITE_BLOCK:
- ret = sh_mmcif_single_write(host, mrq);
- break;
+ sh_mmcif_single_write(host, mrq);
+ return 0;
case MMC_READ_SINGLE_BLOCK:
case MMC_SEND_EXT_CSD:
- ret = sh_mmcif_single_read(host, mrq);
- break;
+ sh_mmcif_single_read(host, mrq);
+ return 0;
default:
dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
- return ret;
}
static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
- struct mmc_request *mrq, struct mmc_command *cmd)
+ struct mmc_request *mrq)
{
- long time;
- int ret = 0, mask = 0;
+ struct mmc_command *cmd = mrq->cmd;
u32 opc = cmd->opcode;
+ u32 mask;
switch (opc) {
- /* respons busy check */
+ /* response busy check */
case MMC_SWITCH:
case MMC_STOP_TRANSMISSION:
case MMC_SET_WRITE_PROT:
case MMC_CLR_WRITE_PROT:
case MMC_ERASE:
case MMC_GEN_CMD:
- mask = MASK_MRBSYE;
+ mask = MASK_START_CMD | MASK_MRBSYE;
break;
default:
- mask = MASK_MCRSPE;
+ mask = MASK_START_CMD | MASK_MCRSPE;
break;
}
- mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
- MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
- MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
- MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
- if (host->data) {
+ if (mrq->data) {
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0);
sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET,
mrq->data->blksz);
}
- opc = sh_mmcif_set_cmd(host, mrq, cmd, opc);
+ opc = sh_mmcif_set_cmd(host, mrq);
sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask);
@@ -744,80 +850,28 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
/* set cmd */
sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc);
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0) {
- cmd->error = sh_mmcif_error_manage(host);
- return;
- }
- if (host->sd_error) {
- switch (cmd->opcode) {
- case MMC_ALL_SEND_CID:
- case MMC_SELECT_CARD:
- case MMC_APP_CMD:
- cmd->error = -ETIMEDOUT;
- break;
- default:
- dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n",
- cmd->opcode);
- cmd->error = sh_mmcif_error_manage(host);
- break;
- }
- host->sd_error = false;
- return;
- }
- if (!(cmd->flags & MMC_RSP_PRESENT)) {
- cmd->error = 0;
- return;
- }
- sh_mmcif_get_response(host, cmd);
- if (host->data) {
- if (!host->dma_active) {
- ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
- } else {
- long time =
- wait_for_completion_interruptible_timeout(&host->dma_complete,
- host->timeout);
- if (!time)
- ret = -ETIMEDOUT;
- else if (time < 0)
- ret = time;
- sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
- BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
- host->dma_active = false;
- }
- if (ret < 0)
- mrq->data->bytes_xfered = 0;
- else
- mrq->data->bytes_xfered =
- mrq->data->blocks * mrq->data->blksz;
- }
- cmd->error = ret;
+ host->wait_for = MMCIF_WAIT_FOR_CMD;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
}
static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
- struct mmc_request *mrq, struct mmc_command *cmd)
+ struct mmc_request *mrq)
{
- long time;
-
- if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK)
+ switch (mrq->cmd->opcode) {
+ case MMC_READ_MULTIPLE_BLOCK:
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
- else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK)
+ break;
+ case MMC_WRITE_MULTIPLE_BLOCK:
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
- else {
+ break;
+ default:
dev_err(&host->pd->dev, "unsupported stop cmd\n");
- cmd->error = sh_mmcif_error_manage(host);
+ mrq->stop->error = sh_mmcif_error_manage(host);
return;
}
- time = wait_for_completion_interruptible_timeout(&host->intr_wait,
- host->timeout);
- if (time <= 0 || host->sd_error) {
- cmd->error = sh_mmcif_error_manage(host);
- return;
- }
- sh_mmcif_get_cmd12response(host, cmd);
- cmd->error = 0;
+ host->wait_for = MMCIF_WAIT_FOR_STOP;
+ schedule_delayed_work(&host->timeout_work, host->timeout);
}
static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -856,23 +910,10 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
default:
break;
}
- host->data = mrq->data;
- if (mrq->data) {
- if (mrq->data->flags & MMC_DATA_READ) {
- if (host->chan_rx)
- sh_mmcif_start_dma_rx(host);
- } else {
- if (host->chan_tx)
- sh_mmcif_start_dma_tx(host);
- }
- }
- sh_mmcif_start_cmd(host, mrq, mrq->cmd);
- host->data = NULL;
- if (!mrq->cmd->error && mrq->stop)
- sh_mmcif_stop_cmd(host, mrq, mrq->stop);
- host->state = STATE_IDLE;
- mmc_request_done(mmc, mrq);
+ host->mrq = mrq;
+
+ sh_mmcif_start_cmd(host, mrq);
}
static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -947,9 +988,156 @@ static struct mmc_host_ops sh_mmcif_ops = {
.get_cd = sh_mmcif_get_cd,
};
-static void sh_mmcif_detect(struct mmc_host *mmc)
+static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
{
- mmc_detect_change(mmc, 0);
+ struct mmc_command *cmd = host->mrq->cmd;
+ struct mmc_data *data = host->mrq->data;
+ long time;
+
+ if (host->sd_error) {
+ switch (cmd->opcode) {
+ case MMC_ALL_SEND_CID:
+ case MMC_SELECT_CARD:
+ case MMC_APP_CMD:
+ cmd->error = -ETIMEDOUT;
+ host->sd_error = false;
+ break;
+ default:
+ cmd->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n",
+ cmd->opcode, cmd->error);
+ break;
+ }
+ return false;
+ }
+ if (!(cmd->flags & MMC_RSP_PRESENT)) {
+ cmd->error = 0;
+ return false;
+ }
+
+ sh_mmcif_get_response(host, cmd);
+
+ if (!data)
+ return false;
+
+ if (data->flags & MMC_DATA_READ) {
+ if (host->chan_rx)
+ sh_mmcif_start_dma_rx(host);
+ } else {
+ if (host->chan_tx)
+ sh_mmcif_start_dma_tx(host);
+ }
+
+ if (!host->dma_active) {
+ data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode);
+ if (!data->error)
+ return true;
+ return false;
+ }
+
+ /* Running in the IRQ thread, can sleep */
+ time = wait_for_completion_interruptible_timeout(&host->dma_complete,
+ host->timeout);
+ if (host->sd_error) {
+ dev_err(host->mmc->parent,
+ "Error IRQ while waiting for DMA completion!\n");
+ /* Woken up by an error IRQ: abort DMA */
+ if (data->flags & MMC_DATA_READ)
+ dmaengine_terminate_all(host->chan_rx);
+ else
+ dmaengine_terminate_all(host->chan_tx);
+ data->error = sh_mmcif_error_manage(host);
+ } else if (!time) {
+ data->error = -ETIMEDOUT;
+ } else if (time < 0) {
+ data->error = time;
+ }
+ sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
+ BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
+ host->dma_active = false;
+
+ if (data->error)
+ data->bytes_xfered = 0;
+
+ return false;
+}
+
+static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
+{
+ struct sh_mmcif_host *host = dev_id;
+ struct mmc_request *mrq = host->mrq;
+ struct mmc_data *data = mrq->data;
+
+ cancel_delayed_work_sync(&host->timeout_work);
+
+ /*
+ * All handlers return true, if processing continues, and false, if the
+ * request has to be completed - successfully or not
+ */
+ switch (host->wait_for) {
+ case MMCIF_WAIT_FOR_REQUEST:
+ /* We're too late, the timeout has already kicked in */
+ return IRQ_HANDLED;
+ case MMCIF_WAIT_FOR_CMD:
+ if (sh_mmcif_end_cmd(host))
+ /* Wait for data */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_MREAD:
+ if (sh_mmcif_mread_block(host))
+ /* Wait for more data */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_READ:
+ if (sh_mmcif_read_block(host))
+ /* Wait for data end */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_MWRITE:
+ if (sh_mmcif_mwrite_block(host))
+ /* Wait data to write */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_WRITE:
+ if (sh_mmcif_write_block(host))
+ /* Wait for data end */
+ return IRQ_HANDLED;
+ break;
+ case MMCIF_WAIT_FOR_STOP:
+ if (host->sd_error) {
+ mrq->stop->error = sh_mmcif_error_manage(host);
+ break;
+ }
+ sh_mmcif_get_cmd12response(host, mrq->stop);
+ mrq->stop->error = 0;
+ break;
+ case MMCIF_WAIT_FOR_READ_END:
+ case MMCIF_WAIT_FOR_WRITE_END:
+ if (host->sd_error)
+ data->error = sh_mmcif_error_manage(host);
+ break;
+ default:
+ BUG();
+ }
+
+ if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
+ if (!mrq->cmd->error && data && !data->error)
+ data->bytes_xfered =
+ data->blocks * data->blksz;
+
+ if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) {
+ sh_mmcif_stop_cmd(host, mrq);
+ if (!mrq->stop->error)
+ return IRQ_HANDLED;
+ }
+ }
+
+ host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+ host->state = STATE_IDLE;
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, mrq);
+
+ return IRQ_HANDLED;
}
static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
@@ -960,7 +1148,12 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
- if (state & INT_RBSYE) {
+ if (state & INT_ERR_STS) {
+ /* error interrupts - process first */
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
+ sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
+ err = 1;
+ } else if (state & INT_RBSYE) {
sh_mmcif_writel(host->addr, MMCIF_CE_INT,
~(INT_RBSYE | INT_CRSPE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
@@ -988,11 +1181,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
sh_mmcif_writel(host->addr, MMCIF_CE_INT,
~(INT_CMD12RBE | INT_CMD12CRE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
- } else if (state & INT_ERR_STS) {
- /* err interrupts */
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
- err = 1;
} else {
dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state);
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
@@ -1003,14 +1191,57 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
host->sd_error = true;
dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
}
- if (state & ~(INT_CMD12RBE | INT_CMD12CRE))
- complete(&host->intr_wait);
- else
+ if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
+ if (!host->dma_active)
+ return IRQ_WAKE_THREAD;
+ else if (host->sd_error)
+ mmcif_dma_complete(host);
+ } else {
dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state);
+ }
return IRQ_HANDLED;
}
+static void mmcif_timeout_work(struct work_struct *work)
+{
+ struct delayed_work *d = container_of(work, struct delayed_work, work);
+ struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work);
+ struct mmc_request *mrq = host->mrq;
+
+ if (host->dying)
+ /* Don't run after mmc_remove_host() */
+ return;
+
+ /*
+ * Handle races with cancel_delayed_work(), unless
+ * cancel_delayed_work_sync() is used
+ */
+ switch (host->wait_for) {
+ case MMCIF_WAIT_FOR_CMD:
+ mrq->cmd->error = sh_mmcif_error_manage(host);
+ break;
+ case MMCIF_WAIT_FOR_STOP:
+ mrq->stop->error = sh_mmcif_error_manage(host);
+ break;
+ case MMCIF_WAIT_FOR_MREAD:
+ case MMCIF_WAIT_FOR_MWRITE:
+ case MMCIF_WAIT_FOR_READ:
+ case MMCIF_WAIT_FOR_WRITE:
+ case MMCIF_WAIT_FOR_READ_END:
+ case MMCIF_WAIT_FOR_WRITE_END:
+ mrq->data->error = sh_mmcif_error_manage(host);
+ break;
+ default:
+ BUG();
+ }
+
+ host->state = STATE_IDLE;
+ host->wait_for = MMCIF_WAIT_FOR_REQUEST;
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, mrq);
+}
+
static int __devinit sh_mmcif_probe(struct platform_device *pdev)
{
int ret = 0, irq[2];
@@ -1064,7 +1295,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
host->clk = clk_get_rate(host->hclk);
host->pd = pdev;
- init_completion(&host->intr_wait);
spin_lock_init(&host->lock);
mmc->ops = &sh_mmcif_ops;
@@ -1101,19 +1331,21 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
- ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
+ ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
if (ret) {
dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
goto clean_up3;
}
- ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
+ ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
if (ret) {
free_irq(irq[0], host);
dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
goto clean_up3;
}
- sh_mmcif_detect(host->mmc);
+ INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
+
+ mmc_detect_change(host->mmc, 0);
dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
dev_dbg(&pdev->dev, "chip ver H'%04x\n",
@@ -1139,11 +1371,19 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
int irq[2];
+ host->dying = true;
pm_runtime_get_sync(&pdev->dev);
mmc_remove_host(host->mmc);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+ /*
+ * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the
+ * mmc_remove_host() call above. But swapping order doesn't help either
+ * (a query on the linux-mmc mailing list didn't bring any replies).
+ */
+ cancel_delayed_work_sync(&host->timeout_work);
+
if (host->addr)
iounmap(host->addr);
@@ -1206,19 +1446,7 @@ static struct platform_driver sh_mmcif_driver = {
},
};
-static int __init sh_mmcif_init(void)
-{
- return platform_driver_register(&sh_mmcif_driver);
-}
-
-static void __exit sh_mmcif_exit(void)
-{
- platform_driver_unregister(&sh_mmcif_driver);
-}
-
-module_init(sh_mmcif_init);
-module_exit(sh_mmcif_exit);
-
+module_platform_driver(sh_mmcif_driver);
MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 41ae646..58da3c4 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -282,18 +282,7 @@ static struct platform_driver sh_mobile_sdhi_driver = {
.remove = __devexit_p(sh_mobile_sdhi_remove),
};
-static int __init sh_mobile_sdhi_init(void)
-{
- return platform_driver_register(&sh_mobile_sdhi_driver);
-}
-
-static void __exit sh_mobile_sdhi_exit(void)
-{
- platform_driver_unregister(&sh_mobile_sdhi_driver);
-}
-
-module_init(sh_mobile_sdhi_init);
-module_exit(sh_mobile_sdhi_exit);
+module_platform_driver(sh_mobile_sdhi_driver);
MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
MODULE_AUTHOR("Magnus Damm");
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index f70d046..43d9628 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -22,8 +22,8 @@
#define DRIVER_NAME "tifm_sd"
#define DRIVER_VERSION "0.8"
-static int no_dma = 0;
-static int fixed_timeout = 0;
+static bool no_dma = 0;
+static bool fixed_timeout = 0;
module_param(no_dma, bool, 0644);
module_param(fixed_timeout, bool, 0644);
@@ -118,7 +118,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg,
unsigned char *buf;
unsigned int pos = 0, val;
- buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off;
+ buf = kmap_atomic(pg) + off;
if (host->cmd_flags & DATA_CARRY) {
buf[pos++] = host->bounce_buf_data[0];
host->cmd_flags &= ~DATA_CARRY;
@@ -134,7 +134,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg,
}
buf[pos++] = (val >> 8) & 0xff;
}
- kunmap_atomic(buf - off, KM_BIO_DST_IRQ);
+ kunmap_atomic(buf - off);
}
static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
@@ -144,7 +144,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
unsigned char *buf;
unsigned int pos = 0, val;
- buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off;
+ buf = kmap_atomic(pg) + off;
if (host->cmd_flags & DATA_CARRY) {
val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00);
writel(val, sock->addr + SOCK_MMCSD_DATA);
@@ -161,7 +161,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
val |= (buf[pos++] << 8) & 0xff00;
writel(val, sock->addr + SOCK_MMCSD_DATA);
}
- kunmap_atomic(buf - off, KM_BIO_SRC_IRQ);
+ kunmap_atomic(buf - off);
}
static void tifm_sd_transfer_data(struct tifm_sd *host)
@@ -212,13 +212,13 @@ static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off,
struct page *src, unsigned int src_off,
unsigned int count)
{
- unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off;
- unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off;
+ unsigned char *src_buf = kmap_atomic(src) + src_off;
+ unsigned char *dst_buf = kmap_atomic(dst) + dst_off;
memcpy(dst_buf, src_buf, count);
- kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ);
- kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ);
+ kunmap_atomic(dst_buf - dst_off);
+ kunmap_atomic(src_buf - src_off);
}
static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data)
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index a4ea102..113ce6c 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -138,19 +138,7 @@ static struct platform_driver tmio_mmc_driver = {
.resume = tmio_mmc_resume,
};
-
-static int __init tmio_mmc_init(void)
-{
- return platform_driver_register(&tmio_mmc_driver);
-}
-
-static void __exit tmio_mmc_exit(void)
-{
- platform_driver_unregister(&tmio_mmc_driver);
-}
-
-module_init(tmio_mmc_init);
-module_exit(tmio_mmc_exit);
+module_platform_driver(tmio_mmc_driver);
MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver");
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 3020f98..a95e6d9 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -105,13 +105,13 @@ static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
unsigned long *flags)
{
local_irq_save(*flags);
- return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ return kmap_atomic(sg_page(sg)) + sg->offset;
}
static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
unsigned long *flags, void *virt)
{
- kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
+ kunmap_atomic(virt - sg->offset);
local_irq_restore(*flags);
}
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c
index 86f259c..7a6e6cc 100644
--- a/drivers/mmc/host/tmio_mmc_dma.c
+++ b/drivers/mmc/host/tmio_mmc_dma.c
@@ -77,7 +77,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
if (ret > 0)
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
- DMA_FROM_DEVICE, DMA_CTRL_ACK);
+ DMA_DEV_TO_MEM, DMA_CTRL_ACK);
if (desc) {
cookie = dmaengine_submit(desc);
@@ -158,7 +158,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
if (ret > 0)
desc = chan->device->device_prep_slave_sg(chan, sg, ret,
- DMA_TO_DEVICE, DMA_CTRL_ACK);
+ DMA_MEM_TO_DEV, DMA_CTRL_ACK);
if (desc) {
cookie = dmaengine_submit(desc);
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 4208b39..abad01b 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -800,8 +800,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} else if (ios->power_mode != MMC_POWER_UP) {
if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
host->set_pwr(host->pdev, 0);
- if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) &&
- pdata->power) {
+ if (pdata->power) {
pdata->power = false;
pm_runtime_put(&host->pdev->dev);
}
@@ -915,6 +914,23 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
if (ret < 0)
goto pm_disable;
+ /*
+ * There are 4 different scenarios for the card detection:
+ * 1) an external gpio irq handles the cd (best for power savings)
+ * 2) internal sdhi irq handles the cd
+ * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
+ * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
+ *
+ * While we increment the rtpm counter for all scenarios when the mmc
+ * core activates us by calling an appropriate set_ios(), we must
+ * additionally ensure that in case 2) the tmio mmc hardware stays
+ * powered on during runtime for the card detection to work.
+ */
+ if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD
+ || mmc->caps & MMC_CAP_NEEDS_POLL
+ || mmc->caps & MMC_CAP_NONREMOVABLE))
+ pm_runtime_get_noresume(&pdev->dev);
+
tmio_mmc_clk_stop(_host);
tmio_mmc_reset(_host);
@@ -933,12 +949,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
/* See if we also get DMA */
tmio_mmc_request_dma(_host, pdata);
- /* We have to keep the device powered for its card detection to work */
- if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) {
- pdata->power = true;
- pm_runtime_get_noresume(&pdev->dev);
- }
-
mmc_add_host(mmc);
/* Unmask the IRQs we want to know about */
@@ -974,7 +984,9 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
* the controller, the runtime PM is suspended and pdata->power == false,
* so, our .runtime_resume() will not try to detect a card in the slot.
*/
- if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD)
+ if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD
+ || host->mmc->caps & MMC_CAP_NEEDS_POLL
+ || host->mmc->caps & MMC_CAP_NONREMOVABLE)
pm_runtime_get_sync(&pdev->dev);
mmc_remove_host(host->mmc);
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index 2ec978b..3135a1a 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -223,25 +223,25 @@ enum SD_RESPONSE_TYPE {
#define FUN(c) (0x000007 & (c->arg>>28))
#define REG(c) (0x01FFFF & (c->arg>>9))
-static int limit_speed_to_24_MHz;
+static bool limit_speed_to_24_MHz;
module_param(limit_speed_to_24_MHz, bool, 0644);
MODULE_PARM_DESC(limit_speed_to_24_MHz, "Limit Max SDIO Clock Speed to 24 MHz");
-static int pad_input_to_usb_pkt;
+static bool pad_input_to_usb_pkt;
module_param(pad_input_to_usb_pkt, bool, 0644);
MODULE_PARM_DESC(pad_input_to_usb_pkt,
"Pad USB data input transfers to whole USB Packet");
-static int disable_offload_processing;
+static bool disable_offload_processing;
module_param(disable_offload_processing, bool, 0644);
MODULE_PARM_DESC(disable_offload_processing, "Disable Offload Processing");
-static int force_1_bit_data_xfers;
+static bool force_1_bit_data_xfers;
module_param(force_1_bit_data_xfers, bool, 0644);
MODULE_PARM_DESC(force_1_bit_data_xfers,
"Force SDIO Data Transfers to 1-bit Mode");
-static int force_polling_for_irqs;
+static bool force_polling_for_irqs;
module_param(force_polling_for_irqs, bool, 0644);
MODULE_PARM_DESC(force_polling_for_irqs, "Force Polling for SDIO interrupts");
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index db8e827..3ce99e0 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -315,8 +315,7 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper,
char *dst;
if (reason != KMSG_DUMP_OOPS &&
- reason != KMSG_DUMP_PANIC &&
- reason != KMSG_DUMP_KEXEC)
+ reason != KMSG_DUMP_PANIC)
return;
/* Only dump oopses if dump_oops is set */
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 7dd3700..73abbc3 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -17,35 +17,19 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1550nd.h>
-#ifdef CONFIG_MIPS_PB1550
-#include <asm/mach-pb1x00/pb1550.h>
-#elif defined(CONFIG_MIPS_DB1550)
-#include <asm/mach-db1x00/db1x00.h>
-#endif
-#include <asm/mach-db1x00/bcsr.h>
-/*
- * MTD structure for NAND controller
- */
-static struct mtd_info *au1550_mtd = NULL;
-static void __iomem *p_nand;
-static int nand_width = 1; /* default x8 */
-static void (*au1550_write_byte)(struct mtd_info *, u_char);
+struct au1550nd_ctx {
+ struct mtd_info info;
+ struct nand_chip chip;
-/*
- * Define partitions for flash device
- */
-static const struct mtd_partition partition_info[] = {
- {
- .name = "NAND FS 0",
- .offset = 0,
- .size = 8 * 1024 * 1024},
- {
- .name = "NAND FS 1",
- .offset = MTDPART_OFS_APPEND,
- .size = MTDPART_SIZ_FULL}
+ int cs;
+ void __iomem *base;
+ void (*write_byte)(struct mtd_info *, u_char);
};
/**
@@ -259,24 +243,25 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
{
- register struct nand_chip *this = mtd->priv;
+ struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info);
+ struct nand_chip *this = mtd->priv;
switch (cmd) {
case NAND_CTL_SETCLE:
- this->IO_ADDR_W = p_nand + MEM_STNAND_CMD;
+ this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
break;
case NAND_CTL_CLRCLE:
- this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
+ this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
break;
case NAND_CTL_SETALE:
- this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR;
+ this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
break;
case NAND_CTL_CLRALE:
- this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
+ this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
/* FIXME: Nobody knows why this is necessary,
* but it works only that way */
udelay(1);
@@ -284,7 +269,7 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
case NAND_CTL_SETNCE:
/* assert (force assert) chip enable */
- au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
+ au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
break;
case NAND_CTL_CLRNCE:
@@ -331,9 +316,10 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip)
*/
static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
- register struct nand_chip *this = mtd->priv;
+ struct au1550nd_ctx *ctx = container_of(mtd, struct au1550nd_ctx, info);
+ struct nand_chip *this = mtd->priv;
int ce_override = 0, i;
- ulong flags;
+ unsigned long flags = 0;
/* Begin command latch cycle */
au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
@@ -354,9 +340,9 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
column -= 256;
readcmd = NAND_CMD_READ1;
}
- au1550_write_byte(mtd, readcmd);
+ ctx->write_byte(mtd, readcmd);
}
- au1550_write_byte(mtd, command);
+ ctx->write_byte(mtd, command);
/* Set ALE and clear CLE to start address cycle */
au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
@@ -369,10 +355,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
/* Adjust columns for 16 bit buswidth */
if (this->options & NAND_BUSWIDTH_16)
column >>= 1;
- au1550_write_byte(mtd, column);
+ ctx->write_byte(mtd, column);
}
if (page_addr != -1) {
- au1550_write_byte(mtd, (u8)(page_addr & 0xff));
+ ctx->write_byte(mtd, (u8)(page_addr & 0xff));
if (command == NAND_CMD_READ0 ||
command == NAND_CMD_READ1 ||
@@ -390,11 +376,12 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
}
- au1550_write_byte(mtd, (u8)(page_addr >> 8));
+ ctx->write_byte(mtd, (u8)(page_addr >> 8));
/* One more address cycle for devices > 32MiB */
if (this->chipsize > (32 << 20))
- au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
+ ctx->write_byte(mtd,
+ ((page_addr >> 16) & 0x0f));
}
/* Latch in address */
au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
@@ -440,121 +427,79 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i
while(!this->dev_ready(mtd));
}
-
-/*
- * Main initialization routine
- */
-static int __init au1xxx_nand_init(void)
+static int __devinit find_nand_cs(unsigned long nand_base)
{
- struct nand_chip *this;
- u16 boot_swapboot = 0; /* default value */
- int retval;
- u32 mem_staddr;
- u32 nand_phys;
-
- /* Allocate memory for MTD device structure and private data */
- au1550_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
- if (!au1550_mtd) {
- printk("Unable to allocate NAND MTD dev structure.\n");
- return -ENOMEM;
- }
-
- /* Get pointer to private data */
- this = (struct nand_chip *)(&au1550_mtd[1]);
-
- /* Link the private data with the MTD structure */
- au1550_mtd->priv = this;
- au1550_mtd->owner = THIS_MODULE;
-
+ void __iomem *base =
+ (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
+ unsigned long addr, staddr, start, mask, end;
+ int i;
- /* MEM_STNDCTL: disable ints, disable nand boot */
- au_writel(0, MEM_STNDCTL);
+ for (i = 0; i < 4; i++) {
+ addr = 0x1000 + (i * 0x10); /* CSx */
+ staddr = __raw_readl(base + addr + 0x08); /* STADDRx */
+ /* figure out the decoded range of this CS */
+ start = (staddr << 4) & 0xfffc0000;
+ mask = (staddr << 18) & 0xfffc0000;
+ end = (start | (start - 1)) & ~(start ^ mask);
+ if ((nand_base >= start) && (nand_base < end))
+ return i;
+ }
-#ifdef CONFIG_MIPS_PB1550
- /* set gpio206 high */
- gpio_direction_input(206);
+ return -ENODEV;
+}
- boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
+static int __devinit au1550nd_probe(struct platform_device *pdev)
+{
+ struct au1550nd_platdata *pd;
+ struct au1550nd_ctx *ctx;
+ struct nand_chip *this;
+ struct resource *r;
+ int ret, cs;
- switch (boot_swapboot) {
- case 0:
- case 2:
- case 8:
- case 0xC:
- case 0xD:
- /* x16 NAND Flash */
- nand_width = 0;
- break;
- case 1:
- case 9:
- case 3:
- case 0xE:
- case 0xF:
- /* x8 NAND Flash */
- nand_width = 1;
- break;
- default:
- printk("Pb1550 NAND: bad boot:swap\n");
- retval = -EINVAL;
- goto outmem;
+ pd = pdev->dev.platform_data;
+ if (!pd) {
+ dev_err(&pdev->dev, "missing platform data\n");
+ return -ENODEV;
}
-#endif
-
- /* Configure chip-select; normally done by boot code, e.g. YAMON */
-#ifdef NAND_STCFG
- if (NAND_CS == 0) {
- au_writel(NAND_STCFG, MEM_STCFG0);
- au_writel(NAND_STTIME, MEM_STTIME0);
- au_writel(NAND_STADDR, MEM_STADDR0);
- }
- if (NAND_CS == 1) {
- au_writel(NAND_STCFG, MEM_STCFG1);
- au_writel(NAND_STTIME, MEM_STTIME1);
- au_writel(NAND_STADDR, MEM_STADDR1);
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ dev_err(&pdev->dev, "no memory for NAND context\n");
+ return -ENOMEM;
}
- if (NAND_CS == 2) {
- au_writel(NAND_STCFG, MEM_STCFG2);
- au_writel(NAND_STTIME, MEM_STTIME2);
- au_writel(NAND_STADDR, MEM_STADDR2);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no NAND memory resource\n");
+ ret = -ENODEV;
+ goto out1;
}
- if (NAND_CS == 3) {
- au_writel(NAND_STCFG, MEM_STCFG3);
- au_writel(NAND_STTIME, MEM_STTIME3);
- au_writel(NAND_STADDR, MEM_STADDR3);
+ if (request_mem_region(r->start, resource_size(r), "au1550-nand")) {
+ dev_err(&pdev->dev, "cannot claim NAND memory area\n");
+ ret = -ENOMEM;
+ goto out1;
}
-#endif
-
- /* Locate NAND chip-select in order to determine NAND phys address */
- mem_staddr = 0x00000000;
- if (((au_readl(MEM_STCFG0) & 0x7) == 0x5) && (NAND_CS == 0))
- mem_staddr = au_readl(MEM_STADDR0);
- else if (((au_readl(MEM_STCFG1) & 0x7) == 0x5) && (NAND_CS == 1))
- mem_staddr = au_readl(MEM_STADDR1);
- else if (((au_readl(MEM_STCFG2) & 0x7) == 0x5) && (NAND_CS == 2))
- mem_staddr = au_readl(MEM_STADDR2);
- else if (((au_readl(MEM_STCFG3) & 0x7) == 0x5) && (NAND_CS == 3))
- mem_staddr = au_readl(MEM_STADDR3);
-
- if (mem_staddr == 0x00000000) {
- printk("Au1xxx NAND: ERROR WITH NAND CHIP-SELECT\n");
- kfree(au1550_mtd);
- return 1;
+
+ ctx->base = ioremap_nocache(r->start, 0x1000);
+ if (!ctx->base) {
+ dev_err(&pdev->dev, "cannot remap NAND memory area\n");
+ ret = -ENODEV;
+ goto out2;
}
- nand_phys = (mem_staddr << 4) & 0xFFFC0000;
- p_nand = ioremap(nand_phys, 0x1000);
+ this = &ctx->chip;
+ ctx->info.priv = this;
+ ctx->info.owner = THIS_MODULE;
- /* make controller and MTD agree */
- if (NAND_CS == 0)
- nand_width = au_readl(MEM_STCFG0) & (1 << 22);
- if (NAND_CS == 1)
- nand_width = au_readl(MEM_STCFG1) & (1 << 22);
- if (NAND_CS == 2)
- nand_width = au_readl(MEM_STCFG2) & (1 << 22);
- if (NAND_CS == 3)
- nand_width = au_readl(MEM_STCFG3) & (1 << 22);
+ /* figure out which CS# r->start belongs to */
+ cs = find_nand_cs(r->start);
+ if (cs < 0) {
+ dev_err(&pdev->dev, "cannot detect NAND chipselect\n");
+ ret = -ENODEV;
+ goto out3;
+ }
+ ctx->cs = cs;
- /* Set address of hardware control function */
this->dev_ready = au1550_device_ready;
this->select_chip = au1550_select_chip;
this->cmdfunc = au1550_command;
@@ -565,54 +510,57 @@ static int __init au1xxx_nand_init(void)
this->options = NAND_NO_AUTOINCR;
- if (!nand_width)
+ if (pd->devwidth)
this->options |= NAND_BUSWIDTH_16;
- this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
- au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
+ this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
+ ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte;
this->read_word = au_read_word;
- this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
- this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
- this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
-
- /* Scan to find existence of the device */
- if (nand_scan(au1550_mtd, 1)) {
- retval = -ENXIO;
- goto outio;
+ this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
+ this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
+ this->verify_buf = (pd->devwidth) ? au_verify_buf16 : au_verify_buf;
+
+ ret = nand_scan(&ctx->info, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
+ goto out3;
}
- /* Register the partitions */
- mtd_device_register(au1550_mtd, partition_info,
- ARRAY_SIZE(partition_info));
+ mtd_device_register(&ctx->info, pd->parts, pd->num_parts);
return 0;
- outio:
- iounmap(p_nand);
-
- outmem:
- kfree(au1550_mtd);
- return retval;
+out3:
+ iounmap(ctx->base);
+out2:
+ release_mem_region(r->start, resource_size(r));
+out1:
+ kfree(ctx);
+ return ret;
}
-module_init(au1xxx_nand_init);
-
-/*
- * Clean up routine
- */
-static void __exit au1550_cleanup(void)
+static int __devexit au1550nd_remove(struct platform_device *pdev)
{
- /* Release resources, unregister device */
- nand_release(au1550_mtd);
+ struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
+ struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- /* Free the MTD device structure */
- kfree(au1550_mtd);
-
- /* Unmap */
- iounmap(p_nand);
+ nand_release(&ctx->info);
+ iounmap(ctx->base);
+ release_mem_region(r->start, 0x1000);
+ kfree(ctx);
+ return 0;
}
-module_exit(au1550_cleanup);
+static struct platform_driver au1550nd_driver = {
+ .driver = {
+ .name = "au1550-nand",
+ .owner = THIS_MODULE,
+ },
+ .probe = au1550nd_probe,
+ .remove = __devexit_p(au1550nd_remove),
+};
+
+module_platform_driver(au1550nd_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Embedded Edge, LLC");
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 2a56fc6..7f68042 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -827,7 +827,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
pio[1] = pio[2] = 0;
desc = channel->device->device_prep_slave_sg(channel,
(struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_NONE, 0);
+ ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
if (!desc) {
pr_err("step 1 error\n");
return -1;
@@ -839,7 +839,7 @@ int gpmi_send_command(struct gpmi_nand_data *this)
sg_init_one(sgl, this->cmd_buffer, this->command_length);
dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
desc = channel->device->device_prep_slave_sg(channel,
- sgl, 1, DMA_TO_DEVICE, 1);
+ sgl, 1, DMA_MEM_TO_DEV, 1);
if (!desc) {
pr_err("step 2 error\n");
return -1;
@@ -872,7 +872,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
pio[1] = 0;
desc = channel->device->device_prep_slave_sg(channel,
(struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_NONE, 0);
+ ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
if (!desc) {
pr_err("step 1 error\n");
return -1;
@@ -881,7 +881,7 @@ int gpmi_send_data(struct gpmi_nand_data *this)
/* [2] send DMA request */
prepare_data_dma(this, DMA_TO_DEVICE);
desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_TO_DEVICE, 1);
+ 1, DMA_MEM_TO_DEV, 1);
if (!desc) {
pr_err("step 2 error\n");
return -1;
@@ -908,7 +908,7 @@ int gpmi_read_data(struct gpmi_nand_data *this)
pio[1] = 0;
desc = channel->device->device_prep_slave_sg(channel,
(struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_NONE, 0);
+ ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
if (!desc) {
pr_err("step 1 error\n");
return -1;
@@ -917,7 +917,7 @@ int gpmi_read_data(struct gpmi_nand_data *this)
/* [2] : send DMA request */
prepare_data_dma(this, DMA_FROM_DEVICE);
desc = channel->device->device_prep_slave_sg(channel, &this->data_sgl,
- 1, DMA_FROM_DEVICE, 1);
+ 1, DMA_DEV_TO_MEM, 1);
if (!desc) {
pr_err("step 2 error\n");
return -1;
@@ -964,7 +964,7 @@ int gpmi_send_page(struct gpmi_nand_data *this,
desc = channel->device->device_prep_slave_sg(channel,
(struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_NONE, 0);
+ ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
if (!desc) {
pr_err("step 2 error\n");
return -1;
@@ -998,7 +998,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
| BF_GPMI_CTRL0_XFER_COUNT(0);
pio[1] = 0;
desc = channel->device->device_prep_slave_sg(channel,
- (struct scatterlist *)pio, 2, DMA_NONE, 0);
+ (struct scatterlist *)pio, 2,
+ DMA_TRANS_NONE, 0);
if (!desc) {
pr_err("step 1 error\n");
return -1;
@@ -1027,7 +1028,7 @@ int gpmi_read_page(struct gpmi_nand_data *this,
pio[5] = auxiliary;
desc = channel->device->device_prep_slave_sg(channel,
(struct scatterlist *)pio,
- ARRAY_SIZE(pio), DMA_NONE, 1);
+ ARRAY_SIZE(pio), DMA_TRANS_NONE, 1);
if (!desc) {
pr_err("step 2 error\n");
return -1;
@@ -1045,7 +1046,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size);
pio[1] = 0;
desc = channel->device->device_prep_slave_sg(channel,
- (struct scatterlist *)pio, 2, DMA_NONE, 1);
+ (struct scatterlist *)pio, 2,
+ DMA_TRANS_NONE, 1);
if (!desc) {
pr_err("step 3 error\n");
return -1;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 8544d6b..5c3d719 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -185,7 +185,7 @@ struct pxa3xx_nand_info {
uint32_t ndcb2;
};
-static int use_dma = 1;
+static bool use_dma = 1;
module_param(use_dma, bool, 0444);
MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW");
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index f20f393..769a4e0 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -22,7 +22,7 @@
#include "r852.h"
-static int r852_enable_dma = 1;
+static bool r852_enable_dma = 1;
module_param(r852_enable_dma, bool, S_IRUGO);
MODULE_PARM_DESC(r852_enable_dma, "Enable usage of the DMA (default)");
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 3320a50..ad76592 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -632,6 +632,9 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
if (req->alignment != 1 && n)
goto bad;
+ if (!req->name[0] || !req->name_len)
+ goto bad;
+
if (req->name_len > UBI_VOL_NAME_MAX) {
err = -ENAMETOOLONG;
goto bad;
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 64fbb00..ead2cd1 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -43,7 +43,10 @@
pr_debug("UBI DBG " type ": " fmt "\n", ##__VA_ARGS__)
/* Just a debugging messages not related to any specific UBI subsystem */
-#define dbg_msg(fmt, ...) ubi_dbg_msg("msg", fmt, ##__VA_ARGS__)
+#define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
+ current->pid, __func__, ##__VA_ARGS__)
+
/* General debugging messages */
#define dbg_gen(fmt, ...) ubi_dbg_msg("gen", fmt, ##__VA_ARGS__)
/* Messages from the eraseblock association sub-system */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fb7f19b..cd26da8 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1028,12 +1028,14 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
* 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
* holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
* LEB is already locked, we just do not move it and return
- * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later.
+ * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because
+ * we do not know the reasons of the contention - it may be just a
+ * normal I/O on this LEB, so we want to re-try.
*/
err = leb_write_trylock(ubi, vol_id, lnum);
if (err) {
dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
- return MOVE_CANCEL_RACE;
+ return MOVE_RETRY;
}
/*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index dc64c76..d51d75d 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -120,6 +120,7 @@ enum {
* PEB
* MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
* target PEB
+ * MOVE_RETRY: retry scrubbing the PEB
*/
enum {
MOVE_CANCEL_RACE = 1,
@@ -127,6 +128,7 @@ enum {
MOVE_TARGET_RD_ERR,
MOVE_TARGET_WR_ERR,
MOVE_CANCEL_BITFLIPS,
+ MOVE_RETRY,
};
/**
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 9ad18da..17cec0c 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -306,7 +306,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
int copy, void *vtbl)
{
int err, tries = 0;
- static struct ubi_vid_hdr *vid_hdr;
+ struct ubi_vid_hdr *vid_hdr;
struct ubi_scan_leb *new_seb;
ubi_msg("create volume table (copy #%d)", copy + 1);
@@ -322,7 +322,7 @@ retry:
goto out_free;
}
- vid_hdr->vol_type = UBI_VID_DYNAMIC;
+ vid_hdr->vol_type = UBI_LAYOUT_VOLUME_TYPE;
vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID);
vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT;
vid_hdr->data_size = vid_hdr->used_ebs =
@@ -632,7 +632,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
return -ENOMEM;
vol->reserved_pebs = UBI_LAYOUT_VOLUME_EBS;
- vol->alignment = 1;
+ vol->alignment = UBI_LAYOUT_VOLUME_ALIGN;
vol->vol_type = UBI_DYNAMIC_VOLUME;
vol->name_len = sizeof(UBI_LAYOUT_VOLUME_NAME) - 1;
memcpy(vol->name, UBI_LAYOUT_VOLUME_NAME, vol->name_len + 1);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 42c684c..0696e36 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -795,7 +795,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
protect = 1;
goto out_not_moved;
}
-
+ if (err == MOVE_RETRY) {
+ scrubbing = 1;
+ goto out_not_moved;
+ }
if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
err == MOVE_TARGET_RD_ERR) {
/*
@@ -1049,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
ubi_err("failed to erase PEB %d, error %d", pnum, err);
kfree(wl_wrk);
- kmem_cache_free(ubi_wl_entry_slab, e);
if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
err == -EBUSY) {
@@ -1062,14 +1064,16 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
goto out_ro;
}
return err;
- } else if (err != -EIO) {
+ }
+
+ kmem_cache_free(ubi_wl_entry_slab, e);
+ if (err != -EIO)
/*
* If this is not %-EIO, we have no idea what to do. Scheduling
* this physical eraseblock for erasure again would cause
* errors again and again. Well, lets switch to R/O mode.
*/
goto out_ro;
- }
/* It is %-EIO, the PEB went bad */
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 106b88a..342626f 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -99,16 +99,26 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
/*********************** tlb specific functions ***************************/
-static inline void _lock_tx_hashtbl(struct bonding *bond)
+static inline void _lock_tx_hashtbl_bh(struct bonding *bond)
{
spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
-static inline void _unlock_tx_hashtbl(struct bonding *bond)
+static inline void _unlock_tx_hashtbl_bh(struct bonding *bond)
{
spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
+static inline void _lock_tx_hashtbl(struct bonding *bond)
+{
+ spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+}
+
+static inline void _unlock_tx_hashtbl(struct bonding *bond)
+{
+ spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+}
+
/* Caller must hold tx_hashtbl lock */
static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
{
@@ -129,14 +139,13 @@ static inline void tlb_init_slave(struct slave *slave)
SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX;
}
-/* Caller must hold bond lock for read */
-static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_load)
+/* Caller must hold bond lock for read, BH disabled */
+static void __tlb_clear_slave(struct bonding *bond, struct slave *slave,
+ int save_load)
{
struct tlb_client_info *tx_hash_table;
u32 index;
- _lock_tx_hashtbl(bond);
-
/* clear slave from tx_hashtbl */
tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
@@ -151,8 +160,15 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
}
tlb_init_slave(slave);
+}
- _unlock_tx_hashtbl(bond);
+/* Caller must hold bond lock for read */
+static void tlb_clear_slave(struct bonding *bond, struct slave *slave,
+ int save_load)
+{
+ _lock_tx_hashtbl_bh(bond);
+ __tlb_clear_slave(bond, slave, save_load);
+ _unlock_tx_hashtbl_bh(bond);
}
/* Must be called before starting the monitor timer */
@@ -169,7 +185,7 @@ static int tlb_initialize(struct bonding *bond)
bond->dev->name);
return -1;
}
- _lock_tx_hashtbl(bond);
+ _lock_tx_hashtbl_bh(bond);
bond_info->tx_hashtbl = new_hashtbl;
@@ -177,7 +193,7 @@ static int tlb_initialize(struct bonding *bond)
tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
}
- _unlock_tx_hashtbl(bond);
+ _unlock_tx_hashtbl_bh(bond);
return 0;
}
@@ -187,12 +203,12 @@ static void tlb_deinitialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- _lock_tx_hashtbl(bond);
+ _lock_tx_hashtbl_bh(bond);
kfree(bond_info->tx_hashtbl);
bond_info->tx_hashtbl = NULL;
- _unlock_tx_hashtbl(bond);
+ _unlock_tx_hashtbl_bh(bond);
}
static long long compute_gap(struct slave *slave)
@@ -226,15 +242,13 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
return least_loaded;
}
-/* Caller must hold bond lock for read */
-static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index,
+ u32 skb_len)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct tlb_client_info *hash_table;
struct slave *assigned_slave;
- _lock_tx_hashtbl(bond);
-
hash_table = bond_info->tx_hashtbl;
assigned_slave = hash_table[hash_index].tx_slave;
if (!assigned_slave) {
@@ -263,22 +277,46 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
hash_table[hash_index].tx_bytes += skb_len;
}
- _unlock_tx_hashtbl(bond);
-
return assigned_slave;
}
+/* Caller must hold bond lock for read */
+static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index,
+ u32 skb_len)
+{
+ struct slave *tx_slave;
+ /*
+ * We don't need to disable softirq here, becase
+ * tlb_choose_channel() is only called by bond_alb_xmit()
+ * which already has softirq disabled.
+ */
+ _lock_tx_hashtbl(bond);
+ tx_slave = __tlb_choose_channel(bond, hash_index, skb_len);
+ _unlock_tx_hashtbl(bond);
+ return tx_slave;
+}
+
/*********************** rlb specific functions ***************************/
-static inline void _lock_rx_hashtbl(struct bonding *bond)
+static inline void _lock_rx_hashtbl_bh(struct bonding *bond)
{
spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
-static inline void _unlock_rx_hashtbl(struct bonding *bond)
+static inline void _unlock_rx_hashtbl_bh(struct bonding *bond)
{
spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
+static inline void _lock_rx_hashtbl(struct bonding *bond)
+{
+ spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+}
+
+static inline void _unlock_rx_hashtbl(struct bonding *bond)
+{
+ spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+}
+
/* when an ARP REPLY is received from a client update its info
* in the rx_hashtbl
*/
@@ -288,7 +326,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
struct rlb_client_info *client_info;
u32 hash_index;
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -303,7 +341,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
bond_info->rx_ntt = 1;
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond,
@@ -401,7 +439,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
u32 index, next_index;
/* clear slave from rx_hashtbl */
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
rx_hash_table = bond_info->rx_hashtbl;
index = bond_info->rx_hashtbl_head;
@@ -432,7 +470,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
}
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
write_lock_bh(&bond->curr_slave_lock);
@@ -489,7 +527,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
struct rlb_client_info *client_info;
u32 hash_index;
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
@@ -507,7 +545,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
*/
bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY;
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
/* The slave was assigned a new mac address - update the clients */
@@ -518,7 +556,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
int ntt = 0;
u32 hash_index;
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
@@ -538,7 +576,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
/* mark all clients using src_ip to be updated */
@@ -709,7 +747,7 @@ static void rlb_rebalance(struct bonding *bond)
int ntt;
u32 hash_index;
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
ntt = 0;
hash_index = bond_info->rx_hashtbl_head;
@@ -727,7 +765,7 @@ static void rlb_rebalance(struct bonding *bond)
if (ntt) {
bond_info->rx_ntt = 1;
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
/* Caller must hold rx_hashtbl lock */
@@ -751,7 +789,7 @@ static int rlb_initialize(struct bonding *bond)
bond->dev->name);
return -1;
}
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
bond_info->rx_hashtbl = new_hashtbl;
@@ -761,7 +799,7 @@ static int rlb_initialize(struct bonding *bond)
rlb_init_table_entry(bond_info->rx_hashtbl + i);
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
/* register to receive ARPs */
bond->recv_probe = rlb_arp_recv;
@@ -773,13 +811,13 @@ static void rlb_deinitialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
kfree(bond_info->rx_hashtbl);
bond_info->rx_hashtbl = NULL;
bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
@@ -787,7 +825,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 curr_index;
- _lock_rx_hashtbl(bond);
+ _lock_rx_hashtbl_bh(bond);
curr_index = bond_info->rx_hashtbl_head;
while (curr_index != RLB_NULL_INDEX) {
@@ -812,7 +850,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
curr_index = next_index;
}
- _unlock_rx_hashtbl(bond);
+ _unlock_rx_hashtbl_bh(bond);
}
/*********************** tlb/rlb shared functions *********************/
@@ -1320,7 +1358,9 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
} else {
if (tx_slave) {
- tlb_clear_slave(bond, tx_slave, 0);
+ _lock_tx_hashtbl(bond);
+ __tlb_clear_slave(bond, tx_slave, 0);
+ _unlock_tx_hashtbl(bond);
}
}
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 9e8ba4f..0f92e35 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -623,7 +623,8 @@ static int ax_mii_init(struct net_device *dev)
ax->mii_bus->name = "ax88796_mii_bus";
ax->mii_bus->parent = dev->dev.parent;
- snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, pdev->id);
ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!ax->mii_bus->irq) {
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index b6d69c9..d812a10 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -1670,7 +1670,8 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
miibus->name = "bfin_mii_bus";
miibus->phy_mask = mii_bus_pd->phy_mask;
- snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
+ snprintf(miibus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, pdev->id);
miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
if (!miibus->irq)
goto out_err_irq_alloc;
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index cc9262b..8b95dd3 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -1171,7 +1171,8 @@ static int __devinit au1000_probe(struct platform_device *pdev)
aup->mii_bus->write = au1000_mdiobus_write;
aup->mii_bus->reset = au1000_mdiobus_reset;
aup->mii_bus->name = "au1000_eth_mii";
- snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
+ snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, aup->mac_id);
aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
if (aup->mii_bus->irq == NULL)
goto err_out;
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index d44331e..986019b 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1727,7 +1727,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
bus->priv = priv;
bus->read = bcm_enet_mdio_read_phylib;
bus->write = bcm_enet_mdio_write_phylib;
- sprintf(bus->id, "%d", priv->mac_id);
+ sprintf(bus->id, "%s-%d", pdev->name, priv->mac_id);
/* only probe bus where we think the PHY is, because
* the mdio read operation return 0 instead of 0xffff
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index a688b9d97..f99c6e3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -365,13 +365,18 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
DP(NETIF_MSG_LINK, "cfg_idx = %x\n", cfg_idx);
if (cmd->autoneg == AUTONEG_ENABLE) {
+ u32 an_supported_speed = bp->port.supported[cfg_idx];
+ if (bp->link_params.phy[EXT_PHY1].type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ an_supported_speed |= (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full);
if (!(bp->port.supported[cfg_idx] & SUPPORTED_Autoneg)) {
DP(NETIF_MSG_LINK, "Autoneg not supported\n");
return -EINVAL;
}
/* advertise the requested speed and duplex if supported */
- if (cmd->advertising & ~(bp->port.supported[cfg_idx])) {
+ if (cmd->advertising & ~an_supported_speed) {
DP(NETIF_MSG_LINK, "Advertisement parameters "
"are not supported\n");
return -EINVAL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 4df9505..2091e5d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -2502,7 +2502,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
struct bnx2x_nig_brb_pfc_port_params *nig_params)
{
u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
- u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
+ u32 llfc_enable = 0, xcm_out_en = 0, hwpfc_enable = 0;
u32 pkt_priority_to_cos = 0;
struct bnx2x *bp = params->bp;
u8 port = params->port;
@@ -2516,9 +2516,8 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
* MAC control frames (that are not pause packets)
* will be forwarded to the XCM.
*/
- xcm_mask = REG_RD(bp,
- port ? NIG_REG_LLH1_XCM_MASK :
- NIG_REG_LLH0_XCM_MASK);
+ xcm_mask = REG_RD(bp, port ? NIG_REG_LLH1_XCM_MASK :
+ NIG_REG_LLH0_XCM_MASK);
/*
* nig params will override non PFC params, since it's possible to
* do transition from PFC to SAFC
@@ -2533,8 +2532,8 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
ppp_enable = 1;
xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
- xcm0_out_en = 0;
- p0_hwpfc_enable = 1;
+ xcm_out_en = 0;
+ hwpfc_enable = 1;
} else {
if (nig_params) {
llfc_out_en = nig_params->llfc_out_en;
@@ -2545,7 +2544,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
- xcm0_out_en = 1;
+ xcm_out_en = 1;
}
if (CHIP_IS_E3(bp))
@@ -2564,13 +2563,16 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
NIG_REG_LLH0_XCM_MASK, xcm_mask);
- REG_WR(bp, NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
+ REG_WR(bp, port ? NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 :
+ NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
/* output enable for RX_XCM # IF */
- REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
+ REG_WR(bp, port ? NIG_REG_XCM1_OUT_EN :
+ NIG_REG_XCM0_OUT_EN, xcm_out_en);
/* HW PFC TX enable */
- REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
+ REG_WR(bp, port ? NIG_REG_P1_HWPFC_ENABLE :
+ NIG_REG_P0_HWPFC_ENABLE, hwpfc_enable);
if (nig_params) {
u8 i = 0;
@@ -3761,7 +3763,15 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertise pause */
bnx2x_ext_phy_set_pause(params, phy, vars);
- vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+ /*
+ * Set KR Autoneg Work-Around flag for Warpcore version older than D108
+ */
+ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
+ if (val16 < 0xd108) {
+ DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+ vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+ }
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, &val16);
@@ -9266,62 +9276,68 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
/* BCM8481/BCM84823/BCM84833 PHY SECTION */
/******************************************************************/
static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
- struct link_params *params)
+ struct bnx2x *bp,
+ u8 port)
{
u16 val, fw_ver1, fw_ver2, cnt;
- u8 port;
- struct bnx2x *bp = params->bp;
- port = params->port;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
+ bnx2x_save_spirom_version(bp, port,
+ ((fw_ver1 & 0xf000)>>5) | (fw_ver1 & 0x7f),
+ phy->ver_addr);
+ } else {
+ /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
+ /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+ if (val & 1)
+ break;
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 848xx "
+ "phy fw version(1)\n");
+ bnx2x_save_spirom_version(bp, port, 0,
+ phy->ver_addr);
+ return;
+ }
- /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
- /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
- for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
- if (val & 1)
- break;
- udelay(5);
- }
- if (cnt == 100) {
- DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
- bnx2x_save_spirom_version(bp, port, 0,
- phy->ver_addr);
- return;
- }
+ /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
+ for (cnt = 0; cnt < 100; cnt++) {
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+ if (val & 1)
+ break;
+ udelay(5);
+ }
+ if (cnt == 100) {
+ DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw "
+ "version(2)\n");
+ bnx2x_save_spirom_version(bp, port, 0,
+ phy->ver_addr);
+ return;
+ }
+ /* lower 16 bits of the register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+ /* upper 16 bits of register SPI_FW_STATUS */
+ bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
- /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
- bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
- for (cnt = 0; cnt < 100; cnt++) {
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
- if (val & 1)
- break;
- udelay(5);
- }
- if (cnt == 100) {
- DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
- bnx2x_save_spirom_version(bp, port, 0,
+ bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
phy->ver_addr);
- return;
}
- /* lower 16 bits of the register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
- /* upper 16 bits of register SPI_FW_STATUS */
- bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
-
- bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
- phy->ver_addr);
}
-
static void bnx2x_848xx_set_led(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
@@ -9392,10 +9408,13 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
u16 tmp_req_line_speed;
tmp_req_line_speed = phy->req_line_speed;
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
if (phy->req_line_speed == SPEED_10000)
phy->req_line_speed = SPEED_AUTO_NEG;
-
+ } else {
+ /* Save spirom version */
+ bnx2x_save_848xx_spirom_version(phy, bp, params->port);
+ }
/*
* This phy uses the NIG latch mechanism since link indication
* arrives through its LED4 and not via its LASI signal, so we
@@ -9443,13 +9462,10 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
an_1000_val);
/* set 100 speed advertisement */
- if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+ if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
(PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
- (phy->supported &
- (SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full)))) {
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))) {
an_10_100_val |= (1<<7);
/* Enable autoneg and restart autoneg for legacy speeds */
autoneg_val |= (1<<9 | 1<<12);
@@ -9539,9 +9555,6 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
1);
- /* Save spirom version */
- bnx2x_save_848xx_spirom_version(phy, params);
-
phy->req_line_speed = tmp_req_line_speed;
return 0;
@@ -9749,17 +9762,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
/* Wait for GPHY to come out of reset */
msleep(50);
- if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
- /* Bring PHY out of super isolate mode */
- bnx2x_cl45_read(bp, phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
- val &= ~MDIO_84833_SUPER_ISOLATE;
- bnx2x_cl45_write(bp, phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
- bnx2x_84833_pair_swap_cfg(phy, params, vars);
- } else {
+ if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
/*
* BCM84823 requires that XGXS links up first @ 10G for normal
* behavior.
@@ -9816,24 +9819,23 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
params->multi_phy_config, val);
- /* AutogrEEEn */
- if (params->feature_config_flags &
- FEATURE_CONFIG_AUTOGREEEN_ENABLED)
- cmd_args[0] = 0x2;
- else
- cmd_args[0] = 0x0;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ bnx2x_84833_pair_swap_cfg(phy, params, vars);
- cmd_args[1] = 0x0;
- cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
- cmd_args[3] = PHY84833_CONSTANT_LATENCY;
- rc = bnx2x_84833_cmd_hdlr(phy, params,
- PHY84833_CMD_SET_EEE_MODE, cmd_args);
- if (rc != 0)
- DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
+ /* Keep AutogrEEEn disabled. */
+ cmd_args[0] = 0x0;
+ cmd_args[1] = 0x0;
+ cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
+ cmd_args[3] = PHY84833_CONSTANT_LATENCY;
+ rc = bnx2x_84833_cmd_hdlr(phy, params,
+ PHY84833_CMD_SET_EEE_MODE, cmd_args);
+ if (rc != 0)
+ DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
+ }
if (initialize)
rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
else
- bnx2x_save_848xx_spirom_version(phy, params);
+ bnx2x_save_848xx_spirom_version(phy, bp, params->port);
/* 84833 PHY has a better feature and doesn't need to support this. */
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
cms_enable = REG_RD(bp, params->shmem_base +
@@ -9851,6 +9853,16 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
MDIO_CTL_REG_84823_USER_CTRL_REG, val);
}
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+ /* Bring PHY out of super isolate mode as the final step. */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+ val &= ~MDIO_84833_SUPER_ISOLATE;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+ }
return rc;
}
@@ -9988,10 +10000,11 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
} else {
bnx2x_cl45_read(bp, phy,
MDIO_CTL_DEVAD,
- 0x400f, &val16);
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val16);
+ val16 |= MDIO_84833_SUPER_ISOLATE;
bnx2x_cl45_write(bp, phy,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL, 0x800);
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, val16);
}
}
@@ -11516,6 +11529,19 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
}
phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
+ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+ (phy->ver_addr)) {
+ /*
+ * Remove 100Mb link supported for BCM84833 when phy fw
+ * version lower than or equal to 1.39
+ */
+ u32 raw_ver = REG_RD(bp, phy->ver_addr);
+ if (((raw_ver & 0x7F) <= 39) &&
+ (((raw_ver & 0xF80) >> 7) <= 1))
+ phy->supported &= ~(SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full);
+ }
+
/*
* In case mdc/mdio_access of the external phy is different than the
* mdc/mdio access of the XGXS, a HW lock must be taken in each access
@@ -12333,55 +12359,69 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
u32 chip_id)
{
u8 reset_gpios;
- struct bnx2x_phy phy;
- u32 shmem_base, shmem2_base, cnt;
- s8 port = 0;
- u16 val;
-
reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
udelay(10);
bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
reset_gpios);
- for (port = PORT_MAX - 1; port >= PORT_0; port--) {
- /* This PHY is for E2 and E3. */
- shmem_base = shmem_base_path[port];
- shmem2_base = shmem2_base_path[port];
- /* Extract the ext phy address for the port */
- if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
- 0, &phy) !=
- 0) {
- DP(NETIF_MSG_LINK, "populate_phy failed\n");
- return -EINVAL;
- }
+ return 0;
+}
- /* Wait for FW completing its initialization. */
- for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, &phy,
+static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
+ struct bnx2x_phy *phy)
+{
+ u16 val, cnt;
+ /* Wait for FW completing its initialization. */
+ for (cnt = 0; cnt < 1500; cnt++) {
+ bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_CTRL, &val);
- if (!(val & (1<<15)))
- break;
- msleep(1);
- }
- if (cnt >= 1000)
- DP(NETIF_MSG_LINK,
- "84833 Cmn reset timeout (%d)\n", port);
-
- /* Put the port in super isolate mode. */
- bnx2x_cl45_read(bp, &phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
- val |= MDIO_84833_SUPER_ISOLATE;
- bnx2x_cl45_write(bp, &phy,
- MDIO_CTL_DEVAD,
- MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+ if (!(val & (1<<15)))
+ break;
+ msleep(1);
+ }
+ if (cnt >= 1500) {
+ DP(NETIF_MSG_LINK, "84833 reset timeout\n");
+ return -EINVAL;
}
+ /* Put the port in super isolate mode. */
+ bnx2x_cl45_read(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+ val |= MDIO_84833_SUPER_ISOLATE;
+ bnx2x_cl45_write(bp, phy,
+ MDIO_CTL_DEVAD,
+ MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+
+ /* Save spirom version */
+ bnx2x_save_848xx_spirom_version(phy, bp, PORT_0);
return 0;
}
+int bnx2x_pre_init_phy(struct bnx2x *bp,
+ u32 shmem_base,
+ u32 shmem2_base,
+ u32 chip_id)
+{
+ int rc = 0;
+ struct bnx2x_phy phy;
+ bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
+ if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
+ PORT_0, &phy)) {
+ DP(NETIF_MSG_LINK, "populate_phy failed\n");
+ return -EINVAL;
+ }
+ switch (phy.type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+ rc = bnx2x_84833_pre_init_phy(bp, &phy);
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
u32 shmem2_base_path[], u8 phy_index,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index 44609de..dddbcf6 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -2176,6 +2176,7 @@
* set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
* accommodate the 9 input clients to ETS arbiter. */
#define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB 0x18684
+#define NIG_REG_P1_HWPFC_ENABLE 0x181d0
#define NIG_REG_P1_MAC_IN_EN 0x185c0
/* [RW 1] Output enable for TX MAC interface */
#define NIG_REG_P1_MAC_OUT_EN 0x185c4
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index 8fa7abc..084904c 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -2259,7 +2259,8 @@ static int sbmac_init(struct platform_device *pldev, long long base)
}
sc->mii_bus->name = sbmac_mdio_string;
- snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
+ snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pldev->name, idx);
sc->mii_bus->priv = sc;
sc->mii_bus->read = sbmac_mii_read;
sc->mii_bus->write = sbmac_mii_write;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 076e02a..d529af9 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8846,9 +8846,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
udelay(100);
- if (tg3_flag(tp, USING_MSIX) && tp->irq_cnt > 1) {
+ if (tg3_flag(tp, USING_MSIX)) {
val = tr32(MSGINT_MODE);
- val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
+ val |= MSGINT_MODE_ENABLE;
+ if (tp->irq_cnt > 1)
+ val |= MSGINT_MODE_MULTIVEC_EN;
if (!tg3_flag(tp, 1SHOT_MSI))
val |= MSGINT_MODE_ONE_SHOT_DISABLE;
tw32(MSGINT_MODE, val);
@@ -9548,19 +9550,18 @@ static int tg3_request_firmware(struct tg3 *tp)
static bool tg3_enable_msix(struct tg3 *tp)
{
- int i, rc, cpus = num_online_cpus();
+ int i, rc;
struct msix_entry msix_ent[tp->irq_max];
- if (cpus == 1)
- /* Just fallback to the simpler MSI mode. */
- return false;
-
- /*
- * We want as many rx rings enabled as there are cpus.
- * The first MSIX vector only deals with link interrupts, etc,
- * so we add one to the number of vectors we are requesting.
- */
- tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max);
+ tp->irq_cnt = num_online_cpus();
+ if (tp->irq_cnt > 1) {
+ /* We want as many rx rings enabled as there are cpus.
+ * In multiqueue MSI-X mode, the first MSI-X vector
+ * only deals with link interrupts, etc, so we add
+ * one to the number of vectors we are requesting.
+ */
+ tp->irq_cnt = min_t(unsigned, tp->irq_cnt + 1, tp->irq_max);
+ }
for (i = 0; i < tp->irq_max; i++) {
msix_ent[i].entry = i;
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index f3d5c65..2320068 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -243,7 +243,8 @@ static int macb_mii_init(struct macb *bp)
bp->mii_bus->read = &macb_mdio_read;
bp->mii_bus->write = &macb_mdio_write;
bp->mii_bus->reset = &macb_mdio_reset;
- snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", bp->pdev->id);
+ snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ bp->pdev->name, bp->pdev->id);
bp->mii_bus->priv = bp;
bp->mii_bus->parent = &bp->dev->dev;
pdata = bp->pdev->dev.platform_data;
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index ce88c0f..925c9ba 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -325,7 +325,8 @@ static int dnet_mii_init(struct dnet *bp)
bp->mii_bus->write = &dnet_mdio_write;
bp->mii_bus->reset = &dnet_mdio_reset;
- snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+ snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ bp->pdev->name, bp->pdev->id);
bp->mii_bus->priv = bp;
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index ddcbbb3..7b25e9c 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -476,6 +476,7 @@ fec_restart(struct net_device *ndev, int duplex)
} else {
#ifdef FEC_MIIGSK_ENR
if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
+ u32 cfgr;
/* disable the gasket and wait */
writel(0, fep->hwp + FEC_MIIGSK_ENR);
while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
@@ -486,9 +487,11 @@ fec_restart(struct net_device *ndev, int duplex)
* RMII, 50 MHz, no loopback, no echo
* MII, 25 MHz, no loopback, no echo
*/
- writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ?
- 1 : 0, fep->hwp + FEC_MIIGSK_CFGR);
-
+ cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+ ? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII;
+ if (fep->phy_dev && fep->phy_dev->speed == SPEED_10)
+ cfgr |= BM_MIIGSK_CFGR_FRCONT_10M;
+ writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR);
/* re-enable the gasket */
writel(2, fep->hwp + FEC_MIIGSK_ENR);
@@ -1077,7 +1080,8 @@ static int fec_enet_mii_init(struct platform_device *pdev)
fep->mii_bus->read = fec_enet_mdio_read;
fep->mii_bus->write = fec_enet_mdio_write;
fep->mii_bus->reset = fec_enet_mdio_reset;
- snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1);
+ snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, fep->dev_id + 1);
fep->mii_bus->priv = fep;
fep->mii_bus->parent = &pdev->dev;
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 8b2c6d7..8408c62 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -47,6 +47,10 @@
#define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */
#define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */
+#define BM_MIIGSK_CFGR_MII 0x00
+#define BM_MIIGSK_CFGR_RMII 0x01
+#define BM_MIIGSK_CFGR_FRCONT_10M 0x40
+
#else
#define FEC_ECNTRL 0x000 /* Ethernet control reg */
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index e01cdaa..39d160d 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1984,7 +1984,8 @@ static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
return fcb;
}
-static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
+static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,
+ int fcb_length)
{
u8 flags = 0;
@@ -2006,7 +2007,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
* frame (skb->data) and the start of the IP hdr.
* l4os is the distance between the start of the
* l3 hdr and the l4 hdr */
- fcb->l3os = (u16)(skb_network_offset(skb) - GMAC_FCB_LEN);
+ fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length);
fcb->l4os = skb_network_header_len(skb);
fcb->flags = flags;
@@ -2046,7 +2047,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
int i, rq = 0, do_tstamp = 0;
u32 bufaddr;
unsigned long flags;
- unsigned int nr_frags, nr_txbds, length;
+ unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN;
/*
* TOE=1 frames larger than 2500 bytes may see excess delays
@@ -2070,22 +2071,28 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* check if time stamp should be generated */
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
- priv->hwts_tx_en))
+ priv->hwts_tx_en)) {
do_tstamp = 1;
+ fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
+ }
/* make space for additional header when fcb is needed */
if (((skb->ip_summed == CHECKSUM_PARTIAL) ||
vlan_tx_tag_present(skb) ||
unlikely(do_tstamp)) &&
- (skb_headroom(skb) < GMAC_FCB_LEN)) {
+ (skb_headroom(skb) < fcb_length)) {
struct sk_buff *skb_new;
- skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN);
+ skb_new = skb_realloc_headroom(skb, fcb_length);
if (!skb_new) {
dev->stats.tx_errors++;
kfree_skb(skb);
return NETDEV_TX_OK;
}
+
+ /* Steal sock reference for processing TX time stamps */
+ swap(skb_new->sk, skb->sk);
+ swap(skb_new->destructor, skb->destructor);
kfree_skb(skb);
skb = skb_new;
}
@@ -2154,6 +2161,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
lstatus = txbdp_start->lstatus;
}
+ /* Add TxPAL between FCB and frame if required */
+ if (unlikely(do_tstamp)) {
+ skb_push(skb, GMAC_TXPAL_LEN);
+ memset(skb->data, 0, GMAC_TXPAL_LEN);
+ }
+
/* Set up checksumming */
if (CHECKSUM_PARTIAL == skb->ip_summed) {
fcb = gfar_add_fcb(skb);
@@ -2164,7 +2177,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_checksum_help(skb);
} else {
lstatus |= BD_LFLAG(TXBD_TOE);
- gfar_tx_checksum(skb, fcb);
+ gfar_tx_checksum(skb, fcb, fcb_length);
}
}
@@ -2196,9 +2209,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
* the full frame length.
*/
if (unlikely(do_tstamp)) {
- txbdp_tstamp->bufPtr = txbdp_start->bufPtr + GMAC_FCB_LEN;
+ txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length;
txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) |
- (skb_headlen(skb) - GMAC_FCB_LEN);
+ (skb_headlen(skb) - fcb_length);
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
} else {
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
@@ -2490,7 +2503,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
next = next_txbd(bdp, base, tx_ring_size);
- buflen = next->length + GMAC_FCB_LEN;
+ buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN;
} else
buflen = bdp->length;
@@ -2502,6 +2515,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(*ns);
+ skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN);
skb_tstamp_tx(skb, &shhwtstamps);
bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
bdp = next;
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index fe7ac3a..40c33a7 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -63,6 +63,9 @@ struct ethtool_rx_list {
/* Length for FCB */
#define GMAC_FCB_LEN 8
+/* Length for TxPAL */
+#define GMAC_TXPAL_LEN 16
+
/* Default padding amount */
#define DEFAULT_PADDING 2
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
index 05b7359..6bdd8e3 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
@@ -263,7 +263,7 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
data[i++] = atomic_read(&port->port_res[k].swqe_avail);
}
-const struct ethtool_ops ehea_ethtool_ops = {
+static const struct ethtool_ops ehea_ethtool_ops = {
.get_settings = ehea_get_settings,
.get_drvinfo = ehea_get_drvinfo,
.get_msglevel = ehea_get_msglevel,
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 3554414..5d5fb26 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -94,8 +94,8 @@ static int port_name_cnt;
static LIST_HEAD(adapter_list);
static unsigned long ehea_driver_flags;
static DEFINE_MUTEX(dlpar_mem_lock);
-struct ehea_fw_handle_array ehea_fw_handles;
-struct ehea_bcmc_reg_array ehea_bcmc_regs;
+static struct ehea_fw_handle_array ehea_fw_handles;
+static struct ehea_bcmc_reg_array ehea_bcmc_regs;
static int __devinit ehea_probe_adapter(struct platform_device *dev,
@@ -133,7 +133,7 @@ void ehea_dump(void *adr, int len, char *msg)
}
}
-void ehea_schedule_port_reset(struct ehea_port *port)
+static void ehea_schedule_port_reset(struct ehea_port *port)
{
if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
schedule_work(&port->reset_task);
@@ -1404,7 +1404,7 @@ out:
return ret;
}
-int ehea_gen_smrs(struct ehea_port_res *pr)
+static int ehea_gen_smrs(struct ehea_port_res *pr)
{
int ret;
struct ehea_adapter *adapter = pr->port->adapter;
@@ -1426,7 +1426,7 @@ out:
return -EIO;
}
-int ehea_rem_smrs(struct ehea_port_res *pr)
+static int ehea_rem_smrs(struct ehea_port_res *pr)
{
if ((ehea_rem_mr(&pr->send_mr)) ||
(ehea_rem_mr(&pr->recv_mr)))
@@ -2190,7 +2190,7 @@ out:
return err;
}
-int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
+static int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
{
int ret = -EIO;
u64 hret;
@@ -2531,7 +2531,7 @@ static void ehea_flush_sq(struct ehea_port *port)
}
}
-int ehea_stop_qps(struct net_device *dev)
+static int ehea_stop_qps(struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
struct ehea_adapter *adapter = port->adapter;
@@ -2600,7 +2600,7 @@ out:
return ret;
}
-void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
+static void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
{
struct ehea_qp qp = *orig_qp;
struct ehea_qp_init_attr *init_attr = &qp.init_attr;
@@ -2633,7 +2633,7 @@ void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
}
}
-int ehea_restart_qps(struct net_device *dev)
+static int ehea_restart_qps(struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
struct ehea_adapter *adapter = port->adapter;
@@ -2824,7 +2824,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
ehea_schedule_port_reset(port);
}
-int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
+static int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
{
struct hcp_query_ehea *cb;
u64 hret;
@@ -2852,7 +2852,7 @@ out:
return ret;
}
-int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
+static int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
{
struct hcp_ehea_port_cb4 *cb4;
u64 hret;
@@ -2966,7 +2966,7 @@ static const struct net_device_ops ehea_netdev_ops = {
.ndo_tx_timeout = ehea_tx_watchdog,
};
-struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
u32 logical_port_id,
struct device_node *dn)
{
@@ -3237,7 +3237,7 @@ static ssize_t ehea_remove_port(struct device *dev,
static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
-int ehea_create_device_sysfs(struct platform_device *dev)
+static int ehea_create_device_sysfs(struct platform_device *dev)
{
int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
if (ret)
@@ -3248,7 +3248,7 @@ out:
return ret;
}
-void ehea_remove_device_sysfs(struct platform_device *dev)
+static void ehea_remove_device_sysfs(struct platform_device *dev)
{
device_remove_file(&dev->dev, &dev_attr_probe_port);
device_remove_file(&dev->dev, &dev_attr_remove_port);
@@ -3379,7 +3379,7 @@ static int __devexit ehea_remove(struct platform_device *dev)
return 0;
}
-void ehea_crash_handler(void)
+static void ehea_crash_handler(void)
{
int i;
@@ -3491,7 +3491,7 @@ static ssize_t ehea_show_capabilities(struct device_driver *drv,
static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
ehea_show_capabilities, NULL);
-int __init ehea_module_init(void)
+static int __init ehea_module_init(void)
{
int ret;
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
index 95b9f4f..c25b05b 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c
@@ -34,9 +34,7 @@
#include "ehea_phyp.h"
#include "ehea_qmr.h"
-struct ehea_bmap *ehea_bmap = NULL;
-
-
+static struct ehea_bmap *ehea_bmap;
static void *hw_qpageit_get_inc(struct hw_queue *queue)
{
@@ -212,7 +210,7 @@ out_nomem:
return NULL;
}
-u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
+static u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
{
u64 hret;
u64 adapter_handle = cq->adapter->handle;
@@ -337,7 +335,7 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
return eqe;
}
-u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)
+static u64 ehea_destroy_eq_res(struct ehea_eq *eq, u64 force)
{
u64 hret;
unsigned long flags;
@@ -381,7 +379,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
/**
* allocates memory for a queue and registers pages in phyp
*/
-int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
+static int ehea_qp_alloc_register(struct ehea_qp *qp, struct hw_queue *hw_queue,
int nr_pages, int wqe_size, int act_nr_sges,
struct ehea_adapter *adapter, int h_call_q_selector)
{
@@ -516,7 +514,7 @@ out_freemem:
return NULL;
}
-u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
+static u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
{
u64 hret;
struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
@@ -976,7 +974,7 @@ int ehea_gen_smr(struct ehea_adapter *adapter, struct ehea_mr *old_mr,
return 0;
}
-void print_error_data(u64 *data)
+static void print_error_data(u64 *data)
{
int length;
u64 type = EHEA_BMASK_GET(ERROR_DATA_TYPE, data[2]);
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 0b3567a..85e2c6c 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -98,6 +98,7 @@ struct ltq_etop_chan {
struct ltq_etop_priv {
struct net_device *netdev;
+ struct platform_device *pdev;
struct ltq_eth_data *pldata;
struct resource *res;
@@ -436,7 +437,8 @@ ltq_etop_mdio_init(struct net_device *dev)
priv->mii_bus->read = ltq_etop_mdio_rd;
priv->mii_bus->write = ltq_etop_mdio_wr;
priv->mii_bus->name = "ltq_mii";
- snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ priv->pdev->name, priv->pdev->id);
priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!priv->mii_bus->irq) {
err = -ENOMEM;
@@ -734,6 +736,7 @@ ltq_etop_probe(struct platform_device *pdev)
dev->ethtool_ops = &ltq_etop_ethtool_ops;
priv = netdev_priv(dev);
priv->res = res;
+ priv->pdev = pdev;
priv->pldata = dev_get_platdata(&pdev->dev);
priv->netdev = dev;
spin_lock_init(&priv->lock);
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 80aab4e..9c049d2 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2613,7 +2613,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
msp->smi_bus->name = "mv643xx_eth smi";
msp->smi_bus->read = smi_bus_read;
msp->smi_bus->write = smi_bus_write,
- snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
+ snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
+ pdev->name, pdev->id);
msp->smi_bus->parent = &pdev->dev;
msp->smi_bus->phy_mask = 0xffffffff;
if (mdiobus_register(msp->smi_bus) < 0)
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 5ec409e..953ba58 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1552,7 +1552,8 @@ static int pxa168_eth_probe(struct platform_device *pdev)
pep->smi_bus->name = "pxa168_eth smi";
pep->smi_bus->read = pxa168_smi_read;
pep->smi_bus->write = pxa168_smi_write;
- snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id);
+ snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d",
+ pdev->name, pdev->id);
pep->smi_bus->parent = &pdev->dev;
pep->smi_bus->phy_mask = 0xffffffff;
err = mdiobus_register(pep->smi_bus);
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 75ec87a..0a85690 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -459,7 +459,7 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
- &ctl->sg, 1, DMA_TO_DEVICE,
+ &ctl->sg, 1, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
if (!ctl->adesc)
return NETDEV_TX_BUSY;
@@ -571,7 +571,7 @@ static int __ks8842_start_new_rx_dma(struct net_device *netdev)
sg_dma_len(sg) = DMA_BUFFER_SIZE;
ctl->adesc = ctl->chan->device->device_prep_slave_sg(ctl->chan,
- sg, 1, DMA_FROM_DEVICE,
+ sg, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
if (!ctl->adesc)
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 6ed09a8..e52cd31 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -746,7 +746,7 @@
#define MAC_ADDR_ORDER(i) (ETH_ALEN - 1 - (i))
#define MAX_ETHERNET_BODY_SIZE 1500
-#define ETHERNET_HEADER_SIZE 14
+#define ETHERNET_HEADER_SIZE (14 + VLAN_HLEN)
#define MAX_ETHERNET_PACKET_SIZE \
(MAX_ETHERNET_BODY_SIZE + ETHERNET_HEADER_SIZE)
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index fc9bda9..813d41c 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1702,7 +1702,8 @@ static int sh_mdio_init(struct net_device *ndev, int id,
/* Hook up MII support for ethtool */
mdp->mii_bus->name = "sh_mii";
mdp->mii_bus->parent = &ndev->dev;
- snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id);
+ snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ mdp->pdev->name, id);
/* PHY IRQ */
mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index a7ff8ea..22e9c01 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -1004,7 +1004,7 @@ static int __devinit s6gmac_probe(struct platform_device *pdev)
mb->write = s6mii_write;
mb->reset = s6mii_reset;
mb->priv = pd;
- snprintf(mb->id, MII_BUS_ID_SIZE, "0");
+ snprintf(mb->id, MII_BUS_ID_SIZE, "%s-%x", pdev->name, pdev->id);
mb->phy_mask = ~(1 << 0);
mb->irq = &pd->mii.irq[0];
for (i = 0; i < PHY_MAX_ADDR; i++) {
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 9d0b8ce..24d2df0 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1044,7 +1044,8 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev,
}
pdata->mii_bus->name = SMSC_MDIONAME;
- snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, pdev->id);
pdata->mii_bus->priv = pdata;
pdata->mii_bus->read = smsc911x_mii_read;
pdata->mii_bus->write = smsc911x_mii_write;
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
index 41e6b33..c07cfe9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -22,6 +22,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
+#include <linux/kernel.h>
#include <linux/io.h>
#include "mmc.h"
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3738b47..96fa2da 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -307,7 +307,7 @@ static int stmmac_init_phy(struct net_device *dev)
priv->speed = 0;
priv->oldduplex = -1;
- snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
+ snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id);
snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
priv->plat->phy_addr);
pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id);
@@ -772,7 +772,7 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv)
dwmac_mmc_ctrl(priv->ioaddr, mode);
memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
} else
- pr_info(" No MAC Management Counters available");
+ pr_info(" No MAC Management Counters available\n");
}
static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 51f4412..da4a104 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -158,7 +158,8 @@ int stmmac_mdio_register(struct net_device *ndev)
new_bus->read = &stmmac_mdio_read;
new_bus->write = &stmmac_mdio_write;
new_bus->reset = &stmmac_mdio_reset;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", mdio_bus_data->bus_id);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ new_bus->name, mdio_bus_data->bus_id);
new_bus->priv = ndev;
new_bus->irq = irqlist;
new_bus->phy_mask = mdio_bus_data->phy_mask;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 7b1594f..1ac8324 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -62,7 +62,7 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat);
if (!priv) {
pr_err("%s: main drivr probe failed", __func__);
- goto out_release_region;
+ goto out_unmap;
}
priv->ioaddr = addr;
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index aaac0c7..4d9a28f 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -1269,7 +1269,7 @@ int __devinit cpmac_init(void)
}
cpmac_mii->phy_mask = ~(mask | 0x80000000);
- snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1");
+ snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "cpmac-1");
res = mdiobus_register(cpmac_mii);
if (res)
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 7615040..ef7c9c1 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -313,7 +313,8 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
data->bus->reset = davinci_mdio_reset,
data->bus->parent = dev;
data->bus->priv = data;
- snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pdev->name, pdev->id);
data->clk = clk_get(dev, NULL);
if (IS_ERR(data->clk)) {
diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c
index a9ce01ba..164fb77 100644
--- a/drivers/net/ethernet/tundra/tsi108_eth.c
+++ b/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1604,7 +1604,7 @@ tsi108_init_one(struct platform_device *pdev)
data->phyregs = ioremap(einfo->phyregs, 0x400);
if (NULL == data->phyregs) {
err = -ENOMEM;
- goto regs_fail;
+ goto phyregs_fail;
}
/* MII setup */
data->mii_if.dev = dev;
@@ -1663,9 +1663,11 @@ tsi108_init_one(struct platform_device *pdev)
return 0;
register_fail:
- iounmap(data->regs);
iounmap(data->phyregs);
+phyregs_fail:
+ iounmap(data->regs);
+
regs_fail:
free_netdev(dev);
return err;
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 5c4983b..10b18eb 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -39,10 +39,9 @@
/* A few user-configurable values.
These may be modified when a driver module is loaded. */
-
-#define DEBUG
-static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
-static int max_interrupt_work = 20;
+static int debug = 0;
+#define RHINE_MSG_DEFAULT \
+ (0x0000)
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1518 effectively disables this feature. */
@@ -128,12 +127,10 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
MODULE_LICENSE("GPL");
-module_param(max_interrupt_work, int, 0);
module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param(avoid_D3, bool, 0);
-MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
-MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
+MODULE_PARM_DESC(debug, "VIA Rhine debug message flags");
MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
@@ -351,16 +348,25 @@ static const int mmio_verify_registers[] = {
/* Bits in the interrupt status/mask registers. */
enum intr_status_bits {
- IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
- IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
- IntrPCIErr=0x0040,
- IntrStatsMax=0x0080, IntrRxEarly=0x0100,
- IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
- IntrTxAborted=0x2000, IntrLinkChange=0x4000,
- IntrRxWakeUp=0x8000,
- IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
- IntrTxDescRace=0x080000, /* mapped from IntrStatus2 */
- IntrTxErrSummary=0x082218,
+ IntrRxDone = 0x0001,
+ IntrTxDone = 0x0002,
+ IntrRxErr = 0x0004,
+ IntrTxError = 0x0008,
+ IntrRxEmpty = 0x0020,
+ IntrPCIErr = 0x0040,
+ IntrStatsMax = 0x0080,
+ IntrRxEarly = 0x0100,
+ IntrTxUnderrun = 0x0210,
+ IntrRxOverflow = 0x0400,
+ IntrRxDropped = 0x0800,
+ IntrRxNoBuf = 0x1000,
+ IntrTxAborted = 0x2000,
+ IntrLinkChange = 0x4000,
+ IntrRxWakeUp = 0x8000,
+ IntrTxDescRace = 0x080000, /* mapped from IntrStatus2 */
+ IntrNormalSummary = IntrRxDone | IntrTxDone,
+ IntrTxErrSummary = IntrTxDescRace | IntrTxAborted | IntrTxError |
+ IntrTxUnderrun,
};
/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
@@ -439,8 +445,13 @@ struct rhine_private {
struct net_device *dev;
struct napi_struct napi;
spinlock_t lock;
+ struct mutex task_lock;
+ bool task_enable;
+ struct work_struct slow_event_task;
struct work_struct reset_task;
+ u32 msg_enable;
+
/* Frequently used values: keep some adjacent for cache effect. */
u32 quirks;
struct rx_desc *rx_head_desc;
@@ -476,41 +487,50 @@ static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
static int rhine_open(struct net_device *dev);
static void rhine_reset_task(struct work_struct *work);
+static void rhine_slow_event_task(struct work_struct *work);
static void rhine_tx_timeout(struct net_device *dev);
static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
struct net_device *dev);
static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
static void rhine_tx(struct net_device *dev);
static int rhine_rx(struct net_device *dev, int limit);
-static void rhine_error(struct net_device *dev, int intr_status);
static void rhine_set_rx_mode(struct net_device *dev);
static struct net_device_stats *rhine_get_stats(struct net_device *dev);
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static const struct ethtool_ops netdev_ethtool_ops;
static int rhine_close(struct net_device *dev);
-static void rhine_shutdown (struct pci_dev *pdev);
static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid);
static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
-static void rhine_set_cam(void __iomem *ioaddr, int idx, u8 *addr);
-static void rhine_set_vlan_cam(void __iomem *ioaddr, int idx, u8 *addr);
-static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask);
-static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask);
-static void rhine_init_cam_filter(struct net_device *dev);
-static void rhine_update_vcam(struct net_device *dev);
-
-#define RHINE_WAIT_FOR(condition) \
-do { \
- int i = 1024; \
- while (!(condition) && --i) \
- ; \
- if (debug > 1 && i < 512) \
- pr_info("%4d cycles used @ %s:%d\n", \
- 1024 - i, __func__, __LINE__); \
-} while (0)
-
-static inline u32 get_intr_status(struct net_device *dev)
+static void rhine_restart_tx(struct net_device *dev);
+
+static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high)
+{
+ void __iomem *ioaddr = rp->base;
+ int i;
+
+ for (i = 0; i < 1024; i++) {
+ if (high ^ !!(ioread8(ioaddr + reg) & mask))
+ break;
+ udelay(10);
+ }
+ if (i > 64) {
+ netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle "
+ "count: %04d\n", high ? "high" : "low", reg, mask, i);
+ }
+}
+
+static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask)
+{
+ rhine_wait_bit(rp, reg, mask, true);
+}
+
+static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask)
+{
+ rhine_wait_bit(rp, reg, mask, false);
+}
+
+static u32 rhine_get_events(struct rhine_private *rp)
{
- struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
u32 intr_status;
@@ -521,6 +541,16 @@ static inline u32 get_intr_status(struct net_device *dev)
return intr_status;
}
+static void rhine_ack_events(struct rhine_private *rp, u32 mask)
+{
+ void __iomem *ioaddr = rp->base;
+
+ if (rp->quirks & rqStatusWBRace)
+ iowrite8(mask >> 16, ioaddr + IntrStatus2);
+ iowrite16(mask, ioaddr + IntrStatus);
+ mmiowb();
+}
+
/*
* Get power related registers into sane state.
* Notify user about past WOL event.
@@ -585,6 +615,7 @@ static void rhine_chip_reset(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
+ u8 cmd1;
iowrite8(Cmd1Reset, ioaddr + ChipCmd1);
IOSYNC;
@@ -597,13 +628,12 @@ static void rhine_chip_reset(struct net_device *dev)
iowrite8(0x40, ioaddr + MiscCmd);
/* Reset can take somewhat longer (rare) */
- RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd1) & Cmd1Reset));
+ rhine_wait_bit_low(rp, ChipCmd1, Cmd1Reset);
}
- if (debug > 1)
- netdev_info(dev, "Reset %s\n",
- (ioread8(ioaddr + ChipCmd1) & Cmd1Reset) ?
- "failed" : "succeeded");
+ cmd1 = ioread8(ioaddr + ChipCmd1);
+ netif_info(rp, hw, dev, "Reset %s\n", (cmd1 & Cmd1Reset) ?
+ "failed" : "succeeded");
}
#ifdef USE_MMIO
@@ -629,9 +659,15 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
+ int i;
outb(0x20, pioaddr + MACRegEEcsr);
- RHINE_WAIT_FOR(!(inb(pioaddr + MACRegEEcsr) & 0x20));
+ for (i = 0; i < 1024; i++) {
+ if (!(inb(pioaddr + MACRegEEcsr) & 0x20))
+ break;
+ }
+ if (i > 512)
+ pr_info("%4d cycles used @ %s:%d\n", i, __func__, __LINE__);
#ifdef USE_MMIO
/*
@@ -657,23 +693,127 @@ static void rhine_poll(struct net_device *dev)
}
#endif
+static void rhine_kick_tx_threshold(struct rhine_private *rp)
+{
+ if (rp->tx_thresh < 0xe0) {
+ void __iomem *ioaddr = rp->base;
+
+ rp->tx_thresh += 0x20;
+ BYTE_REG_BITS_SET(rp->tx_thresh, 0x80, ioaddr + TxConfig);
+ }
+}
+
+static void rhine_tx_err(struct rhine_private *rp, u32 status)
+{
+ struct net_device *dev = rp->dev;
+
+ if (status & IntrTxAborted) {
+ netif_info(rp, tx_err, dev,
+ "Abort %08x, frame dropped\n", status);
+ }
+
+ if (status & IntrTxUnderrun) {
+ rhine_kick_tx_threshold(rp);
+ netif_info(rp, tx_err ,dev, "Transmitter underrun, "
+ "Tx threshold now %02x\n", rp->tx_thresh);
+ }
+
+ if (status & IntrTxDescRace)
+ netif_info(rp, tx_err, dev, "Tx descriptor write-back race\n");
+
+ if ((status & IntrTxError) &&
+ (status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) {
+ rhine_kick_tx_threshold(rp);
+ netif_info(rp, tx_err, dev, "Unspecified error. "
+ "Tx threshold now %02x\n", rp->tx_thresh);
+ }
+
+ rhine_restart_tx(dev);
+}
+
+static void rhine_update_rx_crc_and_missed_errord(struct rhine_private *rp)
+{
+ void __iomem *ioaddr = rp->base;
+ struct net_device_stats *stats = &rp->dev->stats;
+
+ stats->rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
+ stats->rx_missed_errors += ioread16(ioaddr + RxMissed);
+
+ /*
+ * Clears the "tally counters" for CRC errors and missed frames(?).
+ * It has been reported that some chips need a write of 0 to clear
+ * these, for others the counters are set to 1 when written to and
+ * instead cleared when read. So we clear them both ways ...
+ */
+ iowrite32(0, ioaddr + RxMissed);
+ ioread16(ioaddr + RxCRCErrs);
+ ioread16(ioaddr + RxMissed);
+}
+
+#define RHINE_EVENT_NAPI_RX (IntrRxDone | \
+ IntrRxErr | \
+ IntrRxEmpty | \
+ IntrRxOverflow | \
+ IntrRxDropped | \
+ IntrRxNoBuf | \
+ IntrRxWakeUp)
+
+#define RHINE_EVENT_NAPI_TX_ERR (IntrTxError | \
+ IntrTxAborted | \
+ IntrTxUnderrun | \
+ IntrTxDescRace)
+#define RHINE_EVENT_NAPI_TX (IntrTxDone | RHINE_EVENT_NAPI_TX_ERR)
+
+#define RHINE_EVENT_NAPI (RHINE_EVENT_NAPI_RX | \
+ RHINE_EVENT_NAPI_TX | \
+ IntrStatsMax)
+#define RHINE_EVENT_SLOW (IntrPCIErr | IntrLinkChange)
+#define RHINE_EVENT (RHINE_EVENT_NAPI | RHINE_EVENT_SLOW)
+
static int rhine_napipoll(struct napi_struct *napi, int budget)
{
struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
struct net_device *dev = rp->dev;
void __iomem *ioaddr = rp->base;
- int work_done;
+ u16 enable_mask = RHINE_EVENT & 0xffff;
+ int work_done = 0;
+ u32 status;
+
+ status = rhine_get_events(rp);
+ rhine_ack_events(rp, status & ~RHINE_EVENT_SLOW);
+
+ if (status & RHINE_EVENT_NAPI_RX)
+ work_done += rhine_rx(dev, budget);
+
+ if (status & RHINE_EVENT_NAPI_TX) {
+ if (status & RHINE_EVENT_NAPI_TX_ERR) {
+ /* Avoid scavenging before Tx engine turned off */
+ rhine_wait_bit_low(rp, ChipCmd, CmdTxOn);
+ if (ioread8(ioaddr + ChipCmd) & CmdTxOn)
+ netif_warn(rp, tx_err, dev, "Tx still on\n");
+ }
- work_done = rhine_rx(dev, budget);
+ rhine_tx(dev);
+
+ if (status & RHINE_EVENT_NAPI_TX_ERR)
+ rhine_tx_err(rp, status);
+ }
+
+ if (status & IntrStatsMax) {
+ spin_lock(&rp->lock);
+ rhine_update_rx_crc_and_missed_errord(rp);
+ spin_unlock(&rp->lock);
+ }
+
+ if (status & RHINE_EVENT_SLOW) {
+ enable_mask &= ~RHINE_EVENT_SLOW;
+ schedule_work(&rp->slow_event_task);
+ }
if (work_done < budget) {
napi_complete(napi);
-
- iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
- IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
- IntrTxDone | IntrTxError | IntrTxUnderrun |
- IntrPCIErr | IntrStatsMax | IntrLinkChange,
- ioaddr + IntrEnable);
+ iowrite16(enable_mask, ioaddr + IntrEnable);
+ mmiowb();
}
return work_done;
}
@@ -797,6 +937,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
rp->quirks = quirks;
rp->pioaddr = pioaddr;
rp->pdev = pdev;
+ rp->msg_enable = netif_msg_init(debug, RHINE_MSG_DEFAULT);
rc = pci_request_regions(pdev, DRV_NAME);
if (rc)
@@ -856,7 +997,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
dev->irq = pdev->irq;
spin_lock_init(&rp->lock);
+ mutex_init(&rp->task_lock);
INIT_WORK(&rp->reset_task, rhine_reset_task);
+ INIT_WORK(&rp->slow_event_task, rhine_slow_event_task);
rp->mii_if.dev = dev;
rp->mii_if.mdio_read = mdio_read;
@@ -916,8 +1059,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
}
}
rp->mii_if.phy_id = phy_id;
- if (debug > 1 && avoid_D3)
- netdev_info(dev, "No D3 power state at shutdown\n");
+ if (avoid_D3)
+ netif_info(rp, probe, dev, "No D3 power state at shutdown\n");
return 0;
@@ -1093,7 +1236,7 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
- mii_check_media(&rp->mii_if, debug, init_media);
+ mii_check_media(&rp->mii_if, netif_msg_link(rp), init_media);
if (rp->mii_if.full_duplex)
iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1FDuplex,
@@ -1101,24 +1244,26 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media)
else
iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
ioaddr + ChipCmd1);
- if (debug > 1)
- netdev_info(dev, "force_media %d, carrier %d\n",
- rp->mii_if.force_media, netif_carrier_ok(dev));
+
+ netif_info(rp, link, dev, "force_media %d, carrier %d\n",
+ rp->mii_if.force_media, netif_carrier_ok(dev));
}
/* Called after status of force_media possibly changed */
static void rhine_set_carrier(struct mii_if_info *mii)
{
+ struct net_device *dev = mii->dev;
+ struct rhine_private *rp = netdev_priv(dev);
+
if (mii->force_media) {
/* autoneg is off: Link is always assumed to be up */
- if (!netif_carrier_ok(mii->dev))
- netif_carrier_on(mii->dev);
- }
- else /* Let MMI library update carrier status */
- rhine_check_media(mii->dev, 0);
- if (debug > 1)
- netdev_info(mii->dev, "force_media %d, carrier %d\n",
- mii->force_media, netif_carrier_ok(mii->dev));
+ if (!netif_carrier_ok(dev))
+ netif_carrier_on(dev);
+ } else /* Let MMI library update carrier status */
+ rhine_check_media(dev, 0);
+
+ netif_info(rp, link, dev, "force_media %d, carrier %d\n",
+ mii->force_media, netif_carrier_ok(dev));
}
/**
@@ -1266,10 +1411,10 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
struct rhine_private *rp = netdev_priv(dev);
- spin_lock_irq(&rp->lock);
+ spin_lock_bh(&rp->lock);
set_bit(vid, rp->active_vlans);
rhine_update_vcam(dev);
- spin_unlock_irq(&rp->lock);
+ spin_unlock_bh(&rp->lock);
return 0;
}
@@ -1277,10 +1422,10 @@ static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct rhine_private *rp = netdev_priv(dev);
- spin_lock_irq(&rp->lock);
+ spin_lock_bh(&rp->lock);
clear_bit(vid, rp->active_vlans);
rhine_update_vcam(dev);
- spin_unlock_irq(&rp->lock);
+ spin_unlock_bh(&rp->lock);
return 0;
}
@@ -1310,12 +1455,7 @@ static void init_registers(struct net_device *dev)
napi_enable(&rp->napi);
- /* Enable interrupts by setting the interrupt mask. */
- iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
- IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
- IntrTxDone | IntrTxError | IntrTxUnderrun |
- IntrPCIErr | IntrStatsMax | IntrLinkChange,
- ioaddr + IntrEnable);
+ iowrite16(RHINE_EVENT & 0xffff, ioaddr + IntrEnable);
iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
ioaddr + ChipCmd);
@@ -1323,23 +1463,27 @@ static void init_registers(struct net_device *dev)
}
/* Enable MII link status auto-polling (required for IntrLinkChange) */
-static void rhine_enable_linkmon(void __iomem *ioaddr)
+static void rhine_enable_linkmon(struct rhine_private *rp)
{
+ void __iomem *ioaddr = rp->base;
+
iowrite8(0, ioaddr + MIICmd);
iowrite8(MII_BMSR, ioaddr + MIIRegAddr);
iowrite8(0x80, ioaddr + MIICmd);
- RHINE_WAIT_FOR((ioread8(ioaddr + MIIRegAddr) & 0x20));
+ rhine_wait_bit_high(rp, MIIRegAddr, 0x20);
iowrite8(MII_BMSR | 0x40, ioaddr + MIIRegAddr);
}
/* Disable MII link status auto-polling (required for MDIO access) */
-static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
+static void rhine_disable_linkmon(struct rhine_private *rp)
{
+ void __iomem *ioaddr = rp->base;
+
iowrite8(0, ioaddr + MIICmd);
- if (quirks & rqRhineI) {
+ if (rp->quirks & rqRhineI) {
iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR
/* Can be called from ISR. Evil. */
@@ -1348,13 +1492,13 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks)
/* 0x80 must be set immediately before turning it off */
iowrite8(0x80, ioaddr + MIICmd);
- RHINE_WAIT_FOR(ioread8(ioaddr + MIIRegAddr) & 0x20);
+ rhine_wait_bit_high(rp, MIIRegAddr, 0x20);
/* Heh. Now clear 0x80 again. */
iowrite8(0, ioaddr + MIICmd);
}
else
- RHINE_WAIT_FOR(ioread8(ioaddr + MIIRegAddr) & 0x80);
+ rhine_wait_bit_high(rp, MIIRegAddr, 0x80);
}
/* Read and write over the MII Management Data I/O (MDIO) interface. */
@@ -1365,16 +1509,16 @@ static int mdio_read(struct net_device *dev, int phy_id, int regnum)
void __iomem *ioaddr = rp->base;
int result;
- rhine_disable_linkmon(ioaddr, rp->quirks);
+ rhine_disable_linkmon(rp);
/* rhine_disable_linkmon already cleared MIICmd */
iowrite8(phy_id, ioaddr + MIIPhyAddr);
iowrite8(regnum, ioaddr + MIIRegAddr);
iowrite8(0x40, ioaddr + MIICmd); /* Trigger read */
- RHINE_WAIT_FOR(!(ioread8(ioaddr + MIICmd) & 0x40));
+ rhine_wait_bit_low(rp, MIICmd, 0x40);
result = ioread16(ioaddr + MIIData);
- rhine_enable_linkmon(ioaddr);
+ rhine_enable_linkmon(rp);
return result;
}
@@ -1383,16 +1527,33 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
- rhine_disable_linkmon(ioaddr, rp->quirks);
+ rhine_disable_linkmon(rp);
/* rhine_disable_linkmon already cleared MIICmd */
iowrite8(phy_id, ioaddr + MIIPhyAddr);
iowrite8(regnum, ioaddr + MIIRegAddr);
iowrite16(value, ioaddr + MIIData);
iowrite8(0x20, ioaddr + MIICmd); /* Trigger write */
- RHINE_WAIT_FOR(!(ioread8(ioaddr + MIICmd) & 0x20));
+ rhine_wait_bit_low(rp, MIICmd, 0x20);
- rhine_enable_linkmon(ioaddr);
+ rhine_enable_linkmon(rp);
+}
+
+static void rhine_task_disable(struct rhine_private *rp)
+{
+ mutex_lock(&rp->task_lock);
+ rp->task_enable = false;
+ mutex_unlock(&rp->task_lock);
+
+ cancel_work_sync(&rp->slow_event_task);
+ cancel_work_sync(&rp->reset_task);
+}
+
+static void rhine_task_enable(struct rhine_private *rp)
+{
+ mutex_lock(&rp->task_lock);
+ rp->task_enable = true;
+ mutex_unlock(&rp->task_lock);
}
static int rhine_open(struct net_device *dev)
@@ -1406,8 +1567,7 @@ static int rhine_open(struct net_device *dev)
if (rc)
return rc;
- if (debug > 1)
- netdev_dbg(dev, "%s() irq %d\n", __func__, rp->pdev->irq);
+ netif_dbg(rp, ifup, dev, "%s() irq %d\n", __func__, rp->pdev->irq);
rc = alloc_ring(dev);
if (rc) {
@@ -1417,11 +1577,12 @@ static int rhine_open(struct net_device *dev)
alloc_rbufs(dev);
alloc_tbufs(dev);
rhine_chip_reset(dev);
+ rhine_task_enable(rp);
init_registers(dev);
- if (debug > 2)
- netdev_dbg(dev, "%s() Done - status %04x MII status: %04x\n",
- __func__, ioread16(ioaddr + ChipCmd),
- mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+
+ netif_dbg(rp, ifup, dev, "%s() Done - status %04x MII status: %04x\n",
+ __func__, ioread16(ioaddr + ChipCmd),
+ mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
netif_start_queue(dev);
@@ -1434,11 +1595,12 @@ static void rhine_reset_task(struct work_struct *work)
reset_task);
struct net_device *dev = rp->dev;
- /* protect against concurrent rx interrupts */
- disable_irq(rp->pdev->irq);
+ mutex_lock(&rp->task_lock);
- napi_disable(&rp->napi);
+ if (!rp->task_enable)
+ goto out_unlock;
+ napi_disable(&rp->napi);
spin_lock_bh(&rp->lock);
/* clear all descriptors */
@@ -1452,11 +1614,13 @@ static void rhine_reset_task(struct work_struct *work)
init_registers(dev);
spin_unlock_bh(&rp->lock);
- enable_irq(rp->pdev->irq);
dev->trans_start = jiffies; /* prevent tx timeout */
dev->stats.tx_errors++;
netif_wake_queue(dev);
+
+out_unlock:
+ mutex_unlock(&rp->task_lock);
}
static void rhine_tx_timeout(struct net_device *dev)
@@ -1477,7 +1641,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
unsigned entry;
- unsigned long flags;
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
@@ -1529,7 +1692,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
rp->tx_ring[entry].tx_status = 0;
/* lock eth irq */
- spin_lock_irqsave(&rp->lock, flags);
wmb();
rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
wmb();
@@ -1550,78 +1712,43 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN)
netif_stop_queue(dev);
- spin_unlock_irqrestore(&rp->lock, flags);
+ netif_dbg(rp, tx_queued, dev, "Transmit frame #%d queued in slot %d\n",
+ rp->cur_tx - 1, entry);
- if (debug > 4) {
- netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n",
- rp->cur_tx-1, entry);
- }
return NETDEV_TX_OK;
}
+static void rhine_irq_disable(struct rhine_private *rp)
+{
+ iowrite16(0x0000, rp->base + IntrEnable);
+ mmiowb();
+}
+
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct rhine_private *rp = netdev_priv(dev);
- void __iomem *ioaddr = rp->base;
- u32 intr_status;
- int boguscnt = max_interrupt_work;
+ u32 status;
int handled = 0;
- while ((intr_status = get_intr_status(dev))) {
- handled = 1;
-
- /* Acknowledge all of the current interrupt sources ASAP. */
- if (intr_status & IntrTxDescRace)
- iowrite8(0x08, ioaddr + IntrStatus2);
- iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
- IOSYNC;
+ status = rhine_get_events(rp);
- if (debug > 4)
- netdev_dbg(dev, "Interrupt, status %08x\n",
- intr_status);
-
- if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
- IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
- iowrite16(IntrTxAborted |
- IntrTxDone | IntrTxError | IntrTxUnderrun |
- IntrPCIErr | IntrStatsMax | IntrLinkChange,
- ioaddr + IntrEnable);
-
- napi_schedule(&rp->napi);
- }
+ netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status);
- if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
- if (intr_status & IntrTxErrSummary) {
- /* Avoid scavenging before Tx engine turned off */
- RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
- if (debug > 2 &&
- ioread8(ioaddr+ChipCmd) & CmdTxOn)
- netdev_warn(dev,
- "%s: Tx engine still on\n",
- __func__);
- }
- rhine_tx(dev);
- }
+ if (status & RHINE_EVENT) {
+ handled = 1;
- /* Abnormal error summary/uncommon events handlers. */
- if (intr_status & (IntrPCIErr | IntrLinkChange |
- IntrStatsMax | IntrTxError | IntrTxAborted |
- IntrTxUnderrun | IntrTxDescRace))
- rhine_error(dev, intr_status);
+ rhine_irq_disable(rp);
+ napi_schedule(&rp->napi);
+ }
- if (--boguscnt < 0) {
- netdev_warn(dev, "Too much work at interrupt, status=%#08x\n",
- intr_status);
- break;
- }
+ if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) {
+ netif_err(rp, intr, dev, "Something Wicked happened! %08x\n",
+ status);
}
- if (debug > 3)
- netdev_dbg(dev, "exiting interrupt, status=%08x\n",
- ioread16(ioaddr + IntrStatus));
return IRQ_RETVAL(handled);
}
@@ -1632,20 +1759,16 @@ static void rhine_tx(struct net_device *dev)
struct rhine_private *rp = netdev_priv(dev);
int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
- spin_lock(&rp->lock);
-
/* find and cleanup dirty tx descriptors */
while (rp->dirty_tx != rp->cur_tx) {
txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
- if (debug > 6)
- netdev_dbg(dev, "Tx scavenge %d status %08x\n",
- entry, txstatus);
+ netif_dbg(rp, tx_done, dev, "Tx scavenge %d status %08x\n",
+ entry, txstatus);
if (txstatus & DescOwn)
break;
if (txstatus & 0x8000) {
- if (debug > 1)
- netdev_dbg(dev, "Transmit error, Tx status %08x\n",
- txstatus);
+ netif_dbg(rp, tx_done, dev,
+ "Transmit error, Tx status %08x\n", txstatus);
dev->stats.tx_errors++;
if (txstatus & 0x0400)
dev->stats.tx_carrier_errors++;
@@ -1667,10 +1790,8 @@ static void rhine_tx(struct net_device *dev)
dev->stats.collisions += (txstatus >> 3) & 0x0F;
else
dev->stats.collisions += txstatus & 0x0F;
- if (debug > 6)
- netdev_dbg(dev, "collisions: %1.1x:%1.1x\n",
- (txstatus >> 3) & 0xF,
- txstatus & 0xF);
+ netif_dbg(rp, tx_done, dev, "collisions: %1.1x:%1.1x\n",
+ (txstatus >> 3) & 0xF, txstatus & 0xF);
dev->stats.tx_bytes += rp->tx_skbuff[entry]->len;
dev->stats.tx_packets++;
}
@@ -1687,8 +1808,6 @@ static void rhine_tx(struct net_device *dev)
}
if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
netif_wake_queue(dev);
-
- spin_unlock(&rp->lock);
}
/**
@@ -1713,11 +1832,8 @@ static int rhine_rx(struct net_device *dev, int limit)
int count;
int entry = rp->cur_rx % RX_RING_SIZE;
- if (debug > 4) {
- netdev_dbg(dev, "%s(), entry %d status %08x\n",
- __func__, entry,
- le32_to_cpu(rp->rx_head_desc->rx_status));
- }
+ netif_dbg(rp, rx_status, dev, "%s(), entry %d status %08x\n", __func__,
+ entry, le32_to_cpu(rp->rx_head_desc->rx_status));
/* If EOP is set on the next entry, it's a new packet. Send it up. */
for (count = 0; count < limit; ++count) {
@@ -1729,9 +1845,8 @@ static int rhine_rx(struct net_device *dev, int limit)
if (desc_status & DescOwn)
break;
- if (debug > 4)
- netdev_dbg(dev, "%s() status is %08x\n",
- __func__, desc_status);
+ netif_dbg(rp, rx_status, dev, "%s() status %08x\n", __func__,
+ desc_status);
if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
if ((desc_status & RxWholePkt) != RxWholePkt) {
@@ -1747,9 +1862,9 @@ static int rhine_rx(struct net_device *dev, int limit)
dev->stats.rx_length_errors++;
} else if (desc_status & RxErr) {
/* There was a error. */
- if (debug > 2)
- netdev_dbg(dev, "%s() Rx error was %08x\n",
- __func__, desc_status);
+ netif_dbg(rp, rx_err, dev,
+ "%s() Rx error %08x\n", __func__,
+ desc_status);
dev->stats.rx_errors++;
if (desc_status & 0x0030)
dev->stats.rx_length_errors++;
@@ -1839,19 +1954,6 @@ static int rhine_rx(struct net_device *dev, int limit)
return count;
}
-/*
- * Clears the "tally counters" for CRC errors and missed frames(?).
- * It has been reported that some chips need a write of 0 to clear
- * these, for others the counters are set to 1 when written to and
- * instead cleared when read. So we clear them both ways ...
- */
-static inline void clear_tally_counters(void __iomem *ioaddr)
-{
- iowrite32(0, ioaddr + RxMissed);
- ioread16(ioaddr + RxCRCErrs);
- ioread16(ioaddr + RxMissed);
-}
-
static void rhine_restart_tx(struct net_device *dev) {
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
@@ -1862,7 +1964,7 @@ static void rhine_restart_tx(struct net_device *dev) {
* If new errors occurred, we need to sort them out before doing Tx.
* In that case the ISR will be back here RSN anyway.
*/
- intr_status = get_intr_status(dev);
+ intr_status = rhine_get_events(rp);
if ((intr_status & IntrTxErrSummary) == 0) {
@@ -1883,79 +1985,50 @@ static void rhine_restart_tx(struct net_device *dev) {
}
else {
/* This should never happen */
- if (debug > 1)
- netdev_warn(dev, "%s() Another error occurred %08x\n",
- __func__, intr_status);
+ netif_warn(rp, tx_err, dev, "another error occurred %08x\n",
+ intr_status);
}
}
-static void rhine_error(struct net_device *dev, int intr_status)
+static void rhine_slow_event_task(struct work_struct *work)
{
- struct rhine_private *rp = netdev_priv(dev);
- void __iomem *ioaddr = rp->base;
+ struct rhine_private *rp =
+ container_of(work, struct rhine_private, slow_event_task);
+ struct net_device *dev = rp->dev;
+ u32 intr_status;
- spin_lock(&rp->lock);
+ mutex_lock(&rp->task_lock);
+
+ if (!rp->task_enable)
+ goto out_unlock;
+
+ intr_status = rhine_get_events(rp);
+ rhine_ack_events(rp, intr_status & RHINE_EVENT_SLOW);
if (intr_status & IntrLinkChange)
rhine_check_media(dev, 0);
- if (intr_status & IntrStatsMax) {
- dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
- dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
- clear_tally_counters(ioaddr);
- }
- if (intr_status & IntrTxAborted) {
- if (debug > 1)
- netdev_info(dev, "Abort %08x, frame dropped\n",
- intr_status);
- }
- if (intr_status & IntrTxUnderrun) {
- if (rp->tx_thresh < 0xE0)
- BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
- if (debug > 1)
- netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n",
- rp->tx_thresh);
- }
- if (intr_status & IntrTxDescRace) {
- if (debug > 2)
- netdev_info(dev, "Tx descriptor write-back race\n");
- }
- if ((intr_status & IntrTxError) &&
- (intr_status & (IntrTxAborted |
- IntrTxUnderrun | IntrTxDescRace)) == 0) {
- if (rp->tx_thresh < 0xE0) {
- BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
- }
- if (debug > 1)
- netdev_info(dev, "Unspecified error. Tx threshold now %02x\n",
- rp->tx_thresh);
- }
- if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace |
- IntrTxError))
- rhine_restart_tx(dev);
-
- if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
- IntrTxError | IntrTxAborted | IntrNormalSummary |
- IntrTxDescRace)) {
- if (debug > 1)
- netdev_err(dev, "Something Wicked happened! %08x\n",
- intr_status);
- }
- spin_unlock(&rp->lock);
+ if (intr_status & IntrPCIErr)
+ netif_warn(rp, hw, dev, "PCI error\n");
+
+ napi_disable(&rp->napi);
+ rhine_irq_disable(rp);
+ /* Slow and safe. Consider __napi_schedule as a replacement ? */
+ napi_enable(&rp->napi);
+ napi_schedule(&rp->napi);
+
+out_unlock:
+ mutex_unlock(&rp->task_lock);
}
static struct net_device_stats *rhine_get_stats(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
- void __iomem *ioaddr = rp->base;
- unsigned long flags;
- spin_lock_irqsave(&rp->lock, flags);
- dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
- dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
- clear_tally_counters(ioaddr);
- spin_unlock_irqrestore(&rp->lock, flags);
+ spin_lock_bh(&rp->lock);
+ rhine_update_rx_crc_and_missed_errord(rp);
+ spin_unlock_bh(&rp->lock);
return &dev->stats;
}
@@ -2022,9 +2095,9 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct rhine_private *rp = netdev_priv(dev);
int rc;
- spin_lock_irq(&rp->lock);
+ mutex_lock(&rp->task_lock);
rc = mii_ethtool_gset(&rp->mii_if, cmd);
- spin_unlock_irq(&rp->lock);
+ mutex_unlock(&rp->task_lock);
return rc;
}
@@ -2034,10 +2107,10 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct rhine_private *rp = netdev_priv(dev);
int rc;
- spin_lock_irq(&rp->lock);
+ mutex_lock(&rp->task_lock);
rc = mii_ethtool_sset(&rp->mii_if, cmd);
- spin_unlock_irq(&rp->lock);
rhine_set_carrier(&rp->mii_if);
+ mutex_unlock(&rp->task_lock);
return rc;
}
@@ -2058,12 +2131,16 @@ static u32 netdev_get_link(struct net_device *dev)
static u32 netdev_get_msglevel(struct net_device *dev)
{
- return debug;
+ struct rhine_private *rp = netdev_priv(dev);
+
+ return rp->msg_enable;
}
static void netdev_set_msglevel(struct net_device *dev, u32 value)
{
- debug = value;
+ struct rhine_private *rp = netdev_priv(dev);
+
+ rp->msg_enable = value;
}
static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -2119,10 +2196,10 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!netif_running(dev))
return -EINVAL;
- spin_lock_irq(&rp->lock);
+ mutex_lock(&rp->task_lock);
rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
- spin_unlock_irq(&rp->lock);
rhine_set_carrier(&rp->mii_if);
+ mutex_unlock(&rp->task_lock);
return rc;
}
@@ -2132,27 +2209,21 @@ static int rhine_close(struct net_device *dev)
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
+ rhine_task_disable(rp);
napi_disable(&rp->napi);
- cancel_work_sync(&rp->reset_task);
netif_stop_queue(dev);
- spin_lock_irq(&rp->lock);
-
- if (debug > 1)
- netdev_dbg(dev, "Shutting down ethercard, status was %04x\n",
- ioread16(ioaddr + ChipCmd));
+ netif_dbg(rp, ifdown, dev, "Shutting down ethercard, status was %04x\n",
+ ioread16(ioaddr + ChipCmd));
/* Switch to loopback mode to avoid hardware races. */
iowrite8(rp->tx_thresh | 0x02, ioaddr + TxConfig);
- /* Disable interrupts by clearing the interrupt mask. */
- iowrite16(0x0000, ioaddr + IntrEnable);
+ rhine_irq_disable(rp);
/* Stop the chip's Tx and Rx processes. */
iowrite16(CmdStop, ioaddr + ChipCmd);
- spin_unlock_irq(&rp->lock);
-
free_irq(rp->pdev->irq, dev);
free_rbufs(dev);
free_tbufs(dev);
@@ -2192,6 +2263,8 @@ static void rhine_shutdown (struct pci_dev *pdev)
if (rp->quirks & rq6patterns)
iowrite8(0x04, ioaddr + WOLcgClr);
+ spin_lock(&rp->lock);
+
if (rp->wolopts & WAKE_MAGIC) {
iowrite8(WOLmagic, ioaddr + WOLcrSet);
/*
@@ -2216,58 +2289,46 @@ static void rhine_shutdown (struct pci_dev *pdev)
iowrite8(ioread8(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW);
}
- /* Hit power state D3 (sleep) */
- if (!avoid_D3)
- iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+ spin_unlock(&rp->lock);
- /* TODO: Check use of pci_enable_wake() */
+ if (system_state == SYSTEM_POWER_OFF && !avoid_D3) {
+ iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+ pci_wake_from_d3(pdev, true);
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
}
-#ifdef CONFIG_PM
-static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int rhine_suspend(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
- unsigned long flags;
if (!netif_running(dev))
return 0;
+ rhine_task_disable(rp);
+ rhine_irq_disable(rp);
napi_disable(&rp->napi);
netif_device_detach(dev);
- pci_save_state(pdev);
- spin_lock_irqsave(&rp->lock, flags);
rhine_shutdown(pdev);
- spin_unlock_irqrestore(&rp->lock, flags);
- free_irq(dev->irq, dev);
return 0;
}
-static int rhine_resume(struct pci_dev *pdev)
+static int rhine_resume(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
- unsigned long flags;
- int ret;
if (!netif_running(dev))
return 0;
- if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
- netdev_err(dev, "request_irq failed\n");
-
- ret = pci_set_power_state(pdev, PCI_D0);
- if (debug > 1)
- netdev_info(dev, "Entering power state D0 %s (%d)\n",
- ret ? "failed" : "succeeded", ret);
-
- pci_restore_state(pdev);
-
- spin_lock_irqsave(&rp->lock, flags);
#ifdef USE_MMIO
enable_mmio(rp->pioaddr, rp->quirks);
#endif
@@ -2276,25 +2337,32 @@ static int rhine_resume(struct pci_dev *pdev)
free_rbufs(dev);
alloc_tbufs(dev);
alloc_rbufs(dev);
+ rhine_task_enable(rp);
+ spin_lock_bh(&rp->lock);
init_registers(dev);
- spin_unlock_irqrestore(&rp->lock, flags);
+ spin_unlock_bh(&rp->lock);
netif_device_attach(dev);
return 0;
}
-#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(rhine_pm_ops, rhine_suspend, rhine_resume);
+#define RHINE_PM_OPS (&rhine_pm_ops)
+
+#else
+
+#define RHINE_PM_OPS NULL
+
+#endif /* !CONFIG_PM_SLEEP */
static struct pci_driver rhine_driver = {
.name = DRV_NAME,
.id_table = rhine_pci_tbl,
.probe = rhine_init_one,
.remove = __devexit_p(rhine_remove_one),
-#ifdef CONFIG_PM
- .suspend = rhine_suspend,
- .resume = rhine_resume,
-#endif /* CONFIG_PM */
- .shutdown = rhine_shutdown,
+ .shutdown = rhine_shutdown,
+ .driver.pm = RHINE_PM_OPS,
};
static struct dmi_system_id __initdata rhine_dmi_table[] = {
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index f45c85a..72a854f 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -529,7 +529,7 @@ static int ixp4xx_mdio_register(void)
mdio_bus->name = "IXP4xx MII Bus";
mdio_bus->read = &ixp4xx_mdio_read;
mdio_bus->write = &ixp4xx_mdio_write;
- strcpy(mdio_bus->id, "0");
+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "ixp4xx-eth-0");
if ((err = mdiobus_register(mdio_bus)))
mdiobus_free(mdio_bus);
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index d423d18..e535137 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -313,8 +313,12 @@ config TOSHIBA_FIR
donauboe.
config AU1000_FIR
- tristate "Alchemy Au1000 SIR/FIR"
+ tristate "Alchemy IrDA SIR/FIR"
depends on IRDA && MIPS_ALCHEMY
+ help
+ Say Y/M here to build suppor the the IrDA peripheral on the
+ Alchemy Au1000 and Au1100 SoCs.
+ Say M to build a module; it will be called au1k_ir.ko
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
diff --git a/drivers/net/irda/au1000_ircc.h b/drivers/net/irda/au1000_ircc.h
deleted file mode 100644
index c072c09..0000000
--- a/drivers/net/irda/au1000_ircc.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * Au1000 IrDA driver.
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or 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.
- *
- * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
- *
- * 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 AU1000_IRCC_H
-#define AU1000_IRCC_H
-
-#include <linux/time.h>
-
-#include <linux/spinlock.h>
-#include <linux/pm.h>
-#include <asm/io.h>
-
-#define NUM_IR_IFF 1
-#define NUM_IR_DESC 64
-#define RING_SIZE_4 0x0
-#define RING_SIZE_16 0x3
-#define RING_SIZE_64 0xF
-#define MAX_NUM_IR_DESC 64
-#define MAX_BUF_SIZE 2048
-
-#define BPS_115200 0
-#define BPS_57600 1
-#define BPS_38400 2
-#define BPS_19200 5
-#define BPS_9600 11
-#define BPS_2400 47
-
-/* Ring descriptor flags */
-#define AU_OWN (1<<7) /* tx,rx */
-
-#define IR_DIS_CRC (1<<6) /* tx */
-#define IR_BAD_CRC (1<<5) /* tx */
-#define IR_NEED_PULSE (1<<4) /* tx */
-#define IR_FORCE_UNDER (1<<3) /* tx */
-#define IR_DISABLE_TX (1<<2) /* tx */
-#define IR_HW_UNDER (1<<0) /* tx */
-#define IR_TX_ERROR (IR_DIS_CRC|IR_BAD_CRC|IR_HW_UNDER)
-
-#define IR_PHY_ERROR (1<<6) /* rx */
-#define IR_CRC_ERROR (1<<5) /* rx */
-#define IR_MAX_LEN (1<<4) /* rx */
-#define IR_FIFO_OVER (1<<3) /* rx */
-#define IR_SIR_ERROR (1<<2) /* rx */
-#define IR_RX_ERROR (IR_PHY_ERROR|IR_CRC_ERROR| \
- IR_MAX_LEN|IR_FIFO_OVER|IR_SIR_ERROR)
-
-typedef struct db_dest {
- struct db_dest *pnext;
- volatile u32 *vaddr;
- dma_addr_t dma_addr;
-} db_dest_t;
-
-
-typedef struct ring_desc {
- u8 count_0; /* 7:0 */
- u8 count_1; /* 12:8 */
- u8 reserved;
- u8 flags;
- u8 addr_0; /* 7:0 */
- u8 addr_1; /* 15:8 */
- u8 addr_2; /* 23:16 */
- u8 addr_3; /* 31:24 */
-} ring_dest_t;
-
-
-/* Private data for each instance */
-struct au1k_private {
-
- db_dest_t *pDBfree;
- db_dest_t db[2*NUM_IR_DESC];
- volatile ring_dest_t *rx_ring[NUM_IR_DESC];
- volatile ring_dest_t *tx_ring[NUM_IR_DESC];
- db_dest_t *rx_db_inuse[NUM_IR_DESC];
- db_dest_t *tx_db_inuse[NUM_IR_DESC];
- u32 rx_head;
- u32 tx_head;
- u32 tx_tail;
- u32 tx_full;
-
- iobuff_t rx_buff;
-
- struct net_device *netdev;
-
- struct timeval stamp;
- struct timeval now;
- struct qos_info qos;
- struct irlap_cb *irlap;
-
- u8 open;
- u32 speed;
- u32 newspeed;
-
- u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
- struct timer_list timer;
-
- spinlock_t lock; /* For serializing operations */
-};
-#endif /* AU1000_IRCC_H */
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index a3d696a..fc503aa 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -18,104 +18,220 @@
* 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/types.h>
+
#include <linux/init.h>
-#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/slab.h>
-#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
-#include <linux/pm.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/au1000.h>
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100)
-#include <asm/pb1000.h>
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
-#include <asm/db1x00.h>
-#include <asm/mach-db1x00/bcsr.h>
-#else
-#error au1k_ir: unsupported board
-#endif
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/types.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
-#include "au1000_ircc.h"
+#include <asm/mach-au1x00/au1000.h>
+
+/* registers */
+#define IR_RING_PTR_STATUS 0x00
+#define IR_RING_BASE_ADDR_H 0x04
+#define IR_RING_BASE_ADDR_L 0x08
+#define IR_RING_SIZE 0x0C
+#define IR_RING_PROMPT 0x10
+#define IR_RING_ADDR_CMPR 0x14
+#define IR_INT_CLEAR 0x18
+#define IR_CONFIG_1 0x20
+#define IR_SIR_FLAGS 0x24
+#define IR_STATUS 0x28
+#define IR_READ_PHY_CONFIG 0x2C
+#define IR_WRITE_PHY_CONFIG 0x30
+#define IR_MAX_PKT_LEN 0x34
+#define IR_RX_BYTE_CNT 0x38
+#define IR_CONFIG_2 0x3C
+#define IR_ENABLE 0x40
+
+/* Config1 */
+#define IR_RX_INVERT_LED (1 << 0)
+#define IR_TX_INVERT_LED (1 << 1)
+#define IR_ST (1 << 2)
+#define IR_SF (1 << 3)
+#define IR_SIR (1 << 4)
+#define IR_MIR (1 << 5)
+#define IR_FIR (1 << 6)
+#define IR_16CRC (1 << 7)
+#define IR_TD (1 << 8)
+#define IR_RX_ALL (1 << 9)
+#define IR_DMA_ENABLE (1 << 10)
+#define IR_RX_ENABLE (1 << 11)
+#define IR_TX_ENABLE (1 << 12)
+#define IR_LOOPBACK (1 << 14)
+#define IR_SIR_MODE (IR_SIR | IR_DMA_ENABLE | \
+ IR_RX_ALL | IR_RX_ENABLE | IR_SF | \
+ IR_16CRC)
+
+/* ir_status */
+#define IR_RX_STATUS (1 << 9)
+#define IR_TX_STATUS (1 << 10)
+#define IR_PHYEN (1 << 15)
+
+/* ir_write_phy_config */
+#define IR_BR(x) (((x) & 0x3f) << 10) /* baud rate */
+#define IR_PW(x) (((x) & 0x1f) << 5) /* pulse width */
+#define IR_P(x) ((x) & 0x1f) /* preamble bits */
+
+/* Config2 */
+#define IR_MODE_INV (1 << 0)
+#define IR_ONE_PIN (1 << 1)
+#define IR_PHYCLK_40MHZ (0 << 2)
+#define IR_PHYCLK_48MHZ (1 << 2)
+#define IR_PHYCLK_56MHZ (2 << 2)
+#define IR_PHYCLK_64MHZ (3 << 2)
+#define IR_DP (1 << 4)
+#define IR_DA (1 << 5)
+#define IR_FLT_HIGH (0 << 6)
+#define IR_FLT_MEDHI (1 << 6)
+#define IR_FLT_MEDLO (2 << 6)
+#define IR_FLT_LO (3 << 6)
+#define IR_IEN (1 << 8)
+
+/* ir_enable */
+#define IR_HC (1 << 3) /* divide SBUS clock by 2 */
+#define IR_CE (1 << 2) /* clock enable */
+#define IR_C (1 << 1) /* coherency bit */
+#define IR_BE (1 << 0) /* set in big endian mode */
+
+#define NUM_IR_DESC 64
+#define RING_SIZE_4 0x0
+#define RING_SIZE_16 0x3
+#define RING_SIZE_64 0xF
+#define MAX_NUM_IR_DESC 64
+#define MAX_BUF_SIZE 2048
+
+/* Ring descriptor flags */
+#define AU_OWN (1 << 7) /* tx,rx */
+#define IR_DIS_CRC (1 << 6) /* tx */
+#define IR_BAD_CRC (1 << 5) /* tx */
+#define IR_NEED_PULSE (1 << 4) /* tx */
+#define IR_FORCE_UNDER (1 << 3) /* tx */
+#define IR_DISABLE_TX (1 << 2) /* tx */
+#define IR_HW_UNDER (1 << 0) /* tx */
+#define IR_TX_ERROR (IR_DIS_CRC | IR_BAD_CRC | IR_HW_UNDER)
+
+#define IR_PHY_ERROR (1 << 6) /* rx */
+#define IR_CRC_ERROR (1 << 5) /* rx */
+#define IR_MAX_LEN (1 << 4) /* rx */
+#define IR_FIFO_OVER (1 << 3) /* rx */
+#define IR_SIR_ERROR (1 << 2) /* rx */
+#define IR_RX_ERROR (IR_PHY_ERROR | IR_CRC_ERROR | \
+ IR_MAX_LEN | IR_FIFO_OVER | IR_SIR_ERROR)
+
+struct db_dest {
+ struct db_dest *pnext;
+ volatile u32 *vaddr;
+ dma_addr_t dma_addr;
+};
-static int au1k_irda_net_init(struct net_device *);
-static int au1k_irda_start(struct net_device *);
-static int au1k_irda_stop(struct net_device *dev);
-static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
-static int au1k_irda_rx(struct net_device *);
-static void au1k_irda_interrupt(int, void *);
-static void au1k_tx_timeout(struct net_device *);
-static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
-static int au1k_irda_set_speed(struct net_device *dev, int speed);
+struct ring_dest {
+ u8 count_0; /* 7:0 */
+ u8 count_1; /* 12:8 */
+ u8 reserved;
+ u8 flags;
+ u8 addr_0; /* 7:0 */
+ u8 addr_1; /* 15:8 */
+ u8 addr_2; /* 23:16 */
+ u8 addr_3; /* 31:24 */
+};
-static void *dma_alloc(size_t, dma_addr_t *);
-static void dma_free(void *, size_t);
+/* Private data for each instance */
+struct au1k_private {
+ void __iomem *iobase;
+ int irq_rx, irq_tx;
+
+ struct db_dest *pDBfree;
+ struct db_dest db[2 * NUM_IR_DESC];
+ volatile struct ring_dest *rx_ring[NUM_IR_DESC];
+ volatile struct ring_dest *tx_ring[NUM_IR_DESC];
+ struct db_dest *rx_db_inuse[NUM_IR_DESC];
+ struct db_dest *tx_db_inuse[NUM_IR_DESC];
+ u32 rx_head;
+ u32 tx_head;
+ u32 tx_tail;
+ u32 tx_full;
+
+ iobuff_t rx_buff;
+
+ struct net_device *netdev;
+ struct timeval stamp;
+ struct timeval now;
+ struct qos_info qos;
+ struct irlap_cb *irlap;
+
+ u8 open;
+ u32 speed;
+ u32 newspeed;
+
+ struct timer_list timer;
+
+ struct resource *ioarea;
+ struct au1k_irda_platform_data *platdata;
+};
static int qos_mtt_bits = 0x07; /* 1 ms or more */
-static struct net_device *ir_devs[NUM_IR_IFF];
-static char version[] __devinitdata =
- "au1k_ircc:1.2 ppopov@mvista.com\n";
#define RUN_AT(x) (jiffies + (x))
-static DEFINE_SPINLOCK(ir_lock);
+static void au1k_irda_plat_set_phy_mode(struct au1k_private *p, int mode)
+{
+ if (p->platdata && p->platdata->set_phy_mode)
+ p->platdata->set_phy_mode(mode);
+}
-/*
- * IrDA peripheral bug. You have to read the register
- * twice to get the right value.
- */
-u32 read_ir_reg(u32 addr)
-{
- readl(addr);
- return readl(addr);
+static inline unsigned long irda_read(struct au1k_private *p,
+ unsigned long ofs)
+{
+ /*
+ * IrDA peripheral bug. You have to read the register
+ * twice to get the right value.
+ */
+ (void)__raw_readl(p->iobase + ofs);
+ return __raw_readl(p->iobase + ofs);
}
+static inline void irda_write(struct au1k_private *p, unsigned long ofs,
+ unsigned long val)
+{
+ __raw_writel(val, p->iobase + ofs);
+ wmb();
+}
/*
* Buffer allocation/deallocation routines. The buffer descriptor returned
- * has the virtual and dma address of a buffer suitable for
+ * has the virtual and dma address of a buffer suitable for
* both, receive and transmit operations.
*/
-static db_dest_t *GetFreeDB(struct au1k_private *aup)
+static struct db_dest *GetFreeDB(struct au1k_private *aup)
{
- db_dest_t *pDB;
- pDB = aup->pDBfree;
-
- if (pDB) {
- aup->pDBfree = pDB->pnext;
- }
- return pDB;
-}
+ struct db_dest *db;
+ db = aup->pDBfree;
-static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB)
-{
- db_dest_t *pDBfree = aup->pDBfree;
- if (pDBfree)
- pDBfree->pnext = pDB;
- aup->pDBfree = pDB;
+ if (db)
+ aup->pDBfree = db->pnext;
+ return db;
}
-
/*
DMA memory allocation, derived from pci_alloc_consistent.
However, the Au1000 data cache is coherent (when programmed
so), therefore we return KSEG0 address, not KSEG1.
*/
-static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
+static void *dma_alloc(size_t size, dma_addr_t *dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC | GFP_DMA;
- ret = (void *) __get_free_pages(gfp, get_order(size));
+ ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
@@ -125,7 +241,6 @@ static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
return ret;
}
-
static void dma_free(void *vaddr, size_t size)
{
vaddr = (void *)KSEG0ADDR(vaddr);
@@ -133,206 +248,306 @@ static void dma_free(void *vaddr, size_t size)
}
-static void
-setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
+static void setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
{
int i;
- for (i=0; i<NUM_IR_DESC; i++) {
- aup->rx_ring[i] = (volatile ring_dest_t *)
- (rx_base + sizeof(ring_dest_t)*i);
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ aup->rx_ring[i] = (volatile struct ring_dest *)
+ (rx_base + sizeof(struct ring_dest) * i);
}
- for (i=0; i<NUM_IR_DESC; i++) {
- aup->tx_ring[i] = (volatile ring_dest_t *)
- (tx_base + sizeof(ring_dest_t)*i);
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ aup->tx_ring[i] = (volatile struct ring_dest *)
+ (tx_base + sizeof(struct ring_dest) * i);
}
}
-static int au1k_irda_init(void)
-{
- static unsigned version_printed = 0;
- struct au1k_private *aup;
- struct net_device *dev;
- int err;
-
- if (version_printed++ == 0) printk(version);
-
- dev = alloc_irdadev(sizeof(struct au1k_private));
- if (!dev)
- return -ENOMEM;
-
- dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
- err = au1k_irda_net_init(dev);
- if (err)
- goto out;
- err = register_netdev(dev);
- if (err)
- goto out1;
- ir_devs[0] = dev;
- printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
- return 0;
-
-out1:
- aup = netdev_priv(dev);
- dma_free((void *)aup->db[0].vaddr,
- MAX_BUF_SIZE * 2*NUM_IR_DESC);
- dma_free((void *)aup->rx_ring[0],
- 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
- kfree(aup->rx_buff.head);
-out:
- free_netdev(dev);
- return err;
-}
-
static int au1k_irda_init_iobuf(iobuff_t *io, int size)
{
io->head = kmalloc(size, GFP_KERNEL);
if (io->head != NULL) {
- io->truesize = size;
- io->in_frame = FALSE;
- io->state = OUTSIDE_FRAME;
- io->data = io->head;
+ io->truesize = size;
+ io->in_frame = FALSE;
+ io->state = OUTSIDE_FRAME;
+ io->data = io->head;
}
return io->head ? 0 : -ENOMEM;
}
-static const struct net_device_ops au1k_irda_netdev_ops = {
- .ndo_open = au1k_irda_start,
- .ndo_stop = au1k_irda_stop,
- .ndo_start_xmit = au1k_irda_hard_xmit,
- .ndo_tx_timeout = au1k_tx_timeout,
- .ndo_do_ioctl = au1k_irda_ioctl,
-};
-
-static int au1k_irda_net_init(struct net_device *dev)
+/*
+ * Set the IrDA communications speed.
+ */
+static int au1k_irda_set_speed(struct net_device *dev, int speed)
{
struct au1k_private *aup = netdev_priv(dev);
- int i, retval = 0, err;
- db_dest_t *pDB, *pDBfree;
- dma_addr_t temp;
+ volatile struct ring_dest *ptxd;
+ unsigned long control;
+ int ret = 0, timeout = 10, i;
- err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
- if (err)
- goto out1;
+ if (speed == aup->speed)
+ return ret;
- dev->netdev_ops = &au1k_irda_netdev_ops;
+ /* disable PHY first */
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF);
+ irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) & ~IR_PHYEN);
- irda_init_max_qos_capabilies(&aup->qos);
+ /* disable RX/TX */
+ irda_write(aup, IR_CONFIG_1,
+ irda_read(aup, IR_CONFIG_1) & ~(IR_RX_ENABLE | IR_TX_ENABLE));
+ msleep(20);
+ while (irda_read(aup, IR_STATUS) & (IR_RX_STATUS | IR_TX_STATUS)) {
+ msleep(20);
+ if (!timeout--) {
+ printk(KERN_ERR "%s: rx/tx disable timeout\n",
+ dev->name);
+ break;
+ }
+ }
- /* The only value we must override it the baudrate */
- aup->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
- IR_115200|IR_576000 |(IR_4000000 << 8);
-
- aup->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value(&aup->qos);
+ /* disable DMA */
+ irda_write(aup, IR_CONFIG_1,
+ irda_read(aup, IR_CONFIG_1) & ~IR_DMA_ENABLE);
+ msleep(20);
- retval = -ENOMEM;
+ /* After we disable tx/rx. the index pointers go back to zero. */
+ aup->tx_head = aup->tx_tail = aup->rx_head = 0;
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ ptxd = aup->tx_ring[i];
+ ptxd->flags = 0;
+ ptxd->count_0 = 0;
+ ptxd->count_1 = 0;
+ }
- /* Tx ring follows rx ring + 512 bytes */
- /* we need a 1k aligned buffer */
- aup->rx_ring[0] = (ring_dest_t *)
- dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
- if (!aup->rx_ring[0])
- goto out2;
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ ptxd = aup->rx_ring[i];
+ ptxd->count_0 = 0;
+ ptxd->count_1 = 0;
+ ptxd->flags = AU_OWN;
+ }
- /* allocate the data buffers */
- aup->db[0].vaddr =
- (void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
- if (!aup->db[0].vaddr)
- goto out3;
+ if (speed == 4000000)
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_FIR);
+ else
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_SIR);
- setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
+ switch (speed) {
+ case 9600:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(11) | IR_PW(12));
+ irda_write(aup, IR_CONFIG_1, IR_SIR_MODE);
+ break;
+ case 19200:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(5) | IR_PW(12));
+ irda_write(aup, IR_CONFIG_1, IR_SIR_MODE);
+ break;
+ case 38400:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(2) | IR_PW(12));
+ irda_write(aup, IR_CONFIG_1, IR_SIR_MODE);
+ break;
+ case 57600:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(1) | IR_PW(12));
+ irda_write(aup, IR_CONFIG_1, IR_SIR_MODE);
+ break;
+ case 115200:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_PW(12));
+ irda_write(aup, IR_CONFIG_1, IR_SIR_MODE);
+ break;
+ case 4000000:
+ irda_write(aup, IR_WRITE_PHY_CONFIG, IR_P(15));
+ irda_write(aup, IR_CONFIG_1, IR_FIR | IR_DMA_ENABLE |
+ IR_RX_ENABLE);
+ break;
+ default:
+ printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed);
+ ret = -EINVAL;
+ break;
+ }
- pDBfree = NULL;
- pDB = aup->db;
- for (i=0; i<(2*NUM_IR_DESC); i++) {
- pDB->pnext = pDBfree;
- pDBfree = pDB;
- pDB->vaddr =
- (u32 *)((unsigned)aup->db[0].vaddr + MAX_BUF_SIZE*i);
- pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
- pDB++;
+ aup->speed = speed;
+ irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) | IR_PHYEN);
+
+ control = irda_read(aup, IR_STATUS);
+ irda_write(aup, IR_RING_PROMPT, 0);
+
+ if (control & (1 << 14)) {
+ printk(KERN_ERR "%s: configuration error\n", dev->name);
+ } else {
+ if (control & (1 << 11))
+ printk(KERN_DEBUG "%s Valid SIR config\n", dev->name);
+ if (control & (1 << 12))
+ printk(KERN_DEBUG "%s Valid MIR config\n", dev->name);
+ if (control & (1 << 13))
+ printk(KERN_DEBUG "%s Valid FIR config\n", dev->name);
+ if (control & (1 << 10))
+ printk(KERN_DEBUG "%s TX enabled\n", dev->name);
+ if (control & (1 << 9))
+ printk(KERN_DEBUG "%s RX enabled\n", dev->name);
}
- aup->pDBfree = pDBfree;
- /* attach a data buffer to each descriptor */
- for (i=0; i<NUM_IR_DESC; i++) {
- pDB = GetFreeDB(aup);
- if (!pDB) goto out;
- aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
- aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
- aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
- aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
- aup->rx_db_inuse[i] = pDB;
+ return ret;
+}
+
+static void update_rx_stats(struct net_device *dev, u32 status, u32 count)
+{
+ struct net_device_stats *ps = &dev->stats;
+
+ ps->rx_packets++;
+
+ if (status & IR_RX_ERROR) {
+ ps->rx_errors++;
+ if (status & (IR_PHY_ERROR | IR_FIFO_OVER))
+ ps->rx_missed_errors++;
+ if (status & IR_MAX_LEN)
+ ps->rx_length_errors++;
+ if (status & IR_CRC_ERROR)
+ ps->rx_crc_errors++;
+ } else
+ ps->rx_bytes += count;
+}
+
+static void update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
+{
+ struct net_device_stats *ps = &dev->stats;
+
+ ps->tx_packets++;
+ ps->tx_bytes += pkt_len;
+
+ if (status & IR_TX_ERROR) {
+ ps->tx_errors++;
+ ps->tx_aborted_errors++;
}
- for (i=0; i<NUM_IR_DESC; i++) {
- pDB = GetFreeDB(aup);
- if (!pDB) goto out;
- aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
- aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
- aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
- aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
- aup->tx_ring[i]->count_0 = 0;
- aup->tx_ring[i]->count_1 = 0;
- aup->tx_ring[i]->flags = 0;
- aup->tx_db_inuse[i] = pDB;
+}
+
+static void au1k_tx_ack(struct net_device *dev)
+{
+ struct au1k_private *aup = netdev_priv(dev);
+ volatile struct ring_dest *ptxd;
+
+ ptxd = aup->tx_ring[aup->tx_tail];
+ while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) {
+ update_tx_stats(dev, ptxd->flags,
+ (ptxd->count_1 << 8) | ptxd->count_0);
+ ptxd->count_0 = 0;
+ ptxd->count_1 = 0;
+ wmb();
+ aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1);
+ ptxd = aup->tx_ring[aup->tx_tail];
+
+ if (aup->tx_full) {
+ aup->tx_full = 0;
+ netif_wake_queue(dev);
+ }
}
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
- /* power on */
- bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK,
- BCSR_RESETS_IRDA_MODE_FULL);
-#endif
+ if (aup->tx_tail == aup->tx_head) {
+ if (aup->newspeed) {
+ au1k_irda_set_speed(dev, aup->newspeed);
+ aup->newspeed = 0;
+ } else {
+ irda_write(aup, IR_CONFIG_1,
+ irda_read(aup, IR_CONFIG_1) & ~IR_TX_ENABLE);
+ irda_write(aup, IR_CONFIG_1,
+ irda_read(aup, IR_CONFIG_1) | IR_RX_ENABLE);
+ irda_write(aup, IR_RING_PROMPT, 0);
+ }
+ }
+}
- return 0;
+static int au1k_irda_rx(struct net_device *dev)
+{
+ struct au1k_private *aup = netdev_priv(dev);
+ volatile struct ring_dest *prxd;
+ struct sk_buff *skb;
+ struct db_dest *pDB;
+ u32 flags, count;
-out3:
- dma_free((void *)aup->rx_ring[0],
- 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
-out2:
- kfree(aup->rx_buff.head);
-out1:
- printk(KERN_ERR "au1k_init_module failed. Returns %d\n", retval);
- return retval;
+ prxd = aup->rx_ring[aup->rx_head];
+ flags = prxd->flags;
+
+ while (!(flags & AU_OWN)) {
+ pDB = aup->rx_db_inuse[aup->rx_head];
+ count = (prxd->count_1 << 8) | prxd->count_0;
+ if (!(flags & IR_RX_ERROR)) {
+ /* good frame */
+ update_rx_stats(dev, flags, count);
+ skb = alloc_skb(count + 1, GFP_ATOMIC);
+ if (skb == NULL) {
+ dev->stats.rx_dropped++;
+ continue;
+ }
+ skb_reserve(skb, 1);
+ if (aup->speed == 4000000)
+ skb_put(skb, count);
+ else
+ skb_put(skb, count - 2);
+ skb_copy_to_linear_data(skb, (void *)pDB->vaddr,
+ count - 2);
+ skb->dev = dev;
+ skb_reset_mac_header(skb);
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx(skb);
+ prxd->count_0 = 0;
+ prxd->count_1 = 0;
+ }
+ prxd->flags |= AU_OWN;
+ aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1);
+ irda_write(aup, IR_RING_PROMPT, 0);
+
+ /* next descriptor */
+ prxd = aup->rx_ring[aup->rx_head];
+ flags = prxd->flags;
+
+ }
+ return 0;
}
+static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct au1k_private *aup = netdev_priv(dev);
+
+ irda_write(aup, IR_INT_CLEAR, 0); /* ack irda interrupts */
+
+ au1k_irda_rx(dev);
+ au1k_tx_ack(dev);
+
+ return IRQ_HANDLED;
+}
static int au1k_init(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
+ u32 enable, ring_address;
int i;
- u32 control;
- u32 ring_address;
- /* bring the device out of reset */
- control = 0xe; /* coherent, clock enable, one half system clock */
-
+ enable = IR_HC | IR_CE | IR_C;
#ifndef CONFIG_CPU_LITTLE_ENDIAN
- control |= 1;
+ enable |= IR_BE;
#endif
aup->tx_head = 0;
aup->tx_tail = 0;
aup->rx_head = 0;
- for (i=0; i<NUM_IR_DESC; i++) {
+ for (i = 0; i < NUM_IR_DESC; i++)
aup->rx_ring[i]->flags = AU_OWN;
- }
- writel(control, IR_INTERFACE_CONFIG);
- au_sync_delay(10);
+ irda_write(aup, IR_ENABLE, enable);
+ msleep(20);
- writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); /* disable PHY */
- au_sync_delay(1);
+ /* disable PHY */
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF);
+ irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) & ~IR_PHYEN);
+ msleep(20);
- writel(MAX_BUF_SIZE, IR_MAX_PKT_LEN);
+ irda_write(aup, IR_MAX_PKT_LEN, MAX_BUF_SIZE);
ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]);
- writel(ring_address >> 26, IR_RING_BASE_ADDR_H);
- writel((ring_address >> 10) & 0xffff, IR_RING_BASE_ADDR_L);
+ irda_write(aup, IR_RING_BASE_ADDR_H, ring_address >> 26);
+ irda_write(aup, IR_RING_BASE_ADDR_L, (ring_address >> 10) & 0xffff);
- writel(RING_SIZE_64<<8 | RING_SIZE_64<<12, IR_RING_SIZE);
+ irda_write(aup, IR_RING_SIZE,
+ (RING_SIZE_64 << 8) | (RING_SIZE_64 << 12));
- writel(1<<2 | IR_ONE_PIN, IR_CONFIG_2); /* 48MHz */
- writel(0, IR_RING_ADDR_CMPR);
+ irda_write(aup, IR_CONFIG_2, IR_PHYCLK_48MHZ | IR_ONE_PIN);
+ irda_write(aup, IR_RING_ADDR_CMPR, 0);
au1k_irda_set_speed(dev, 9600);
return 0;
@@ -340,25 +555,28 @@ static int au1k_init(struct net_device *dev)
static int au1k_irda_start(struct net_device *dev)
{
- int retval;
- char hwname[32];
struct au1k_private *aup = netdev_priv(dev);
+ char hwname[32];
+ int retval;
- if ((retval = au1k_init(dev))) {
+ retval = au1k_init(dev);
+ if (retval) {
printk(KERN_ERR "%s: error in au1k_init\n", dev->name);
return retval;
}
- if ((retval = request_irq(AU1000_IRDA_TX_INT, au1k_irda_interrupt,
- 0, dev->name, dev))) {
- printk(KERN_ERR "%s: unable to get IRQ %d\n",
+ retval = request_irq(aup->irq_tx, &au1k_irda_interrupt, 0,
+ dev->name, dev);
+ if (retval) {
+ printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
return retval;
}
- if ((retval = request_irq(AU1000_IRDA_RX_INT, au1k_irda_interrupt,
- 0, dev->name, dev))) {
- free_irq(AU1000_IRDA_TX_INT, dev);
- printk(KERN_ERR "%s: unable to get IRQ %d\n",
+ retval = request_irq(aup->irq_rx, &au1k_irda_interrupt, 0,
+ dev->name, dev);
+ if (retval) {
+ free_irq(aup->irq_tx, dev);
+ printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
return retval;
}
@@ -368,9 +586,13 @@ static int au1k_irda_start(struct net_device *dev)
aup->irlap = irlap_open(dev, &aup->qos, hwname);
netif_start_queue(dev);
- writel(read_ir_reg(IR_CONFIG_2) | 1<<8, IR_CONFIG_2); /* int enable */
+ /* int enable */
+ irda_write(aup, IR_CONFIG_2, irda_read(aup, IR_CONFIG_2) | IR_IEN);
+
+ /* power up */
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_SIR);
- aup->timer.expires = RUN_AT((3*HZ));
+ aup->timer.expires = RUN_AT((3 * HZ));
aup->timer.data = (unsigned long)dev;
return 0;
}
@@ -379,11 +601,12 @@ static int au1k_irda_stop(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
+ au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF);
+
/* disable interrupts */
- writel(read_ir_reg(IR_CONFIG_2) & ~(1<<8), IR_CONFIG_2);
- writel(0, IR_CONFIG_1);
- writel(0, IR_INTERFACE_CONFIG); /* disable clock */
- au_sync();
+ irda_write(aup, IR_CONFIG_2, irda_read(aup, IR_CONFIG_2) & ~IR_IEN);
+ irda_write(aup, IR_CONFIG_1, 0);
+ irda_write(aup, IR_ENABLE, 0); /* disable clock */
if (aup->irlap) {
irlap_close(aup->irlap);
@@ -394,83 +617,12 @@ static int au1k_irda_stop(struct net_device *dev)
del_timer(&aup->timer);
/* disable the interrupt */
- free_irq(AU1000_IRDA_TX_INT, dev);
- free_irq(AU1000_IRDA_RX_INT, dev);
- return 0;
-}
-
-static void __exit au1k_irda_exit(void)
-{
- struct net_device *dev = ir_devs[0];
- struct au1k_private *aup = netdev_priv(dev);
+ free_irq(aup->irq_tx, dev);
+ free_irq(aup->irq_rx, dev);
- unregister_netdev(dev);
-
- dma_free((void *)aup->db[0].vaddr,
- MAX_BUF_SIZE * 2*NUM_IR_DESC);
- dma_free((void *)aup->rx_ring[0],
- 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
- kfree(aup->rx_buff.head);
- free_netdev(dev);
-}
-
-
-static inline void
-update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
-{
- struct au1k_private *aup = netdev_priv(dev);
- struct net_device_stats *ps = &aup->stats;
-
- ps->tx_packets++;
- ps->tx_bytes += pkt_len;
-
- if (status & IR_TX_ERROR) {
- ps->tx_errors++;
- ps->tx_aborted_errors++;
- }
-}
-
-
-static void au1k_tx_ack(struct net_device *dev)
-{
- struct au1k_private *aup = netdev_priv(dev);
- volatile ring_dest_t *ptxd;
-
- ptxd = aup->tx_ring[aup->tx_tail];
- while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) {
- update_tx_stats(dev, ptxd->flags,
- ptxd->count_1<<8 | ptxd->count_0);
- ptxd->count_0 = 0;
- ptxd->count_1 = 0;
- au_sync();
-
- aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1);
- ptxd = aup->tx_ring[aup->tx_tail];
-
- if (aup->tx_full) {
- aup->tx_full = 0;
- netif_wake_queue(dev);
- }
- }
-
- if (aup->tx_tail == aup->tx_head) {
- if (aup->newspeed) {
- au1k_irda_set_speed(dev, aup->newspeed);
- aup->newspeed = 0;
- }
- else {
- writel(read_ir_reg(IR_CONFIG_1) & ~IR_TX_ENABLE,
- IR_CONFIG_1);
- au_sync();
- writel(read_ir_reg(IR_CONFIG_1) | IR_RX_ENABLE,
- IR_CONFIG_1);
- writel(0, IR_RING_PROMPT);
- au_sync();
- }
- }
+ return 0;
}
-
/*
* Au1000 transmit routine.
*/
@@ -478,15 +630,12 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
int speed = irda_get_next_speed(skb);
- volatile ring_dest_t *ptxd;
- u32 len;
-
- u32 flags;
- db_dest_t *pDB;
+ volatile struct ring_dest *ptxd;
+ struct db_dest *pDB;
+ u32 len, flags;
- if (speed != aup->speed && speed != -1) {
+ if (speed != aup->speed && speed != -1)
aup->newspeed = speed;
- }
if ((skb->len == 0) && (aup->newspeed)) {
if (aup->tx_tail == aup->tx_head) {
@@ -504,138 +653,47 @@ static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
printk(KERN_DEBUG "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
- return NETDEV_TX_BUSY;
- }
- else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
+ return 1;
+ } else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
printk(KERN_DEBUG "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
- return NETDEV_TX_BUSY;
+ return 1;
}
pDB = aup->tx_db_inuse[aup->tx_head];
#if 0
- if (read_ir_reg(IR_RX_BYTE_CNT) != 0) {
- printk("tx warning: rx byte cnt %x\n",
- read_ir_reg(IR_RX_BYTE_CNT));
+ if (irda_read(aup, IR_RX_BYTE_CNT) != 0) {
+ printk(KERN_DEBUG "tx warning: rx byte cnt %x\n",
+ irda_read(aup, IR_RX_BYTE_CNT));
}
#endif
-
+
if (aup->speed == 4000000) {
/* FIR */
- skb_copy_from_linear_data(skb, pDB->vaddr, skb->len);
+ skb_copy_from_linear_data(skb, (void *)pDB->vaddr, skb->len);
ptxd->count_0 = skb->len & 0xff;
ptxd->count_1 = (skb->len >> 8) & 0xff;
-
- }
- else {
+ } else {
/* SIR */
len = async_wrap_skb(skb, (u8 *)pDB->vaddr, MAX_BUF_SIZE);
ptxd->count_0 = len & 0xff;
ptxd->count_1 = (len >> 8) & 0xff;
ptxd->flags |= IR_DIS_CRC;
- au_writel(au_readl(0xae00000c) & ~(1<<13), 0xae00000c);
}
ptxd->flags |= AU_OWN;
- au_sync();
+ wmb();
- writel(read_ir_reg(IR_CONFIG_1) | IR_TX_ENABLE, IR_CONFIG_1);
- writel(0, IR_RING_PROMPT);
- au_sync();
+ irda_write(aup, IR_CONFIG_1,
+ irda_read(aup, IR_CONFIG_1) | IR_TX_ENABLE);
+ irda_write(aup, IR_RING_PROMPT, 0);
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1);
return NETDEV_TX_OK;
}
-
-static inline void
-update_rx_stats(struct net_device *dev, u32 status, u32 count)
-{
- struct au1k_private *aup = netdev_priv(dev);
- struct net_device_stats *ps = &aup->stats;
-
- ps->rx_packets++;
-
- if (status & IR_RX_ERROR) {
- ps->rx_errors++;
- if (status & (IR_PHY_ERROR|IR_FIFO_OVER))
- ps->rx_missed_errors++;
- if (status & IR_MAX_LEN)
- ps->rx_length_errors++;
- if (status & IR_CRC_ERROR)
- ps->rx_crc_errors++;
- }
- else
- ps->rx_bytes += count;
-}
-
-/*
- * Au1000 receive routine.
- */
-static int au1k_irda_rx(struct net_device *dev)
-{
- struct au1k_private *aup = netdev_priv(dev);
- struct sk_buff *skb;
- volatile ring_dest_t *prxd;
- u32 flags, count;
- db_dest_t *pDB;
-
- prxd = aup->rx_ring[aup->rx_head];
- flags = prxd->flags;
-
- while (!(flags & AU_OWN)) {
- pDB = aup->rx_db_inuse[aup->rx_head];
- count = prxd->count_1<<8 | prxd->count_0;
- if (!(flags & IR_RX_ERROR)) {
- /* good frame */
- update_rx_stats(dev, flags, count);
- skb=alloc_skb(count+1,GFP_ATOMIC);
- if (skb == NULL) {
- aup->netdev->stats.rx_dropped++;
- continue;
- }
- skb_reserve(skb, 1);
- if (aup->speed == 4000000)
- skb_put(skb, count);
- else
- skb_put(skb, count-2);
- skb_copy_to_linear_data(skb, pDB->vaddr, count - 2);
- skb->dev = dev;
- skb_reset_mac_header(skb);
- skb->protocol = htons(ETH_P_IRDA);
- netif_rx(skb);
- prxd->count_0 = 0;
- prxd->count_1 = 0;
- }
- prxd->flags |= AU_OWN;
- aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1);
- writel(0, IR_RING_PROMPT);
- au_sync();
-
- /* next descriptor */
- prxd = aup->rx_ring[aup->rx_head];
- flags = prxd->flags;
-
- }
- return 0;
-}
-
-
-static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id)
-{
- struct net_device *dev = dev_id;
-
- writel(0, IR_INT_CLEAR); /* ack irda interrupts */
-
- au1k_irda_rx(dev);
- au1k_tx_ack(dev);
-
- return IRQ_HANDLED;
-}
-
-
/*
* The Tx ring has been full longer than the watchdog timeout
* value. The transmitter must be hung?
@@ -653,142 +711,7 @@ static void au1k_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-
-/*
- * Set the IrDA communications speed.
- */
-static int
-au1k_irda_set_speed(struct net_device *dev, int speed)
-{
- unsigned long flags;
- struct au1k_private *aup = netdev_priv(dev);
- u32 control;
- int ret = 0, timeout = 10, i;
- volatile ring_dest_t *ptxd;
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
- unsigned long irda_resets;
-#endif
-
- if (speed == aup->speed)
- return ret;
-
- spin_lock_irqsave(&ir_lock, flags);
-
- /* disable PHY first */
- writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE);
-
- /* disable RX/TX */
- writel(read_ir_reg(IR_CONFIG_1) & ~(IR_RX_ENABLE|IR_TX_ENABLE),
- IR_CONFIG_1);
- au_sync_delay(1);
- while (read_ir_reg(IR_ENABLE) & (IR_RX_STATUS | IR_TX_STATUS)) {
- mdelay(1);
- if (!timeout--) {
- printk(KERN_ERR "%s: rx/tx disable timeout\n",
- dev->name);
- break;
- }
- }
-
- /* disable DMA */
- writel(read_ir_reg(IR_CONFIG_1) & ~IR_DMA_ENABLE, IR_CONFIG_1);
- au_sync_delay(1);
-
- /*
- * After we disable tx/rx. the index pointers
- * go back to zero.
- */
- aup->tx_head = aup->tx_tail = aup->rx_head = 0;
- for (i=0; i<NUM_IR_DESC; i++) {
- ptxd = aup->tx_ring[i];
- ptxd->flags = 0;
- ptxd->count_0 = 0;
- ptxd->count_1 = 0;
- }
-
- for (i=0; i<NUM_IR_DESC; i++) {
- ptxd = aup->rx_ring[i];
- ptxd->count_0 = 0;
- ptxd->count_1 = 0;
- ptxd->flags = AU_OWN;
- }
-
- if (speed == 4000000) {
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
- bcsr_mod(BCSR_RESETS, 0, BCSR_RESETS_FIR_SEL);
-#else /* Pb1000 and Pb1100 */
- writel(1<<13, CPLD_AUX1);
-#endif
- }
- else {
-#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
- bcsr_mod(BCSR_RESETS, BCSR_RESETS_FIR_SEL, 0);
-#else /* Pb1000 and Pb1100 */
- writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1);
-#endif
- }
-
- switch (speed) {
- case 9600:
- writel(11<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
- writel(IR_SIR_MODE, IR_CONFIG_1);
- break;
- case 19200:
- writel(5<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
- writel(IR_SIR_MODE, IR_CONFIG_1);
- break;
- case 38400:
- writel(2<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
- writel(IR_SIR_MODE, IR_CONFIG_1);
- break;
- case 57600:
- writel(1<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
- writel(IR_SIR_MODE, IR_CONFIG_1);
- break;
- case 115200:
- writel(12<<5, IR_WRITE_PHY_CONFIG);
- writel(IR_SIR_MODE, IR_CONFIG_1);
- break;
- case 4000000:
- writel(0xF, IR_WRITE_PHY_CONFIG);
- writel(IR_FIR|IR_DMA_ENABLE|IR_RX_ENABLE, IR_CONFIG_1);
- break;
- default:
- printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed);
- ret = -EINVAL;
- break;
- }
-
- aup->speed = speed;
- writel(read_ir_reg(IR_ENABLE) | 0x8000, IR_ENABLE);
- au_sync();
-
- control = read_ir_reg(IR_ENABLE);
- writel(0, IR_RING_PROMPT);
- au_sync();
-
- if (control & (1<<14)) {
- printk(KERN_ERR "%s: configuration error\n", dev->name);
- }
- else {
- if (control & (1<<11))
- printk(KERN_DEBUG "%s Valid SIR config\n", dev->name);
- if (control & (1<<12))
- printk(KERN_DEBUG "%s Valid MIR config\n", dev->name);
- if (control & (1<<13))
- printk(KERN_DEBUG "%s Valid FIR config\n", dev->name);
- if (control & (1<<10))
- printk(KERN_DEBUG "%s TX enabled\n", dev->name);
- if (control & (1<<9))
- printk(KERN_DEBUG "%s RX enabled\n", dev->name);
- }
-
- spin_unlock_irqrestore(&ir_lock, flags);
- return ret;
-}
-
-static int
-au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
+static int au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
{
struct if_irda_req *rq = (struct if_irda_req *)ifreq;
struct au1k_private *aup = netdev_priv(dev);
@@ -829,8 +752,218 @@ au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
return ret;
}
+static const struct net_device_ops au1k_irda_netdev_ops = {
+ .ndo_open = au1k_irda_start,
+ .ndo_stop = au1k_irda_stop,
+ .ndo_start_xmit = au1k_irda_hard_xmit,
+ .ndo_tx_timeout = au1k_tx_timeout,
+ .ndo_do_ioctl = au1k_irda_ioctl,
+};
+
+static int __devinit au1k_irda_net_init(struct net_device *dev)
+{
+ struct au1k_private *aup = netdev_priv(dev);
+ struct db_dest *pDB, *pDBfree;
+ int i, err, retval = 0;
+ dma_addr_t temp;
+
+ err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
+ if (err)
+ goto out1;
+
+ dev->netdev_ops = &au1k_irda_netdev_ops;
+
+ irda_init_max_qos_capabilies(&aup->qos);
+
+ /* The only value we must override it the baudrate */
+ aup->qos.baud_rate.bits = IR_9600 | IR_19200 | IR_38400 |
+ IR_57600 | IR_115200 | IR_576000 | (IR_4000000 << 8);
+
+ aup->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&aup->qos);
+
+ retval = -ENOMEM;
+
+ /* Tx ring follows rx ring + 512 bytes */
+ /* we need a 1k aligned buffer */
+ aup->rx_ring[0] = (struct ring_dest *)
+ dma_alloc(2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest)),
+ &temp);
+ if (!aup->rx_ring[0])
+ goto out2;
+
+ /* allocate the data buffers */
+ aup->db[0].vaddr =
+ (void *)dma_alloc(MAX_BUF_SIZE * 2 * NUM_IR_DESC, &temp);
+ if (!aup->db[0].vaddr)
+ goto out3;
+
+ setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
+
+ pDBfree = NULL;
+ pDB = aup->db;
+ for (i = 0; i < (2 * NUM_IR_DESC); i++) {
+ pDB->pnext = pDBfree;
+ pDBfree = pDB;
+ pDB->vaddr =
+ (u32 *)((unsigned)aup->db[0].vaddr + (MAX_BUF_SIZE * i));
+ pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
+ pDB++;
+ }
+ aup->pDBfree = pDBfree;
+
+ /* attach a data buffer to each descriptor */
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ pDB = GetFreeDB(aup);
+ if (!pDB)
+ goto out3;
+ aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
+ aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr >> 8) & 0xff);
+ aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr >> 16) & 0xff);
+ aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr >> 24) & 0xff);
+ aup->rx_db_inuse[i] = pDB;
+ }
+ for (i = 0; i < NUM_IR_DESC; i++) {
+ pDB = GetFreeDB(aup);
+ if (!pDB)
+ goto out3;
+ aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
+ aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr >> 8) & 0xff);
+ aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr >> 16) & 0xff);
+ aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr >> 24) & 0xff);
+ aup->tx_ring[i]->count_0 = 0;
+ aup->tx_ring[i]->count_1 = 0;
+ aup->tx_ring[i]->flags = 0;
+ aup->tx_db_inuse[i] = pDB;
+ }
+
+ return 0;
+
+out3:
+ dma_free((void *)aup->rx_ring[0],
+ 2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest)));
+out2:
+ kfree(aup->rx_buff.head);
+out1:
+ printk(KERN_ERR "au1k_irda_net_init() failed. Returns %d\n", retval);
+ return retval;
+}
+
+static int __devinit au1k_irda_probe(struct platform_device *pdev)
+{
+ struct au1k_private *aup;
+ struct net_device *dev;
+ struct resource *r;
+ int err;
+
+ dev = alloc_irdadev(sizeof(struct au1k_private));
+ if (!dev)
+ return -ENOMEM;
+
+ aup = netdev_priv(dev);
+
+ aup->platdata = pdev->dev.platform_data;
+
+ err = -EINVAL;
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!r)
+ goto out;
+
+ aup->irq_tx = r->start;
+
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ if (!r)
+ goto out;
+
+ aup->irq_rx = r->start;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r)
+ goto out;
+
+ err = -EBUSY;
+ aup->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+ pdev->name);
+ if (!aup->ioarea)
+ goto out;
+
+ aup->iobase = ioremap_nocache(r->start, r->end - r->start + 1);
+ if (!aup->iobase)
+ goto out2;
+
+ dev->irq = aup->irq_rx;
+
+ err = au1k_irda_net_init(dev);
+ if (err)
+ goto out3;
+ err = register_netdev(dev);
+ if (err)
+ goto out4;
+
+ platform_set_drvdata(pdev, dev);
+
+ printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
+ return 0;
+
+out4:
+ dma_free((void *)aup->db[0].vaddr,
+ MAX_BUF_SIZE * 2 * NUM_IR_DESC);
+ dma_free((void *)aup->rx_ring[0],
+ 2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest)));
+ kfree(aup->rx_buff.head);
+out3:
+ iounmap(aup->iobase);
+out2:
+ release_resource(aup->ioarea);
+ kfree(aup->ioarea);
+out:
+ free_netdev(dev);
+ return err;
+}
+
+static int __devexit au1k_irda_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct au1k_private *aup = netdev_priv(dev);
+
+ unregister_netdev(dev);
+
+ dma_free((void *)aup->db[0].vaddr,
+ MAX_BUF_SIZE * 2 * NUM_IR_DESC);
+ dma_free((void *)aup->rx_ring[0],
+ 2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest)));
+ kfree(aup->rx_buff.head);
+
+ iounmap(aup->iobase);
+ release_resource(aup->ioarea);
+ kfree(aup->ioarea);
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+static struct platform_driver au1k_irda_driver = {
+ .driver = {
+ .name = "au1000-irda",
+ .owner = THIS_MODULE,
+ },
+ .probe = au1k_irda_probe,
+ .remove = __devexit_p(au1k_irda_remove),
+};
+
+static int __init au1k_irda_load(void)
+{
+ return platform_driver_register(&au1k_irda_driver);
+}
+
+static void __exit au1k_irda_unload(void)
+{
+ return platform_driver_unregister(&au1k_irda_driver);
+}
+
MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
-module_init(au1k_irda_init);
-module_exit(au1k_irda_exit);
+module_init(au1k_irda_load);
+module_exit(au1k_irda_unload);
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index 9663e0b..ba3c591 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1159,7 +1159,7 @@ static void rx_timestamp_work(struct work_struct *work)
}
}
spin_unlock_irqrestore(&dp83640->rx_lock, flags);
- netif_rx(skb);
+ netif_rx_ni(skb);
}
/* Clear out expired time stamps. */
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 1fa4d73..633680d 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -220,7 +220,7 @@ static int __init fixed_mdio_bus_init(void)
goto err_mdiobus_reg;
}
- snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "0");
+ snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0");
fmb->mii_bus->name = "Fixed MDIO Bus";
fmb->mii_bus->priv = fmb;
fmb->mii_bus->parent = &pdev->dev;
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 89c5a3e..50e8e5e 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -116,7 +116,7 @@ static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
if (!new_bus->irq[i])
new_bus->irq[i] = PHY_POLL;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", bus_id);
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
if (gpio_request(bitbang->mdc, "mdc"))
goto out_free_bus;
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index bd12ba9..826d961 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -118,7 +118,8 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
bus->mii_bus->priv = bus;
bus->mii_bus->irq = bus->phy_irq;
bus->mii_bus->name = "mdio-octeon";
- snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
+ snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ bus->mii_bus->name, bus->unit);
bus->mii_bus->parent = &pdev->dev;
bus->mii_bus->read = octeon_mdiobus_read;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 6c58da2..88cc5db 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -37,22 +37,36 @@
#include <asm/uaccess.h>
/**
- * mdiobus_alloc - allocate a mii_bus structure
+ * mdiobus_alloc_size - allocate a mii_bus structure
*
* Description: called by a bus driver to allocate an mii_bus
* structure to fill in.
+ *
+ * 'size' is an an extra amount of memory to allocate for private storage.
+ * If non-zero, then bus->priv is points to that memory.
*/
-struct mii_bus *mdiobus_alloc(void)
+struct mii_bus *mdiobus_alloc_size(size_t size)
{
struct mii_bus *bus;
+ size_t aligned_size = ALIGN(sizeof(*bus), NETDEV_ALIGN);
+ size_t alloc_size;
+
+ /* If we alloc extra space, it should be aligned */
+ if (size)
+ alloc_size = aligned_size + size;
+ else
+ alloc_size = sizeof(*bus);
- bus = kzalloc(sizeof(*bus), GFP_KERNEL);
- if (bus != NULL)
+ bus = kzalloc(alloc_size, GFP_KERNEL);
+ if (bus) {
bus->state = MDIOBUS_ALLOCATED;
+ if (size)
+ bus->priv = (void *)bus + aligned_size;
+ }
return bus;
}
-EXPORT_SYMBOL(mdiobus_alloc);
+EXPORT_SYMBOL(mdiobus_alloc_size);
/**
* mdiobus_release - mii_bus device release callback
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index c1c9293..df884dd 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -585,8 +585,8 @@ static int pptp_create(struct net *net, struct socket *sock)
po = pppox_sk(sk);
opt = &po->proto.pptp;
- opt->seq_sent = 0; opt->seq_recv = 0;
- opt->ack_recv = 0; opt->ack_sent = 0;
+ opt->seq_sent = 0; opt->seq_recv = 0xffffffff;
+ opt->ack_recv = 0; opt->ack_sent = 0xffffffff;
error = 0;
out:
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index d0937c4..8e84f5b 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -978,6 +978,7 @@ static int ax88772_link_reset(struct usbnet *dev)
static int ax88772_reset(struct usbnet *dev)
{
+ struct asix_data *data = (struct asix_data *)&dev->data;
int ret, embd_phy;
u16 rx_ctl;
@@ -1055,6 +1056,13 @@ static int ax88772_reset(struct usbnet *dev)
goto out;
}
+ /* Rewrite MAC address */
+ memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
+ data->mac_addr);
+ if (ret < 0)
+ goto out;
+
/* Set RX_CTL to default values with 2k buffer, and enable cactus */
ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
if (ret < 0)
@@ -1320,6 +1328,13 @@ static int ax88178_reset(struct usbnet *dev)
if (ret < 0)
return ret;
+ /* Rewrite MAC address */
+ memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
+ ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
+ data->mac_addr);
+ if (ret < 0)
+ return ret;
+
ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
if (ret < 0)
return ret;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 76fe14e..4880aa8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -370,7 +370,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
- err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
+ err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
if (err < 0)
dev_kfree_skb(skb);
@@ -415,8 +415,8 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
/* chain first in list head */
first->private = (unsigned long)list;
- err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
- first, gfp);
+ err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+ first, gfp);
if (err < 0)
give_pages(vi, first);
@@ -434,7 +434,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
- err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
+ err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
if (err < 0)
give_pages(vi, page);
@@ -609,7 +609,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
- 0, skb);
+ 0, skb, GFP_ATOMIC);
}
static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -767,7 +767,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
- BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi) < 0);
+ BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
virtqueue_kick(vi->cvq);
@@ -985,15 +985,38 @@ static void virtnet_config_changed(struct virtio_device *vdev)
virtnet_update_status(vi);
}
+static int init_vqs(struct virtnet_info *vi)
+{
+ struct virtqueue *vqs[3];
+ vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
+ const char *names[] = { "input", "output", "control" };
+ int nvqs, err;
+
+ /* We expect two virtqueues, receive then send,
+ * and optionally control. */
+ nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
+
+ err = vi->vdev->config->find_vqs(vi->vdev, nvqs, vqs, callbacks, names);
+ if (err)
+ return err;
+
+ vi->rvq = vqs[0];
+ vi->svq = vqs[1];
+
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
+ vi->cvq = vqs[2];
+
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
+ vi->dev->features |= NETIF_F_HW_VLAN_FILTER;
+ }
+ return 0;
+}
+
static int virtnet_probe(struct virtio_device *vdev)
{
int err;
struct net_device *dev;
struct virtnet_info *vi;
- struct virtqueue *vqs[3];
- vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
- const char *names[] = { "input", "output", "control" };
- int nvqs;
/* Allocate ourselves a network device with room for our info */
dev = alloc_etherdev(sizeof(struct virtnet_info));
@@ -1065,24 +1088,10 @@ static int virtnet_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
vi->mergeable_rx_bufs = true;
- /* We expect two virtqueues, receive then send,
- * and optionally control. */
- nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
-
- err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
+ err = init_vqs(vi);
if (err)
goto free_stats;
- vi->rvq = vqs[0];
- vi->svq = vqs[1];
-
- if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
- vi->cvq = vqs[2];
-
- if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
- dev->features |= NETIF_F_HW_VLAN_FILTER;
- }
-
err = register_netdev(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
@@ -1144,27 +1153,73 @@ static void free_unused_bufs(struct virtnet_info *vi)
BUG_ON(vi->num != 0);
}
-static void __devexit virtnet_remove(struct virtio_device *vdev)
+static void remove_vq_common(struct virtnet_info *vi)
{
- struct virtnet_info *vi = vdev->priv;
-
- /* Stop all the virtqueues. */
- vdev->config->reset(vdev);
-
- unregister_netdev(vi->dev);
+ vi->vdev->config->reset(vi->vdev);
/* Free unused buffers in both send and recv, if any. */
free_unused_bufs(vi);
- vdev->config->del_vqs(vi->vdev);
+ vi->vdev->config->del_vqs(vi->vdev);
while (vi->pages)
__free_pages(get_a_page(vi, GFP_KERNEL), 0);
+}
+
+static void __devexit virtnet_remove(struct virtio_device *vdev)
+{
+ struct virtnet_info *vi = vdev->priv;
+
+ unregister_netdev(vi->dev);
+
+ remove_vq_common(vi);
free_percpu(vi->stats);
free_netdev(vi->dev);
}
+#ifdef CONFIG_PM
+static int virtnet_freeze(struct virtio_device *vdev)
+{
+ struct virtnet_info *vi = vdev->priv;
+
+ virtqueue_disable_cb(vi->rvq);
+ virtqueue_disable_cb(vi->svq);
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
+ virtqueue_disable_cb(vi->cvq);
+
+ netif_device_detach(vi->dev);
+ cancel_delayed_work_sync(&vi->refill);
+
+ if (netif_running(vi->dev))
+ napi_disable(&vi->napi);
+
+ remove_vq_common(vi);
+
+ return 0;
+}
+
+static int virtnet_restore(struct virtio_device *vdev)
+{
+ struct virtnet_info *vi = vdev->priv;
+ int err;
+
+ err = init_vqs(vi);
+ if (err)
+ return err;
+
+ if (netif_running(vi->dev))
+ virtnet_napi_enable(vi);
+
+ netif_device_attach(vi->dev);
+
+ if (!try_fill_recv(vi, GFP_KERNEL))
+ queue_delayed_work(system_nrt_wq, &vi->refill, 0);
+
+ return 0;
+}
+#endif
+
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
{ 0 },
@@ -1189,6 +1244,10 @@ static struct virtio_driver virtio_net_driver = {
.probe = virtnet_probe,
.remove = __devexit_p(virtnet_remove),
.config_changed = virtnet_config_changed,
+#ifdef CONFIG_PM
+ .freeze = virtnet_freeze,
+ .restore = virtnet_restore,
+#endif
};
static int __init init(void)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 88c81c5..09b8c9d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -557,10 +557,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (rxsp->status11 & AR_MichaelErr)
rxs->rs_status |= ATH9K_RXERR_MIC;
- if (rxsp->status11 & AR_KeyMiss)
- rxs->rs_status |= ATH9K_RXERR_KEYMISS;
}
+ if (rxsp->status11 & AR_KeyMiss)
+ rxs->rs_status |= ATH9K_RXERR_KEYMISS;
+
return 0;
}
EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 2589b38..2b0bfb8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -46,7 +46,7 @@ static const int m2ThreshExt_off = 127;
* @chan:
*
* This is the function to change channel on single-chip devices, that is
- * all devices after ar9280.
+ * for AR9300 family of chipsets.
*
* This function takes the channel value in MHz and sets
* hardware channel value. Assumes writes have been enabled to analog bus.
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index b30e9fc..171ccf7 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -679,7 +679,6 @@ void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_reload_chainmask_settings(struct ath_softc *sc);
-void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_uses_beacons(int type);
#ifdef CONFIG_ATH9K_PCI
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 172e33d..2f4b48e 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -400,6 +400,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
ah->noise = ath9k_hw_getchan_noise(ah, chan);
return true;
}
+EXPORT_SYMBOL(ath9k_hw_getnf);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_channel *chan)
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 05b9dbf..3b33996d 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -19,7 +19,6 @@
#include "hw.h"
-#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5
#define NUM_NF_READINGS 6
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index fd3f19c..e196aba 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -618,10 +618,11 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
- if (ads.ds_rxstatus8 & AR_KeyMiss)
- rs->rs_status |= ATH9K_RXERR_KEYMISS;
}
+ if (ads.ds_rxstatus8 & AR_KeyMiss)
+ rs->rs_status |= ATH9K_RXERR_KEYMISS;
+
return 0;
}
EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e267c92..4a00806 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1629,7 +1629,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
- struct ath9k_channel old_chan;
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1654,11 +1653,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
* Preserve the current channel values, before updating
* the same channel
*/
- if (old_pos == pos) {
- memcpy(&old_chan, &sc->sc_ah->channels[pos],
- sizeof(struct ath9k_channel));
- ah->curchan = &old_chan;
- }
+ if (ah->curchan && (old_pos == pos))
+ ath9k_hw_getnf(ah, ah->curchan);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
curchan, conf->channel_type);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 1c6f193..b91f28e 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4852,6 +4852,9 @@ static void b43_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&(wl->beacon_update_trigger));
+ if (!dev)
+ goto out;
+
mutex_lock(&wl->mutex);
if (b43_status(dev) >= B43_STAT_STARTED) {
dev = b43_wireless_core_stop(dev);
@@ -4863,7 +4866,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
out_unlock:
mutex_unlock(&wl->mutex);
-
+out:
cancel_work_sync(&(wl->txpower_adjust_work));
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 5a002a2..f7eeee1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3119,8 +3119,10 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
/* Verify NVRAM bytes */
brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize);
nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
- if (!nvram_ularray)
+ if (!nvram_ularray) {
+ kfree(vbuffer);
return -ENOMEM;
+ }
/* Upload image to verify downloaded contents. */
memset(nvram_ularray, 0xaa, varsize);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index f23b0c3..bf11850a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -2475,7 +2475,7 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
return err;
}
-static void brcmf_delay(u32 ms)
+static __always_inline void brcmf_delay(u32 ms)
{
if (ms < 1000 / HZ) {
cond_resched();
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index d106576..448ab9c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1128,14 +1128,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
return 0;
}
-static int brcms_pci_suspend(struct pci_dev *pdev)
-{
- pci_save_state(pdev);
- pci_disable_device(pdev);
- return pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
+static int brcms_suspend(struct bcma_device *pdev)
{
struct brcms_info *wl;
struct ieee80211_hw *hw;
@@ -1153,40 +1146,15 @@ static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
wl->pub->hw_up = false;
spin_unlock_bh(&wl->lock);
- /* temporarily do suspend ourselves */
- return brcms_pci_suspend(pdev->bus->host_pci);
-}
-
-static int brcms_pci_resume(struct pci_dev *pdev)
-{
- int err = 0;
- uint val;
-
- err = pci_set_power_state(pdev, PCI_D0);
- if (err)
- return err;
-
- pci_restore_state(pdev);
-
- err = pci_enable_device(pdev);
- if (err)
- return err;
-
- pci_set_master(pdev);
-
- pci_read_config_dword(pdev, 0x40, &val);
- if ((val & 0x0000ff00) != 0)
- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+ pr_debug("brcms_suspend ok\n");
return 0;
}
static int brcms_resume(struct bcma_device *pdev)
{
- /*
- * just do pci resume for now until bcma supports it.
- */
- return brcms_pci_resume(pdev->bus->host_pci);
+ pr_debug("brcms_resume ok\n");
+ return 0;
}
static struct bcma_driver brcms_bcma_driver = {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
index 6109215..5637436 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
@@ -764,6 +764,22 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
}
/*
+ * The crc check is done on a little-endian array, we need
+ * to switch the bytes around before checking crc (and
+ * then switch it back).
+ */
+static int do_crc_check(u16 *buf, unsigned nwords)
+{
+ u8 crc;
+
+ cpu_to_le16_buf(buf, nwords);
+ crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE);
+ le16_to_cpu_buf(buf, nwords);
+
+ return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table);
+}
+
+/*
* Read in and validate sprom.
* Return 0 on success, nonzero on error.
*/
@@ -772,8 +788,6 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
{
int err = 0;
uint i;
- u8 *bbuf = (u8 *)buf; /* byte buffer */
- uint nbytes = nwords << 1;
struct bcma_device *core;
uint sprom_offset;
@@ -786,9 +800,9 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
sprom_offset = CHIPCREGOFFS(sromotp);
}
- /* read the sprom in bytes */
- for (i = 0; i < nbytes; i++)
- bbuf[i] = bcma_read8(core, sprom_offset+i);
+ /* read the sprom */
+ for (i = 0; i < nwords; i++)
+ buf[i] = bcma_read16(core, sprom_offset+i*2);
if (buf[0] == 0xffff)
/*
@@ -798,13 +812,8 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
*/
return -ENODATA;
- if (check_crc &&
- crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
- CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ if (check_crc && !do_crc_check(buf, nwords))
err = -EIO;
- else
- /* now correct the endianness of the byte array */
- le16_to_cpu_buf(buf, nwords);
return err;
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 018a8de..4fcdac6 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -7848,7 +7848,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
* more efficiently than we can parse it. ORDER MATTERS HERE */
struct ipw_rt_hdr *ipw_rt;
- short len = le16_to_cpu(pkt->u.frame.length);
+ unsigned short len = le16_to_cpu(pkt->u.frame.length);
/* We received data from the HW, so stop the watchdog */
dev->trans_start = jiffies;
@@ -8023,7 +8023,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
s8 noise = (s8) le16_to_cpu(frame->noise);
u8 rate = frame->rate;
- short len = le16_to_cpu(pkt->u.frame.length);
+ unsigned short len = le16_to_cpu(pkt->u.frame.length);
struct sk_buff *skb;
int hdr_only = 0;
u16 filter = priv->prom_priv->filter;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 084aa2c..a645472 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -569,7 +569,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
struct iwl_scan_cmd *scan;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
u32 rate_flags = 0;
- u16 cmd_len;
+ u16 cmd_len = 0;
u16 rx_chain = 0;
enum ieee80211_band band;
u8 n_probes = 0;
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 7becea3..dd5aeaf 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2777,7 +2777,7 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
else if (channel->band == IEEE80211_BAND_5GHZ)
cmd->band = cpu_to_le16(0x4);
- cmd->channel = channel->hw_value;
+ cmd->channel = cpu_to_le16(channel->hw_value);
if (conf->channel_type == NL80211_CHAN_NO_HT ||
conf->channel_type == NL80211_CHAN_HT20) {
@@ -4066,7 +4066,7 @@ static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
goto done;
if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
- WLAN_CIPHER_SUITE_WEP104)
+ key->cipher == WLAN_CIPHER_SUITE_WEP104)
mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 4941a1a..dc88bae 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -422,7 +422,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- int mask = (state == STATE_RADIO_IRQ_ON);
u32 reg;
unsigned long flags;
@@ -436,25 +435,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
+ reg = 0;
+ if (state == STATE_RADIO_IRQ_ON) {
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
+ }
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 6f91a14..3fda6b1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -196,6 +196,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
/* Allocate skb buffer to contain firmware */
/* info and tx descriptor info. */
skb = dev_alloc_skb(frag_length);
+ if (!skb)
+ return false;
skb_reserve(skb, extra_descoffset);
seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length -
extra_descoffset));
@@ -573,6 +575,8 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
skb = dev_alloc_skb(len);
+ if (!skb)
+ return false;
cb_desc = (struct rtl_tcb_desc *)(skb->cb);
cb_desc->queue_index = TXCMD_QUEUE;
cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72c33fb..66d96f1 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -14,7 +14,7 @@
static struct of_bus *of_match_bus(struct device_node *np);
static int __of_address_to_resource(struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
- struct resource *r);
+ const char *name, struct resource *r);
/* Debug utility */
#ifdef DEBUG
@@ -215,7 +215,7 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
addrp = of_get_pci_address(dev, bar, &size, &flags);
if (addrp == NULL)
return -EINVAL;
- return __of_address_to_resource(dev, addrp, size, flags, r);
+ return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
#endif /* CONFIG_PCI */
@@ -529,7 +529,7 @@ EXPORT_SYMBOL(of_get_address);
static int __of_address_to_resource(struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
- struct resource *r)
+ const char *name, struct resource *r)
{
u64 taddr;
@@ -551,7 +551,8 @@ static int __of_address_to_resource(struct device_node *dev,
r->end = taddr + size - 1;
}
r->flags = flags;
- r->name = dev->full_name;
+ r->name = name ? name : dev->full_name;
+
return 0;
}
@@ -569,11 +570,16 @@ int of_address_to_resource(struct device_node *dev, int index,
const __be32 *addrp;
u64 size;
unsigned int flags;
+ const char *name = NULL;
addrp = of_get_address(dev, index, &size, &flags);
if (addrp == NULL)
return -EINVAL;
- return __of_address_to_resource(dev, addrp, size, flags, r);
+
+ /* Get optional "reg-names" property to add a name to a resource */
+ of_property_read_string_index(dev, "reg-names", index, &name);
+
+ return __of_address_to_resource(dev, addrp, size, flags, name, r);
}
EXPORT_SYMBOL_GPL(of_address_to_resource);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 91a375f..ea2bd1b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -23,6 +23,7 @@
#include <asm/machdep.h>
#endif /* CONFIG_PPC */
+#include <asm/setup.h>
#include <asm/page.h>
char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 0f0cfa3..9cf0060 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -341,9 +341,18 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
/* Only dereference the resource if both the
* resource and the irq are valid. */
if (r && irq) {
+ const char *name = NULL;
+
+ /*
+ * Get optional "interrupts-names" property to add a name
+ * to the resource.
+ */
+ of_property_read_string_index(dev, "interrupt-names", index,
+ &name);
+
r->start = r->end = irq;
r->flags = IORESOURCE_IRQ;
- r->name = dev->full_name;
+ r->name = name ? name : dev->full_name;
}
return irq;
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index bcd5d54..7ff10c1 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -562,19 +562,6 @@ dino_fixup_bus(struct pci_bus *bus)
/* Firmware doesn't set up card-mode dino, so we have to */
if (is_card_dino(&dino_dev->hba.dev->id)) {
dino_card_setup(bus, dino_dev->hba.base_addr);
- } else if(bus->parent == NULL) {
- /* must have a dino above it, reparent the resources
- * into the dino window */
- int i;
- struct resource *res = &dino_dev->hba.lmmio_space;
-
- bus->resource[0] = &(dino_dev->hba.io_space);
- for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) {
- if(res[i].flags == 0)
- break;
- bus->resource[i+1] = &res[i];
- }
-
} else if (bus->parent) {
int i;
@@ -927,6 +914,7 @@ static int __init dino_probe(struct parisc_device *dev)
const char *version = "unknown";
char *name;
int is_cujo = 0;
+ LIST_HEAD(resources);
struct pci_bus *bus;
unsigned long hpa = dev->hpa.start;
@@ -1003,26 +991,37 @@ static int __init dino_probe(struct parisc_device *dev)
dev->dev.platform_data = dino_dev;
+ pci_add_resource(&resources, &dino_dev->hba.io_space);
+ if (dino_dev->hba.lmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.lmmio_space);
+ if (dino_dev->hba.elmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.elmmio_space);
+ if (dino_dev->hba.gmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
+
/*
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
*/
- dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev,
- dino_current_bus, &dino_cfg_ops, NULL);
-
- if(bus) {
- /* This code *depends* on scanning being single threaded
- * if it isn't, this global bus number count will fail
- */
- dino_current_bus = bus->subordinate + 1;
- pci_bus_assign_resources(bus);
- pci_bus_add_devices(bus);
- } else {
+ dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
+ dino_current_bus, &dino_cfg_ops, NULL, &resources);
+ if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
+ pci_free_resource_list(&resources);
/* increment the bus number in case of duplicates */
dino_current_bus++;
+ return 0;
}
+
+ bus->subordinate = pci_scan_child_bus(bus);
+
+ /* This code *depends* on scanning being single threaded
+ * if it isn't, this global bus number count will fail
+ */
+ dino_current_bus = bus->subordinate + 1;
+ pci_bus_assign_resources(bus);
+ pci_bus_add_devices(bus);
return 0;
}
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 3aeb327..d5f3d75 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -653,7 +653,7 @@ lba_fixup_bus(struct pci_bus *bus)
}
} else {
/* Host-PCI Bridge */
- int err, i;
+ int err;
DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
ldev->hba.io_space.name,
@@ -669,9 +669,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&ioport_resource, 2);
BUG();
}
- /* advertize Host bridge resources to PCI bus */
- bus->resource[0] = &(ldev->hba.io_space);
- i = 1;
if (ldev->hba.elmmio_space.start) {
err = request_resource(&iomem_resource,
@@ -685,35 +682,17 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */
/* BUG(); */
- } else
- bus->resource[i++] = &(ldev->hba.elmmio_space);
+ }
}
-
- /* Overlaps with elmmio can (and should) fail here.
- * We will prune (or ignore) the distributed range.
- *
- * FIXME: SBA code should register all elmmio ranges first.
- * that would take care of elmmio ranges routed
- * to a different rope (already discovered) from
- * getting registered *after* LBA code has already
- * registered it's distributed lmmio range.
- */
- if (truncate_pat_collision(&iomem_resource,
- &(ldev->hba.lmmio_space))) {
-
- printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
- (long)ldev->hba.lmmio_space.start,
- (long)ldev->hba.lmmio_space.end);
- } else {
+ if (ldev->hba.lmmio_space.flags) {
err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
if (err < 0) {
printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
"lmmio_space [%lx/%lx]\n",
(long)ldev->hba.lmmio_space.start,
(long)ldev->hba.lmmio_space.end);
- } else
- bus->resource[i++] = &(ldev->hba.lmmio_space);
+ }
}
#ifdef CONFIG_64BIT
@@ -728,7 +707,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&iomem_resource, 2);
BUG();
}
- bus->resource[i++] = &(ldev->hba.gmmio_space);
}
#endif
@@ -1404,6 +1382,7 @@ static int __init
lba_driver_probe(struct parisc_device *dev)
{
struct lba_device *lba_dev;
+ LIST_HEAD(resources);
struct pci_bus *lba_bus;
struct pci_ops *cfg_ops;
u32 func_class;
@@ -1518,10 +1497,41 @@ lba_driver_probe(struct parisc_device *dev)
if (lba_dev->hba.bus_num.start < lba_next_bus)
lba_dev->hba.bus_num.start = lba_next_bus;
+ /* Overlaps with elmmio can (and should) fail here.
+ * We will prune (or ignore) the distributed range.
+ *
+ * FIXME: SBA code should register all elmmio ranges first.
+ * that would take care of elmmio ranges routed
+ * to a different rope (already discovered) from
+ * getting registered *after* LBA code has already
+ * registered it's distributed lmmio range.
+ */
+ if (truncate_pat_collision(&iomem_resource,
+ &(lba_dev->hba.lmmio_space))) {
+ printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+ (long)lba_dev->hba.lmmio_space.start,
+ (long)lba_dev->hba.lmmio_space.end);
+ lba_dev->hba.lmmio_space.flags = 0;
+ }
+
+ pci_add_resource(&resources, &lba_dev->hba.io_space);
+ if (lba_dev->hba.elmmio_space.start)
+ pci_add_resource(&resources, &lba_dev->hba.elmmio_space);
+ if (lba_dev->hba.lmmio_space.flags)
+ pci_add_resource(&resources, &lba_dev->hba.lmmio_space);
+ if (lba_dev->hba.gmmio_space.flags)
+ pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
+
dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
- pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
- cfg_ops, NULL);
+ pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
+ cfg_ops, NULL, &resources);
+ if (!lba_bus) {
+ pci_free_resource_list(&resources);
+ return 0;
+ }
+
+ lba_bus->subordinate = pci_scan_child_bus(lba_bus);
/* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
@@ -1551,10 +1561,8 @@ lba_driver_probe(struct parisc_device *dev)
lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
}
- if (lba_bus) {
- lba_next_bus = lba_bus->subordinate + 1;
- pci_bus_add_devices(lba_bus);
- }
+ lba_next_bus = lba_bus->subordinate + 1;
+ pci_bus_add_devices(lba_bus);
/* Whew! Finally done! Tell services we got this one covered. */
return 0;
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
index 0dc34f1..d471627 100644
--- a/drivers/parport/parport_ip32.c
+++ b/drivers/parport/parport_ip32.c
@@ -135,7 +135,7 @@
#define PARPORT_IP32_ENABLE_EPP (1U << 3)
#define PARPORT_IP32_ENABLE_ECP (1U << 4)
static unsigned int features = ~0U;
-static int verbose_probing = DEFAULT_VERBOSE_PROBING;
+static bool verbose_probing = DEFAULT_VERBOSE_PROBING;
/* We do not support more than one port. */
static struct parport *this_port = NULL;
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index d0b597b..0cb64f5 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -3404,8 +3404,8 @@ static int __init parport_init_mode_setup(char *str)
#endif
#ifdef MODULE
-static const char *irq[PARPORT_PC_MAX_PORTS];
-static const char *dma[PARPORT_PC_MAX_PORTS];
+static char *irq[PARPORT_PC_MAX_PORTS];
+static char *dma[PARPORT_PC_MAX_PORTS];
MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
module_param_array(io, int, NULL, 0);
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index fdaa42a..2a58164 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -13,7 +13,7 @@
* configuration space.
*/
-static DEFINE_RAW_SPINLOCK(pci_lock);
+DEFINE_RAW_SPINLOCK(pci_lock);
/*
* Wrappers for all PCI configuration access functions. They just check
@@ -127,20 +127,20 @@ EXPORT_SYMBOL(pci_write_vpd);
* We have a bit per device to indicate it's blocked and a global wait queue
* for callers to sleep on until devices are unblocked.
*/
-static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait);
+static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
-static noinline void pci_wait_ucfg(struct pci_dev *dev)
+static noinline void pci_wait_cfg(struct pci_dev *dev)
{
DECLARE_WAITQUEUE(wait, current);
- __add_wait_queue(&pci_ucfg_wait, &wait);
+ __add_wait_queue(&pci_cfg_wait, &wait);
do {
set_current_state(TASK_UNINTERRUPTIBLE);
raw_spin_unlock_irq(&pci_lock);
schedule();
raw_spin_lock_irq(&pci_lock);
- } while (dev->block_ucfg_access);
- __remove_wait_queue(&pci_ucfg_wait, &wait);
+ } while (dev->block_cfg_access);
+ __remove_wait_queue(&pci_cfg_wait, &wait);
}
/* Returns 0 on success, negative values indicate error. */
@@ -153,7 +153,8 @@ int pci_user_read_config_##size \
if (PCI_##size##_BAD) \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \
- if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ if (unlikely(dev->block_cfg_access)) \
+ pci_wait_cfg(dev); \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \
raw_spin_unlock_irq(&pci_lock); \
@@ -172,7 +173,8 @@ int pci_user_write_config_##size \
if (PCI_##size##_BAD) \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \
- if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ if (unlikely(dev->block_cfg_access)) \
+ pci_wait_cfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
raw_spin_unlock_irq(&pci_lock); \
@@ -401,36 +403,56 @@ int pci_vpd_truncate(struct pci_dev *dev, size_t size)
EXPORT_SYMBOL(pci_vpd_truncate);
/**
- * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * pci_cfg_access_lock - Lock PCI config reads/writes
* @dev: pci device struct
*
- * When user access is blocked, any reads or writes to config space will
- * sleep until access is unblocked again. We don't allow nesting of
- * block/unblock calls.
+ * When access is locked, any userspace reads or writes to config
+ * space and concurrent lock requests will sleep until access is
+ * allowed via pci_cfg_access_unlocked again.
*/
-void pci_block_user_cfg_access(struct pci_dev *dev)
+void pci_cfg_access_lock(struct pci_dev *dev)
+{
+ might_sleep();
+
+ raw_spin_lock_irq(&pci_lock);
+ if (dev->block_cfg_access)
+ pci_wait_cfg(dev);
+ dev->block_cfg_access = 1;
+ raw_spin_unlock_irq(&pci_lock);
+}
+EXPORT_SYMBOL_GPL(pci_cfg_access_lock);
+
+/**
+ * pci_cfg_access_trylock - try to lock PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * Same as pci_cfg_access_lock, but will return 0 if access is
+ * already locked, 1 otherwise. This function can be used from
+ * atomic contexts.
+ */
+bool pci_cfg_access_trylock(struct pci_dev *dev)
{
unsigned long flags;
- int was_blocked;
+ bool locked = true;
raw_spin_lock_irqsave(&pci_lock, flags);
- was_blocked = dev->block_ucfg_access;
- dev->block_ucfg_access = 1;
+ if (dev->block_cfg_access)
+ locked = false;
+ else
+ dev->block_cfg_access = 1;
raw_spin_unlock_irqrestore(&pci_lock, flags);
- /* If we BUG() inside the pci_lock, we're guaranteed to hose
- * the machine */
- BUG_ON(was_blocked);
+ return locked;
}
-EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+EXPORT_SYMBOL_GPL(pci_cfg_access_trylock);
/**
- * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * pci_cfg_access_unlock - Unlock PCI config reads/writes
* @dev: pci device struct
*
- * This function allows userspace PCI config accesses to resume.
+ * This function allows PCI config accesses to resume.
*/
-void pci_unblock_user_cfg_access(struct pci_dev *dev)
+void pci_cfg_access_unlock(struct pci_dev *dev)
{
unsigned long flags;
@@ -438,10 +460,10 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev)
/* This indicates a problem in the caller, but we don't need
* to kill them, unlike a double-block above. */
- WARN_ON(!dev->block_ucfg_access);
+ WARN_ON(!dev->block_cfg_access);
- dev->block_ucfg_access = 0;
- wake_up_all(&pci_ucfg_wait);
+ dev->block_cfg_access = 0;
+ wake_up_all(&pci_cfg_wait);
raw_spin_unlock_irqrestore(&pci_lock, flags);
}
-EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
+EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index 9dd90b3..95655d7 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -128,6 +128,23 @@ void pci_disable_ats(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_disable_ats);
+void pci_restore_ats_state(struct pci_dev *dev)
+{
+ u16 ctrl;
+
+ if (!pci_ats_enabled(dev))
+ return;
+ if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
+ BUG();
+
+ ctrl = PCI_ATS_CTRL_ENABLE;
+ if (!dev->is_virtfn)
+ ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
+
+ pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+}
+EXPORT_SYMBOL_GPL(pci_restore_ats_state);
+
/**
* pci_ats_queue_depth - query the ATS Invalidate Queue Depth
* @dev: the PCI device
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 1e2ad92..398f5d8 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -18,6 +18,32 @@
#include "pci.h"
+void pci_add_resource(struct list_head *resources, struct resource *res)
+{
+ struct pci_bus_resource *bus_res;
+
+ bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
+ if (!bus_res) {
+ printk(KERN_ERR "PCI: can't add bus resource %pR\n", res);
+ return;
+ }
+
+ bus_res->res = res;
+ list_add_tail(&bus_res->list, resources);
+}
+EXPORT_SYMBOL(pci_add_resource);
+
+void pci_free_resource_list(struct list_head *resources)
+{
+ struct pci_bus_resource *bus_res, *tmp;
+
+ list_for_each_entry_safe(bus_res, tmp, resources, list) {
+ list_del(&bus_res->list);
+ kfree(bus_res);
+ }
+}
+EXPORT_SYMBOL(pci_free_resource_list);
+
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
unsigned int flags)
{
@@ -52,16 +78,12 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n);
void pci_bus_remove_resources(struct pci_bus *bus)
{
- struct pci_bus_resource *bus_res, *tmp;
int i;
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
bus->resource[i] = NULL;
- list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
- list_del(&bus_res->list);
- kfree(bus_res);
- }
+ pci_free_resource_list(&bus->resources);
}
/**
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 095f29e..2a47e82 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -44,7 +44,7 @@
#define METHOD_NAME__SUN "_SUN"
#define METHOD_NAME_OSHP "OSHP"
-static int debug_acpi;
+static bool debug_acpi;
static acpi_status
decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index efa9f2d..aa41631 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -47,7 +47,7 @@
/* name size which is used for entries in pcihpfs */
#define SLOT_NAME_SIZE 21 /* {_SUN} */
-static int debug;
+static bool debug;
int acpiphp_debug;
/* local variables */
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index e525263..c35e8ad 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -43,7 +43,7 @@
#define DRIVER_AUTHOR "Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver IBM extension"
-static int debug;
+static bool debug;
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index 41f6a8d..6bf8d2a 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -57,8 +57,8 @@
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
-static int debug;
-static int poll;
+static bool debug;
+static bool poll;
static struct cpci_hp_controller_ops zt5550_hpc_ops;
static struct cpci_hp_controller zt5550_hpc;
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index f1ce99c..187a199 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -57,8 +57,8 @@ struct irq_routing_table *cpqhp_routing_table;
static void __iomem *smbios_table;
static void __iomem *smbios_start;
static void __iomem *cpqhp_rom_start;
-static int power_mode;
-static int debug;
+static bool power_mode;
+static bool debug;
static int initialized;
#define DRIVER_VERSION "0.9.8"
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index d934dd4..5506e0e 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -49,7 +49,7 @@
int ibmphp_debug;
-static int debug;
+static bool debug;
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC (debug, "Debugging mode enabled or not");
MODULE_LICENSE ("GPL");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 6d2eea9..202f4a9 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -51,7 +51,7 @@
/* local variables */
-static int debug;
+static bool debug;
#define DRIVER_VERSION "0.5"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Scott Murray <scottm@somanetworks.com>"
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 9a33fdd..4b7cce1 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -40,10 +40,10 @@
#define MY_NAME "pciehp"
-extern int pciehp_poll_mode;
+extern bool pciehp_poll_mode;
extern int pciehp_poll_time;
-extern int pciehp_debug;
-extern int pciehp_force;
+extern bool pciehp_debug;
+extern bool pciehp_force;
extern struct workqueue_struct *pciehp_wq;
#define dbg(format, arg...) \
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index b8c99d3..365c6b9 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -38,10 +38,10 @@
#include <linux/time.h>
/* Global variables */
-int pciehp_debug;
-int pciehp_poll_mode;
+bool pciehp_debug;
+bool pciehp_poll_mode;
int pciehp_poll_time;
-int pciehp_force;
+bool pciehp_force;
struct workqueue_struct *pciehp_wq;
#define DRIVER_VERSION "0.4"
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
index 5175d9b..b20ceaa 100644
--- a/drivers/pci/hotplug/pcihp_skeleton.c
+++ b/drivers/pci/hotplug/pcihp_skeleton.c
@@ -59,7 +59,7 @@ static LIST_HEAD(slot_list);
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
-static int debug;
+static bool debug;
static int num_slots;
#define DRIVER_VERSION "0.3"
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 419919a..df56774 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -46,7 +46,7 @@
#define PRESENT 1 /* Card in slot */
#define MY_NAME "rpaphp"
-extern int rpaphp_debug;
+extern bool rpaphp_debug;
#define dbg(format, arg...) \
do { \
if (rpaphp_debug) \
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 758adb5..127d6e6 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -37,7 +37,7 @@
/* and pci_do_scan_bus */
#include "rpaphp.h"
-int rpaphp_debug;
+bool rpaphp_debug;
LIST_HEAD(rpaphp_slot_head);
#define DRIVER_VERSION "0.1"
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index e0c90e6..ca64932 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -43,9 +43,9 @@
#define MY_NAME THIS_MODULE->name
#endif
-extern int shpchp_poll_mode;
+extern bool shpchp_poll_mode;
extern int shpchp_poll_time;
-extern int shpchp_debug;
+extern bool shpchp_debug;
extern struct workqueue_struct *shpchp_wq;
extern struct workqueue_struct *shpchp_ordered_wq;
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index dd7e0c5..7414fd9 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -36,8 +36,8 @@
#include "shpchp.h"
/* Global variables */
-int shpchp_debug;
-int shpchp_poll_mode;
+bool shpchp_debug;
+bool shpchp_poll_mode;
int shpchp_poll_time;
struct workqueue_struct *shpchp_wq;
struct workqueue_struct *shpchp_ordered_wq;
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 1969a3e..0321fa3 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -347,11 +347,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return rc;
}
+ pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
+
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
msleep(100);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
iov->initial = initial;
if (nr_virtfn < initial)
@@ -379,10 +381,10 @@ failed:
virtfn_remove(dev, j, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
@@ -405,10 +407,10 @@ static void sriov_disable(struct pci_dev *dev)
virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
@@ -452,7 +454,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
found:
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
- pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
if (!offset || (total > 1 && !stride))
@@ -465,7 +466,6 @@ found:
return -EIO;
pgsz &= ~(pgsz - 1);
- pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 337e16a..a825d78 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -86,6 +86,31 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
}
#endif
+#ifndef arch_restore_msi_irqs
+# define arch_restore_msi_irqs default_restore_msi_irqs
+# define HAVE_DEFAULT_MSI_RESTORE_IRQS
+#endif
+
+#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
+void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+ struct msi_desc *entry;
+
+ entry = NULL;
+ if (dev->msix_enabled) {
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (irq == entry->irq)
+ break;
+ }
+ } else if (dev->msi_enabled) {
+ entry = irq_get_msi_desc(irq);
+ }
+
+ if (entry)
+ write_msi_msg(irq, &entry->msg);
+}
+#endif
+
static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
{
u16 control;
@@ -323,8 +348,18 @@ static void free_msi_irqs(struct pci_dev *dev)
if (list_is_last(&entry->list, &dev->msi_list))
iounmap(entry->mask_base);
}
- kobject_del(&entry->kobj);
- kobject_put(&entry->kobj);
+
+ /*
+ * Its possible that we get into this path
+ * When populate_msi_sysfs fails, which means the entries
+ * were not registered with sysfs. In that case don't
+ * unregister them.
+ */
+ if (entry->kobj.parent) {
+ kobject_del(&entry->kobj);
+ kobject_put(&entry->kobj);
+ }
+
list_del(&entry->list);
kfree(entry);
}
@@ -362,7 +397,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
pci_intx_for_msi(dev, 0);
msi_set_enable(dev, pos, 0);
- write_msi_msg(dev->irq, &entry->msg);
+ arch_restore_msi_irqs(dev, dev->irq);
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@@ -390,7 +425,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
list_for_each_entry(entry, &dev->msi_list, list) {
- write_msi_msg(entry->irq, &entry->msg);
+ arch_restore_msi_irqs(dev, entry->irq);
msix_mask_irq(entry, entry->masked);
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 12d1e81..3623d65 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -604,7 +604,8 @@ static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
* supported as well. Drivers are supposed to support either the
* former, or the latter, but not both at the same time.
*/
- WARN_ON(ret && drv->driver.pm);
+ WARN(ret && drv->driver.pm, "driver %s device %04x:%04x\n",
+ drv->name, pci_dev->vendor, pci_dev->device);
return ret;
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 106be0d..a3cd8ca 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -432,7 +432,7 @@ pci_read_config(struct file *filp, struct kobject *kobj,
u8 *data = (u8*) buf;
/* Several chips lock up trying to read undefined config space */
- if (security_capable(&init_user_ns, filp->f_cred, CAP_SYS_ADMIN) == 0) {
+ if (security_capable(filp->f_cred, &init_user_ns, CAP_SYS_ADMIN) == 0) {
size = dev->cfg_size;
} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
size = 128;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6d4a531..97fff78 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -88,6 +88,12 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
u8 pci_cache_line_size;
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
@@ -959,6 +965,7 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);
+ pci_restore_ats_state(dev);
/*
* The Base Address register should be programmed before the command
@@ -967,7 +974,7 @@ void pci_restore_state(struct pci_dev *dev)
for (i = 15; i >= 0; i--) {
pci_read_config_dword(dev, i * 4, &val);
if (val != dev->saved_config_space[i]) {
- dev_printk(KERN_DEBUG, &dev->dev, "restoring config "
+ dev_dbg(&dev->dev, "restoring config "
"space at offset %#x (was %#x, writing %#x)\n",
i, val, (int)dev->saved_config_space[i]);
pci_write_config_dword(dev,i * 4,
@@ -1536,8 +1543,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
}
out:
- dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
- enable ? "enabled" : "disabled");
+ dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled");
}
/**
@@ -2596,6 +2602,33 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
}
/**
+ * pcibios_set_master - enable PCI bus-mastering for device dev
+ * @dev: the PCI device to enable
+ *
+ * Enables PCI bus-mastering for the device. This is the default
+ * implementation. Architecture specific implementations can override
+ * this if necessary.
+ */
+void __weak pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+
+ /* The latency timer doesn't apply to PCIe (either Type 0 or Type 1) */
+ if (pci_is_pcie(dev))
+ return;
+
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+/**
* pci_set_master - enables bus-mastering for device dev
* @dev: the PCI device to enable
*
@@ -2768,6 +2801,116 @@ pci_intx(struct pci_dev *pdev, int enable)
}
/**
+ * pci_intx_mask_supported - probe for INTx masking support
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev support INTx masking via the config space
+ * command word.
+ */
+bool pci_intx_mask_supported(struct pci_dev *dev)
+{
+ bool mask_supported = false;
+ u16 orig, new;
+
+ pci_cfg_access_lock(dev);
+
+ pci_read_config_word(dev, PCI_COMMAND, &orig);
+ pci_write_config_word(dev, PCI_COMMAND,
+ orig ^ PCI_COMMAND_INTX_DISABLE);
+ pci_read_config_word(dev, PCI_COMMAND, &new);
+
+ /*
+ * There's no way to protect against hardware bugs or detect them
+ * reliably, but as long as we know what the value should be, let's
+ * go ahead and check it.
+ */
+ if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
+ dev_err(&dev->dev, "Command register changed from "
+ "0x%x to 0x%x: driver or hardware bug?\n", orig, new);
+ } else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
+ mask_supported = true;
+ pci_write_config_word(dev, PCI_COMMAND, orig);
+ }
+
+ pci_cfg_access_unlock(dev);
+ return mask_supported;
+}
+EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
+
+static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
+{
+ struct pci_bus *bus = dev->bus;
+ bool mask_updated = true;
+ u32 cmd_status_dword;
+ u16 origcmd, newcmd;
+ unsigned long flags;
+ bool irq_pending;
+
+ /*
+ * We do a single dword read to retrieve both command and status.
+ * Document assumptions that make this possible.
+ */
+ BUILD_BUG_ON(PCI_COMMAND % 4);
+ BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
+
+ raw_spin_lock_irqsave(&pci_lock, flags);
+
+ bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
+
+ irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
+
+ /*
+ * Check interrupt status register to see whether our device
+ * triggered the interrupt (when masking) or the next IRQ is
+ * already pending (when unmasking).
+ */
+ if (mask != irq_pending) {
+ mask_updated = false;
+ goto done;
+ }
+
+ origcmd = cmd_status_dword;
+ newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
+ if (mask)
+ newcmd |= PCI_COMMAND_INTX_DISABLE;
+ if (newcmd != origcmd)
+ bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
+
+done:
+ raw_spin_unlock_irqrestore(&pci_lock, flags);
+
+ return mask_updated;
+}
+
+/**
+ * pci_check_and_mask_intx - mask INTx on pending interrupt
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, mask it and
+ * return true in that case. False is returned if not interrupt was
+ * pending.
+ */
+bool pci_check_and_mask_intx(struct pci_dev *dev)
+{
+ return pci_check_and_set_intx_mask(dev, true);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
+
+/**
+ * pci_check_and_mask_intx - unmask INTx of no interrupt is pending
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, unmask it if not
+ * and return true. False is returned and the mask remains active if
+ * there was still an interrupt pending.
+ */
+bool pci_check_and_unmask_intx(struct pci_dev *dev)
+{
+ return pci_check_and_set_intx_mask(dev, false);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
+
+/**
* pci_msi_off - disables any msi or msix capabilities
* @dev: the PCI device to operate on
*
@@ -2965,7 +3108,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
might_sleep();
if (!probe) {
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
/* block PM suspend, driver probe, etc. */
device_lock(&dev->dev);
}
@@ -2990,7 +3133,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
done:
if (!probe) {
device_unlock(&dev->dev);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
}
return rc;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index b74084e..1009a5e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -136,6 +136,8 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/* Lock for read/write access to pci device and bus lists */
extern struct rw_semaphore pci_bus_sem;
+extern raw_spinlock_t pci_lock;
+
extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
@@ -249,6 +251,14 @@ struct pci_sriov {
u8 __iomem *mstate; /* VF Migration State Array */
};
+#ifdef CONFIG_PCI_ATS
+extern void pci_restore_ats_state(struct pci_dev *dev);
+#else
+static inline void pci_restore_ats_state(struct pci_dev *dev)
+{
+}
+#endif /* CONFIG_PCI_ATS */
+
#ifdef CONFIG_PCI_IOV
extern int pci_iov_init(struct pci_dev *dev);
extern void pci_iov_release(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index dc29348..72962cc 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -39,7 +39,7 @@ config PCIEASPM
Power Management) and Clock Power Management. ASPM supports
state L0/L0s/L1.
- ASPM is initially set up the the firmware. With this option enabled,
+ ASPM is initially set up by the firmware. With this option enabled,
Linux can modify this state in order to disable ASPM on known-bad
hardware or configurations and enable it when known-safe.
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 95489cd..5222986 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -28,7 +28,7 @@
#include "aerdrv.h"
/* Override the existing corrected and uncorrected error masks */
-static int aer_mask_override;
+static bool aer_mask_override;
module_param(aer_mask_override, bool, 0);
struct aer_error_inj {
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 9674e9f..0ca0535 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -27,8 +27,8 @@
#include <linux/kfifo.h>
#include "aerdrv.h"
-static int forceload;
-static int nosourceid;
+static bool forceload;
+static bool nosourceid;
module_param(forceload, bool, 0);
module_param(nosourceid, bool, 0);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 04e74f4..7cc9e2f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1522,19 +1522,21 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
return max;
}
-struct pci_bus * pci_create_bus(struct device *parent,
- int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
- int error;
+ int error, i;
struct pci_bus *b, *b2;
struct device *dev;
+ struct pci_bus_resource *bus_res, *n;
+ struct resource *res;
b = pci_alloc_bus();
if (!b)
return NULL;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev){
+ if (!dev) {
kfree(b);
return NULL;
}
@@ -1577,8 +1579,20 @@ struct pci_bus * pci_create_bus(struct device *parent,
pci_create_legacy_files(b);
b->number = b->secondary = bus;
- b->resource[0] = &ioport_resource;
- b->resource[1] = &iomem_resource;
+
+ /* Add initial resources to the bus */
+ list_for_each_entry_safe(bus_res, n, resources, list)
+ list_move_tail(&bus_res->list, &b->resources);
+
+ if (parent)
+ dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
+ else
+ printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
+
+ pci_bus_for_each_resource(b, res, i) {
+ if (res)
+ dev_info(&b->dev, "root bus resource %pR\n", res);
+ }
return b;
@@ -1594,18 +1608,58 @@ err_out:
return NULL;
}
+struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+ struct pci_bus *b;
+
+ b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
+ if (!b)
+ return NULL;
+
+ b->subordinate = pci_scan_child_bus(b);
+ pci_bus_add_devices(b);
+ return b;
+}
+EXPORT_SYMBOL(pci_scan_root_bus);
+
+/* Deprecated; use pci_scan_root_bus() instead */
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
+ LIST_HEAD(resources);
struct pci_bus *b;
- b = pci_create_bus(parent, bus, ops, sysdata);
+ pci_add_resource(&resources, &ioport_resource);
+ pci_add_resource(&resources, &iomem_resource);
+ b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b)
b->subordinate = pci_scan_child_bus(b);
+ else
+ pci_free_resource_list(&resources);
return b;
}
EXPORT_SYMBOL(pci_scan_bus_parented);
+struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
+ void *sysdata)
+{
+ LIST_HEAD(resources);
+ struct pci_bus *b;
+
+ pci_add_resource(&resources, &ioport_resource);
+ pci_add_resource(&resources, &iomem_resource);
+ b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
+ if (b) {
+ b->subordinate = pci_scan_child_bus(b);
+ pci_bus_add_devices(b);
+ } else {
+ pci_free_resource_list(&resources);
+ }
+ return b;
+}
+EXPORT_SYMBOL(pci_scan_bus);
+
#ifdef CONFIG_HOTPLUG
/**
* pci_rescan_bus - scan a PCI bus for devices.
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 7f87bee..6def362 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -89,9 +89,8 @@ EXPORT_SYMBOL(pci_remove_bus);
* device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug).
*/
-void pci_remove_bus_device(struct pci_dev *dev)
+static void __pci_remove_bus_device(struct pci_dev *dev)
{
- pci_stop_bus_device(dev);
if (dev->subordinate) {
struct pci_bus *b = dev->subordinate;
@@ -102,6 +101,11 @@ void pci_remove_bus_device(struct pci_dev *dev)
pci_destroy_dev(dev);
}
+void pci_remove_bus_device(struct pci_dev *dev)
+{
+ pci_stop_bus_device(dev);
+ __pci_remove_bus_device(dev);
+}
/**
* pci_remove_behind_bridge - remove all devices behind a PCI bridge
@@ -117,7 +121,7 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
if (dev->subordinate)
list_for_each_safe(l, n, &dev->subordinate->devices)
- pci_remove_bus_device(pci_dev_b(l));
+ __pci_remove_bus_device(pci_dev_b(l));
}
static void pci_stop_bus_devices(struct pci_bus *bus)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 5717509b..b66bfdb 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -85,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
}
}
res->flags &= ~IORESOURCE_UNSET;
- dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
- resno, res, (unsigned long long)region.start,
- (unsigned long long)region.end);
+ dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
+ resno, res, (unsigned long long)region.start,
+ (unsigned long long)region.end);
}
int pci_claim_resource(struct pci_dev *dev, int resource)
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6e318ce..f9e3fb3 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -155,18 +155,14 @@ config PCMCIA_M8XX
This driver is also available as a module called m8xx_pcmcia.
-config PCMCIA_AU1X00
- tristate "Au1x00 pcmcia support"
- depends on MIPS_ALCHEMY && PCMCIA
-
config PCMCIA_ALCHEMY_DEVBOARD
tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
depends on MIPS_ALCHEMY && PCMCIA
select 64BIT_PHYS_ADDR
help
Enable this driver of you want PCMCIA support on your Alchemy
- Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200 board.
- NOT suitable for the PB1000!
+ Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200, DB1300
+ board. NOT suitable for the PB1000!
This driver is also available as a module called db1xxx_ss.ko
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 29935ea..ec543a4 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_base.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_base.o sa1111_cs.o
obj-$(CONFIG_M32R_PCC) += m32r_pcc.o
obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
-obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
obj-$(CONFIG_PCMCIA_BCM63XX) += bcm63xx_pcmcia.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
@@ -39,9 +38,6 @@ obj-$(CONFIG_AT91_CF) += at91_cf.o
obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
-au1x00_ss-y += au1000_generic.o
-au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
-
sa1111_cs-y += sa1111_generic.o
sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
sa1111_cs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
deleted file mode 100644
index 95dd7c6..0000000
--- a/drivers/pcmcia/au1000_generic.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- *
- * Alchemy Semi Au1000 pcmcia driver
- *
- * Copyright 2001-2003 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@embeddedalley.com or source@mvista.com
- *
- * Copyright 2004 Pete Popov, Embedded Alley Solutions, Inc.
- * Updated the driver to 2.6. Followed the sa11xx API and largely
- * copied many of the hardware independent functions.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute 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 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/moduleparam.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include "au1000_generic.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Pete Popov <ppopov@embeddedalley.com>");
-MODULE_DESCRIPTION("Linux PCMCIA Card Services: Au1x00 Socket Controller");
-
-#if 0
-#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
-#else
-#define debug(x,args...)
-#endif
-
-#define MAP_SIZE 0x100000
-extern struct au1000_pcmcia_socket au1000_pcmcia_socket[];
-#define PCMCIA_SOCKET(x) (au1000_pcmcia_socket + (x))
-#define to_au1000_socket(x) container_of(x, struct au1000_pcmcia_socket, socket)
-
-/* Some boards like to support CF cards as IDE root devices, so they
- * grab pcmcia sockets directly.
- */
-u32 *pcmcia_base_vaddrs[2];
-extern const unsigned long mips_io_port_base;
-
-static DEFINE_MUTEX(pcmcia_sockets_lock);
-
-static int (*au1x00_pcmcia_hw_init[])(struct device *dev) = {
- au1x_board_init,
-};
-
-static int
-au1x00_pcmcia_skt_state(struct au1000_pcmcia_socket *skt)
-{
- struct pcmcia_state state;
- unsigned int stat;
-
- memset(&state, 0, sizeof(struct pcmcia_state));
-
- skt->ops->socket_state(skt, &state);
-
- stat = state.detect ? SS_DETECT : 0;
- stat |= state.ready ? SS_READY : 0;
- stat |= state.wrprot ? SS_WRPROT : 0;
- stat |= state.vs_3v ? SS_3VCARD : 0;
- stat |= state.vs_Xv ? SS_XVCARD : 0;
- stat |= skt->cs_state.Vcc ? SS_POWERON : 0;
-
- if (skt->cs_state.flags & SS_IOCARD)
- stat |= state.bvd1 ? SS_STSCHG : 0;
- else {
- if (state.bvd1 == 0)
- stat |= SS_BATDEAD;
- else if (state.bvd2 == 0)
- stat |= SS_BATWARN;
- }
- return stat;
-}
-
-/*
- * au100_pcmcia_config_skt
- *
- * Convert PCMCIA socket state to our socket configure structure.
- */
-static int
-au1x00_pcmcia_config_skt(struct au1000_pcmcia_socket *skt, socket_state_t *state)
-{
- int ret;
-
- ret = skt->ops->configure_socket(skt, state);
- if (ret == 0) {
- skt->cs_state = *state;
- }
-
- if (ret < 0)
- debug("unable to configure socket %d\n", skt->nr);
-
- return ret;
-}
-
-/* au1x00_pcmcia_sock_init()
- *
- * (Re-)Initialise the socket, turning on status interrupts
- * and PCMCIA bus. This must wait for power to stabilise
- * so that the card status signals report correctly.
- *
- * Returns: 0
- */
-static int au1x00_pcmcia_sock_init(struct pcmcia_socket *sock)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("initializing socket %u\n", skt->nr);
-
- skt->ops->socket_init(skt);
- return 0;
-}
-
-/*
- * au1x00_pcmcia_suspend()
- *
- * Remove power on the socket, disable IRQs from the card.
- * Turn off status interrupts, and disable the PCMCIA bus.
- *
- * Returns: 0
- */
-static int au1x00_pcmcia_suspend(struct pcmcia_socket *sock)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("suspending socket %u\n", skt->nr);
-
- skt->ops->socket_suspend(skt);
-
- return 0;
-}
-
-static DEFINE_SPINLOCK(status_lock);
-
-/*
- * au1x00_check_status()
- */
-static void au1x00_check_status(struct au1000_pcmcia_socket *skt)
-{
- unsigned int events;
-
- debug("entering PCMCIA monitoring thread\n");
-
- do {
- unsigned int status;
- unsigned long flags;
-
- status = au1x00_pcmcia_skt_state(skt);
-
- spin_lock_irqsave(&status_lock, flags);
- events = (status ^ skt->status) & skt->cs_state.csc_mask;
- skt->status = status;
- spin_unlock_irqrestore(&status_lock, flags);
-
- debug("events: %s%s%s%s%s%s\n",
- events == 0 ? "<NONE>" : "",
- events & SS_DETECT ? "DETECT " : "",
- events & SS_READY ? "READY " : "",
- events & SS_BATDEAD ? "BATDEAD " : "",
- events & SS_BATWARN ? "BATWARN " : "",
- events & SS_STSCHG ? "STSCHG " : "");
-
- if (events)
- pcmcia_parse_events(&skt->socket, events);
- } while (events);
-}
-
-/*
- * au1x00_pcmcia_poll_event()
- * Let's poll for events in addition to IRQs since IRQ only is unreliable...
- */
-static void au1x00_pcmcia_poll_event(unsigned long dummy)
-{
- struct au1000_pcmcia_socket *skt = (struct au1000_pcmcia_socket *)dummy;
- debug("polling for events\n");
-
- mod_timer(&skt->poll_timer, jiffies + AU1000_PCMCIA_POLL_PERIOD);
-
- au1x00_check_status(skt);
-}
-
-/* au1x00_pcmcia_get_status()
- *
- * From the sa11xx_core.c:
- * Implements the get_status() operation for the in-kernel PCMCIA
- * service (formerly SS_GetStatus in Card Services). Essentially just
- * fills in bits in `status' according to internal driver state or
- * the value of the voltage detect chipselect register.
- *
- * As a debugging note, during card startup, the PCMCIA core issues
- * three set_socket() commands in a row the first with RESET deasserted,
- * the second with RESET asserted, and the last with RESET deasserted
- * again. Following the third set_socket(), a get_status() command will
- * be issued. The kernel is looking for the SS_READY flag (see
- * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- skt->status = au1x00_pcmcia_skt_state(skt);
- *status = skt->status;
-
- return 0;
-}
-
-/* au1x00_pcmcia_set_socket()
- * Implements the set_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_SetSocket in Card Services). We more or
- * less punt all of this work and let the kernel handle the details
- * of power configuration, reset, &c. We also record the value of
- * `state' in order to regurgitate it to the PCMCIA core later.
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("for sock %u\n", skt->nr);
-
- debug("\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n",
- (state->csc_mask==0)?"<NONE>":"",
- (state->csc_mask&SS_DETECT)?"DETECT ":"",
- (state->csc_mask&SS_READY)?"READY ":"",
- (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
- (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
- (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
- (state->flags==0)?"<NONE>":"",
- (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
- (state->flags&SS_IOCARD)?"IOCARD ":"",
- (state->flags&SS_RESET)?"RESET ":"",
- (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
- (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"");
- debug("\tVcc %d Vpp %d irq %d\n",
- state->Vcc, state->Vpp, state->io_irq);
-
- return au1x00_pcmcia_config_skt(skt, state);
-}
-
-int
-au1x00_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
- unsigned int speed;
-
- if(map->map>=MAX_IO_WIN){
- debug("map (%d) out of range\n", map->map);
- return -1;
- }
-
- if(map->flags&MAP_ACTIVE){
- speed=(map->speed>0)?map->speed:AU1000_PCMCIA_IO_SPEED;
- skt->spd_io[map->map] = speed;
- }
-
- map->start=(unsigned int)(u32)skt->virt_io;
- map->stop=map->start+MAP_SIZE;
- return 0;
-
-} /* au1x00_pcmcia_set_io_map() */
-
-
-static int
-au1x00_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
- unsigned short speed = map->speed;
-
- if(map->map>=MAX_WIN){
- debug("map (%d) out of range\n", map->map);
- return -1;
- }
-
- if (map->flags & MAP_ATTRIB) {
- skt->spd_attr[map->map] = speed;
- skt->spd_mem[map->map] = 0;
- } else {
- skt->spd_attr[map->map] = 0;
- skt->spd_mem[map->map] = speed;
- }
-
- if (map->flags & MAP_ATTRIB) {
- map->static_start = skt->phys_attr + map->card_start;
- }
- else {
- map->static_start = skt->phys_mem + map->card_start;
- }
-
- debug("set_mem_map %d start %08lx card_start %08x\n",
- map->map, map->static_start, map->card_start);
- return 0;
-
-} /* au1x00_pcmcia_set_mem_map() */
-
-static struct pccard_operations au1x00_pcmcia_operations = {
- .init = au1x00_pcmcia_sock_init,
- .suspend = au1x00_pcmcia_suspend,
- .get_status = au1x00_pcmcia_get_status,
- .set_socket = au1x00_pcmcia_set_socket,
- .set_io_map = au1x00_pcmcia_set_io_map,
- .set_mem_map = au1x00_pcmcia_set_mem_map,
-};
-
-static const char *skt_names[] = {
- "PCMCIA socket 0",
- "PCMCIA socket 1",
-};
-
-struct skt_dev_info {
- int nskt;
-};
-
-int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
-{
- struct skt_dev_info *sinfo;
- struct au1000_pcmcia_socket *skt;
- int ret, i;
-
- sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
- if (!sinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- sinfo->nskt = nr;
-
- /*
- * Initialise the per-socket structure.
- */
- for (i = 0; i < nr; i++) {
- skt = PCMCIA_SOCKET(i);
- memset(skt, 0, sizeof(*skt));
-
- skt->socket.resource_ops = &pccard_static_ops;
- skt->socket.ops = &au1x00_pcmcia_operations;
- skt->socket.owner = ops->owner;
- skt->socket.dev.parent = dev;
-
- init_timer(&skt->poll_timer);
- skt->poll_timer.function = au1x00_pcmcia_poll_event;
- skt->poll_timer.data = (unsigned long)skt;
- skt->poll_timer.expires = jiffies + AU1000_PCMCIA_POLL_PERIOD;
-
- skt->nr = first + i;
- skt->irq = 255;
- skt->dev = dev;
- skt->ops = ops;
-
- skt->res_skt.name = skt_names[skt->nr];
- skt->res_io.name = "io";
- skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- skt->res_mem.name = "memory";
- skt->res_mem.flags = IORESOURCE_MEM;
- skt->res_attr.name = "attribute";
- skt->res_attr.flags = IORESOURCE_MEM;
-
- /*
- * PCMCIA client drivers use the inb/outb macros to access the
- * IO registers. Since mips_io_port_base is added to the
- * access address of the mips implementation of inb/outb,
- * we need to subtract it here because we want to access the
- * I/O or MEM address directly, without going through this
- * "mips_io_port_base" mechanism.
- */
- if (i == 0) {
- skt->virt_io = (void *)
- (ioremap((phys_t)AU1X_SOCK0_IO, 0x1000) -
- (u32)mips_io_port_base);
- skt->phys_attr = AU1X_SOCK0_PHYS_ATTR;
- skt->phys_mem = AU1X_SOCK0_PHYS_MEM;
- }
- else {
- skt->virt_io = (void *)
- (ioremap((phys_t)AU1X_SOCK1_IO, 0x1000) -
- (u32)mips_io_port_base);
- skt->phys_attr = AU1X_SOCK1_PHYS_ATTR;
- skt->phys_mem = AU1X_SOCK1_PHYS_MEM;
- }
- pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io;
- ret = ops->hw_init(skt);
-
- skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
- skt->socket.irq_mask = 0;
- skt->socket.map_size = MAP_SIZE;
- skt->socket.pci_irq = skt->irq;
- skt->socket.io_offset = (unsigned long)skt->virt_io;
-
- skt->status = au1x00_pcmcia_skt_state(skt);
-
- ret = pcmcia_register_socket(&skt->socket);
- if (ret)
- goto out_err;
-
- WARN_ON(skt->socket.sock != i);
-
- add_timer(&skt->poll_timer);
- }
-
- dev_set_drvdata(dev, sinfo);
- return 0;
-
-
-out_err:
- ops->hw_shutdown(skt);
- while (i-- > 0) {
- skt = PCMCIA_SOCKET(i);
-
- del_timer_sync(&skt->poll_timer);
- pcmcia_unregister_socket(&skt->socket);
- if (i == 0) {
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-#ifndef CONFIG_MIPS_XXS1500
- else {
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-#endif
- ops->hw_shutdown(skt);
-
- }
- kfree(sinfo);
-out:
- return ret;
-}
-
-int au1x00_drv_pcmcia_remove(struct platform_device *dev)
-{
- struct skt_dev_info *sinfo = platform_get_drvdata(dev);
- int i;
-
- mutex_lock(&pcmcia_sockets_lock);
- platform_set_drvdata(dev, NULL);
-
- for (i = 0; i < sinfo->nskt; i++) {
- struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i);
-
- del_timer_sync(&skt->poll_timer);
- pcmcia_unregister_socket(&skt->socket);
- skt->ops->hw_shutdown(skt);
- au1x00_pcmcia_config_skt(skt, &dead_socket);
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-
- kfree(sinfo);
- mutex_unlock(&pcmcia_sockets_lock);
- return 0;
-}
-
-
-/*
- * PCMCIA "Driver" API
- */
-
-static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
-{
- int i, ret = -ENODEV;
-
- mutex_lock(&pcmcia_sockets_lock);
- for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) {
- ret = au1x00_pcmcia_hw_init[i](&dev->dev);
- if (ret == 0)
- break;
- }
- mutex_unlock(&pcmcia_sockets_lock);
- return ret;
-}
-
-static struct platform_driver au1x00_pcmcia_driver = {
- .driver = {
- .name = "au1x00-pcmcia",
- .owner = THIS_MODULE,
- },
- .probe = au1x00_drv_pcmcia_probe,
- .remove = au1x00_drv_pcmcia_remove,
-};
-
-
-/* au1x00_pcmcia_init()
- *
- * This routine performs low-level PCMCIA initialization and then
- * registers this socket driver with Card Services.
- *
- * Returns: 0 on success, -ve error code on failure
- */
-static int __init au1x00_pcmcia_init(void)
-{
- int error = 0;
- error = platform_driver_register(&au1x00_pcmcia_driver);
- return error;
-}
-
-/* au1x00_pcmcia_exit()
- * Invokes the low-level kernel service to free IRQs associated with this
- * socket controller and reset GPIO edge detection.
- */
-static void __exit au1x00_pcmcia_exit(void)
-{
- platform_driver_unregister(&au1x00_pcmcia_driver);
-}
-
-module_init(au1x00_pcmcia_init);
-module_exit(au1x00_pcmcia_exit);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
deleted file mode 100644
index 5c36bda..0000000
--- a/drivers/pcmcia/au1000_generic.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Alchemy Semi Au1000 pcmcia driver include file
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This program is free software; you can distribute 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 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 __ASM_AU1000_PCMCIA_H
-#define __ASM_AU1000_PCMCIA_H
-
-/* include the world */
-
-#include <pcmcia/ss.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-#define AU1000_PCMCIA_POLL_PERIOD (2*HZ)
-#define AU1000_PCMCIA_IO_SPEED (255)
-#define AU1000_PCMCIA_MEM_SPEED (300)
-
-#define AU1X_SOCK0_IO 0xF00000000ULL
-#define AU1X_SOCK0_PHYS_ATTR 0xF40000000ULL
-#define AU1X_SOCK0_PHYS_MEM 0xF80000000ULL
-
-/* pcmcia socket 1 needs external glue logic so the memory map
- * differs from board to board.
- */
-#if defined(CONFIG_MIPS_PB1000)
-#define AU1X_SOCK1_IO 0xF08000000ULL
-#define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL
-#define AU1X_SOCK1_PHYS_MEM 0xF88000000ULL
-#endif
-
-struct pcmcia_state {
- unsigned detect: 1,
- ready: 1,
- wrprot: 1,
- bvd1: 1,
- bvd2: 1,
- vs_3v: 1,
- vs_Xv: 1;
-};
-
-struct pcmcia_configure {
- unsigned sock: 8,
- vcc: 8,
- vpp: 8,
- output: 1,
- speaker: 1,
- reset: 1;
-};
-
-struct pcmcia_irqs {
- int sock;
- int irq;
- const char *str;
-};
-
-
-struct au1000_pcmcia_socket {
- struct pcmcia_socket socket;
-
- /*
- * Info from low level handler
- */
- struct device *dev;
- unsigned int nr;
- unsigned int irq;
-
- /*
- * Core PCMCIA state
- */
- struct pcmcia_low_level *ops;
-
- unsigned int status;
- socket_state_t cs_state;
-
- unsigned short spd_io[MAX_IO_WIN];
- unsigned short spd_mem[MAX_WIN];
- unsigned short spd_attr[MAX_WIN];
-
- struct resource res_skt;
- struct resource res_io;
- struct resource res_mem;
- struct resource res_attr;
-
- void * virt_io;
- unsigned int phys_io;
- unsigned int phys_attr;
- unsigned int phys_mem;
- unsigned short speed_io, speed_attr, speed_mem;
-
- unsigned int irq_state;
-
- struct timer_list poll_timer;
-};
-
-struct pcmcia_low_level {
- struct module *owner;
-
- int (*hw_init)(struct au1000_pcmcia_socket *);
- void (*hw_shutdown)(struct au1000_pcmcia_socket *);
-
- void (*socket_state)(struct au1000_pcmcia_socket *, struct pcmcia_state *);
- int (*configure_socket)(struct au1000_pcmcia_socket *, struct socket_state_t *);
-
- /*
- * Enable card status IRQs on (re-)initialisation. This can
- * be called at initialisation, power management event, or
- * pcmcia event.
- */
- void (*socket_init)(struct au1000_pcmcia_socket *);
-
- /*
- * Disable card status IRQs and PCMCIA bus on suspend.
- */
- void (*socket_suspend)(struct au1000_pcmcia_socket *);
-};
-
-extern int au1x_board_init(struct device *dev);
-
-#endif /* __ASM_AU1000_PCMCIA_H */
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
deleted file mode 100644
index b239664..0000000
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- *
- * Alchemy Semi Pb1000 boards specific pcmcia routines.
- *
- * Copyright 2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- * This program is free software; you can distribute 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 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/delay.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/proc_fs.h>
-#include <linux/types.h>
-
-#include <pcmcia/ss.h>
-#include <pcmcia/cistpl.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include <asm/au1000.h>
-#include <asm/au1000_pcmcia.h>
-
-#define debug(fmt, arg...) do { } while (0)
-
-#include <asm/pb1000.h>
-#define PCMCIA_IRQ AU1000_GPIO_15
-
-static int pb1x00_pcmcia_init(struct pcmcia_init *init)
-{
- u16 pcr;
- pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
-
- au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */
- au_sync_delay(100);
- au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */
- au_sync();
-
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(20);
-
- return PCMCIA_NUM_SOCKS;
-}
-
-static int pb1x00_pcmcia_shutdown(void)
-{
- u16 pcr;
- pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(20);
- return 0;
-}
-
-static int
-pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
-{
- u32 inserted0, inserted1;
- u16 vs0, vs1;
-
- vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
- inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
- inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
- vs0 = (vs0 >> 4) & 0x3;
- vs1 = (vs1 >> 12) & 0x3;
-
- state->ready = 0;
- state->vs_Xv = 0;
- state->vs_3v = 0;
- state->detect = 0;
-
- if (sock == 0) {
- if (inserted0) {
- switch (vs0) {
- case 0:
- case 2:
- state->vs_3v=1;
- break;
- case 3: /* 5V */
- break;
- default:
- /* return without setting 'detect' */
- printk(KERN_ERR "pb1x00 bad VS (%d)\n",
- vs0);
- return 0;
- }
- state->detect = 1;
- }
- }
- else {
- if (inserted1) {
- switch (vs1) {
- case 0:
- case 2:
- state->vs_3v=1;
- break;
- case 3: /* 5V */
- break;
- default:
- /* return without setting 'detect' */
- printk(KERN_ERR "pb1x00 bad VS (%d)\n",
- vs1);
- return 0;
- }
- state->detect = 1;
- }
- }
-
- if (state->detect) {
- state->ready = 1;
- }
-
- state->bvd1=1;
- state->bvd2=1;
- state->wrprot=0;
- return 1;
-}
-
-
-static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-{
-
- if(info->sock > PCMCIA_MAX_SOCK) return -1;
-
- /*
- * Even in the case of the Pb1000, both sockets are connected
- * to the same irq line.
- */
- info->irq = PCMCIA_IRQ;
-
- return 0;
-}
-
-
-static int
-pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
-{
- u16 pcr;
-
- if(configure->sock > PCMCIA_MAX_SOCK) return -1;
-
- pcr = au_readl(PB1000_PCR);
-
- if (configure->sock == 0) {
- pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 |
- PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1);
- }
- else {
- pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 |
- PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1);
- }
-
- pcr &= ~PCR_SLOT_0_RST;
- debug("Vcc %dV Vpp %dV, pcr %x\n",
- configure->vcc, configure->vpp, pcr);
- switch(configure->vcc){
- case 0: /* Vcc 0 */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- case 50: /* Vcc 5V */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_GND,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_5V,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_12V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- case 33: /* Vcc 3.3V */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_GND,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_5V,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_12V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- default: /* what's this ? */
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
- printk(KERN_ERR "%s: bad Vcc %d\n",
- __func__, configure->vcc);
- break;
- }
-
- if (configure->sock == 0) {
- pcr &= ~(PCR_SLOT_0_RST);
- if (configure->reset)
- pcr |= PCR_SLOT_0_RST;
- }
- else {
- pcr &= ~(PCR_SLOT_1_RST);
- if (configure->reset)
- pcr |= PCR_SLOT_1_RST;
- }
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(300);
-
- return 0;
-}
-
-
-struct pcmcia_low_level pb1x00_pcmcia_ops = {
- pb1x00_pcmcia_init,
- pb1x00_pcmcia_shutdown,
- pb1x00_pcmcia_socket_state,
- pb1x00_pcmcia_get_irq_info,
- pb1x00_pcmcia_configure_socket
-};
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 3e49df6..5b7c227 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -7,7 +7,7 @@
/* This is a fairly generic PCMCIA socket driver suitable for the
* following Alchemy Development boards:
- * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200.
+ * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200, Db1300
*
* The Db1000 is used as a reference: Per-socket card-, carddetect- and
* statuschange IRQs connected to SoC GPIOs, control and status register
@@ -18,6 +18,7 @@
* - Pb1100/Pb1500: single socket only; voltage key bits VS are
* at STATUS[5:4] (instead of STATUS[1:0]).
* - Au1200-based: additional card-eject irqs, irqs not gpios!
+ * - Db1300: Db1200-like, no pwr ctrl, single socket (#1).
*/
#include <linux/delay.h>
@@ -59,11 +60,17 @@ struct db1x_pcmcia_sock {
#define BOARD_TYPE_DEFAULT 0 /* most boards */
#define BOARD_TYPE_DB1200 1 /* IRQs aren't gpios */
#define BOARD_TYPE_PB1100 2 /* VS bits slightly different */
+#define BOARD_TYPE_DB1300 3 /* no power control */
int board_type;
};
#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)
+static int db1300_card_inserted(struct db1x_pcmcia_sock *sock)
+{
+ return bcsr_read(BCSR_SIGSTAT) & (1 << 8);
+}
+
/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */
static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)
{
@@ -84,6 +91,8 @@ static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)
switch (sock->board_type) {
case BOARD_TYPE_DB1200:
return db1200_card_inserted(sock);
+ case BOARD_TYPE_DB1300:
+ return db1300_card_inserted(sock);
default:
return db1000_card_inserted(sock);
}
@@ -160,7 +169,8 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
* ejection handler have been registered and the currently
* active one disabled.
*/
- if (sock->board_type == BOARD_TYPE_DB1200) {
+ if ((sock->board_type == BOARD_TYPE_DB1200) ||
+ (sock->board_type == BOARD_TYPE_DB1300)) {
ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
IRQF_DISABLED, "pcmcia_insert", sock);
if (ret)
@@ -174,7 +184,7 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
}
/* enable the currently silent one */
- if (db1200_card_inserted(sock))
+ if (db1x_card_inserted(sock))
enable_irq(sock->eject_irq);
else
enable_irq(sock->insert_irq);
@@ -270,7 +280,8 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
}
/* create new voltage code */
- cr_set |= ((v << 2) | p) << (sock->nr * 8);
+ if (sock->board_type != BOARD_TYPE_DB1300)
+ cr_set |= ((v << 2) | p) << (sock->nr * 8);
changed = state->flags ^ sock->old_flags;
@@ -343,6 +354,10 @@ static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,
/* if Vcc is not zero, we have applied power to a card */
status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;
+ /* DB1300: power always on, but don't tell when no card present */
+ if ((sock->board_type == BOARD_TYPE_DB1300) && (status & SS_DETECT))
+ status = SS_POWERON | SS_3VCARD | SS_DETECT;
+
/* reset de-asserted? then we're ready */
status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;
@@ -419,6 +434,9 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
sock->board_type = BOARD_TYPE_DB1200;
break;
+ case BCSR_WHOAMI_DB1300:
+ sock->board_type = BOARD_TYPE_DB1300;
+ break;
default:
printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
ret = -ENODEV;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 9dc565c..849c0c1 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -24,15 +24,15 @@
#include "yenta_socket.h"
#include "i82365.h"
-static int disable_clkrun;
+static bool disable_clkrun;
module_param(disable_clkrun, bool, 0444);
MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
-static int isa_probe = 1;
+static bool isa_probe = 1;
module_param(isa_probe, bool, 0444);
MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing");
-static int pwr_irqs_off;
+static bool pwr_irqs_off;
module_param(pwr_irqs_off, bool, 0644);
MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7f43cf8..f995e6e 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -639,7 +639,7 @@ config ACPI_CMPC
config INTEL_SCU_IPC
bool "Intel SCU IPC Support"
- depends on X86_MRST
+ depends on X86_INTEL_MID
default y
---help---
IPC is used to bridge the communications between kernel and SCU on
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 8877b83..d967344 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -189,7 +189,7 @@ struct compal_data{
/* =============== */
/* General globals */
/* =============== */
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c
index 7f88c79..6ee0b5c 100644
--- a/drivers/platform/x86/intel_oaktrail.c
+++ b/drivers/platform/x86/intel_oaktrail.c
@@ -95,7 +95,7 @@
#define OT_EC_BL_CONTROL_ON_DATA 0x1A
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index f204643..bb51321 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -89,7 +89,7 @@ static int msi_laptop_resume(struct platform_device *device);
#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 09e26bf..fd73ea8 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -228,12 +228,12 @@ static struct platform_device *sdev;
static struct rfkill *rfk;
static bool has_stepping_quirk;
-static int force;
+static bool force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force,
"Disable the DMI check and forces the driver to be loaded");
-static int debug;
+static bool debug;
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 62533c1..ea0c607 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -378,13 +378,13 @@ static unsigned int bright_maxlvl; /* 0 = unknown */
#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
static int dbg_wlswemul;
-static int tpacpi_wlsw_emulstate;
+static bool tpacpi_wlsw_emulstate;
static int dbg_bluetoothemul;
-static int tpacpi_bluetooth_emulstate;
+static bool tpacpi_bluetooth_emulstate;
static int dbg_wwanemul;
-static int tpacpi_wwan_emulstate;
+static bool tpacpi_wwan_emulstate;
static int dbg_uwbemul;
-static int tpacpi_uwb_emulstate;
+static bool tpacpi_uwb_emulstate;
#endif
@@ -6444,7 +6444,7 @@ static struct ibm_struct brightness_driver_data = {
static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */
static char *alsa_id = "ThinkPadEC";
-static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
+static bool alsa_enable = SNDRV_DEFAULT_ENABLE1;
struct tpacpi_alsa_data {
struct snd_card *card;
@@ -6487,7 +6487,7 @@ static enum tpacpi_volume_access_mode volume_mode =
TPACPI_VOL_MODE_MAX;
static enum tpacpi_volume_capabilities volume_capabilities;
-static int volume_control_allowed;
+static bool volume_control_allowed;
/*
* Used to syncronize writers to TP_EC_AUDIO and
@@ -7265,7 +7265,7 @@ enum fan_control_commands {
* and also watchdog cmd */
};
-static int fan_control_allowed;
+static bool fan_control_allowed;
static enum fan_status_access_mode fan_status_access_mode;
static enum fan_control_access_mode fan_control_access_mode;
@@ -8437,7 +8437,7 @@ static struct proc_dir_entry *proc_dir;
* Module and infrastructure proble, init and exit handling
*/
-static int force_load;
+static bool force_load;
#ifdef CONFIG_THINKPAD_ACPI_DEBUG
static const char * __init str_supported(int is_supported)
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index a134c26..42a4dcc 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -82,12 +82,12 @@ struct wmi_block {
#define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */
#define ACPI_WMI_EVENT 0x8 /* GUID is an event */
-static int debug_event;
+static bool debug_event;
module_param(debug_event, bool, 0444);
MODULE_PARM_DESC(debug_event,
"Log WMI Events [0/1]");
-static int debug_dump_wdg;
+static bool debug_dump_wdg;
module_param(debug_dump_wdg, bool, 0444);
MODULE_PARM_DESC(debug_dump_wdg,
"Dump available WMI interfaces [0/1]");
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index dfbd5a6..258fef2 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -295,6 +295,45 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
}
}
+#ifdef CONFIG_AMD_NB
+
+#include <asm/amd_nb.h>
+
+static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
+{
+ resource_size_t start, end;
+ struct pnp_resource *pnp_res;
+ struct resource *res;
+ struct resource mmconfig_res, *mmconfig;
+
+ mmconfig = amd_get_mmconfig_range(&mmconfig_res);
+ if (!mmconfig)
+ return;
+
+ list_for_each_entry(pnp_res, &dev->resources, list) {
+ res = &pnp_res->res;
+ if (res->end < mmconfig->start || res->start > mmconfig->end ||
+ (res->start == mmconfig->start && res->end == mmconfig->end))
+ continue;
+
+ dev_info(&dev->dev, FW_BUG
+ "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
+ res, mmconfig);
+ if (mmconfig->start < res->start) {
+ start = mmconfig->start;
+ end = res->start - 1;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ if (mmconfig->end > res->end) {
+ start = res->end + 1;
+ end = mmconfig->end;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ break;
+ }
+}
+#endif
+
/*
* PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info
@@ -322,6 +361,9 @@ static struct pnp_fixup pnp_fixups[] = {
/* PnP resources that might overlap PCI BARs */
{"PNP0c01", quirk_system_pci_resources},
{"PNP0c02", quirk_system_pci_resources},
+#ifdef CONFIG_AMD_NB
+ {"PNP0c01", quirk_amd_mmconfig_area},
+#endif
{""}
};
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9f88641..3a8daf8 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -116,12 +116,12 @@ config BATTERY_WM97XX
help
Say Y to enable support for battery measured by WM97xx aux port.
-config BATTERY_BQ20Z75
- tristate "TI BQ20z75 gas gauge"
+config BATTERY_SBS
+ tristate "SBS Compliant gas gauge"
depends on I2C
help
- Say Y to include support for TI BQ20z75 SBS-compliant
- gas gauge and protection IC.
+ Say Y to include support for SBS battery driver for SBS-compliant
+ gas gauges.
config BATTERY_BQ27x00
tristate "BQ27x00 battery driver"
@@ -150,6 +150,14 @@ config BATTERY_DA9030
Say Y here to enable support for batteries charger integrated into
DA9030 PMIC.
+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.
+
config BATTERY_MAX17040
tristate "Maxim MAX17040 Fuel Gauge"
depends on I2C
@@ -226,6 +234,12 @@ config CHARGER_TWL4030
help
Say Y here to enable support for TWL4030 Battery Charge Interface.
+config CHARGER_LP8727
+ tristate "National Semiconductor LP8727 charger driver"
+ depends on I2C
+ help
+ Say Y here to enable support for LP8727 Charger Driver.
+
config CHARGER_GPIO
tristate "GPIO charger"
depends on GPIOLIB
@@ -236,6 +250,16 @@ config CHARGER_GPIO
This driver can be build as a module. If so, the module will be
called gpio-charger.
+config CHARGER_MANAGER
+ bool "Battery charger manager for multiple chargers"
+ depends on REGULATOR && RTC_CLASS
+ help
+ Say Y to enable charger-manager support, which allows multiple
+ chargers attached to a battery and multiple batteries attached to a
+ system. The charger-manager also can monitor charging status in
+ runtime and in suspend-to-RAM by waking up the system periodically
+ with help of suspend_again support.
+
config CHARGER_MAX8997
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
depends on MFD_MAX8997 && REGULATOR_MAX8997
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b4af13d..e429008 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -22,9 +22,10 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
-obj-$(CONFIG_BATTERY_BQ20Z75) += bq20z75.o
+obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
+obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
@@ -35,6 +36,8 @@ obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
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_GPIO) += gpio-charger.o
+obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index bb16f5b..98bf567 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -54,13 +54,19 @@
#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
-#define BQ27000_FLAG_CHGS BIT(7)
+#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */
#define BQ27000_FLAG_FC BIT(5)
+#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
#define BQ27500_REG_SOC 0x2C
#define BQ27500_REG_DCAP 0x3C /* Design capacity */
-#define BQ27500_FLAG_DSC BIT(0)
-#define BQ27500_FLAG_FC BIT(9)
+#define BQ27500_FLAG_DSG BIT(0) /* Discharging */
+#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
+#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27500_FLAG_CHG BIT(8) /* Charging */
+#define BQ27500_FLAG_FC BIT(9) /* Fully charged */
#define BQ27000_RS 20 /* Resistor sense */
@@ -79,9 +85,8 @@ struct bq27x00_reg_cache {
int charge_full;
int cycle_count;
int capacity;
+ int energy;
int flags;
-
- int current_now;
};
struct bq27x00_device_info {
@@ -108,6 +113,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -149,7 +155,7 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
if (rsoc < 0)
- dev_err(di->dev, "error reading relative State-of-Charge\n");
+ dev_dbg(di->dev, "error reading relative State-of-Charge\n");
return rsoc;
}
@@ -164,7 +170,8 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
charge = bq27x00_read(di, reg, false);
if (charge < 0) {
- dev_err(di->dev, "error reading nominal available capacity\n");
+ dev_dbg(di->dev, "error reading charge register %02x: %d\n",
+ reg, charge);
return charge;
}
@@ -208,7 +215,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
if (ilmd < 0) {
- dev_err(di->dev, "error reading initial last measured discharge\n");
+ dev_dbg(di->dev, "error reading initial last measured discharge\n");
return ilmd;
}
@@ -221,6 +228,50 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
}
/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
+{
+ int ae;
+
+ ae = bq27x00_read(di, BQ27x00_REG_AE, false);
+ if (ae < 0) {
+ dev_dbg(di->dev, "error reading available energy\n");
+ return ae;
+ }
+
+ if (di->chip == BQ27500)
+ ae *= 1000;
+ else
+ ae = ae * 29200 / BQ27000_RS;
+
+ return ae;
+}
+
+/*
+ * Return the battery temperature in tenths of degree Celsius
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
+{
+ int temp;
+
+ temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
+ if (temp < 0) {
+ dev_err(di->dev, "error reading temperature\n");
+ return temp;
+ }
+
+ if (di->chip == BQ27500)
+ temp -= 2731;
+ else
+ temp = ((temp * 5) - 5463) / 2;
+
+ return temp;
+}
+
+/*
* Return the battery Cycle count total
* Or < 0 if something fails.
*/
@@ -245,7 +296,8 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
tval = bq27x00_read(di, reg, false);
if (tval < 0) {
- dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);
+ dev_dbg(di->dev, "error reading time register %02x: %d\n",
+ reg, tval);
return tval;
}
@@ -262,25 +314,31 @@ static void bq27x00_update(struct bq27x00_device_info *di)
cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
if (cache.flags >= 0) {
- cache.capacity = bq27x00_battery_read_rsoc(di);
- cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);
- cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
- cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
- cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
- cache.charge_full = bq27x00_battery_read_lmd(di);
+ if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
+ dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
+ cache.capacity = -ENODATA;
+ cache.energy = -ENODATA;
+ cache.time_to_empty = -ENODATA;
+ cache.time_to_empty_avg = -ENODATA;
+ cache.time_to_full = -ENODATA;
+ cache.charge_full = -ENODATA;
+ } else {
+ cache.capacity = bq27x00_battery_read_rsoc(di);
+ cache.energy = bq27x00_battery_read_energy(di);
+ cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
+ cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
+ cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
+ cache.charge_full = bq27x00_battery_read_lmd(di);
+ }
+ cache.temperature = bq27x00_battery_read_temperature(di);
cache.cycle_count = bq27x00_battery_read_cyct(di);
- if (!is_bq27500)
- cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
-
/* We only have to read charge design full once */
if (di->charge_design_full <= 0)
di->charge_design_full = bq27x00_battery_read_ilmd(di);
}
- /* Ignore current_now which is a snapshot of the current battery state
- * and is likely to be different even between two consecutive reads */
- if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
+ if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
di->cache = cache;
power_supply_changed(&di->bat);
}
@@ -302,25 +360,6 @@ static void bq27x00_battery_poll(struct work_struct *work)
}
}
-
-/*
- * Return the battery temperature in tenths of degree Celsius
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- if (di->cache.temperature < 0)
- return di->cache.temperature;
-
- if (di->chip == BQ27500)
- val->intval = di->cache.temperature - 2731;
- else
- val->intval = ((di->cache.temperature * 5) - 5463) / 2;
-
- return 0;
-}
-
/*
* Return the battery average current in µA
* Note that current can be negative signed as well
@@ -330,20 +369,20 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
int curr;
+ int flags;
- if (di->chip == BQ27500)
- curr = bq27x00_read(di, BQ27x00_REG_AI, false);
- else
- curr = di->cache.current_now;
-
- if (curr < 0)
+ curr = bq27x00_read(di, BQ27x00_REG_AI, false);
+ if (curr < 0) {
+ dev_err(di->dev, "error reading current\n");
return curr;
+ }
if (di->chip == BQ27500) {
/* bq27500 returns signed value */
val->intval = (int)((s16)curr) * 1000;
} else {
- if (di->cache.flags & BQ27000_FLAG_CHGS) {
+ flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
+ if (flags & BQ27000_FLAG_CHGS) {
dev_dbg(di->dev, "negative current!\n");
curr = -curr;
}
@@ -362,10 +401,14 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
if (di->chip == BQ27500) {
if (di->cache.flags & BQ27500_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
- else if (di->cache.flags & BQ27500_FLAG_DSC)
+ else if (di->cache.flags & BQ27500_FLAG_DSG)
status = POWER_SUPPLY_STATUS_DISCHARGING;
- else
+ else if (di->cache.flags & BQ27500_FLAG_CHG)
status = POWER_SUPPLY_STATUS_CHARGING;
+ else if (power_supply_am_i_supplied(&di->bat))
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ status = POWER_SUPPLY_STATUS_UNKNOWN;
} else {
if (di->cache.flags & BQ27000_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
@@ -382,50 +425,56 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
return 0;
}
-/*
- * Return the battery Voltage in milivolts
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
+static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
- int volt;
+ int level;
- volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
- if (volt < 0)
- return volt;
+ if (di->chip == BQ27500) {
+ if (di->cache.flags & BQ27500_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27500_FLAG_SOC1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27500_FLAG_SOCF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ } else {
+ if (di->cache.flags & BQ27000_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27000_FLAG_EDV1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27000_FLAG_EDVF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ }
- val->intval = volt * 1000;
+ val->intval = level;
return 0;
}
/*
- * Return the battery Available energy in µWh
+ * Return the battery Voltage in milivolts
* Or < 0 if something fails.
*/
-static int bq27x00_battery_energy(struct bq27x00_device_info *di,
+static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
- int ae;
+ int volt;
- ae = bq27x00_read(di, BQ27x00_REG_AE, false);
- if (ae < 0) {
- dev_err(di->dev, "error reading available energy\n");
- return ae;
+ volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
+ if (volt < 0) {
+ dev_err(di->dev, "error reading voltage\n");
+ return volt;
}
- if (di->chip == BQ27500)
- ae *= 1000;
- else
- ae = ae * 29200 / BQ27000_RS;
-
- val->intval = ae;
+ val->intval = volt * 1000;
return 0;
}
-
static int bq27x00_simple_value(int value,
union power_supply_propval *val)
{
@@ -473,8 +522,11 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
ret = bq27x00_simple_value(di->cache.capacity, val);
break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ ret = bq27x00_battery_capacity_level(di, val);
+ break;
case POWER_SUPPLY_PROP_TEMP:
- ret = bq27x00_battery_temperature(di, val);
+ ret = bq27x00_simple_value(di->cache.temperature, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
ret = bq27x00_simple_value(di->cache.time_to_empty, val);
@@ -501,7 +553,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
ret = bq27x00_simple_value(di->cache.cycle_count, val);
break;
case POWER_SUPPLY_PROP_ENERGY_NOW:
- ret = bq27x00_battery_energy(di, val);
+ ret = bq27x00_simple_value(di->cache.energy, val);
break;
default:
return -EINVAL;
@@ -546,6 +598,14 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
{
+ /*
+ * power_supply_unregister call bq27x00_battery_get_property which
+ * call bq27x00_battery_poll.
+ * Make sure that bq27x00_battery_poll will not call
+ * schedule_delayed_work again after unregister (which cause OOPS).
+ */
+ poll_interval = 0;
+
cancel_delayed_work_sync(&di->work);
power_supply_unregister(&di->bat);
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
new file mode 100644
index 0000000..0378d01
--- /dev/null
+++ b/drivers/power/charger-manager.c
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This driver enables to monitor battery health and control charger
+ * during suspend-to-mem.
+ * Charger manager depends on other devices. register this later than
+ * the depending devices.
+ *
+ * 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/io.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/power/charger-manager.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
+ * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
+ * without any delays.
+ */
+#define CM_JIFFIES_SMALL (2)
+
+/* If y is valid (> 0) and smaller than x, do x = y */
+#define CM_MIN_VALID(x, y) x = (((y > 0) && ((x) > (y))) ? (y) : (x))
+
+/*
+ * Regard CM_RTC_SMALL (sec) is small enough to ignore error in invoking
+ * rtc alarm. It should be 2 or larger
+ */
+#define CM_RTC_SMALL (2)
+
+#define UEVENT_BUF_SIZE 32
+
+static LIST_HEAD(cm_list);
+static DEFINE_MUTEX(cm_list_mtx);
+
+/* About in-suspend (suspend-again) monitoring */
+static struct rtc_device *rtc_dev;
+/*
+ * Backup RTC alarm
+ * Save the wakeup alarm before entering suspend-to-RAM
+ */
+static struct rtc_wkalrm rtc_wkalarm_save;
+/* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */
+static unsigned long rtc_wkalarm_save_time;
+static bool cm_suspended;
+static bool cm_rtc_set;
+static unsigned long cm_suspend_duration_ms;
+
+/* Global charger-manager description */
+static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
+
+/**
+ * is_batt_present - See if the battery presents in place.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_batt_present(struct charger_manager *cm)
+{
+ union power_supply_propval val;
+ bool present = false;
+ int i, ret;
+
+ switch (cm->desc->battery_present) {
+ case CM_FUEL_GAUGE:
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_PRESENT, &val);
+ if (ret == 0 && val.intval)
+ present = true;
+ break;
+ case CM_CHARGER_STAT:
+ for (i = 0; cm->charger_stat[i]; i++) {
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_PRESENT, &val);
+ if (ret == 0 && val.intval) {
+ present = true;
+ break;
+ }
+ }
+ break;
+ }
+
+ return present;
+}
+
+/**
+ * is_ext_pwr_online - See if an external power source is attached to charge
+ * @cm: the Charger Manager representing the battery.
+ *
+ * Returns true if at least one of the chargers of the battery has an external
+ * power source attached to charge the battery regardless of whether it is
+ * actually charging or not.
+ */
+static bool is_ext_pwr_online(struct charger_manager *cm)
+{
+ union power_supply_propval val;
+ bool online = false;
+ int i, ret;
+
+ /* If at least one of them has one, it's yes. */
+ for (i = 0; cm->charger_stat[i]; i++) {
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_ONLINE, &val);
+ if (ret == 0 && val.intval) {
+ online = true;
+ break;
+ }
+ }
+
+ return online;
+}
+
+/**
+ * get_batt_uV - Get the voltage level of the battery
+ * @cm: the Charger Manager representing the battery.
+ * @uV: the voltage level returned.
+ *
+ * Returns 0 if there is no error.
+ * Returns a negative value on error.
+ */
+static int get_batt_uV(struct charger_manager *cm, int *uV)
+{
+ union power_supply_propval val;
+ int ret;
+
+ if (cm->fuel_gauge)
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+ else
+ return -ENODEV;
+
+ if (ret)
+ return ret;
+
+ *uV = val.intval;
+ return 0;
+}
+
+/**
+ * is_charging - Returns true if the battery is being charged.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_charging(struct charger_manager *cm)
+{
+ int i, ret;
+ bool charging = false;
+ union power_supply_propval val;
+
+ /* If there is no battery, it cannot be charged */
+ if (!is_batt_present(cm))
+ return false;
+
+ /* If at least one of the charger is charging, return yes */
+ for (i = 0; cm->charger_stat[i]; i++) {
+ /* 1. The charger sholuld not be DISABLED */
+ if (cm->emergency_stop)
+ continue;
+ if (!cm->charger_enabled)
+ continue;
+
+ /* 2. The charger should be online (ext-power) */
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_ONLINE, &val);
+ if (ret) {
+ dev_warn(cm->dev, "Cannot read ONLINE value from %s.\n",
+ cm->desc->psy_charger_stat[i]);
+ continue;
+ }
+ if (val.intval == 0)
+ continue;
+
+ /*
+ * 3. The charger should not be FULL, DISCHARGING,
+ * or NOT_CHARGING.
+ */
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_STATUS, &val);
+ if (ret) {
+ dev_warn(cm->dev, "Cannot read STATUS value from %s.\n",
+ cm->desc->psy_charger_stat[i]);
+ continue;
+ }
+ if (val.intval == POWER_SUPPLY_STATUS_FULL ||
+ val.intval == POWER_SUPPLY_STATUS_DISCHARGING ||
+ val.intval == POWER_SUPPLY_STATUS_NOT_CHARGING)
+ continue;
+
+ /* Then, this is charging. */
+ charging = true;
+ break;
+ }
+
+ return charging;
+}
+
+/**
+ * is_polling_required - Return true if need to continue polling for this CM.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_polling_required(struct charger_manager *cm)
+{
+ switch (cm->desc->polling_mode) {
+ case CM_POLL_DISABLE:
+ return false;
+ case CM_POLL_ALWAYS:
+ return true;
+ case CM_POLL_EXTERNAL_POWER_ONLY:
+ return is_ext_pwr_online(cm);
+ case CM_POLL_CHARGING_ONLY:
+ return is_charging(cm);
+ default:
+ dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
+ cm->desc->polling_mode);
+ }
+
+ return false;
+}
+
+/**
+ * try_charger_enable - Enable/Disable chargers altogether
+ * @cm: the Charger Manager representing the battery.
+ * @enable: true: enable / false: disable
+ *
+ * Note that Charger Manager keeps the charger enabled regardless whether
+ * the charger is charging or not (because battery is full or no external
+ * power source exists) except when CM needs to disable chargers forcibly
+ * bacause of emergency causes; when the battery is overheated or too cold.
+ */
+static int try_charger_enable(struct charger_manager *cm, bool enable)
+{
+ int err = 0, i;
+ struct charger_desc *desc = cm->desc;
+
+ /* Ignore if it's redundent command */
+ if (enable && cm->charger_enabled)
+ return 0;
+ if (!enable && !cm->charger_enabled)
+ return 0;
+
+ if (enable) {
+ if (cm->emergency_stop)
+ return -EAGAIN;
+ err = regulator_bulk_enable(desc->num_charger_regulators,
+ desc->charger_regulators);
+ } else {
+ /*
+ * Abnormal battery state - Stop charging forcibly,
+ * even if charger was enabled at the other places
+ */
+ err = regulator_bulk_disable(desc->num_charger_regulators,
+ desc->charger_regulators);
+
+ for (i = 0; i < desc->num_charger_regulators; i++) {
+ if (regulator_is_enabled(
+ desc->charger_regulators[i].consumer)) {
+ regulator_force_disable(
+ desc->charger_regulators[i].consumer);
+ dev_warn(cm->dev,
+ "Disable regulator(%s) forcibly.\n",
+ desc->charger_regulators[i].supply);
+ }
+ }
+ }
+
+ if (!err)
+ cm->charger_enabled = enable;
+
+ return err;
+}
+
+/**
+ * uevent_notify - Let users know something has changed.
+ * @cm: the Charger Manager representing the battery.
+ * @event: the event string.
+ *
+ * If @event is null, it implies that uevent_notify is called
+ * by resume function. When called in the resume function, cm_suspended
+ * should be already reset to false in order to let uevent_notify
+ * notify the recent event during the suspend to users. While
+ * suspended, uevent_notify does not notify users, but tracks
+ * events so that uevent_notify can notify users later after resumed.
+ */
+static void uevent_notify(struct charger_manager *cm, const char *event)
+{
+ static char env_str[UEVENT_BUF_SIZE + 1] = "";
+ static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
+
+ if (cm_suspended) {
+ /* Nothing in suspended-event buffer */
+ if (env_str_save[0] == 0) {
+ if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
+ return; /* status not changed */
+ strncpy(env_str_save, event, UEVENT_BUF_SIZE);
+ return;
+ }
+
+ if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
+ return; /* Duplicated. */
+ else
+ strncpy(env_str_save, event, UEVENT_BUF_SIZE);
+
+ return;
+ }
+
+ if (event == NULL) {
+ /* No messages pending */
+ if (!env_str_save[0])
+ return;
+
+ strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
+ kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
+ env_str_save[0] = 0;
+
+ return;
+ }
+
+ /* status not changed */
+ if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
+ return;
+
+ /* save the status and notify the update */
+ strncpy(env_str, event, UEVENT_BUF_SIZE);
+ kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
+
+ dev_info(cm->dev, event);
+}
+
+/**
+ * _cm_monitor - Monitor the temperature and return true for exceptions.
+ * @cm: the Charger Manager representing the battery.
+ *
+ * Returns true if there is an event to notify for the battery.
+ * (True if the status of "emergency_stop" changes)
+ */
+static bool _cm_monitor(struct charger_manager *cm)
+{
+ struct charger_desc *desc = cm->desc;
+ int temp = desc->temperature_out_of_range(&cm->last_temp_mC);
+
+ 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)
+ return false;
+
+ if (temp) {
+ cm->emergency_stop = temp;
+ if (!try_charger_enable(cm, false)) {
+ if (temp > 0)
+ uevent_notify(cm, "OVERHEAT");
+ else
+ uevent_notify(cm, "COLD");
+ }
+ } else {
+ cm->emergency_stop = 0;
+ if (!try_charger_enable(cm, true))
+ uevent_notify(cm, "CHARGING");
+ }
+
+ return true;
+}
+
+/**
+ * cm_monitor - Monitor every battery.
+ *
+ * Returns true if there is an event to notify from any of the batteries.
+ * (True if the status of "emergency_stop" changes)
+ */
+static bool cm_monitor(void)
+{
+ bool stop = false;
+ struct charger_manager *cm;
+
+ mutex_lock(&cm_list_mtx);
+
+ list_for_each_entry(cm, &cm_list, entry)
+ stop = stop || _cm_monitor(cm);
+
+ mutex_unlock(&cm_list_mtx);
+
+ return stop;
+}
+
+static int charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct charger_manager *cm = container_of(psy,
+ struct charger_manager, charger_psy);
+ struct charger_desc *desc = cm->desc;
+ int i, ret = 0, uV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (is_charging(cm))
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (is_ext_pwr_online(cm))
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (cm->emergency_stop > 0)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else if (cm->emergency_stop < 0)
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ if (is_batt_present(cm))
+ val->intval = 1;
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = get_batt_uV(cm, &i);
+ val->intval = i;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CURRENT_NOW, val);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ /* in thenth of centigrade */
+ if (cm->last_temp_mC == INT_MIN)
+ desc->temperature_out_of_range(&cm->last_temp_mC);
+ val->intval = cm->last_temp_mC / 100;
+ if (!desc->measure_battery_temp)
+ ret = -ENODEV;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+ /* in thenth of centigrade */
+ if (cm->last_temp_mC == INT_MIN)
+ desc->temperature_out_of_range(&cm->last_temp_mC);
+ val->intval = cm->last_temp_mC / 100;
+ if (desc->measure_battery_temp)
+ ret = -ENODEV;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (!cm->fuel_gauge) {
+ ret = -ENODEV;
+ break;
+ }
+
+ if (!is_batt_present(cm)) {
+ /* There is no battery. Assume 100% */
+ val->intval = 100;
+ break;
+ }
+
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CAPACITY, val);
+ if (ret)
+ break;
+
+ if (val->intval > 100) {
+ val->intval = 100;
+ break;
+ }
+ if (val->intval < 0)
+ val->intval = 0;
+
+ /* Do not adjust SOC when charging: voltage is overrated */
+ if (is_charging(cm))
+ break;
+
+ /*
+ * If the capacity value is inconsistent, calibrate it base on
+ * the battery voltage values and the thresholds given as desc
+ */
+ ret = get_batt_uV(cm, &uV);
+ if (ret) {
+ /* Voltage information not available. No calibration */
+ ret = 0;
+ break;
+ }
+
+ if (desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
+ !is_charging(cm)) {
+ val->intval = 100;
+ break;
+ }
+
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (is_ext_pwr_online(cm))
+ val->intval = 1;
+ else
+ 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)) {
+ 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;
+ ret = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ if (is_charging(cm)) {
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ val);
+ if (ret) {
+ val->intval = 1;
+ ret = 0;
+ } else {
+ /* If CHARGE_NOW is supplied, use it */
+ val->intval = (val->intval > 0) ?
+ val->intval : 1;
+ }
+ } else {
+ val->intval = 0;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+#define NUM_CHARGER_PSY_OPTIONAL (4)
+static enum power_supply_property default_charger_props[] = {
+ /* Guaranteed to provide */
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ /*
+ * Optional properties are:
+ * POWER_SUPPLY_PROP_CHARGE_NOW,
+ * POWER_SUPPLY_PROP_CURRENT_NOW,
+ * POWER_SUPPLY_PROP_TEMP, and
+ * POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ */
+};
+
+static struct power_supply psy_default = {
+ .name = "battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = default_charger_props,
+ .num_properties = ARRAY_SIZE(default_charger_props),
+ .get_property = charger_get_property,
+};
+
+/**
+ * cm_setup_timer - For in-suspend monitoring setup wakeup alarm
+ * for suspend_again.
+ *
+ * Returns true if the alarm is set for Charger Manager to use.
+ * Returns false if
+ * cm_setup_timer fails to set an alarm,
+ * cm_setup_timer does not need to set an alarm for Charger Manager,
+ * or an alarm previously configured is to be used.
+ */
+static bool cm_setup_timer(void)
+{
+ struct charger_manager *cm;
+ unsigned int wakeup_ms = UINT_MAX;
+ bool ret = false;
+
+ mutex_lock(&cm_list_mtx);
+
+ list_for_each_entry(cm, &cm_list, entry) {
+ /* Skip if polling is not required for this CM */
+ if (!is_polling_required(cm) && !cm->emergency_stop)
+ continue;
+ if (cm->desc->polling_interval_ms == 0)
+ continue;
+ CM_MIN_VALID(wakeup_ms, cm->desc->polling_interval_ms);
+ }
+
+ mutex_unlock(&cm_list_mtx);
+
+ if (wakeup_ms < UINT_MAX && wakeup_ms > 0) {
+ pr_info("Charger Manager wakeup timer: %u ms.\n", wakeup_ms);
+ if (rtc_dev) {
+ struct rtc_wkalrm tmp;
+ unsigned long time, now;
+ unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000);
+
+ /*
+ * Set alarm with the polling interval (wakeup_ms)
+ * except when rtc_wkalarm_save comes first.
+ * However, the alarm time should be NOW +
+ * CM_RTC_SMALL or later.
+ */
+ tmp.enabled = 1;
+ rtc_read_time(rtc_dev, &tmp.time);
+ rtc_tm_to_time(&tmp.time, &now);
+ if (add < CM_RTC_SMALL)
+ add = CM_RTC_SMALL;
+ time = now + add;
+
+ ret = true;
+
+ if (rtc_wkalarm_save.enabled &&
+ rtc_wkalarm_save_time &&
+ rtc_wkalarm_save_time < time) {
+ if (rtc_wkalarm_save_time < now + CM_RTC_SMALL)
+ time = now + CM_RTC_SMALL;
+ else
+ time = rtc_wkalarm_save_time;
+
+ /* The timer is not appointed by CM */
+ ret = false;
+ }
+
+ pr_info("Waking up after %lu secs.\n",
+ time - now);
+
+ rtc_time_to_tm(time, &tmp.time);
+ rtc_set_alarm(rtc_dev, &tmp);
+ cm_suspend_duration_ms += wakeup_ms;
+ return ret;
+ }
+ }
+
+ if (rtc_dev)
+ rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
+ return false;
+}
+
+/**
+ * cm_suspend_again - Determine whether suspend again or not
+ *
+ * Returns true if the system should be suspended again
+ * Returns false if the system should be woken up
+ */
+bool cm_suspend_again(void)
+{
+ struct charger_manager *cm;
+ bool ret = false;
+
+ if (!g_desc || !g_desc->rtc_only_wakeup || !g_desc->rtc_only_wakeup() ||
+ !cm_rtc_set)
+ return false;
+
+ if (cm_monitor())
+ goto out;
+
+ ret = true;
+ mutex_lock(&cm_list_mtx);
+ list_for_each_entry(cm, &cm_list, entry) {
+ if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) ||
+ cm->status_save_batt != is_batt_present(cm))
+ ret = false;
+ }
+ mutex_unlock(&cm_list_mtx);
+
+ cm_rtc_set = cm_setup_timer();
+out:
+ /* It's about the time when the non-CM appointed timer goes off */
+ if (rtc_wkalarm_save.enabled) {
+ unsigned long now;
+ struct rtc_time tmp;
+
+ rtc_read_time(rtc_dev, &tmp);
+ rtc_tm_to_time(&tmp, &now);
+
+ if (rtc_wkalarm_save_time &&
+ now + CM_RTC_SMALL >= rtc_wkalarm_save_time)
+ return false;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cm_suspend_again);
+
+/**
+ * setup_charger_manager - initialize charger_global_desc data
+ * @gd: pointer to instance of charger_global_desc
+ */
+int setup_charger_manager(struct charger_global_desc *gd)
+{
+ if (!gd)
+ return -EINVAL;
+
+ if (rtc_dev)
+ rtc_class_close(rtc_dev);
+ rtc_dev = NULL;
+ g_desc = NULL;
+
+ if (!gd->rtc_only_wakeup) {
+ pr_err("The callback rtc_only_wakeup is not given.\n");
+ return -EINVAL;
+ }
+
+ if (gd->rtc_name) {
+ rtc_dev = rtc_class_open(gd->rtc_name);
+ if (IS_ERR_OR_NULL(rtc_dev)) {
+ rtc_dev = NULL;
+ /* Retry at probe. RTC may be not registered yet */
+ }
+ } else {
+ pr_warn("No wakeup timer is given for charger manager."
+ "In-suspend monitoring won't work.\n");
+ }
+
+ g_desc = gd;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(setup_charger_manager);
+
+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;
+ union power_supply_propval val;
+
+ if (g_desc && !rtc_dev && g_desc->rtc_name) {
+ rtc_dev = rtc_class_open(g_desc->rtc_name);
+ if (IS_ERR_OR_NULL(rtc_dev)) {
+ rtc_dev = NULL;
+ dev_err(&pdev->dev, "Cannot get RTC %s.\n",
+ g_desc->rtc_name);
+ ret = -ENODEV;
+ goto err_alloc;
+ }
+ }
+
+ if (!desc) {
+ dev_err(&pdev->dev, "No platform data (desc) found.\n");
+ ret = -ENODEV;
+ goto err_alloc;
+ }
+
+ cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL);
+ if (!cm) {
+ dev_err(&pdev->dev, "Cannot allocate memory.\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Basic Values. Unspecified are Null or 0 */
+ cm->dev = &pdev->dev;
+ cm->desc = kzalloc(sizeof(struct charger_desc), GFP_KERNEL);
+ if (!cm->desc) {
+ dev_err(&pdev->dev, "Cannot allocate memory.\n");
+ ret = -ENOMEM;
+ goto err_alloc_desc;
+ }
+ memcpy(cm->desc, desc, sizeof(struct charger_desc));
+ cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */
+
+ if (!desc->charger_regulators || desc->num_charger_regulators < 1) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "charger_regulators undefined.\n");
+ goto err_no_charger;
+ }
+
+ if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) {
+ dev_err(&pdev->dev, "No power supply defined.\n");
+ ret = -EINVAL;
+ goto err_no_charger_stat;
+ }
+
+ /* Counting index only */
+ while (desc->psy_charger_stat[i])
+ i++;
+
+ cm->charger_stat = kzalloc(sizeof(struct power_supply *) * (i + 1),
+ GFP_KERNEL);
+ if (!cm->charger_stat) {
+ ret = -ENOMEM;
+ goto err_no_charger_stat;
+ }
+
+ for (i = 0; desc->psy_charger_stat[i]; i++) {
+ cm->charger_stat[i] = power_supply_get_by_name(
+ desc->psy_charger_stat[i]);
+ if (!cm->charger_stat[i]) {
+ dev_err(&pdev->dev, "Cannot find power supply "
+ "\"%s\"\n",
+ desc->psy_charger_stat[i]);
+ ret = -ENODEV;
+ goto err_chg_stat;
+ }
+ }
+
+ cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
+ if (!cm->fuel_gauge) {
+ dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
+ desc->psy_fuel_gauge);
+ ret = -ENODEV;
+ goto err_chg_stat;
+ }
+
+ if (desc->polling_interval_ms == 0 ||
+ msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) {
+ dev_err(&pdev->dev, "polling_interval_ms is too small\n");
+ ret = -EINVAL;
+ goto err_chg_stat;
+ }
+
+ if (!desc->temperature_out_of_range) {
+ dev_err(&pdev->dev, "there is no temperature_out_of_range\n");
+ ret = -EINVAL;
+ goto err_chg_stat;
+ }
+
+ platform_set_drvdata(pdev, cm);
+
+ memcpy(&cm->charger_psy, &psy_default,
+ sizeof(psy_default));
+ if (!desc->psy_name) {
+ strncpy(cm->psy_name_buf, psy_default.name,
+ PSY_NAME_MAX);
+ } else {
+ strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
+ }
+ cm->charger_psy.name = cm->psy_name_buf;
+
+ /* Allocate for psy properties because they may vary */
+ cm->charger_psy.properties = kzalloc(sizeof(enum power_supply_property)
+ * (ARRAY_SIZE(default_charger_props) +
+ NUM_CHARGER_PSY_OPTIONAL),
+ GFP_KERNEL);
+ if (!cm->charger_psy.properties) {
+ dev_err(&pdev->dev, "Cannot allocate for psy properties.\n");
+ ret = -ENOMEM;
+ goto err_chg_stat;
+ }
+ memcpy(cm->charger_psy.properties, default_charger_props,
+ sizeof(enum power_supply_property) *
+ ARRAY_SIZE(default_charger_props));
+ cm->charger_psy.num_properties = psy_default.num_properties;
+
+ /* Find which optional psy-properties are available */
+ if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_CHARGE_NOW;
+ cm->charger_psy.num_properties++;
+ }
+ if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ &val)) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_CURRENT_NOW;
+ cm->charger_psy.num_properties++;
+ }
+ if (!desc->measure_battery_temp) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_TEMP_AMBIENT;
+ cm->charger_psy.num_properties++;
+ }
+ if (desc->measure_battery_temp) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_TEMP;
+ cm->charger_psy.num_properties++;
+ }
+
+ ret = power_supply_register(NULL, &cm->charger_psy);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot register charger-manager with"
+ " name \"%s\".\n", cm->charger_psy.name);
+ goto err_register;
+ }
+
+ ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators,
+ desc->charger_regulators);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot get charger regulators.\n");
+ goto err_bulk_get;
+ }
+
+ ret = try_charger_enable(cm, true);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot enable charger regulators\n");
+ goto err_chg_enable;
+ }
+
+ /* Add to the list */
+ mutex_lock(&cm_list_mtx);
+ list_add(&cm->entry, &cm_list);
+ mutex_unlock(&cm_list_mtx);
+
+ return 0;
+
+err_chg_enable:
+ if (desc->charger_regulators)
+ regulator_bulk_free(desc->num_charger_regulators,
+ desc->charger_regulators);
+err_bulk_get:
+ power_supply_unregister(&cm->charger_psy);
+err_register:
+ kfree(cm->charger_psy.properties);
+err_chg_stat:
+ kfree(cm->charger_stat);
+err_no_charger_stat:
+err_no_charger:
+ kfree(cm->desc);
+err_alloc_desc:
+ kfree(cm);
+err_alloc:
+ return ret;
+}
+
+static int __devexit charger_manager_remove(struct platform_device *pdev)
+{
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+ struct charger_desc *desc = cm->desc;
+
+ /* Remove from the list */
+ mutex_lock(&cm_list_mtx);
+ list_del(&cm->entry);
+ mutex_unlock(&cm_list_mtx);
+
+ if (desc->charger_regulators)
+ regulator_bulk_free(desc->num_charger_regulators,
+ desc->charger_regulators);
+
+ power_supply_unregister(&cm->charger_psy);
+ kfree(cm->charger_psy.properties);
+ kfree(cm->charger_stat);
+ kfree(cm->desc);
+ kfree(cm);
+
+ return 0;
+}
+
+const struct platform_device_id charger_manager_id[] = {
+ { "charger-manager", 0 },
+ { },
+};
+
+static int cm_suspend_prepare(struct device *dev)
+{
+ struct platform_device *pdev = container_of(dev, struct platform_device,
+ dev);
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+
+ if (!cm_suspended) {
+ if (rtc_dev) {
+ struct rtc_time tmp;
+ unsigned long now;
+
+ rtc_read_alarm(rtc_dev, &rtc_wkalarm_save);
+ rtc_read_time(rtc_dev, &tmp);
+
+ if (rtc_wkalarm_save.enabled) {
+ rtc_tm_to_time(&rtc_wkalarm_save.time,
+ &rtc_wkalarm_save_time);
+ rtc_tm_to_time(&tmp, &now);
+ if (now > rtc_wkalarm_save_time)
+ rtc_wkalarm_save_time = 0;
+ } else {
+ rtc_wkalarm_save_time = 0;
+ }
+ }
+ cm_suspended = true;
+ }
+
+ cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm);
+ cm->status_save_batt = is_batt_present(cm);
+
+ if (!cm_rtc_set) {
+ cm_suspend_duration_ms = 0;
+ cm_rtc_set = cm_setup_timer();
+ }
+
+ return 0;
+}
+
+static void cm_suspend_complete(struct device *dev)
+{
+ struct platform_device *pdev = container_of(dev, struct platform_device,
+ dev);
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+
+ if (cm_suspended) {
+ if (rtc_dev) {
+ struct rtc_wkalrm tmp;
+
+ rtc_read_alarm(rtc_dev, &tmp);
+ rtc_wkalarm_save.pending = tmp.pending;
+ rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
+ }
+ cm_suspended = false;
+ cm_rtc_set = false;
+ }
+
+ uevent_notify(cm, NULL);
+}
+
+static const struct dev_pm_ops charger_manager_pm = {
+ .prepare = cm_suspend_prepare,
+ .complete = cm_suspend_complete,
+};
+
+static struct platform_driver charger_manager_driver = {
+ .driver = {
+ .name = "charger-manager",
+ .owner = THIS_MODULE,
+ .pm = &charger_manager_pm,
+ },
+ .probe = charger_manager_probe,
+ .remove = __devexit_p(charger_manager_remove),
+ .id_table = charger_manager_id,
+};
+
+static int __init charger_manager_init(void)
+{
+ return platform_driver_register(&charger_manager_driver);
+}
+late_initcall(charger_manager_init);
+
+static void __exit charger_manager_cleanup(void)
+{
+ platform_driver_unregister(&charger_manager_driver);
+}
+module_exit(charger_manager_cleanup);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("Charger Manager");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("charger-manager");
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
index 548d263..74c6b23 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -146,7 +146,7 @@ static void collie_bat_external_power_changed(struct power_supply *psy)
static irqreturn_t collie_bat_gpio_isr(int irq, void *data)
{
- pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq)));
+ pr_info("collie_bat_gpio irq\n");
schedule_work(&bat_work);
return IRQ_HANDLED;
}
@@ -277,18 +277,13 @@ static struct collie_bat collie_bat_bu = {
.adc_temp_divider = -1,
};
-static struct {
- int gpio;
- char *name;
- bool output;
- int value;
-} gpios[] = {
- { COLLIE_GPIO_CO, "main battery full", 0, 0 },
- { COLLIE_GPIO_MAIN_BAT_LOW, "main battery low", 0, 0 },
- { COLLIE_GPIO_CHARGE_ON, "main charge on", 1, 0 },
- { COLLIE_GPIO_MBAT_ON, "main battery", 1, 0 },
- { COLLIE_GPIO_TMP_ON, "main battery temp", 1, 0 },
- { COLLIE_GPIO_BBAT_ON, "backup battery", 1, 0 },
+static struct gpio collie_batt_gpios[] = {
+ { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" },
+ { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" },
+ { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" },
+ { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" },
+ { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
+ { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
};
#ifdef CONFIG_PM
@@ -313,29 +308,16 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
{
int ret;
- int i;
if (!machine_is_collie())
return -ENODEV;
ucb = dev->ucb;
- for (i = 0; i < ARRAY_SIZE(gpios); i++) {
- ret = gpio_request(gpios[i].gpio, gpios[i].name);
- if (ret) {
- i--;
- goto err_gpio;
- }
-
- if (gpios[i].output)
- ret = gpio_direction_output(gpios[i].gpio,
- gpios[i].value);
- else
- ret = gpio_direction_input(gpios[i].gpio);
-
- if (ret)
- goto err_gpio;
- }
+ ret = gpio_request_array(collie_batt_gpios,
+ ARRAY_SIZE(collie_batt_gpios));
+ if (ret)
+ return ret;
mutex_init(&collie_bat_main.work_lock);
@@ -363,19 +345,12 @@ err_psy_reg_main:
/* see comment in collie_bat_remove */
cancel_work_sync(&bat_work);
-
- i--;
-err_gpio:
- for (; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
return ret;
}
static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
{
- int i;
-
free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
power_supply_unregister(&collie_bat_bu.psy);
@@ -387,9 +362,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
* unregistered now.
*/
cancel_work_sync(&bat_work);
-
- for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
- gpio_free(gpios[i].gpio);
+ gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
}
static struct ucb1x00_driver collie_bat_driver = {
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index d2c793cf..3fd3e95 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -588,18 +588,7 @@ static struct platform_driver da903x_battery_driver = {
.remove = da9030_battery_remove,
};
-static int da903x_battery_init(void)
-{
- return platform_driver_register(&da903x_battery_driver);
-}
-
-static void da903x_battery_exit(void)
-{
- platform_driver_unregister(&da903x_battery_driver);
-}
-
-module_init(da903x_battery_init);
-module_exit(da903x_battery_exit);
+module_platform_driver(da903x_battery_driver);
MODULE_DESCRIPTION("DA9030 battery charger driver");
MODULE_AUTHOR("Mike Rapoport, CompuLab");
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
new file mode 100644
index 0000000..e8ea47a
--- /dev/null
+++ b/drivers/power/da9052-battery.c
@@ -0,0 +1,664 @@
+/*
+ * Batttery Driver for Dialog DA9052 PMICs
+ *
+ * Copyright(c) 2011 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/delay.h>
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/pdata.h>
+#include <linux/mfd/da9052/reg.h>
+
+/* STATIC CONFIGURATION */
+#define DA9052_BAT_CUTOFF_VOLT 2800
+#define DA9052_BAT_TSH 62000
+#define DA9052_BAT_LOW_CAP 4
+#define DA9052_AVG_SZ 4
+#define DA9052_VC_TBL_SZ 68
+#define DA9052_VC_TBL_REF_SZ 3
+
+#define DA9052_ISET_USB_MASK 0x0F
+#define DA9052_CHG_USB_ILIM_MASK 0x40
+#define DA9052_CHG_LIM_COLS 16
+
+#define DA9052_MEAN(x, y) ((x + y) / 2)
+
+enum charger_type_enum {
+ DA9052_NOCHARGER = 1,
+ DA9052_CHARGER,
+};
+
+static const u16 da9052_chg_current_lim[2][DA9052_CHG_LIM_COLS] = {
+ {70, 80, 90, 100, 110, 120, 400, 450,
+ 500, 550, 600, 650, 700, 900, 1100, 1300},
+ {80, 90, 100, 110, 120, 400, 450, 500,
+ 550, 600, 800, 1000, 1200, 1400, 1600, 1800},
+};
+
+static const u16 vc_tbl_ref[3] = {10, 25, 40};
+/* Lookup table for voltage vs capacity */
+static u32 const vc_tbl[3][68][2] = {
+ /* For temperature 10 degree Celsius */
+ {
+ {4082, 100}, {4036, 98},
+ {4020, 96}, {4008, 95},
+ {3997, 93}, {3983, 91},
+ {3964, 90}, {3943, 88},
+ {3926, 87}, {3912, 85},
+ {3900, 84}, {3890, 82},
+ {3881, 80}, {3873, 79},
+ {3865, 77}, {3857, 76},
+ {3848, 74}, {3839, 73},
+ {3829, 71}, {3820, 70},
+ {3811, 68}, {3802, 67},
+ {3794, 65}, {3785, 64},
+ {3778, 62}, {3770, 61},
+ {3763, 59}, {3756, 58},
+ {3750, 56}, {3744, 55},
+ {3738, 53}, {3732, 52},
+ {3727, 50}, {3722, 49},
+ {3717, 47}, {3712, 46},
+ {3708, 44}, {3703, 43},
+ {3700, 41}, {3696, 40},
+ {3693, 38}, {3691, 37},
+ {3688, 35}, {3686, 34},
+ {3683, 32}, {3681, 31},
+ {3678, 29}, {3675, 28},
+ {3672, 26}, {3669, 25},
+ {3665, 23}, {3661, 22},
+ {3656, 21}, {3651, 19},
+ {3645, 18}, {3639, 16},
+ {3631, 15}, {3622, 13},
+ {3611, 12}, {3600, 10},
+ {3587, 9}, {3572, 7},
+ {3548, 6}, {3503, 5},
+ {3420, 3}, {3268, 2},
+ {2992, 1}, {2746, 0}
+ },
+ /* For temperature 25 degree Celsius */
+ {
+ {4102, 100}, {4065, 98},
+ {4048, 96}, {4034, 95},
+ {4021, 93}, {4011, 92},
+ {4001, 90}, {3986, 88},
+ {3968, 87}, {3952, 85},
+ {3938, 84}, {3926, 82},
+ {3916, 81}, {3908, 79},
+ {3900, 77}, {3892, 76},
+ {3883, 74}, {3874, 73},
+ {3864, 71}, {3855, 70},
+ {3846, 68}, {3836, 67},
+ {3827, 65}, {3819, 64},
+ {3810, 62}, {3801, 61},
+ {3793, 59}, {3786, 58},
+ {3778, 56}, {3772, 55},
+ {3765, 53}, {3759, 52},
+ {3754, 50}, {3748, 49},
+ {3743, 47}, {3738, 46},
+ {3733, 44}, {3728, 43},
+ {3724, 41}, {3720, 40},
+ {3716, 38}, {3712, 37},
+ {3709, 35}, {3706, 34},
+ {3703, 33}, {3701, 31},
+ {3698, 30}, {3696, 28},
+ {3693, 27}, {3690, 25},
+ {3687, 24}, {3683, 22},
+ {3680, 21}, {3675, 19},
+ {3671, 18}, {3666, 17},
+ {3660, 15}, {3654, 14},
+ {3647, 12}, {3639, 11},
+ {3630, 9}, {3621, 8},
+ {3613, 6}, {3606, 5},
+ {3597, 4}, {3582, 2},
+ {3546, 1}, {2747, 0}
+ },
+ /* For temperature 40 degree Celsius */
+ {
+ {4114, 100}, {4081, 98},
+ {4065, 96}, {4050, 95},
+ {4036, 93}, {4024, 92},
+ {4013, 90}, {4002, 88},
+ {3990, 87}, {3976, 85},
+ {3962, 84}, {3950, 82},
+ {3939, 81}, {3930, 79},
+ {3921, 77}, {3912, 76},
+ {3902, 74}, {3893, 73},
+ {3883, 71}, {3874, 70},
+ {3865, 68}, {3856, 67},
+ {3847, 65}, {3838, 64},
+ {3829, 62}, {3820, 61},
+ {3812, 59}, {3803, 58},
+ {3795, 56}, {3787, 55},
+ {3780, 53}, {3773, 52},
+ {3767, 50}, {3761, 49},
+ {3756, 47}, {3751, 46},
+ {3746, 44}, {3741, 43},
+ {3736, 41}, {3732, 40},
+ {3728, 38}, {3724, 37},
+ {3720, 35}, {3716, 34},
+ {3713, 33}, {3710, 31},
+ {3707, 30}, {3704, 28},
+ {3701, 27}, {3698, 25},
+ {3695, 24}, {3691, 22},
+ {3686, 21}, {3681, 19},
+ {3676, 18}, {3671, 17},
+ {3666, 15}, {3661, 14},
+ {3655, 12}, {3648, 11},
+ {3640, 9}, {3632, 8},
+ {3622, 6}, {3616, 5},
+ {3611, 4}, {3604, 2},
+ {3594, 1}, {2747, 0}
+ }
+};
+
+struct da9052_battery {
+ struct da9052 *da9052;
+ struct power_supply psy;
+ struct notifier_block nb;
+ int charger_type;
+ int status;
+ int health;
+};
+
+static inline int volt_reg_to_mV(int value)
+{
+ return ((value * 1000) / 512) + 2500;
+}
+
+static inline int ichg_reg_to_mA(int value)
+{
+ return (value * 3900) / 1000;
+}
+
+static int da9052_read_chgend_current(struct da9052_battery *bat,
+ int *current_mA)
+{
+ int ret;
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EINVAL;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_ICHG_END_REG);
+ if (ret < 0)
+ return ret;
+
+ *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGEND_ICHGEND);
+
+ return 0;
+}
+
+static int da9052_read_chg_current(struct da9052_battery *bat, int *current_mA)
+{
+ int ret;
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EINVAL;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_ICHG_AV_REG);
+ if (ret < 0)
+ return ret;
+
+ *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGAV_ICHGAV);
+
+ return 0;
+}
+
+static int da9052_bat_check_status(struct da9052_battery *bat, int *status)
+{
+ u8 v[2] = {0, 0};
+ u8 bat_status;
+ u8 chg_end;
+ int ret;
+ int chg_current;
+ int chg_end_current;
+ bool dcinsel;
+ bool dcindet;
+ bool vbussel;
+ bool vbusdet;
+ bool dc;
+ bool vbus;
+
+ ret = da9052_group_read(bat->da9052, DA9052_STATUS_A_REG, 2, v);
+ if (ret < 0)
+ return ret;
+
+ bat_status = v[0];
+ chg_end = v[1];
+
+ dcinsel = bat_status & DA9052_STATUSA_DCINSEL;
+ dcindet = bat_status & DA9052_STATUSA_DCINDET;
+ vbussel = bat_status & DA9052_STATUSA_VBUSSEL;
+ vbusdet = bat_status & DA9052_STATUSA_VBUSDET;
+ dc = dcinsel && dcindet;
+ vbus = vbussel && vbusdet;
+
+ /* Preference to WALL(DCIN) charger unit */
+ if (dc || vbus) {
+ bat->charger_type = DA9052_CHARGER;
+
+ /* If charging end flag is set and Charging current is greater
+ * than charging end limit then battery is charging
+ */
+ if ((chg_end & DA9052_STATUSB_CHGEND) != 0) {
+ ret = da9052_read_chg_current(bat, &chg_current);
+ if (ret < 0)
+ return ret;
+ ret = da9052_read_chgend_current(bat, &chg_end_current);
+ if (ret < 0)
+ return ret;
+
+ if (chg_current >= chg_end_current)
+ bat->status = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ /* If Charging end flag is cleared then battery is
+ * charging
+ */
+ bat->status = POWER_SUPPLY_STATUS_CHARGING;
+ }
+ } else if (dcindet || vbusdet) {
+ bat->charger_type = DA9052_CHARGER;
+ bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ bat->charger_type = DA9052_NOCHARGER;
+ bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+
+ if (status != NULL)
+ *status = bat->status;
+ return 0;
+}
+
+static int da9052_bat_read_volt(struct da9052_battery *bat, int *volt_mV)
+{
+ int volt;
+
+ volt = da9052_adc_manual_read(bat->da9052, DA9052_ADC_MAN_MUXSEL_VBAT);
+ if (volt < 0)
+ return volt;
+
+ *volt_mV = volt_reg_to_mV(volt);
+
+ return 0;
+}
+
+static int da9052_bat_check_presence(struct da9052_battery *bat, int *illegal)
+{
+ int bat_temp;
+
+ bat_temp = da9052_adc_read_temp(bat->da9052);
+ if (bat_temp < 0)
+ return bat_temp;
+
+ if (bat_temp > DA9052_BAT_TSH)
+ *illegal = 1;
+ else
+ *illegal = 0;
+
+ return 0;
+}
+
+static int da9052_bat_interpolate(int vbat_lower, int vbat_upper,
+ int level_lower, int level_upper,
+ int bat_voltage)
+{
+ int tmp;
+
+ tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower);
+ tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000);
+
+ return tmp;
+}
+
+unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
+{
+ int i;
+
+ if (adc_temp <= vc_tbl_ref[0])
+ return 0;
+
+ if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1])
+ return DA9052_VC_TBL_REF_SZ - 1;
+
+ for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) {
+ if ((adc_temp > vc_tbl_ref[i]) &&
+ (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
+ return i;
+ if ((adc_temp > DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))
+ && (adc_temp <= vc_tbl_ref[i]))
+ return i + 1;
+ }
+}
+
+static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity)
+{
+ int adc_temp;
+ int bat_voltage;
+ int vbat_lower;
+ int vbat_upper;
+ int level_upper;
+ int level_lower;
+ int ret;
+ int flag;
+ int i = 0;
+ int j;
+
+ ret = da9052_bat_read_volt(bat, &bat_voltage);
+ if (ret < 0)
+ return ret;
+
+ adc_temp = da9052_adc_read_temp(bat->da9052);
+ if (adc_temp < 0)
+ return adc_temp;
+
+ i = da9052_determine_vc_tbl_index(adc_temp);
+
+ if (bat_voltage >= vc_tbl[i][0][0]) {
+ *capacity = 100;
+ return 0;
+ }
+ if (bat_voltage <= vc_tbl[i][DA9052_VC_TBL_SZ - 1][0]) {
+ *capacity = 0;
+ return 0;
+ }
+ flag = 0;
+
+ for (j = 0; j < (DA9052_VC_TBL_SZ-1); j++) {
+ if ((bat_voltage <= vc_tbl[i][j][0]) &&
+ (bat_voltage >= vc_tbl[i][j + 1][0])) {
+ vbat_upper = vc_tbl[i][j][0];
+ vbat_lower = vc_tbl[i][j + 1][0];
+ level_upper = vc_tbl[i][j][1];
+ level_lower = vc_tbl[i][j + 1][1];
+ flag = 1;
+ break;
+ }
+ }
+ if (!flag)
+ return -EIO;
+
+ *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower,
+ level_upper, bat_voltage);
+
+ return 0;
+}
+
+static int da9052_bat_check_health(struct da9052_battery *bat, int *health)
+{
+ int ret;
+ int bat_illegal;
+ int capacity;
+
+ ret = da9052_bat_check_presence(bat, &bat_illegal);
+ if (ret < 0)
+ return ret;
+
+ if (bat_illegal) {
+ bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ return 0;
+ }
+
+ if (bat->health != POWER_SUPPLY_HEALTH_OVERHEAT) {
+ ret = da9052_bat_read_capacity(bat, &capacity);
+ if (ret < 0)
+ return ret;
+ if (capacity < DA9052_BAT_LOW_CAP)
+ bat->health = POWER_SUPPLY_HEALTH_DEAD;
+ else
+ bat->health = POWER_SUPPLY_HEALTH_GOOD;
+ }
+
+ *health = bat->health;
+
+ return 0;
+}
+
+static irqreturn_t da9052_bat_irq(int irq, void *data)
+{
+ struct da9052_battery *bat = data;
+
+ irq -= bat->da9052->irq_base;
+
+ if (irq == DA9052_IRQ_CHGEND)
+ bat->status = POWER_SUPPLY_STATUS_FULL;
+ else
+ da9052_bat_check_status(bat, NULL);
+
+ if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN ||
+ irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) {
+ power_supply_changed(&bat->psy);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int da9052_USB_current_notifier(struct notifier_block *nb,
+ unsigned long events, void *data)
+{
+ u8 row;
+ u8 col;
+ int *current_mA = data;
+ int ret;
+ struct da9052_battery *bat = container_of(nb, struct da9052_battery,
+ nb);
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EPERM;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG);
+ if (ret & DA9052_CHG_USB_ILIM_MASK)
+ return -EPERM;
+
+ if (bat->da9052->chip_id == DA9052)
+ row = 0;
+ else
+ row = 1;
+
+ if (*current_mA < da9052_chg_current_lim[row][0] ||
+ *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1])
+ return -EINVAL;
+
+ for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) {
+ if (*current_mA <= da9052_chg_current_lim[row][col])
+ break;
+ }
+
+ return da9052_reg_update(bat->da9052, DA9052_ISET_REG,
+ DA9052_ISET_USB_MASK, col);
+}
+
+static int da9052_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret;
+ int illegal;
+ struct da9052_battery *bat = container_of(psy, struct da9052_battery,
+ psy);
+
+ ret = da9052_bat_check_presence(bat, &illegal);
+ if (ret < 0)
+ return ret;
+
+ if (illegal && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = da9052_bat_check_status(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval =
+ (bat->charger_type == DA9052_NOCHARGER) ? 0 : 1;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = da9052_bat_check_presence(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = da9052_bat_check_health(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = DA9052_BAT_CUTOFF_VOLT * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = da9052_bat_read_volt(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = da9052_read_chg_current(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = da9052_bat_read_capacity(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = da9052_adc_read_temp(bat->da9052);
+ ret = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static enum power_supply_property da9052_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+};
+
+static struct power_supply template_battery = {
+ .name = "da9052-bat",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = da9052_bat_props,
+ .num_properties = ARRAY_SIZE(da9052_bat_props),
+ .get_property = da9052_bat_get_property,
+};
+
+static const char *const da9052_bat_irqs[] = {
+ "BATT TEMP",
+ "DCIN DET",
+ "DCIN REM",
+ "VBUS DET",
+ "VBUS REM",
+ "CHG END",
+};
+
+static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
+{
+ struct da9052_pdata *pdata;
+ struct da9052_battery *bat;
+ int ret;
+ int irq;
+ int i;
+
+ bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
+ if (!bat)
+ return -ENOMEM;
+
+ bat->da9052 = dev_get_drvdata(pdev->dev.parent);
+ bat->psy = template_battery;
+ bat->charger_type = DA9052_NOCHARGER;
+ bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
+ bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ bat->nb.notifier_call = da9052_USB_current_notifier;
+
+ pdata = bat->da9052->dev->platform_data;
+ if (pdata != NULL && pdata->use_for_apm)
+ bat->psy.use_for_apm = pdata->use_for_apm;
+ else
+ bat->psy.use_for_apm = 1;
+
+ for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ ret = request_threaded_irq(bat->da9052->irq_base + irq,
+ NULL, da9052_bat_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ da9052_bat_irqs[i], bat);
+ if (ret != 0) {
+ dev_err(bat->da9052->dev,
+ "DA9052 failed to request %s IRQ %d: %d\n",
+ da9052_bat_irqs[i], irq, ret);
+ goto err;
+ }
+ }
+
+ ret = power_supply_register(&pdev->dev, &bat->psy);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ for (; i >= 0; i--) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ free_irq(bat->da9052->irq_base + irq, bat);
+ }
+ kfree(bat);
+ return ret;
+}
+static int __devexit da9052_bat_remove(struct platform_device *pdev)
+{
+ int i;
+ int irq;
+ struct da9052_battery *bat = platform_get_drvdata(pdev);
+
+ for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ free_irq(bat->da9052->irq_base + irq, bat);
+ }
+ power_supply_unregister(&bat->psy);
+
+ return 0;
+}
+
+static struct platform_driver da9052_bat_driver = {
+ .probe = da9052_bat_probe,
+ .remove = __devexit_p(da9052_bat_remove),
+ .driver = {
+ .name = "da9052-bat",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9052_bat_init(void)
+{
+ return platform_driver_register(&da9052_bat_driver);
+}
+module_init(da9052_bat_init);
+
+static void __exit da9052_bat_exit(void)
+{
+ platform_driver_unregister(&da9052_bat_driver);
+}
+module_exit(da9052_bat_exit);
+
+MODULE_DESCRIPTION("DA9052 BAT Device Driver");
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-bat");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index f2c9cc3..076e211 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -64,7 +64,7 @@ static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
-static unsigned int pmod_enabled;
+static bool pmod_enabled;
module_param(pmod_enabled, bool, 0644);
MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
@@ -95,7 +95,11 @@ static int rated_capacities[] = {
2880, /* Samsung */
2880, /* BYD */
2880, /* Lishen */
- 2880 /* NEC */
+ 2880, /* NEC */
+#ifdef CONFIG_MACH_H4700
+ 0,
+ 3600, /* HP iPAQ hx4700 3.7V 3600mAh (359114-001) */
+#endif
};
/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
@@ -637,18 +641,7 @@ static struct platform_driver ds2760_battery_driver = {
.resume = ds2760_battery_resume,
};
-static int __init ds2760_battery_init(void)
-{
- return platform_driver_register(&ds2760_battery_driver);
-}
-
-static void __exit ds2760_battery_exit(void)
-{
- platform_driver_unregister(&ds2760_battery_driver);
-}
-
-module_init(ds2760_battery_init);
-module_exit(ds2760_battery_exit);
+module_platform_driver(ds2760_battery_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 91a783d..de31cae 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -841,29 +841,17 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
return 0;
}
-MODULE_ALIAS("platform:ds2780-battery");
-
static struct platform_driver ds2780_battery_driver = {
.driver = {
.name = "ds2780-battery",
},
.probe = ds2780_battery_probe,
- .remove = ds2780_battery_remove,
+ .remove = __devexit_p(ds2780_battery_remove),
};
-static int __init ds2780_battery_init(void)
-{
- return platform_driver_register(&ds2780_battery_driver);
-}
-
-static void __exit ds2780_battery_exit(void)
-{
- platform_driver_unregister(&ds2780_battery_driver);
-}
-
-module_init(ds2780_battery_init);
-module_exit(ds2780_battery_exit);
+module_platform_driver(ds2780_battery_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>");
MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver");
+MODULE_ALIAS("platform:ds2780-battery");
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index a64b885..8672c91 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -185,17 +185,7 @@ static struct platform_driver gpio_charger_driver = {
},
};
-static int __init gpio_charger_init(void)
-{
- return platform_driver_register(&gpio_charger_driver);
-}
-module_init(gpio_charger_init);
-
-static void __exit gpio_charger_exit(void)
-{
- platform_driver_unregister(&gpio_charger_driver);
-}
-module_exit(gpio_charger_exit);
+module_platform_driver(gpio_charger_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO");
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index 01fa671..d096497 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -779,18 +779,7 @@ static struct platform_driver platform_pmic_battery_driver = {
.remove = __devexit_p(platform_pmic_battery_remove),
};
-static int __init platform_pmic_battery_module_init(void)
-{
- return platform_driver_register(&platform_pmic_battery_driver);
-}
-
-static void __exit platform_pmic_battery_module_exit(void)
-{
- platform_driver_unregister(&platform_pmic_battery_driver);
-}
-
-module_init(platform_pmic_battery_module_init);
-module_exit(platform_pmic_battery_module_exit);
+module_platform_driver(platform_pmic_battery_driver);
MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index f6d72b4..b806667 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -79,7 +79,7 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
{
struct isp1704_charger_data *board = isp->dev->platform_data;
- if (board->set_power)
+ if (board && board->set_power)
board->set_power(on);
}
@@ -494,17 +494,7 @@ static struct platform_driver isp1704_charger_driver = {
.remove = __devexit_p(isp1704_charger_remove),
};
-static int __init isp1704_charger_init(void)
-{
- return platform_driver_register(&isp1704_charger_driver);
-}
-module_init(isp1704_charger_init);
-
-static void __exit isp1704_charger_exit(void)
-{
- platform_driver_unregister(&isp1704_charger_driver);
-}
-module_exit(isp1704_charger_exit);
+module_platform_driver(isp1704_charger_driver);
MODULE_ALIAS("platform:isp1704_charger");
MODULE_AUTHOR("Nokia Corporation");
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 763f894..8dbc7bf 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -67,7 +67,7 @@ static irqreturn_t jz_battery_irq_handler(int irq, void *devid)
static long jz_battery_read_voltage(struct jz_battery *battery)
{
- unsigned long t;
+ long t;
unsigned long val;
long voltage;
@@ -441,17 +441,7 @@ static struct platform_driver jz_battery_driver = {
},
};
-static int __init jz_battery_init(void)
-{
- return platform_driver_register(&jz_battery_driver);
-}
-module_init(jz_battery_init);
-
-static void __exit jz_battery_exit(void)
-{
- platform_driver_unregister(&jz_battery_driver);
-}
-module_exit(jz_battery_exit);
+module_platform_driver(jz_battery_driver);
MODULE_ALIAS("platform:jz4740-battery");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
new file mode 100644
index 0000000..b15b575
--- /dev/null
+++ b/drivers/power/lp8727_charger.c
@@ -0,0 +1,494 @@
+/*
+ * Driver for LP8727 Micro/Mini USB IC with intergrated charger
+ *
+ * Copyright (C) 2011 National Semiconductor
+ *
+ * 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/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/power_supply.h>
+#include <linux/lp8727.h>
+
+#define 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
+
+/* CTRL1 register */
+#define CP_EN (1 << 0)
+#define ADC_EN (1 << 1)
+#define ID200_EN (1 << 4)
+
+/* CTRL2 register */
+#define CHGDET_EN (1 << 1)
+#define INT_EN (1 << 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)
+
+/* INT1 register */
+#define IDNO (0xF << 0)
+#define VBUS (1 << 4)
+
+/* STATUS1 register */
+#define CHGSTAT (3 << 4)
+#define CHPORT (1 << 6)
+#define DCPORT (1 << 7)
+
+/* STATUS2 register */
+#define TEMP_STAT (3 << 5)
+
+enum lp8727_dev_id {
+ ID_NONE,
+ ID_TA,
+ ID_DEDICATED_CHG,
+ ID_USB_CHG,
+ ID_USB_DS,
+ ID_MAX,
+};
+
+enum lp8727_chg_stat {
+ PRECHG,
+ CC,
+ CV,
+ EOC,
+};
+
+struct lp8727_psy {
+ struct power_supply ac;
+ struct power_supply usb;
+ struct power_supply batt;
+};
+
+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;
+ enum lp8727_dev_id devid;
+};
+
+static int lp8727_i2c_read(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
+{
+ s32 ret;
+
+ mutex_lock(&pchg->xfer_lock);
+ ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);
+ mutex_unlock(&pchg->xfer_lock);
+
+ return (ret != len) ? -EIO : 0;
+}
+
+static int lp8727_i2c_write(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
+{
+ s32 ret;
+
+ mutex_lock(&pchg->xfer_lock);
+ ret = i2c_smbus_write_i2c_block_data(pchg->client, reg, len, data);
+ mutex_unlock(&pchg->xfer_lock);
+
+ return ret;
+}
+
+static inline int lp8727_i2c_read_byte(struct lp8727_chg *pchg, u8 reg,
+ u8 *data)
+{
+ return lp8727_i2c_read(pchg, reg, data, 1);
+}
+
+static inline int lp8727_i2c_write_byte(struct lp8727_chg *pchg, u8 reg,
+ u8 *data)
+{
+ return lp8727_i2c_write(pchg, reg, data, 1);
+}
+
+static int 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;
+ }
+
+ return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0;
+}
+
+static void lp8727_init_device(struct lp8727_chg *pchg)
+{
+ u8 val;
+
+ val = ID200_EN | ADC_EN | CP_EN;
+ if (lp8727_i2c_write_byte(pchg, CTRL1, &val))
+ dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL1);
+
+ val = INT_EN | CHGDET_EN;
+ if (lp8727_i2c_write_byte(pchg, CTRL2, &val))
+ dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL2);
+}
+
+static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
+{
+ u8 val;
+ lp8727_i2c_read_byte(pchg, STATUS1, &val);
+ return (val & DCPORT);
+}
+
+static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
+{
+ u8 val;
+ lp8727_i2c_read_byte(pchg, STATUS1, &val);
+ return (val & CHPORT);
+}
+
+static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
+{
+ u8 val = sw;
+ lp8727_i2c_write_byte(pchg, SWCTRL, &val);
+}
+
+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;
+
+ switch (id) {
+ case 0x5:
+ devid = ID_TA;
+ pchg->chg_parm = &pchg->pdata->ac;
+ break;
+ case 0xB:
+ if (lp8727_is_dedicated_charger(pchg)) {
+ pchg->chg_parm = &pchg->pdata->ac;
+ devid = 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;
+ } else if (vbusin) {
+ devid = ID_USB_DS;
+ swctrl = SW_DM1_DM | SW_DP2_DP;
+ }
+ break;
+ default:
+ devid = ID_NONE;
+ pchg->chg_parm = NULL;
+ break;
+ }
+
+ pchg->devid = devid;
+ lp8727_ctrl_switch(pchg, swctrl);
+}
+
+static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
+{
+ u8 val;
+
+ lp8727_i2c_read_byte(pchg, CTRL2, &val);
+ val |= CHGDET_EN;
+ lp8727_i2c_write_byte(pchg, 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);
+
+ if (lp8727_i2c_read(pchg, INT1, intstat, 2)) {
+ dev_err(pchg->dev, "can not read INT registers\n");
+ return;
+ }
+
+ idno = intstat[0] & IDNO;
+ vbus = intstat[0] & VBUS;
+
+ lp8727_id_detection(pchg, idno, vbus);
+ lp8727_enable_chgdet(pchg);
+
+ power_supply_changed(&pchg->psy->ac);
+ power_supply_changed(&pchg->psy->usb);
+ power_supply_changed(&pchg->psy->batt);
+}
+
+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);
+
+ return IRQ_HANDLED;
+}
+
+static void lp8727_intr_config(struct lp8727_chg *pchg)
+{
+ 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");
+
+ if (request_threaded_irq(pchg->client->irq,
+ NULL,
+ lp8727_isr_func,
+ IRQF_TRIGGER_FALLING, "lp8727_irq", pchg)) {
+ dev_err(pchg->dev, "lp8727 irq can not be registered\n");
+ }
+}
+
+static enum power_supply_property lp8727_charger_prop[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static enum power_supply_property lp8727_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_TEMP,
+};
+
+static char *battery_supplied_to[] = {
+ "main_batt",
+};
+
+static int lp8727_charger_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);
+
+ if (psp == POWER_SUPPLY_PROP_ONLINE)
+ val->intval = lp8727_is_charger_attached(psy->name,
+ pchg->devid);
+
+ return 0;
+}
+
+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);
+ u8 read;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
+ lp8727_i2c_read_byte(pchg, STATUS1, &read);
+ if (((read & CHGSTAT) >> 4) == EOC)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ } else {
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ lp8727_i2c_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;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ if (pchg->pdata->get_batt_present)
+ val->intval = pchg->pdata->get_batt_present();
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (pchg->pdata->get_batt_level)
+ val->intval = pchg->pdata->get_batt_level();
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (pchg->pdata->get_batt_capacity)
+ val->intval = pchg->pdata->get_batt_capacity();
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ if (pchg->pdata->get_batt_temp)
+ val->intval = pchg->pdata->get_batt_temp();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void lp8727_charger_changed(struct power_supply *psy)
+{
+ struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+ 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_i2c_write_byte(pchg, CHGCTRL2, &val);
+ }
+ }
+}
+
+static int lp8727_register_psy(struct lp8727_chg *pchg)
+{
+ struct lp8727_psy *psy;
+
+ psy = kzalloc(sizeof(*psy), GFP_KERNEL);
+ if (!psy)
+ goto err_mem;
+
+ pchg->psy = psy;
+
+ psy->ac.name = "ac";
+ psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
+ psy->ac.properties = lp8727_charger_prop;
+ psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
+ psy->ac.get_property = lp8727_charger_get_property;
+ psy->ac.supplied_to = battery_supplied_to;
+ psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+ if (power_supply_register(pchg->dev, &psy->ac))
+ goto err_psy;
+
+ psy->usb.name = "usb";
+ psy->usb.type = POWER_SUPPLY_TYPE_USB;
+ psy->usb.properties = lp8727_charger_prop;
+ psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
+ psy->usb.get_property = lp8727_charger_get_property;
+ psy->usb.supplied_to = battery_supplied_to;
+ psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+ if (power_supply_register(pchg->dev, &psy->usb))
+ goto err_psy;
+
+ psy->batt.name = "main_batt";
+ psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
+ psy->batt.properties = lp8727_battery_prop;
+ psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop);
+ psy->batt.get_property = lp8727_battery_get_property;
+ psy->batt.external_power_changed = lp8727_charger_changed;
+
+ if (power_supply_register(pchg->dev, &psy->batt))
+ goto err_psy;
+
+ return 0;
+
+err_mem:
+ return -ENOMEM;
+err_psy:
+ kfree(psy);
+ return -EPERM;
+}
+
+static void lp8727_unregister_psy(struct lp8727_chg *pchg)
+{
+ struct lp8727_psy *psy = pchg->psy;
+
+ if (!psy)
+ return;
+
+ 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)
+{
+ struct lp8727_chg *pchg;
+ int ret;
+
+ if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -EIO;
+
+ pchg = kzalloc(sizeof(*pchg), GFP_KERNEL);
+ if (!pchg)
+ return -ENOMEM;
+
+ pchg->client = cl;
+ pchg->dev = &cl->dev;
+ pchg->pdata = cl->dev.platform_data;
+ i2c_set_clientdata(cl, pchg);
+
+ mutex_init(&pchg->xfer_lock);
+
+ lp8727_init_device(pchg);
+ lp8727_intr_config(pchg);
+
+ ret = lp8727_register_psy(pchg);
+ if (ret)
+ dev_err(pchg->dev,
+ "can not register power supplies. err=%d", ret);
+
+ return 0;
+}
+
+static int __devexit lp8727_remove(struct i2c_client *cl)
+{
+ struct lp8727_chg *pchg = i2c_get_clientdata(cl);
+
+ lp8727_unregister_psy(pchg);
+ free_irq(pchg->client->irq, pchg);
+ flush_workqueue(pchg->irqthread);
+ destroy_workqueue(pchg->irqthread);
+ kfree(pchg);
+ return 0;
+}
+
+static const struct i2c_device_id lp8727_ids[] = {
+ {"lp8727", 0},
+};
+
+static struct i2c_driver lp8727_driver = {
+ .driver = {
+ .name = "lp8727",
+ },
+ .probe = lp8727_probe,
+ .remove = __devexit_p(lp8727_remove),
+ .id_table = lp8727_ids,
+};
+
+static int __init lp8727_init(void)
+{
+ return i2c_add_driver(&lp8727_driver);
+}
+
+static void __exit lp8727_exit(void)
+{
+ i2c_del_driver(&lp8727_driver);
+}
+
+module_init(lp8727_init);
+module_exit(lp8727_exit);
+
+MODULE_DESCRIPTION("National Semiconductor LP8727 charger driver");
+MODULE_AUTHOR
+ ("Woogyom Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 9f0183c..86acee2 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -85,55 +85,79 @@ static int max17042_get_property(struct power_supply *psy,
{
struct max17042_chip *chip = container_of(psy,
struct max17042_chip, battery);
+ int ret;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_STATUS);
- if (val->intval & MAX17042_STATUS_BattAbsent)
+ ret = max17042_read_reg(chip->client, MAX17042_STATUS);
+ if (ret < 0)
+ return ret;
+
+ if (ret & MAX17042_STATUS_BattAbsent)
val->intval = 0;
else
val->intval = 1;
break;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Cycles);
+ ret = max17042_read_reg(chip->client, MAX17042_Cycles);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_MinMaxVolt);
- val->intval >>= 8;
+ ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
val->intval *= 20000; /* Units of LSB = 20mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_V_empty);
- val->intval >>= 7;
+ ret = max17042_read_reg(chip->client, MAX17042_V_empty);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 7;
val->intval *= 10000; /* Units of LSB = 10mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */
+ ret = max17042_read_reg(chip->client, MAX17042_VCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgVCELL) * 83;
+ ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_SOC) / 256;
+ ret = max17042_read_reg(chip->client, MAX17042_SOC);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_RepSOC);
- if ((val->intval / 256) >= MAX17042_BATTERY_FULL)
+ ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
+ if (ret < 0)
+ return ret;
+
+ if ((ret >> 8) >= MAX17042_BATTERY_FULL)
val->intval = 1;
- else if (val->intval >= 0)
+ else if (ret >= 0)
val->intval = 0;
break;
case POWER_SUPPLY_PROP_TEMP:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_TEMP);
+ ret = max17042_read_reg(chip->client, MAX17042_TEMP);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
/* The value is signed. */
if (val->intval & 0x8000) {
val->intval = (0x7fff & ~val->intval) + 1;
@@ -145,24 +169,30 @@ static int max17042_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Current);
+ ret = max17042_read_reg(chip->client, MAX17042_Current);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
val->intval++;
val->intval *= -1;
}
- val->intval >>= 4;
- val->intval *= 1000000 * 25 / chip->pdata->r_sns;
+ val->intval *= 1562500 / chip->pdata->r_sns;
} else {
return -EINVAL;
}
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgCurrent);
+ ret = max17042_read_reg(chip->client,
+ MAX17042_AvgCurrent);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
@@ -210,6 +240,9 @@ static int __devinit max17042_probe(struct i2c_client *client,
if (!chip->pdata->enable_current_sense)
chip->battery.num_properties -= 2;
+ if (chip->pdata->r_sns == 0)
+ chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
+
ret = power_supply_register(&client->dev, &chip->battery);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
@@ -226,9 +259,6 @@ static int __devinit max17042_probe(struct i2c_client *client,
max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
- } else {
- if (chip->pdata->r_sns == 0)
- chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
}
return 0;
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 2595145..3e23f43 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -374,19 +374,9 @@ static struct platform_driver max8903_driver = {
},
};
-static int __init max8903_init(void)
-{
- return platform_driver_register(&max8903_driver);
-}
-module_init(max8903_init);
-
-static void __exit max8903_exit(void)
-{
- platform_driver_unregister(&max8903_driver);
-}
-module_exit(max8903_exit);
+module_platform_driver(max8903_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MAX8903 Charger Driver");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
-MODULE_ALIAS("max8903-charger");
+MODULE_ALIAS("platform:max8903-charger");
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index a70e16d..daa333b 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -78,6 +78,8 @@ struct max8925_power_info {
unsigned batt_detect:1; /* detecing MB by ID pin */
unsigned topoff_threshold:2;
unsigned fast_charge:3;
+ unsigned no_temp_support:1;
+ unsigned no_insert_detect:1;
int (*set_charger) (int);
};
@@ -116,17 +118,7 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
case MAX8925_IRQ_VCHG_DC_F:
info->ac_online = 0;
__set_charger(info, 0);
- dev_dbg(chip->dev, "Adapter is removal\n");
- break;
- case MAX8925_IRQ_VCHG_USB_R:
- info->usb_online = 1;
- __set_charger(info, 1);
- dev_dbg(chip->dev, "USB inserted\n");
- break;
- case MAX8925_IRQ_VCHG_USB_F:
- info->usb_online = 0;
- __set_charger(info, 0);
- dev_dbg(chip->dev, "USB is removal\n");
+ dev_dbg(chip->dev, "Adapter removed\n");
break;
case MAX8925_IRQ_VCHG_THM_OK_F:
/* Battery is not ready yet */
@@ -168,27 +160,33 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
static int start_measure(struct max8925_power_info *info, int type)
{
unsigned char buf[2] = {0, 0};
+ int meas_cmd;
int meas_reg = 0, ret;
switch (type) {
case MEASURE_VCHG:
+ meas_cmd = MAX8925_CMD_VCHG;
meas_reg = MAX8925_ADC_VCHG;
break;
case MEASURE_VBBATT:
+ meas_cmd = MAX8925_CMD_VBBATT;
meas_reg = MAX8925_ADC_VBBATT;
break;
case MEASURE_VMBATT:
+ meas_cmd = MAX8925_CMD_VMBATT;
meas_reg = MAX8925_ADC_VMBATT;
break;
case MEASURE_ISNS:
+ meas_cmd = MAX8925_CMD_ISNS;
meas_reg = MAX8925_ADC_ISNS;
break;
default:
return -EINVAL;
}
+ max8925_reg_write(info->adc, meas_cmd, 0);
max8925_bulk_read(info->adc, meas_reg, 2, buf);
- ret = (buf[0] << 4) | (buf[1] >> 4);
+ ret = ((buf[0]<<8) | buf[1]) >> 4;
return ret;
}
@@ -208,7 +206,7 @@ static int max8925_ac_get_prop(struct power_supply *psy,
if (info->ac_online) {
ret = start_measure(info, MEASURE_VCHG);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
goto out;
}
}
@@ -242,7 +240,7 @@ static int max8925_usb_get_prop(struct power_supply *psy,
if (info->usb_online) {
ret = start_measure(info, MEASURE_VCHG);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
goto out;
}
}
@@ -266,7 +264,6 @@ static int max8925_bat_get_prop(struct power_supply *psy,
union power_supply_propval *val)
{
struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
- long long int tmp = 0;
int ret = 0;
switch (psp) {
@@ -277,7 +274,7 @@ static int max8925_bat_get_prop(struct power_supply *psy,
if (info->bat_online) {
ret = start_measure(info, MEASURE_VMBATT);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
ret = 0;
break;
}
@@ -288,8 +285,8 @@ static int max8925_bat_get_prop(struct power_supply *psy,
if (info->bat_online) {
ret = start_measure(info, MEASURE_ISNS);
if (ret >= 0) {
- tmp = (long long int)ret * 6250 / 4096 - 3125;
- ret = (int)tmp;
+ /* assume r_sns is 0.02 */
+ ret = ((ret * 6250) - 3125) /* uA */;
val->intval = 0;
if (ret > 0)
val->intval = ret; /* unit is mA */
@@ -365,13 +362,14 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
int ret;
REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+ if (!info->no_insert_detect) {
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
+ }
+ if (!info->no_temp_support) {
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+ }
REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
@@ -379,9 +377,15 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
- info->ac_online = 0;
info->usb_online = 0;
info->bat_online = 0;
+
+ /* check for power - can miss interrupt at boot time */
+ if (start_measure(info, MEASURE_VCHG) * 2000 > 500000)
+ info->ac_online = 1;
+ else
+ info->ac_online = 0;
+
ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
if (ret >= 0) {
/*
@@ -449,6 +453,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->ac.properties = max8925_ac_props;
info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
info->ac.get_property = max8925_ac_get_prop;
+ info->ac.supplied_to = pdata->supplied_to;
+ info->ac.num_supplicants = pdata->num_supplicants;
ret = power_supply_register(&pdev->dev, &info->ac);
if (ret)
goto out;
@@ -459,6 +465,9 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->usb.properties = max8925_usb_props;
info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
info->usb.get_property = max8925_usb_get_prop;
+ info->usb.supplied_to = pdata->supplied_to;
+ info->usb.num_supplicants = pdata->num_supplicants;
+
ret = power_supply_register(&pdev->dev, &info->usb);
if (ret)
goto out_usb;
@@ -478,6 +487,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->topoff_threshold = pdata->topoff_threshold;
info->fast_charge = pdata->fast_charge;
info->set_charger = pdata->set_charger;
+ info->no_temp_support = pdata->no_temp_support;
+ info->no_insert_detect = pdata->no_insert_detect;
max8925_init_charger(chip, info);
return 0;
@@ -512,17 +523,7 @@ static struct platform_driver max8925_power_driver = {
},
};
-static int __init max8925_power_init(void)
-{
- return platform_driver_register(&max8925_power_driver);
-}
-module_init(max8925_power_init);
-
-static void __exit max8925_power_exit(void)
-{
- platform_driver_unregister(&max8925_power_driver);
-}
-module_exit(max8925_power_exit);
+module_platform_driver(max8925_power_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Power supply driver for MAX8925");
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index a23317d..6e88c5d 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/module.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -98,7 +97,7 @@ static __devinit int max8997_battery_probe(struct platform_device *pdev)
return -EINVAL;
if (pdata->eoc_mA) {
- u8 val = (pdata->eoc_mA - 50) / 10;
+ int val = (pdata->eoc_mA - 50) / 10;
if (val < 0)
val = 0;
if (val > 0xf)
@@ -179,6 +178,7 @@ static int __devexit max8997_battery_remove(struct platform_device *pdev)
static const struct platform_device_id max8997_battery_id[] = {
{ "max8997-battery", 0 },
+ { }
};
static struct platform_driver max8997_battery_driver = {
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 93e3bb4..9b3f2bf5 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -154,6 +154,7 @@ static __devinit int max8998_battery_probe(struct platform_device *pdev)
case 0:
dev_dbg(max8998->dev,
"Full Timeout not set: leave it unchanged.\n");
+ break;
default:
dev_err(max8998->dev, "Invalid Full Timeout value\n");
ret = -EINVAL;
@@ -190,6 +191,7 @@ static int __devexit max8998_battery_remove(struct platform_device *pdev)
static const struct platform_device_id max8998_battery_id[] = {
{ "max8998-battery", TYPE_MAX8998 },
+ { }
};
static struct platform_driver max8998_battery_driver = {
@@ -202,17 +204,7 @@ static struct platform_driver max8998_battery_driver = {
.id_table = max8998_battery_id,
};
-static int __init max8998_battery_init(void)
-{
- return platform_driver_register(&max8998_battery_driver);
-}
-module_init(max8998_battery_init);
-
-static void __exit max8998_battery_cleanup(void)
-{
- platform_driver_unregister(&max8998_battery_driver);
-}
-module_exit(max8998_battery_cleanup);
+module_platform_driver(max8998_battery_driver);
MODULE_DESCRIPTION("MAXIM 8998 battery control driver");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 0b0ff3a..7385092 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -519,29 +519,35 @@ static struct device_attribute olpc_bat_error = {
* Initialisation
*********************************************************************/
-static struct platform_device *bat_pdev;
-
static struct power_supply olpc_bat = {
+ .name = "olpc-battery",
.get_property = olpc_bat_get_property,
.use_for_apm = 1,
};
-void olpc_battery_trigger_uevent(unsigned long cause)
+static int olpc_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
{
- if (cause & EC_SCI_SRC_ACPWR)
- kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
- if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
- kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+ if (device_may_wakeup(olpc_ac.dev))
+ olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
+ else
+ olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
+
+ if (device_may_wakeup(olpc_bat.dev))
+ olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
+ | EC_SCI_SRC_BATERR);
+ else
+ olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
+ | EC_SCI_SRC_BATERR);
+
+ return 0;
}
-static int __init olpc_bat_init(void)
+static int __devinit olpc_battery_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
uint8_t status;
- if (!olpc_platform_info.ecver)
- return -ENXIO;
-
/*
* We've seen a number of EC protocol changes; this driver requires
* the latest EC protocol, supported by 0x44 and above.
@@ -558,15 +564,10 @@ static int __init olpc_bat_init(void)
/* Ignore the status. It doesn't actually matter */
- bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
- if (IS_ERR(bat_pdev))
- return PTR_ERR(bat_pdev);
-
- ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+ ret = power_supply_register(&pdev->dev, &olpc_ac);
if (ret)
- goto ac_failed;
+ return ret;
- olpc_bat.name = bat_pdev->name;
if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
olpc_bat.properties = olpc_xo15_bat_props;
olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
@@ -575,7 +576,7 @@ static int __init olpc_bat_init(void)
olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
}
- ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+ ret = power_supply_register(&pdev->dev, &olpc_bat);
if (ret)
goto battery_failed;
@@ -587,7 +588,12 @@ static int __init olpc_bat_init(void)
if (ret)
goto error_failed;
- goto success;
+ if (olpc_ec_wakeup_available()) {
+ device_set_wakeup_capable(olpc_ac.dev, true);
+ device_set_wakeup_capable(olpc_bat.dev, true);
+ }
+
+ return 0;
error_failed:
device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
@@ -595,23 +601,36 @@ eeprom_failed:
power_supply_unregister(&olpc_bat);
battery_failed:
power_supply_unregister(&olpc_ac);
-ac_failed:
- platform_device_unregister(bat_pdev);
-success:
return ret;
}
-static void __exit olpc_bat_exit(void)
+static int __devexit olpc_battery_remove(struct platform_device *pdev)
{
device_remove_file(olpc_bat.dev, &olpc_bat_error);
device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
power_supply_unregister(&olpc_bat);
power_supply_unregister(&olpc_ac);
- platform_device_unregister(bat_pdev);
+ return 0;
}
-module_init(olpc_bat_init);
-module_exit(olpc_bat_exit);
+static const struct of_device_id olpc_battery_ids[] __devinitconst = {
+ { .compatible = "olpc,xo1-battery" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, olpc_battery_ids);
+
+static struct platform_driver olpc_battery_driver = {
+ .driver = {
+ .name = "olpc-battery",
+ .owner = THIS_MODULE,
+ .of_match_table = olpc_battery_ids,
+ },
+ .probe = olpc_battery_probe,
+ .remove = __devexit_p(olpc_battery_remove),
+ .suspend = olpc_battery_suspend,
+};
+
+module_platform_driver(olpc_battery_driver);
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 4fa52e1..3d1e9ef 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -474,17 +474,7 @@ static struct platform_driver pcf50633_mbc_driver = {
.remove = __devexit_p(pcf50633_mbc_remove),
};
-static int __init pcf50633_mbc_init(void)
-{
- return platform_driver_register(&pcf50633_mbc_driver);
-}
-module_init(pcf50633_mbc_init);
-
-static void __exit pcf50633_mbc_exit(void)
-{
- platform_driver_unregister(&pcf50633_mbc_driver);
-}
-module_exit(pcf50633_mbc_exit);
+module_platform_driver(pcf50633_mbc_driver);
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
MODULE_DESCRIPTION("PCF50633 mbc driver");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 69f8aa3..fd49689 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
+#include <linux/notifier.h>
#include <linux/power_supply.h>
#include <linux/pda_power.h>
#include <linux/regulator/consumer.h>
@@ -40,7 +41,9 @@ static int polling;
#ifdef CONFIG_USB_OTG_UTILS
static struct otg_transceiver *transceiver;
+static struct notifier_block otg_nb;
#endif
+
static struct regulator *ac_draw;
enum {
@@ -222,7 +225,42 @@ static void polling_timer_func(unsigned long unused)
#ifdef CONFIG_USB_OTG_UTILS
static int otg_is_usb_online(void)
{
- return (transceiver->state == OTG_STATE_B_PERIPHERAL);
+ return (transceiver->last_event == USB_EVENT_VBUS ||
+ transceiver->last_event == USB_EVENT_ENUMERATED);
+}
+
+static int otg_is_ac_online(void)
+{
+ return (transceiver->last_event == USB_EVENT_CHARGER);
+}
+
+static int otg_handle_notification(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ switch (event) {
+ case USB_EVENT_CHARGER:
+ ac_status = PDA_PSY_TO_CHANGE;
+ break;
+ case USB_EVENT_VBUS:
+ case USB_EVENT_ENUMERATED:
+ usb_status = PDA_PSY_TO_CHANGE;
+ break;
+ case USB_EVENT_NONE:
+ ac_status = PDA_PSY_TO_CHANGE;
+ usb_status = PDA_PSY_TO_CHANGE;
+ break;
+ default:
+ return NOTIFY_OK;
+ }
+
+ /*
+ * Wait a bit before reading ac/usb line status and setting charger,
+ * because ac/usb status readings may lag from irq.
+ */
+ mod_timer(&charger_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_status));
+
+ return NOTIFY_OK;
}
#endif
@@ -282,6 +320,16 @@ static int pda_power_probe(struct platform_device *pdev)
ret = PTR_ERR(ac_draw);
}
+#ifdef CONFIG_USB_OTG_UTILS
+ transceiver = otg_get_transceiver();
+ if (transceiver && !pdata->is_usb_online) {
+ pdata->is_usb_online = otg_is_usb_online;
+ }
+ if (transceiver && !pdata->is_ac_online) {
+ pdata->is_ac_online = otg_is_ac_online;
+ }
+#endif
+
if (pdata->is_ac_online) {
ret = power_supply_register(&pdev->dev, &pda_psy_ac);
if (ret) {
@@ -303,13 +351,6 @@ static int pda_power_probe(struct platform_device *pdev)
}
}
-#ifdef CONFIG_USB_OTG_UTILS
- transceiver = otg_get_transceiver();
- if (transceiver && !pdata->is_usb_online) {
- pdata->is_usb_online = otg_is_usb_online;
- }
-#endif
-
if (pdata->is_usb_online) {
ret = power_supply_register(&pdev->dev, &pda_psy_usb);
if (ret) {
@@ -331,6 +372,18 @@ static int pda_power_probe(struct platform_device *pdev)
}
}
+#ifdef CONFIG_USB_OTG_UTILS
+ if (transceiver && pdata->use_otg_notifier) {
+ otg_nb.notifier_call = otg_handle_notification;
+ ret = otg_register_notifier(transceiver, &otg_nb);
+ if (ret) {
+ dev_err(dev, "failure to register otg notifier\n");
+ goto otg_reg_notifier_failed;
+ }
+ polling = 0;
+ }
+#endif
+
if (polling) {
dev_dbg(dev, "will poll for status\n");
setup_timer(&polling_timer, polling_timer_func, 0);
@@ -343,6 +396,11 @@ static int pda_power_probe(struct platform_device *pdev)
return 0;
+#ifdef CONFIG_USB_OTG_UTILS
+otg_reg_notifier_failed:
+ if (pdata->is_usb_online && usb_irq)
+ free_irq(usb_irq->start, &pda_psy_usb);
+#endif
usb_irq_failed:
if (pdata->is_usb_online)
power_supply_unregister(&pda_psy_usb);
@@ -440,8 +498,6 @@ static int pda_power_resume(struct platform_device *pdev)
#define pda_power_resume NULL
#endif /* CONFIG_PM */
-MODULE_ALIAS("platform:pda-power");
-
static struct platform_driver pda_power_pdrv = {
.driver = {
.name = "pda-power",
@@ -452,17 +508,8 @@ static struct platform_driver pda_power_pdrv = {
.resume = pda_power_resume,
};
-static int __init pda_power_init(void)
-{
- return platform_driver_register(&pda_power_pdrv);
-}
+module_platform_driver(pda_power_pdrv);
-static void __exit pda_power_exit(void)
-{
- platform_driver_unregister(&pda_power_pdrv);
-}
-
-module_init(pda_power_init);
-module_exit(pda_power_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
+MODULE_ALIAS("platform:pda-power");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 329b46b..6ad6127 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -98,7 +98,9 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
{
union power_supply_propval ret = {0,};
struct power_supply *psy = dev_get_drvdata(dev);
+ unsigned int *count = data;
+ (*count)++;
if (psy->type != POWER_SUPPLY_TYPE_BATTERY) {
if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
return 0;
@@ -111,10 +113,18 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
int power_supply_is_system_supplied(void)
{
int error;
+ unsigned int count = 0;
- error = class_for_each_device(power_supply_class, NULL, NULL,
+ error = class_for_each_device(power_supply_class, NULL, &count,
__power_supply_is_system_supplied);
+ /*
+ * If no power class device was found at all, most probably we are
+ * running on a desktop system, so assume we are on mains power.
+ */
+ if (count == 0)
+ return 1;
+
return error;
}
EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
@@ -147,6 +157,12 @@ struct power_supply *power_supply_get_by_name(char *name)
}
EXPORT_SYMBOL_GPL(power_supply_get_by_name);
+int power_supply_powers(struct power_supply *psy, struct device *dev)
+{
+ return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
+}
+EXPORT_SYMBOL_GPL(power_supply_powers);
+
static void power_supply_dev_release(struct device *dev)
{
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
@@ -202,6 +218,7 @@ EXPORT_SYMBOL_GPL(power_supply_register);
void power_supply_unregister(struct power_supply *psy)
{
cancel_work_sync(&psy->changed_work);
+ sysfs_remove_link(&psy->dev->kobj, "powers");
power_supply_remove_triggers(psy);
device_unregister(psy->dev);
}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index e95cd65..b52b57c 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -43,7 +43,7 @@ static ssize_t power_supply_show_property(struct device *dev,
struct device_attribute *attr,
char *buf) {
static char *type_text[] = {
- "Battery", "UPS", "Mains", "USB",
+ "Unknown", "Battery", "UPS", "Mains", "USB",
"USB_DCP", "USB_CDP", "USB_ACA"
};
static char *status_text[] = {
@@ -63,6 +63,9 @@ static ssize_t power_supply_show_property(struct device *dev,
static char *capacity_level_text[] = {
"Unknown", "Critical", "Low", "Normal", "High", "Full"
};
+ static char *scope_text[] = {
+ "Unknown", "System", "Device"
+ };
ssize_t ret = 0;
struct power_supply *psy = dev_get_drvdata(dev);
const ptrdiff_t off = attr - power_supply_attrs;
@@ -78,8 +81,8 @@ static ssize_t power_supply_show_property(struct device *dev,
dev_dbg(dev, "driver has no data for `%s' property\n",
attr->attr.name);
else if (ret != -ENODEV)
- dev_err(dev, "driver failed to report `%s' property\n",
- attr->attr.name);
+ dev_err(dev, "driver failed to report `%s' property: %zd\n",
+ attr->attr.name, ret);
return ret;
}
@@ -95,6 +98,8 @@ static ssize_t power_supply_show_property(struct device *dev,
return sprintf(buf, "%s\n", capacity_level_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_TYPE)
return sprintf(buf, "%s\n", type_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_SCOPE)
+ return sprintf(buf, "%s\n", scope_text[value.intval]);
else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
return sprintf(buf, "%s\n", value.strval);
@@ -167,6 +172,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(time_to_full_now),
POWER_SUPPLY_ATTR(time_to_full_avg),
POWER_SUPPLY_ATTR(type),
+ POWER_SUPPLY_ATTR(scope),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index d32d0d7..8b804a5 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -47,6 +47,22 @@ static void s3c_adc_bat_ext_power_changed(struct power_supply *psy)
msecs_to_jiffies(JITTER_DELAY));
}
+static int gather_samples(struct s3c_adc_client *client, int num, int channel)
+{
+ int value, i;
+
+ /* default to 1 if nothing is set */
+ if (num < 1)
+ num = 1;
+
+ value = 0;
+ for (i = 0; i < num; i++)
+ value += s3c_adc_read(client, channel);
+ value /= num;
+
+ return value;
+}
+
static enum power_supply_property s3c_adc_backup_bat_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
@@ -67,7 +83,8 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy,
if (bat->volt_value < 0 ||
jiffies_to_msecs(jiffies - bat->timestamp) >
BAT_POLL_INTERVAL) {
- bat->volt_value = s3c_adc_read(bat->client,
+ bat->volt_value = gather_samples(bat->client,
+ bat->pdata->backup_volt_samples,
bat->pdata->backup_volt_channel);
bat->volt_value *= bat->pdata->backup_volt_mult;
bat->timestamp = jiffies;
@@ -139,9 +156,11 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
if (bat->volt_value < 0 || bat->cur_value < 0 ||
jiffies_to_msecs(jiffies - bat->timestamp) >
BAT_POLL_INTERVAL) {
- bat->volt_value = s3c_adc_read(bat->client,
+ bat->volt_value = gather_samples(bat->client,
+ bat->pdata->volt_samples,
bat->pdata->volt_channel) * bat->pdata->volt_mult;
- bat->cur_value = s3c_adc_read(bat->client,
+ bat->cur_value = gather_samples(bat->client,
+ bat->pdata->current_samples,
bat->pdata->current_channel) * bat->pdata->current_mult;
bat->timestamp = jiffies;
}
@@ -421,17 +440,7 @@ static struct platform_driver s3c_adc_bat_driver = {
.resume = s3c_adc_bat_resume,
};
-static int __init s3c_adc_bat_init(void)
-{
- return platform_driver_register(&s3c_adc_bat_driver);
-}
-module_init(s3c_adc_bat_init);
-
-static void __exit s3c_adc_bat_exit(void)
-{
- platform_driver_unregister(&s3c_adc_bat_driver);
-}
-module_exit(s3c_adc_bat_exit);
+module_platform_driver(s3c_adc_bat_driver);
MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver");
diff --git a/drivers/power/bq20z75.c b/drivers/power/sbs-battery.c
index 9c5e5be..9ff8af0 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/sbs-battery.c
@@ -1,5 +1,5 @@
/*
- * Gas Gauge driver for TI's BQ20Z75
+ * Gas Gauge driver for SBS Compliant Batteries
*
* Copyright (c) 2010, NVIDIA Corporation.
*
@@ -28,7 +28,7 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/power/bq20z75.h>
+#include <linux/power/sbs-battery.h>
enum {
REG_MANUFACTURER_DATA,
@@ -53,7 +53,7 @@ enum {
/* Battery Mode defines */
#define BATTERY_MODE_OFFSET 0x03
#define BATTERY_MODE_MASK 0x8000
-enum bq20z75_battery_mode {
+enum sbs_battery_mode {
BATTERY_MODE_AMPS,
BATTERY_MODE_WATTS
};
@@ -67,62 +67,56 @@ enum bq20z75_battery_mode {
#define BATTERY_FULL_CHARGED 0x20
#define BATTERY_FULL_DISCHARGED 0x10
-#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \
+#define SBS_DATA(_psp, _addr, _min_value, _max_value) { \
.psp = _psp, \
.addr = _addr, \
.min_value = _min_value, \
.max_value = _max_value, \
}
-static const struct bq20z75_device_data {
+static const struct chip_data {
enum power_supply_property psp;
u8 addr;
int min_value;
int max_value;
-} bq20z75_data[] = {
+} sbs_data[] = {
[REG_MANUFACTURER_DATA] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
[REG_TEMPERATURE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
[REG_VOLTAGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
+ SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
[REG_CURRENT] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768,
- 32767),
+ SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767),
[REG_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
+ SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
[REG_REMAINING_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
[REG_REMAINING_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
[REG_FULL_CHARGE_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
[REG_FULL_CHARGE_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
[REG_TIME_TO_EMPTY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535),
[REG_TIME_TO_FULL] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 65535),
[REG_STATUS] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
[REG_CYCLE_COUNT] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
[REG_DESIGN_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 65535),
[REG_DESIGN_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, 65535),
[REG_DESIGN_VOLTAGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 65535),
[REG_SERIAL_NUMBER] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
};
-static enum power_supply_property bq20z75_properties[] = {
+static enum power_supply_property sbs_properties[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
@@ -144,10 +138,10 @@ static enum power_supply_property bq20z75_properties[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
};
-struct bq20z75_info {
+struct sbs_info {
struct i2c_client *client;
struct power_supply power_supply;
- struct bq20z75_platform_data *pdata;
+ struct sbs_platform_data *pdata;
bool is_present;
bool gpio_detect;
bool enable_detection;
@@ -158,14 +152,14 @@ struct bq20z75_info {
int ignore_changes;
};
-static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
+static int sbs_read_word_data(struct i2c_client *client, u8 address)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0;
int retries = 1;
- if (bq20z75_device->pdata)
- retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+ if (chip->pdata)
+ retries = max(chip->pdata->i2c_retry_count + 1, 1);
while (retries > 0) {
ret = i2c_smbus_read_word_data(client, address);
@@ -184,15 +178,15 @@ static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
return le16_to_cpu(ret);
}
-static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
+static int sbs_write_word_data(struct i2c_client *client, u8 address,
u16 value)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0;
int retries = 1;
- if (bq20z75_device->pdata)
- retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+ if (chip->pdata)
+ retries = max(chip->pdata->i2c_retry_count + 1, 1);
while (retries > 0) {
ret = i2c_smbus_write_word_data(client, address,
@@ -212,44 +206,41 @@ static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
return 0;
}
-static int bq20z75_get_battery_presence_and_health(
+static int sbs_get_battery_presence_and_health(
struct i2c_client *client, enum power_supply_property psp,
union power_supply_propval *val)
{
s32 ret;
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
if (psp == POWER_SUPPLY_PROP_PRESENT &&
- bq20z75_device->gpio_detect) {
- ret = gpio_get_value(
- bq20z75_device->pdata->battery_detect);
- if (ret == bq20z75_device->pdata->battery_detect_present)
+ chip->gpio_detect) {
+ ret = gpio_get_value(chip->pdata->battery_detect);
+ if (ret == chip->pdata->battery_detect_present)
val->intval = 1;
else
val->intval = 0;
- bq20z75_device->is_present = val->intval;
+ chip->is_present = val->intval;
return ret;
}
/* Write to ManufacturerAccess with
* ManufacturerAccess command and then
* read the status */
- ret = bq20z75_write_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr,
- MANUFACTURER_ACCESS_STATUS);
+ ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
+ MANUFACTURER_ACCESS_STATUS);
if (ret < 0) {
if (psp == POWER_SUPPLY_PROP_PRESENT)
val->intval = 0; /* battery removed */
return ret;
}
- ret = bq20z75_read_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr);
+ ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
if (ret < 0)
return ret;
- if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
- ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
+ if (ret < sbs_data[REG_MANUFACTURER_DATA].min_value ||
+ ret > sbs_data[REG_MANUFACTURER_DATA].max_value) {
val->intval = 0;
return 0;
}
@@ -279,24 +270,23 @@ static int bq20z75_get_battery_presence_and_health(
return 0;
}
-static int bq20z75_get_battery_property(struct i2c_client *client,
+static int sbs_get_battery_property(struct i2c_client *client,
int reg_offset, enum power_supply_property psp,
union power_supply_propval *val)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret;
- ret = bq20z75_read_word_data(client,
- bq20z75_data[reg_offset].addr);
+ ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
if (ret < 0)
return ret;
/* returned values are 16 bit */
- if (bq20z75_data[reg_offset].min_value < 0)
+ if (sbs_data[reg_offset].min_value < 0)
ret = (s16)ret;
- if (ret >= bq20z75_data[reg_offset].min_value &&
- ret <= bq20z75_data[reg_offset].max_value) {
+ if (ret >= sbs_data[reg_offset].min_value &&
+ ret <= sbs_data[reg_offset].max_value) {
val->intval = ret;
if (psp != POWER_SUPPLY_PROP_STATUS)
return 0;
@@ -310,12 +300,12 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
else
val->intval = POWER_SUPPLY_STATUS_CHARGING;
- if (bq20z75_device->poll_time == 0)
- bq20z75_device->last_state = val->intval;
- else if (bq20z75_device->last_state != val->intval) {
- cancel_delayed_work_sync(&bq20z75_device->work);
- power_supply_changed(&bq20z75_device->power_supply);
- bq20z75_device->poll_time = 0;
+ if (chip->poll_time == 0)
+ chip->last_state = val->intval;
+ else if (chip->last_state != val->intval) {
+ cancel_delayed_work_sync(&chip->work);
+ power_supply_changed(&chip->power_supply);
+ chip->poll_time = 0;
}
} else {
if (psp == POWER_SUPPLY_PROP_STATUS)
@@ -327,7 +317,7 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
return 0;
}
-static void bq20z75_unit_adjustment(struct i2c_client *client,
+static void sbs_unit_adjustment(struct i2c_client *client,
enum power_supply_property psp, union power_supply_propval *val)
{
#define BASE_UNIT_CONVERSION 1000
@@ -338,7 +328,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
case POWER_SUPPLY_PROP_ENERGY_NOW:
case POWER_SUPPLY_PROP_ENERGY_FULL:
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
- /* bq20z75 provides energy in units of 10mWh.
+ /* sbs provides energy in units of 10mWh.
* Convert to µWh
*/
val->intval *= BATTERY_MODE_CAP_MULT_WATT;
@@ -354,7 +344,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
break;
case POWER_SUPPLY_PROP_TEMP:
- /* bq20z75 provides battery temperature in 0.1K
+ /* sbs provides battery temperature in 0.1K
* so convert it to 0.1°C
*/
val->intval -= TEMP_KELVIN_TO_CELSIUS;
@@ -362,7 +352,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
- /* bq20z75 provides time to empty and time to full in minutes.
+ /* sbs provides time to empty and time to full in minutes.
* Convert to seconds
*/
val->intval *= TIME_UNIT_CONVERSION;
@@ -374,13 +364,12 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
}
}
-static enum bq20z75_battery_mode
-bq20z75_set_battery_mode(struct i2c_client *client,
- enum bq20z75_battery_mode mode)
+static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client,
+ enum sbs_battery_mode mode)
{
int ret, original_val;
- original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
+ original_val = sbs_read_word_data(client, BATTERY_MODE_OFFSET);
if (original_val < 0)
return original_val;
@@ -392,68 +381,67 @@ bq20z75_set_battery_mode(struct i2c_client *client,
else
ret = original_val | BATTERY_MODE_MASK;
- ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
+ ret = sbs_write_word_data(client, BATTERY_MODE_OFFSET, ret);
if (ret < 0)
return ret;
return original_val & BATTERY_MODE_MASK;
}
-static int bq20z75_get_battery_capacity(struct i2c_client *client,
+static int sbs_get_battery_capacity(struct i2c_client *client,
int reg_offset, enum power_supply_property psp,
union power_supply_propval *val)
{
s32 ret;
- enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
+ enum sbs_battery_mode mode = BATTERY_MODE_WATTS;
if (power_supply_is_amp_property(psp))
mode = BATTERY_MODE_AMPS;
- mode = bq20z75_set_battery_mode(client, mode);
+ mode = sbs_set_battery_mode(client, mode);
if (mode < 0)
return mode;
- ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
+ ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
if (ret < 0)
return ret;
if (psp == POWER_SUPPLY_PROP_CAPACITY) {
- /* bq20z75 spec says that this can be >100 %
+ /* sbs spec says that this can be >100 %
* even if max value is 100 % */
val->intval = min(ret, 100);
} else
val->intval = ret;
- ret = bq20z75_set_battery_mode(client, mode);
+ ret = sbs_set_battery_mode(client, mode);
if (ret < 0)
return ret;
return 0;
}
-static char bq20z75_serial[5];
-static int bq20z75_get_battery_serial_number(struct i2c_client *client,
+static char sbs_serial[5];
+static int sbs_get_battery_serial_number(struct i2c_client *client,
union power_supply_propval *val)
{
int ret;
- ret = bq20z75_read_word_data(client,
- bq20z75_data[REG_SERIAL_NUMBER].addr);
+ ret = sbs_read_word_data(client, sbs_data[REG_SERIAL_NUMBER].addr);
if (ret < 0)
return ret;
- ret = sprintf(bq20z75_serial, "%04x", ret);
- val->strval = bq20z75_serial;
+ ret = sprintf(sbs_serial, "%04x", ret);
+ val->strval = sbs_serial;
return 0;
}
-static int bq20z75_get_property_index(struct i2c_client *client,
+static int sbs_get_property_index(struct i2c_client *client,
enum power_supply_property psp)
{
int count;
- for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
- if (psp == bq20z75_data[count].psp)
+ for (count = 0; count < ARRAY_SIZE(sbs_data); count++)
+ if (psp == sbs_data[count].psp)
return count;
dev_warn(&client->dev,
@@ -462,19 +450,19 @@ static int bq20z75_get_property_index(struct i2c_client *client,
return -EINVAL;
}
-static int bq20z75_get_property(struct power_supply *psy,
+static int sbs_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
int ret = 0;
- struct bq20z75_info *bq20z75_device = container_of(psy,
- struct bq20z75_info, power_supply);
- struct i2c_client *client = bq20z75_device->client;
+ struct sbs_info *chip = container_of(psy,
+ struct sbs_info, power_supply);
+ struct i2c_client *client = chip->client;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH:
- ret = bq20z75_get_battery_presence_and_health(client, psp, val);
+ ret = sbs_get_battery_presence_and_health(client, psp, val);
if (psp == POWER_SUPPLY_PROP_PRESENT)
return 0;
break;
@@ -490,15 +478,15 @@ static int bq20z75_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_CAPACITY:
- ret = bq20z75_get_property_index(client, psp);
+ ret = sbs_get_property_index(client, psp);
if (ret < 0)
break;
- ret = bq20z75_get_battery_capacity(client, ret, psp, val);
+ ret = sbs_get_battery_capacity(client, ret, psp, val);
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
- ret = bq20z75_get_battery_serial_number(client, val);
+ ret = sbs_get_battery_serial_number(client, val);
break;
case POWER_SUPPLY_PROP_STATUS:
@@ -509,11 +497,11 @@ static int bq20z75_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
- ret = bq20z75_get_property_index(client, psp);
+ ret = sbs_get_property_index(client, psp);
if (ret < 0)
break;
- ret = bq20z75_get_battery_property(client, ret, psp, val);
+ ret = sbs_get_battery_property(client, ret, psp, val);
break;
default:
@@ -522,25 +510,25 @@ static int bq20z75_get_property(struct power_supply *psy,
return -EINVAL;
}
- if (!bq20z75_device->enable_detection)
+ if (!chip->enable_detection)
goto done;
- if (!bq20z75_device->gpio_detect &&
- bq20z75_device->is_present != (ret >= 0)) {
- bq20z75_device->is_present = (ret >= 0);
- power_supply_changed(&bq20z75_device->power_supply);
+ if (!chip->gpio_detect &&
+ chip->is_present != (ret >= 0)) {
+ chip->is_present = (ret >= 0);
+ power_supply_changed(&chip->power_supply);
}
done:
if (!ret) {
/* Convert units to match requirements for power supply class */
- bq20z75_unit_adjustment(client, psp, val);
+ sbs_unit_adjustment(client, psp, val);
}
dev_dbg(&client->dev,
"%s: property = %d, value = %x\n", __func__, psp, val->intval);
- if (ret && bq20z75_device->is_present)
+ if (ret && chip->is_present)
return ret;
/* battery not present, so return NODATA for properties */
@@ -550,7 +538,7 @@ done:
return 0;
}
-static irqreturn_t bq20z75_irq(int irq, void *devid)
+static irqreturn_t sbs_irq(int irq, void *devid)
{
struct power_supply *battery = devid;
@@ -559,36 +547,35 @@ static irqreturn_t bq20z75_irq(int irq, void *devid)
return IRQ_HANDLED;
}
-static void bq20z75_external_power_changed(struct power_supply *psy)
+static void sbs_external_power_changed(struct power_supply *psy)
{
- struct bq20z75_info *bq20z75_device;
+ struct sbs_info *chip;
- bq20z75_device = container_of(psy, struct bq20z75_info, power_supply);
+ chip = container_of(psy, struct sbs_info, power_supply);
- if (bq20z75_device->ignore_changes > 0) {
- bq20z75_device->ignore_changes--;
+ if (chip->ignore_changes > 0) {
+ chip->ignore_changes--;
return;
}
/* cancel outstanding work */
- cancel_delayed_work_sync(&bq20z75_device->work);
+ cancel_delayed_work_sync(&chip->work);
- schedule_delayed_work(&bq20z75_device->work, HZ);
- bq20z75_device->poll_time = bq20z75_device->pdata->poll_retry_count;
+ schedule_delayed_work(&chip->work, HZ);
+ chip->poll_time = chip->pdata->poll_retry_count;
}
-static void bq20z75_delayed_work(struct work_struct *work)
+static void sbs_delayed_work(struct work_struct *work)
{
- struct bq20z75_info *bq20z75_device;
+ struct sbs_info *chip;
s32 ret;
- bq20z75_device = container_of(work, struct bq20z75_info, work.work);
+ chip = container_of(work, struct sbs_info, work.work);
- ret = bq20z75_read_word_data(bq20z75_device->client,
- bq20z75_data[REG_STATUS].addr);
+ ret = sbs_read_word_data(chip->client, sbs_data[REG_STATUS].addr);
/* if the read failed, give up on this work */
if (ret < 0) {
- bq20z75_device->poll_time = 0;
+ chip->poll_time = 0;
return;
}
@@ -601,62 +588,145 @@ static void bq20z75_delayed_work(struct work_struct *work)
else
ret = POWER_SUPPLY_STATUS_CHARGING;
- if (bq20z75_device->last_state != ret) {
- bq20z75_device->poll_time = 0;
- power_supply_changed(&bq20z75_device->power_supply);
+ if (chip->last_state != ret) {
+ chip->poll_time = 0;
+ power_supply_changed(&chip->power_supply);
return;
}
- if (bq20z75_device->poll_time > 0) {
- schedule_delayed_work(&bq20z75_device->work, HZ);
- bq20z75_device->poll_time--;
+ if (chip->poll_time > 0) {
+ schedule_delayed_work(&chip->work, HZ);
+ chip->poll_time--;
return;
}
}
-static int __devinit bq20z75_probe(struct i2c_client *client,
+#if defined(CONFIG_OF)
+
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+
+static const struct of_device_id sbs_dt_ids[] = {
+ { .compatible = "sbs,sbs-battery" },
+ { .compatible = "ti,bq20z75" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sbs_dt_ids);
+
+static struct sbs_platform_data *sbs_of_populate_pdata(
+ struct i2c_client *client)
+{
+ struct device_node *of_node = client->dev.of_node;
+ struct sbs_platform_data *pdata = client->dev.platform_data;
+ enum of_gpio_flags gpio_flags;
+ int rc;
+ u32 prop;
+
+ /* verify this driver matches this device */
+ if (!of_node)
+ return NULL;
+
+ /* if platform data is set, honor it */
+ if (pdata)
+ return pdata;
+
+ /* first make sure at least one property is set, otherwise
+ * it won't change behavior from running without pdata.
+ */
+ if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) &&
+ !of_get_property(of_node, "sbs,poll-retry-count", NULL) &&
+ !of_get_property(of_node, "sbs,battery-detect-gpios", NULL))
+ goto of_out;
+
+ pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ goto of_out;
+
+ rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop);
+ if (!rc)
+ pdata->i2c_retry_count = prop;
+
+ rc = of_property_read_u32(of_node, "sbs,poll-retry-count", &prop);
+ if (!rc)
+ pdata->poll_retry_count = prop;
+
+ if (!of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) {
+ pdata->battery_detect = -1;
+ goto of_out;
+ }
+
+ pdata->battery_detect = of_get_named_gpio_flags(of_node,
+ "sbs,battery-detect-gpios", 0, &gpio_flags);
+
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ pdata->battery_detect_present = 0;
+ else
+ pdata->battery_detect_present = 1;
+
+of_out:
+ return pdata;
+}
+#else
+#define sbs_dt_ids NULL
+static struct sbs_platform_data *sbs_of_populate_pdata(
+ struct i2c_client *client)
+{
+ return client->dev.platform_data;
+}
+#endif
+
+static int __devinit sbs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct bq20z75_info *bq20z75_device;
- struct bq20z75_platform_data *pdata = client->dev.platform_data;
+ struct sbs_info *chip;
+ struct sbs_platform_data *pdata = client->dev.platform_data;
int rc;
int irq;
+ char *name;
- bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
- if (!bq20z75_device)
+ name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev));
+ if (!name) {
+ dev_err(&client->dev, "Failed to allocate device name\n");
return -ENOMEM;
+ }
+
+ chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL);
+ if (!chip) {
+ rc = -ENOMEM;
+ goto exit_free_name;
+ }
- bq20z75_device->client = client;
- bq20z75_device->enable_detection = false;
- bq20z75_device->gpio_detect = false;
- bq20z75_device->power_supply.name = "battery";
- bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
- bq20z75_device->power_supply.properties = bq20z75_properties;
- bq20z75_device->power_supply.num_properties =
- ARRAY_SIZE(bq20z75_properties);
- bq20z75_device->power_supply.get_property = bq20z75_get_property;
+ chip->client = client;
+ chip->enable_detection = false;
+ chip->gpio_detect = false;
+ chip->power_supply.name = name;
+ chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
+ chip->power_supply.properties = sbs_properties;
+ chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
+ chip->power_supply.get_property = sbs_get_property;
/* ignore first notification of external change, it is generated
* from the power_supply_register call back
*/
- bq20z75_device->ignore_changes = 1;
- bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
- bq20z75_device->power_supply.external_power_changed =
- bq20z75_external_power_changed;
+ chip->ignore_changes = 1;
+ chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
+ chip->power_supply.external_power_changed = sbs_external_power_changed;
+
+ pdata = sbs_of_populate_pdata(client);
if (pdata) {
- bq20z75_device->gpio_detect =
- gpio_is_valid(pdata->battery_detect);
- bq20z75_device->pdata = pdata;
+ chip->gpio_detect = gpio_is_valid(pdata->battery_detect);
+ chip->pdata = pdata;
}
- i2c_set_clientdata(client, bq20z75_device);
+ i2c_set_clientdata(client, chip);
- if (!bq20z75_device->gpio_detect)
+ if (!chip->gpio_detect)
goto skip_gpio;
rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
if (rc) {
dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
@@ -664,7 +734,7 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
if (rc) {
dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
@@ -672,25 +742,25 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
if (irq <= 0) {
dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
- rc = request_irq(irq, bq20z75_irq,
+ rc = request_irq(irq, sbs_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- dev_name(&client->dev), &bq20z75_device->power_supply);
+ dev_name(&client->dev), &chip->power_supply);
if (rc) {
dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
- bq20z75_device->irq = irq;
+ chip->irq = irq;
skip_gpio:
- rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
+ rc = power_supply_register(&client->dev, &chip->power_supply);
if (rc) {
dev_err(&client->dev,
"%s: Failed to register power supply\n", __func__);
@@ -700,95 +770,100 @@ skip_gpio:
dev_info(&client->dev,
"%s: battery gas gauge device registered\n", client->name);
- INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work);
+ INIT_DELAYED_WORK(&chip->work, sbs_delayed_work);
- bq20z75_device->enable_detection = true;
+ chip->enable_detection = true;
return 0;
exit_psupply:
- if (bq20z75_device->irq)
- free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
- if (bq20z75_device->gpio_detect)
+ if (chip->irq)
+ free_irq(chip->irq, &chip->power_supply);
+ if (chip->gpio_detect)
gpio_free(pdata->battery_detect);
- kfree(bq20z75_device);
+ kfree(chip);
+
+exit_free_name:
+ kfree(name);
return rc;
}
-static int __devexit bq20z75_remove(struct i2c_client *client)
+static int __devexit sbs_remove(struct i2c_client *client)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
- if (bq20z75_device->irq)
- free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
- if (bq20z75_device->gpio_detect)
- gpio_free(bq20z75_device->pdata->battery_detect);
+ if (chip->irq)
+ free_irq(chip->irq, &chip->power_supply);
+ if (chip->gpio_detect)
+ gpio_free(chip->pdata->battery_detect);
- power_supply_unregister(&bq20z75_device->power_supply);
+ power_supply_unregister(&chip->power_supply);
- cancel_delayed_work_sync(&bq20z75_device->work);
+ cancel_delayed_work_sync(&chip->work);
- kfree(bq20z75_device);
- bq20z75_device = NULL;
+ kfree(chip->power_supply.name);
+ kfree(chip);
+ chip = NULL;
return 0;
}
#if defined CONFIG_PM
-static int bq20z75_suspend(struct i2c_client *client,
+static int sbs_suspend(struct i2c_client *client,
pm_message_t state)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret;
- if (bq20z75_device->poll_time > 0)
- cancel_delayed_work_sync(&bq20z75_device->work);
+ if (chip->poll_time > 0)
+ cancel_delayed_work_sync(&chip->work);
/* write to manufacturer access with sleep command */
- ret = bq20z75_write_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr,
+ ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
MANUFACTURER_ACCESS_SLEEP);
- if (bq20z75_device->is_present && ret < 0)
+ if (chip->is_present && ret < 0)
return ret;
return 0;
}
#else
-#define bq20z75_suspend NULL
+#define sbs_suspend NULL
#endif
-/* any smbus transaction will wake up bq20z75 */
-#define bq20z75_resume NULL
+/* any smbus transaction will wake up sbs */
+#define sbs_resume NULL
-static const struct i2c_device_id bq20z75_id[] = {
+static const struct i2c_device_id sbs_id[] = {
{ "bq20z75", 0 },
+ { "sbs-battery", 1 },
{}
};
-MODULE_DEVICE_TABLE(i2c, bq20z75_id);
-
-static struct i2c_driver bq20z75_battery_driver = {
- .probe = bq20z75_probe,
- .remove = __devexit_p(bq20z75_remove),
- .suspend = bq20z75_suspend,
- .resume = bq20z75_resume,
- .id_table = bq20z75_id,
+MODULE_DEVICE_TABLE(i2c, sbs_id);
+
+static struct i2c_driver sbs_battery_driver = {
+ .probe = sbs_probe,
+ .remove = __devexit_p(sbs_remove),
+ .suspend = sbs_suspend,
+ .resume = sbs_resume,
+ .id_table = sbs_id,
.driver = {
- .name = "bq20z75-battery",
+ .name = "sbs-battery",
+ .of_match_table = sbs_dt_ids,
},
};
-static int __init bq20z75_battery_init(void)
+static int __init sbs_battery_init(void)
{
- return i2c_add_driver(&bq20z75_battery_driver);
+ return i2c_add_driver(&sbs_battery_driver);
}
-module_init(bq20z75_battery_init);
+module_init(sbs_battery_init);
-static void __exit bq20z75_battery_exit(void)
+static void __exit sbs_battery_exit(void)
{
- i2c_del_driver(&bq20z75_battery_driver);
+ i2c_del_driver(&sbs_battery_driver);
}
-module_exit(bq20z75_battery_exit);
+module_exit(sbs_battery_exit);
-MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
+MODULE_DESCRIPTION("SBS battery monitor driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index 53f0d35..28bbe7e 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -307,25 +307,20 @@ static struct tosa_bat tosa_bat_bu = {
.adc_temp_divider = -1,
};
-static struct {
- int gpio;
- char *name;
- bool output;
- int value;
-} gpios[] = {
- { TOSA_GPIO_CHARGE_OFF, "main charge off", 1, 1 },
- { TOSA_GPIO_CHARGE_OFF_JC, "jacket charge off", 1, 1 },
- { TOSA_GPIO_BAT_SW_ON, "battery switch", 1, 0 },
- { TOSA_GPIO_BAT0_V_ON, "main battery", 1, 0 },
- { TOSA_GPIO_BAT1_V_ON, "jacket battery", 1, 0 },
- { TOSA_GPIO_BAT1_TH_ON, "main battery temp", 1, 0 },
- { TOSA_GPIO_BAT0_TH_ON, "jacket battery temp", 1, 0 },
- { TOSA_GPIO_BU_CHRG_ON, "backup battery", 1, 0 },
- { TOSA_GPIO_BAT0_CRG, "main battery full", 0, 0 },
- { TOSA_GPIO_BAT1_CRG, "jacket battery full", 0, 0 },
- { TOSA_GPIO_BAT0_LOW, "main battery low", 0, 0 },
- { TOSA_GPIO_BAT1_LOW, "jacket battery low", 0, 0 },
- { TOSA_GPIO_JACKET_DETECT, "jacket detect", 0, 0 },
+static struct gpio tosa_bat_gpios[] = {
+ { TOSA_GPIO_CHARGE_OFF, GPIOF_OUT_INIT_HIGH, "main charge off" },
+ { TOSA_GPIO_CHARGE_OFF_JC, GPIOF_OUT_INIT_HIGH, "jacket charge off" },
+ { TOSA_GPIO_BAT_SW_ON, GPIOF_OUT_INIT_LOW, "battery switch" },
+ { TOSA_GPIO_BAT0_V_ON, GPIOF_OUT_INIT_LOW, "main battery" },
+ { TOSA_GPIO_BAT1_V_ON, GPIOF_OUT_INIT_LOW, "jacket battery" },
+ { TOSA_GPIO_BAT1_TH_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
+ { TOSA_GPIO_BAT0_TH_ON, GPIOF_OUT_INIT_LOW, "jacket battery temp" },
+ { TOSA_GPIO_BU_CHRG_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
+ { TOSA_GPIO_BAT0_CRG, GPIOF_IN, "main battery full" },
+ { TOSA_GPIO_BAT1_CRG, GPIOF_IN, "jacket battery full" },
+ { TOSA_GPIO_BAT0_LOW, GPIOF_IN, "main battery low" },
+ { TOSA_GPIO_BAT1_LOW, GPIOF_IN, "jacket battery low" },
+ { TOSA_GPIO_JACKET_DETECT, GPIOF_IN, "jacket detect" },
};
#ifdef CONFIG_PM
@@ -350,27 +345,13 @@ static int tosa_bat_resume(struct platform_device *dev)
static int __devinit tosa_bat_probe(struct platform_device *dev)
{
int ret;
- int i;
if (!machine_is_tosa())
return -ENODEV;
- for (i = 0; i < ARRAY_SIZE(gpios); i++) {
- ret = gpio_request(gpios[i].gpio, gpios[i].name);
- if (ret) {
- i--;
- goto err_gpio;
- }
-
- if (gpios[i].output)
- ret = gpio_direction_output(gpios[i].gpio,
- gpios[i].value);
- else
- ret = gpio_direction_input(gpios[i].gpio);
-
- if (ret)
- goto err_gpio;
- }
+ ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
+ if (ret)
+ return ret;
mutex_init(&tosa_bat_main.work_lock);
mutex_init(&tosa_bat_jacket.work_lock);
@@ -424,18 +405,12 @@ err_psy_reg_main:
/* see comment in tosa_bat_remove */
cancel_work_sync(&bat_work);
- i--;
-err_gpio:
- for (; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
return ret;
}
static int __devexit tosa_bat_remove(struct platform_device *dev)
{
- int i;
-
free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
@@ -450,10 +425,7 @@ static int __devexit tosa_bat_remove(struct platform_device *dev)
* unregistered now.
*/
cancel_work_sync(&bat_work);
-
- for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
return 0;
}
@@ -466,18 +438,7 @@ static struct platform_driver tosa_bat_driver = {
.resume = tosa_bat_resume,
};
-static int __init tosa_bat_init(void)
-{
- return platform_driver_register(&tosa_bat_driver);
-}
-
-static void __exit tosa_bat_exit(void)
-{
- platform_driver_unregister(&tosa_bat_driver);
-}
-
-module_init(tosa_bat_init);
-module_exit(tosa_bat_exit);
+module_platform_driver(tosa_bat_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dmitry Baryshkov");
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index e648cbe..6243e69 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -226,17 +226,7 @@ static struct platform_driver wm831x_backup_driver = {
},
};
-static int __init wm831x_backup_init(void)
-{
- return platform_driver_register(&wm831x_backup_driver);
-}
-module_init(wm831x_backup_init);
-
-static void __exit wm831x_backup_exit(void)
-{
- platform_driver_unregister(&wm831x_backup_driver);
-}
-module_exit(wm831x_backup_exit);
+module_platform_driver(wm831x_backup_driver);
MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 6cc2ca6..987332b 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -27,6 +27,7 @@ struct wm831x_power {
char wall_name[20];
char usb_name[20];
char battery_name[20];
+ bool have_battery;
};
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -449,7 +450,8 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
/* The battery charger is autonomous so we don't need to do
* anything except kick user space */
- power_supply_changed(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_changed(&wm831x_power->battery);
return IRQ_HANDLED;
}
@@ -479,7 +481,8 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
dev_dbg(wm831x->dev, "Power source changed\n");
/* Just notify for everything - little harm in overnotifying. */
- power_supply_changed(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_changed(&wm831x_power->battery);
power_supply_changed(&wm831x_power->usb);
power_supply_changed(&wm831x_power->wall);
@@ -537,15 +540,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
if (ret)
goto err_kmalloc;
- battery->name = power->battery_name;
- battery->properties = wm831x_bat_props;
- battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
- battery->get_property = wm831x_bat_get_prop;
- battery->use_for_apm = 1;
- ret = power_supply_register(&pdev->dev, battery);
- if (ret)
- goto err_wall;
-
usb->name = power->usb_name,
usb->type = POWER_SUPPLY_TYPE_USB;
usb->properties = wm831x_usb_props;
@@ -553,7 +547,23 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
usb->get_property = wm831x_usb_get_prop;
ret = power_supply_register(&pdev->dev, usb);
if (ret)
- goto err_battery;
+ goto err_wall;
+
+ ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
+ if (ret < 0)
+ goto err_wall;
+ power->have_battery = ret & WM831X_CHG_ENA;
+
+ if (power->have_battery) {
+ battery->name = power->battery_name;
+ battery->properties = wm831x_bat_props;
+ battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
+ battery->get_property = wm831x_bat_get_prop;
+ battery->use_for_apm = 1;
+ ret = power_supply_register(&pdev->dev, battery);
+ if (ret)
+ goto err_usb;
+ }
irq = platform_get_irq_byname(pdev, "SYSLO");
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
@@ -562,7 +572,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
irq, ret);
- goto err_usb;
+ goto err_battery;
}
irq = platform_get_irq_byname(pdev, "PWR SRC");
@@ -601,10 +611,11 @@ err_bat_irq:
err_syslo:
irq = platform_get_irq_byname(pdev, "SYSLO");
free_irq(irq, power);
+err_battery:
+ if (power->have_battery)
+ power_supply_unregister(battery);
err_usb:
power_supply_unregister(usb);
-err_battery:
- power_supply_unregister(battery);
err_wall:
power_supply_unregister(wall);
err_kmalloc:
@@ -628,7 +639,8 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, "SYSLO");
free_irq(irq, wm831x_power);
- power_supply_unregister(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_unregister(&wm831x_power->battery);
power_supply_unregister(&wm831x_power->wall);
power_supply_unregister(&wm831x_power->usb);
kfree(wm831x_power);
@@ -643,17 +655,7 @@ static struct platform_driver wm831x_power_driver = {
},
};
-static int __init wm831x_power_init(void)
-{
- return platform_driver_register(&wm831x_power_driver);
-}
-module_init(wm831x_power_init);
-
-static void __exit wm831x_power_exit(void)
-{
- platform_driver_unregister(&wm831x_power_driver);
-}
-module_exit(wm831x_power_exit);
+module_platform_driver(wm831x_power_driver);
MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index 0693902..fae04d3 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -522,17 +522,7 @@ static struct platform_driver wm8350_power_driver = {
},
};
-static int __init wm8350_power_init(void)
-{
- return platform_driver_register(&wm8350_power_driver);
-}
-module_init(wm8350_power_init);
-
-static void __exit wm8350_power_exit(void)
-{
- platform_driver_unregister(&wm8350_power_driver);
-}
-module_exit(wm8350_power_exit);
+module_platform_driver(wm8350_power_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Power supply driver for WM8350");
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index 156559e..d2d4c08 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -25,9 +25,8 @@
#include <linux/irq.h>
#include <linux/slab.h>
-static DEFINE_MUTEX(bat_lock);
static struct work_struct bat_work;
-static struct mutex work_lock;
+static DEFINE_MUTEX(work_lock);
static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
static enum power_supply_property *prop;
@@ -181,8 +180,6 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
if (dev->id != -1)
return -EINVAL;
- mutex_init(&work_lock);
-
if (!pdata) {
dev_err(&dev->dev, "No platform_data supplied\n");
return -EINVAL;
@@ -196,7 +193,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
if (ret)
goto err2;
ret = request_irq(gpio_to_irq(pdata->charge_gpio),
- wm97xx_chrg_irq, IRQF_DISABLED,
+ wm97xx_chrg_irq, 0,
"AC Detect", dev);
if (ret)
goto err2;
@@ -291,18 +288,7 @@ static struct platform_driver wm97xx_bat_driver = {
.remove = __devexit_p(wm97xx_bat_remove),
};
-static int __init wm97xx_bat_init(void)
-{
- return platform_driver_register(&wm97xx_bat_driver);
-}
-
-static void __exit wm97xx_bat_exit(void)
-{
- platform_driver_unregister(&wm97xx_bat_driver);
-}
-
-module_init(wm97xx_bat_init);
-module_exit(wm97xx_bat_exit);
+module_platform_driver(wm97xx_bat_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index d119c38..636ebb2 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -218,7 +218,7 @@ static int __devinit z2_batt_probe(struct i2c_client *client,
irq_set_irq_type(gpio_to_irq(info->charge_gpio),
IRQ_TYPE_EDGE_BOTH);
ret = request_irq(gpio_to_irq(info->charge_gpio),
- z2_charge_switch_irq, IRQF_DISABLED,
+ z2_charge_switch_irq, 0,
"AC Detect", charger);
if (ret)
goto err3;
@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
.pm = Z2_BATTERY_PM_OPS
},
.probe = z2_batt_probe,
- .remove = z2_batt_remove,
+ .remove = __devexit_p(z2_batt_remove),
.id_table = z2_batt_id,
};
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index e91b8dd..c9b92531 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 877cf6f..e19a403 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -498,9 +498,9 @@ config RTC_DRV_CMOS
will be called rtc-cmos.
config RTC_DRV_VRTC
- tristate "Virtual RTC for Moorestown platforms"
- depends on X86_MRST
- default y if X86_MRST
+ tristate "Virtual RTC for Intel MID platforms"
+ depends on X86_INTEL_MID
+ default y if X86_INTEL_MID
help
Say "yes" here to get direct support for the real time clock
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 8e28625..8a1c031 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -228,11 +228,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = now.tm_hour;
/* For simplicity, only support date rollover for now */
- if (alarm->time.tm_mday == -1) {
+ if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
alarm->time.tm_mday = now.tm_mday;
missing = day;
}
- if (alarm->time.tm_mon == -1) {
+ if ((unsigned)alarm->time.tm_mon >= 12) {
alarm->time.tm_mon = now.tm_mon;
if (missing == none)
missing = month;
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index 64b847b..f04761e 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -410,17 +410,7 @@ static struct platform_driver pm860x_rtc_driver = {
.remove = __devexit_p(pm860x_rtc_remove),
};
-static int __init pm860x_rtc_init(void)
-{
- return platform_driver_register(&pm860x_rtc_driver);
-}
-module_init(pm860x_rtc_init);
-
-static void __exit pm860x_rtc_exit(void)
-{
- platform_driver_unregister(&pm860x_rtc_driver);
-}
-module_exit(pm860x_rtc_exit);
+module_platform_driver(pm860x_rtc_driver);
MODULE_DESCRIPTION("Marvell 88PM860x RTC driver");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index e346705..4bcf9ca 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -15,7 +15,7 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
#include <linux/delay.h>
#define AB8500_RTC_SOFF_STAT_REG 0x00
@@ -90,7 +90,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* Early AB8500 chips will not clear the rtc read request bit */
if (abx500_get_chip_id(dev) == 0) {
- msleep(1);
+ usleep_range(1000, 1000);
} else {
/* Wait for some cycles after enabling the rtc read in ab8500 */
while (time_before(jiffies, timeout)) {
@@ -102,7 +102,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (!(value & RTC_READ_REQUEST))
break;
- msleep(1);
+ usleep_range(1000, 5000);
}
}
@@ -258,6 +258,109 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return ab8500_rtc_irq_enable(dev, alarm->enabled);
}
+
+static int ab8500_rtc_set_calibration(struct device *dev, int calibration)
+{
+ int retval;
+ u8 rtccal = 0;
+
+ /*
+ * Check that the calibration value (which is in units of 0.5
+ * parts-per-million) is in the AB8500's range for RtcCalibration
+ * register. -128 (0x80) is not permitted because the AB8500 uses
+ * a sign-bit rather than two's complement, so 0x80 is just another
+ * representation of zero.
+ */
+ if ((calibration < -127) || (calibration > 127)) {
+ dev_err(dev, "RtcCalibration value outside permitted range\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
+ * so need to convert to this sort of representation before writing
+ * into RtcCalibration register...
+ */
+ if (calibration >= 0)
+ rtccal = 0x7F & calibration;
+ else
+ rtccal = ~(calibration - 1) | 0x80;
+
+ retval = abx500_set_register_interruptible(dev, AB8500_RTC,
+ AB8500_RTC_CALIB_REG, rtccal);
+
+ return retval;
+}
+
+static int ab8500_rtc_get_calibration(struct device *dev, int *calibration)
+{
+ int retval;
+ u8 rtccal = 0;
+
+ retval = abx500_get_register_interruptible(dev, AB8500_RTC,
+ AB8500_RTC_CALIB_REG, &rtccal);
+ if (retval >= 0) {
+ /*
+ * The AB8500 uses sign (in bit7) and magnitude (in bits0-7)
+ * so need to convert value from RtcCalibration register into
+ * a two's complement signed value...
+ */
+ if (rtccal & 0x80)
+ *calibration = 0 - (rtccal & 0x7F);
+ else
+ *calibration = 0x7F & rtccal;
+ }
+
+ return retval;
+}
+
+static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int retval;
+ int calibration = 0;
+
+ if (sscanf(buf, " %i ", &calibration) != 1) {
+ dev_err(dev, "Failed to store RTC calibration attribute\n");
+ return -EINVAL;
+ }
+
+ retval = ab8500_rtc_set_calibration(dev, calibration);
+
+ return retval ? retval : count;
+}
+
+static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int retval = 0;
+ int calibration = 0;
+
+ retval = ab8500_rtc_get_calibration(dev, &calibration);
+ if (retval < 0) {
+ dev_err(dev, "Failed to read RTC calibration attribute\n");
+ sprintf(buf, "0\n");
+ return retval;
+ }
+
+ return sprintf(buf, "%d\n", calibration);
+}
+
+static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR,
+ ab8500_sysfs_show_rtc_calibration,
+ ab8500_sysfs_store_rtc_calibration);
+
+static int ab8500_sysfs_rtc_register(struct device *dev)
+{
+ return device_create_file(dev, &dev_attr_rtc_calibration);
+}
+
+static void ab8500_sysfs_rtc_unregister(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_rtc_calibration);
+}
+
static irqreturn_t rtc_alarm_handler(int irq, void *data)
{
struct rtc_device *rtc = data;
@@ -295,7 +398,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
return err;
/* Wait for reset by the PorRtc */
- msleep(1);
+ usleep_range(1000, 5000);
err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC,
AB8500_RTC_STAT_REG, &rtc_ctrl);
@@ -308,6 +411,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
return -ENODEV;
}
+ device_init_wakeup(&pdev->dev, true);
+
rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops,
THIS_MODULE);
if (IS_ERR(rtc)) {
@@ -316,8 +421,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
return err;
}
- err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0,
- "ab8500-rtc", rtc);
+ err = request_threaded_irq(irq, NULL, rtc_alarm_handler,
+ IRQF_NO_SUSPEND, "ab8500-rtc", rtc);
if (err < 0) {
rtc_device_unregister(rtc);
return err;
@@ -325,6 +430,13 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
+
+ err = ab8500_sysfs_rtc_register(&pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "sysfs RTC failed to register\n");
+ return err;
+ }
+
return 0;
}
@@ -333,6 +445,8 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev)
struct rtc_device *rtc = platform_get_drvdata(pdev);
int irq = platform_get_irq_byname(pdev, "ALARM");
+ ab8500_sysfs_rtc_unregister(&pdev->dev);
+
free_irq(irq, rtc);
rtc_device_unregister(rtc);
platform_set_drvdata(pdev, NULL);
@@ -349,18 +463,8 @@ static struct platform_driver ab8500_rtc_driver = {
.remove = __devexit_p(ab8500_rtc_remove),
};
-static int __init ab8500_rtc_init(void)
-{
- return platform_driver_register(&ab8500_rtc_driver);
-}
-
-static void __exit ab8500_rtc_exit(void)
-{
- platform_driver_unregister(&ab8500_rtc_driver);
-}
+module_platform_driver(ab8500_rtc_driver);
-module_init(ab8500_rtc_init);
-module_exit(ab8500_rtc_exit);
MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>");
MODULE_DESCRIPTION("AB8500 RTC Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index 90d8662..abfc1a0 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -456,18 +456,7 @@ static struct platform_driver bfin_rtc_driver = {
.resume = bfin_rtc_resume,
};
-static int __init bfin_rtc_init(void)
-{
- return platform_driver_register(&bfin_rtc_driver);
-}
-
-static void __exit bfin_rtc_exit(void)
-{
- platform_driver_unregister(&bfin_rtc_driver);
-}
-
-module_init(bfin_rtc_init);
-module_exit(bfin_rtc_exit);
+module_platform_driver(bfin_rtc_driver);
MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver");
MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index 128270c..bf612ef 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -218,15 +218,4 @@ static struct platform_driver bq4802_driver = {
.remove = __devexit_p(bq4802_remove),
};
-static int __init bq4802_init(void)
-{
- return platform_driver_register(&bq4802_driver);
-}
-
-static void __exit bq4802_exit(void)
-{
- platform_driver_unregister(&bq4802_driver);
-}
-
-module_init(bq4802_init);
-module_exit(bq4802_exit);
+module_platform_driver(bq4802_driver);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 05beb6c..d7782aa 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -164,7 +164,7 @@ static inline unsigned char cmos_read_bank2(unsigned char addr)
static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
{
outb(addr, RTC_PORT(2));
- outb(val, RTC_PORT(2));
+ outb(val, RTC_PORT(3));
}
#else
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c
index 2322c43..d4457af 100644
--- a/drivers/rtc/rtc-dm355evm.c
+++ b/drivers/rtc/rtc-dm355evm.c
@@ -161,16 +161,6 @@ static struct platform_driver rtc_dm355evm_driver = {
},
};
-static int __init dm355evm_rtc_init(void)
-{
- return platform_driver_register(&rtc_dm355evm_driver);
-}
-module_init(dm355evm_rtc_init);
-
-static void __exit dm355evm_rtc_exit(void)
-{
- platform_driver_unregister(&rtc_dm355evm_driver);
-}
-module_exit(dm355evm_rtc_exit);
+module_platform_driver(rtc_dm355evm_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index 68e6caf..990c3ff 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -396,21 +396,10 @@ static struct platform_driver ds1286_platform_driver = {
.remove = __devexit_p(ds1286_remove),
};
-static int __init ds1286_init(void)
-{
- return platform_driver_register(&ds1286_platform_driver);
-}
-
-static void __exit ds1286_exit(void)
-{
- platform_driver_unregister(&ds1286_platform_driver);
-}
+module_platform_driver(ds1286_platform_driver);
MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
MODULE_DESCRIPTION("DS1286 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:rtc-ds1286");
-
-module_init(ds1286_init);
-module_exit(ds1286_exit);
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 586c244..761f36b 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -580,20 +580,7 @@ static struct platform_driver ds1511_rtc_driver = {
},
};
- static int __init
-ds1511_rtc_init(void)
-{
- return platform_driver_register(&ds1511_rtc_driver);
-}
-
- static void __exit
-ds1511_rtc_exit(void)
-{
- platform_driver_unregister(&ds1511_rtc_driver);
-}
-
-module_init(ds1511_rtc_init);
-module_exit(ds1511_rtc_exit);
+module_platform_driver(ds1511_rtc_driver);
MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>");
MODULE_DESCRIPTION("Dallas DS1511 RTC driver");
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 1350029..6f0a1b5 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -361,18 +361,7 @@ static struct platform_driver ds1553_rtc_driver = {
},
};
-static __init int ds1553_init(void)
-{
- return platform_driver_register(&ds1553_rtc_driver);
-}
-
-static __exit void ds1553_exit(void)
-{
- platform_driver_unregister(&ds1553_rtc_driver);
-}
-
-module_init(ds1553_init);
-module_exit(ds1553_exit);
+module_platform_driver(ds1553_rtc_driver);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index e3e0f92..7611266 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -240,18 +240,7 @@ static struct platform_driver ds1742_rtc_driver = {
},
};
-static __init int ds1742_init(void)
-{
- return platform_driver_register(&ds1742_rtc_driver);
-}
-
-static __exit void ds1742_exit(void)
-{
- platform_driver_unregister(&ds1742_rtc_driver);
-}
-
-module_init(ds1742_init);
-module_exit(ds1742_exit);
+module_platform_driver(ds1742_rtc_driver);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
index b647363..05ab227 100644
--- a/drivers/rtc/rtc-jz4740.c
+++ b/drivers/rtc/rtc-jz4740.c
@@ -345,7 +345,7 @@ static const struct dev_pm_ops jz4740_pm_ops = {
#define JZ4740_RTC_PM_OPS NULL
#endif /* CONFIG_PM */
-struct platform_driver jz4740_rtc_driver = {
+static struct platform_driver jz4740_rtc_driver = {
.probe = jz4740_rtc_probe,
.remove = __devexit_p(jz4740_rtc_remove),
.driver = {
@@ -355,17 +355,7 @@ struct platform_driver jz4740_rtc_driver = {
},
};
-static int __init jz4740_rtc_init(void)
-{
- return platform_driver_register(&jz4740_rtc_driver);
-}
-module_init(jz4740_rtc_init);
-
-static void __exit jz4740_rtc_exit(void)
-{
- platform_driver_unregister(&jz4740_rtc_driver);
-}
-module_exit(jz4740_rtc_exit);
+module_platform_driver(jz4740_rtc_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index ae16250..ecc1713 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -396,17 +396,7 @@ static struct platform_driver lpc32xx_rtc_driver = {
},
};
-static int __init lpc32xx_rtc_init(void)
-{
- return platform_driver_register(&lpc32xx_rtc_driver);
-}
-module_init(lpc32xx_rtc_init);
-
-static void __exit lpc32xx_rtc_exit(void)
-{
- platform_driver_unregister(&lpc32xx_rtc_driver);
-}
-module_exit(lpc32xx_rtc_exit);
+module_platform_driver(lpc32xx_rtc_driver);
MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com");
MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC");
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c
index 7317d3b..ef71132 100644
--- a/drivers/rtc/rtc-m41t93.c
+++ b/drivers/rtc/rtc-m41t93.c
@@ -200,7 +200,6 @@ static int __devexit m41t93_remove(struct spi_device *spi)
static struct spi_driver m41t93_driver = {
.driver = {
.name = "rtc-m41t93",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = m41t93_probe,
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index e259ed7..2a4721f 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -147,7 +147,6 @@ static int __devexit m41t94_remove(struct spi_device *spi)
static struct spi_driver m41t94_driver = {
.driver = {
.name = "rtc-m41t94",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = m41t94_probe,
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 8e2a24e..f9e3b358 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -216,21 +216,10 @@ static struct platform_driver m48t35_platform_driver = {
.remove = __devexit_p(m48t35_remove),
};
-static int __init m48t35_init(void)
-{
- return platform_driver_register(&m48t35_platform_driver);
-}
-
-static void __exit m48t35_exit(void)
-{
- platform_driver_unregister(&m48t35_platform_driver);
-}
+module_platform_driver(m48t35_platform_driver);
MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
MODULE_DESCRIPTION("M48T35 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:rtc-m48t35");
-
-module_init(m48t35_init);
-module_exit(m48t35_exit);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 2836538..30ebfec 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -530,18 +530,7 @@ static struct platform_driver m48t59_rtc_driver = {
.remove = __devexit_p(m48t59_rtc_remove),
};
-static int __init m48t59_rtc_init(void)
-{
- return platform_driver_register(&m48t59_rtc_driver);
-}
-
-static void __exit m48t59_rtc_exit(void)
-{
- platform_driver_unregister(&m48t59_rtc_driver);
-}
-
-module_init(m48t59_rtc_init);
-module_exit(m48t59_rtc_exit);
+module_platform_driver(m48t59_rtc_driver);
MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index f981287..863fb33 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -185,21 +185,10 @@ static struct platform_driver m48t86_rtc_platform_driver = {
.remove = __devexit_p(m48t86_rtc_remove),
};
-static int __init m48t86_rtc_init(void)
-{
- return platform_driver_register(&m48t86_rtc_platform_driver);
-}
-
-static void __exit m48t86_rtc_exit(void)
-{
- platform_driver_unregister(&m48t86_rtc_platform_driver);
-}
+module_platform_driver(m48t86_rtc_platform_driver);
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("M48T86 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:rtc-m48t86");
-
-module_init(m48t86_rtc_init);
-module_exit(m48t86_rtc_exit);
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 0ec3f588..1f6b3cc 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -154,7 +154,6 @@ static int __devexit max6902_remove(struct spi_device *spi)
static struct spi_driver max6902_driver = {
.driver = {
.name = "rtc-max6902",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = max6902_probe,
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c
index 3bc046f..2d71943 100644
--- a/drivers/rtc/rtc-max8925.c
+++ b/drivers/rtc/rtc-max8925.c
@@ -261,6 +261,8 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
/* XXX - isn't this redundant? */
platform_set_drvdata(pdev, info);
+ device_init_wakeup(&pdev->dev, 1);
+
info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
&max8925_rtc_ops, THIS_MODULE);
ret = PTR_ERR(info->rtc_dev);
@@ -290,26 +292,40 @@ static int __devexit max8925_rtc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int max8925_rtc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+ if (device_may_wakeup(dev))
+ chip->wakeup_flag |= 1 << MAX8925_IRQ_RTC_ALARM0;
+ return 0;
+}
+static int max8925_rtc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+
+ if (device_may_wakeup(dev))
+ chip->wakeup_flag &= ~(1 << MAX8925_IRQ_RTC_ALARM0);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(max8925_rtc_pm_ops, max8925_rtc_suspend, max8925_rtc_resume);
+
static struct platform_driver max8925_rtc_driver = {
.driver = {
.name = "max8925-rtc",
.owner = THIS_MODULE,
+ .pm = &max8925_rtc_pm_ops,
},
.probe = max8925_rtc_probe,
.remove = __devexit_p(max8925_rtc_remove),
};
-static int __init max8925_rtc_init(void)
-{
- return platform_driver_register(&max8925_rtc_driver);
-}
-module_init(max8925_rtc_init);
-
-static void __exit max8925_rtc_exit(void)
-{
- platform_driver_unregister(&max8925_rtc_driver);
-}
-module_exit(max8925_rtc_exit);
+module_platform_driver(max8925_rtc_driver);
MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index 2e48aa6..7196f43 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -327,17 +327,7 @@ static struct platform_driver max8998_rtc_driver = {
.id_table = max8998_rtc_id,
};
-static int __init max8998_rtc_init(void)
-{
- return platform_driver_register(&max8998_rtc_driver);
-}
-module_init(max8998_rtc_init);
-
-static void __exit max8998_rtc_exit(void)
-{
- platform_driver_unregister(&max8998_rtc_driver);
-}
-module_exit(max8998_rtc_exit);
+module_platform_driver(max8998_rtc_driver);
MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 9d0c3b4..546f685 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -399,7 +399,7 @@ static int __exit mc13xxx_rtc_remove(struct platform_device *pdev)
return 0;
}
-const struct platform_device_id mc13xxx_rtc_idtable[] = {
+static const struct platform_device_id mc13xxx_rtc_idtable[] = {
{
.name = "mc13783-rtc",
}, {
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index da60915..9d3cacc 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -418,17 +418,7 @@ static struct platform_driver mpc5121_rtc_driver = {
.remove = __devexit_p(mpc5121_rtc_remove),
};
-static int __init mpc5121_rtc_init(void)
-{
- return platform_driver_register(&mpc5121_rtc_driver);
-}
-module_init(mpc5121_rtc_init);
-
-static void __exit mpc5121_rtc_exit(void)
-{
- platform_driver_unregister(&mpc5121_rtc_driver);
-}
-module_exit(mpc5121_rtc_exit);
+module_platform_driver(mpc5121_rtc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>");
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index bb21f44..6cd6c72 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -537,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = {
}
};
-static int __init vrtc_mrst_init(void)
-{
- return platform_driver_register(&vrtc_mrst_platform_driver);
-}
-
-static void __exit vrtc_mrst_exit(void)
-{
- platform_driver_unregister(&vrtc_mrst_platform_driver);
-}
-
-module_init(vrtc_mrst_init);
-module_exit(vrtc_mrst_exit);
+module_platform_driver(vrtc_mrst_platform_driver);
MODULE_AUTHOR("Jacob Pan; Feng Tang");
MODULE_DESCRIPTION("Driver for Moorestown virtual RTC");
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 39e41fb..5e1d64e 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -155,7 +155,6 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
{
struct rtc_time alarm_tm, now_tm;
unsigned long now, time;
- int ret;
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr;
@@ -168,21 +167,33 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
alarm_tm.tm_hour = alrm->tm_hour;
alarm_tm.tm_min = alrm->tm_min;
alarm_tm.tm_sec = alrm->tm_sec;
- rtc_tm_to_time(&now_tm, &now);
rtc_tm_to_time(&alarm_tm, &time);
- if (time < now) {
- time += 60 * 60 * 24;
- rtc_time_to_tm(time, &alarm_tm);
- }
-
- ret = rtc_tm_to_time(&alarm_tm, &time);
-
/* clear all the interrupt status bits */
writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR);
set_alarm_or_time(dev, MXC_RTC_ALARM, time);
- return ret;
+ return 0;
+}
+
+static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
+ unsigned int enabled)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ u32 reg;
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ reg = readw(ioaddr + RTC_RTCIENR);
+
+ if (enabled)
+ reg |= bit;
+ else
+ reg &= ~bit;
+
+ writew(reg, ioaddr + RTC_RTCIENR);
+ spin_unlock_irq(&pdata->rtc->irq_lock);
}
/* This function is the RTC interrupt service routine. */
@@ -199,13 +210,12 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
/* clear interrupt sources */
writew(status, ioaddr + RTC_RTCISR);
- /* clear alarm interrupt if it has occurred */
- if (status & RTC_ALM_BIT)
- status &= ~RTC_ALM_BIT;
-
/* update irq data & counter */
- if (status & RTC_ALM_BIT)
+ if (status & RTC_ALM_BIT) {
events |= (RTC_AF | RTC_IRQF);
+ /* RTC alarm should be one-shot */
+ mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0);
+ }
if (status & RTC_1HZ_BIT)
events |= (RTC_UF | RTC_IRQF);
@@ -213,9 +223,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
if (status & PIT_ALL_ON)
events |= (RTC_PF | RTC_IRQF);
- if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm))
- rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm);
-
rtc_update_irq(pdata->rtc, 1, events);
spin_unlock_irq(&pdata->rtc->irq_lock);
@@ -242,26 +249,6 @@ static void mxc_rtc_release(struct device *dev)
spin_unlock_irq(&pdata->rtc->irq_lock);
}
-static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
- unsigned int enabled)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- void __iomem *ioaddr = pdata->ioaddr;
- u32 reg;
-
- spin_lock_irq(&pdata->rtc->irq_lock);
- reg = readw(ioaddr + RTC_RTCIENR);
-
- if (enabled)
- reg |= bit;
- else
- reg &= ~bit;
-
- writew(reg, ioaddr + RTC_RTCIENR);
- spin_unlock_irq(&pdata->rtc->irq_lock);
-}
-
static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled);
@@ -290,6 +277,17 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
static int mxc_rtc_set_mmss(struct device *dev, unsigned long time)
{
+ /*
+ * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
+ */
+ if (cpu_is_mx1()) {
+ struct rtc_time tm;
+
+ rtc_time_to_tm(time, &tm);
+ tm.tm_year = 70;
+ rtc_tm_to_time(&tm, &time);
+ }
+
/* Avoid roll-over from reading the different registers */
do {
set_alarm_or_time(dev, MXC_RTC_TIME, time);
@@ -324,21 +322,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
int ret;
- if (rtc_valid_tm(&alrm->time)) {
- if (alrm->time.tm_sec > 59 ||
- alrm->time.tm_hour > 23 ||
- alrm->time.tm_min > 59)
- return -EINVAL;
-
- ret = rtc_update_alarm(dev, &alrm->time);
- } else {
- ret = rtc_valid_tm(&alrm->time);
- if (ret)
- return ret;
-
- ret = rtc_update_alarm(dev, &alrm->time);
- }
-
+ ret = rtc_update_alarm(dev, &alrm->time);
if (ret)
return ret;
@@ -424,6 +408,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
pdata->irq = -1;
}
+ if (pdata->irq >=0)
+ device_init_wakeup(&pdev->dev, 1);
+
rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
THIS_MODULE);
if (IS_ERR(rtc)) {
@@ -459,9 +446,39 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int mxc_rtc_suspend(struct device *dev)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(pdata->irq);
+
+ return 0;
+}
+
+static int mxc_rtc_resume(struct device *dev)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(pdata->irq);
+
+ return 0;
+}
+
+static struct dev_pm_ops mxc_rtc_pm_ops = {
+ .suspend = mxc_rtc_suspend,
+ .resume = mxc_rtc_resume,
+};
+#endif
+
static struct platform_driver mxc_rtc_driver = {
.driver = {
.name = "mxc_rtc",
+#ifdef CONFIG_PM
+ .pm = &mxc_rtc_pm_ops,
+#endif
.owner = THIS_MODULE,
},
.remove = __exit_p(mxc_rtc_remove),
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 2ee3bbf..b46c400 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -340,7 +340,6 @@ static int __devexit pcf2123_remove(struct spi_device *spi)
static struct spi_driver pcf2123_driver = {
.driver = {
.name = "rtc-pcf2123",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = pcf2123_probe,
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 0c42389..a20202f 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -294,17 +294,7 @@ static struct platform_driver pcf50633_rtc_driver = {
.remove = __devexit_p(pcf50633_rtc_remove),
};
-static int __init pcf50633_rtc_init(void)
-{
- return platform_driver_register(&pcf50633_rtc_driver);
-}
-module_init(pcf50633_rtc_init);
-
-static void __exit pcf50633_rtc_exit(void)
-{
- platform_driver_unregister(&pcf50633_rtc_driver);
-}
-module_exit(pcf50633_rtc_exit);
+module_platform_driver(pcf50633_rtc_driver);
MODULE_DESCRIPTION("PCF50633 RTC driver");
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index d420e9d..9f1d6bc 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -532,17 +532,7 @@ static struct platform_driver pm8xxx_rtc_driver = {
},
};
-static int __init pm8xxx_rtc_init(void)
-{
- return platform_driver_register(&pm8xxx_rtc_driver);
-}
-module_init(pm8xxx_rtc_init);
-
-static void __exit pm8xxx_rtc_exit(void)
-{
- platform_driver_unregister(&pm8xxx_rtc_driver);
-}
-module_exit(pm8xxx_rtc_exit);
+module_platform_driver(pm8xxx_rtc_driver);
MODULE_ALIAS("platform:rtc-pm8xxx");
MODULE_DESCRIPTION("PMIC8xxx RTC driver");
diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c
index e4b6880..ab0acae 100644
--- a/drivers/rtc/rtc-puv3.c
+++ b/drivers/rtc/rtc-puv3.c
@@ -164,7 +164,7 @@ static int puv3_rtc_open(struct device *dev)
int ret;
ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
- IRQF_DISABLED, "pkunity-rtc alarm", rtc_dev);
+ 0, "pkunity-rtc alarm", rtc_dev);
if (ret) {
dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
@@ -172,7 +172,7 @@ static int puv3_rtc_open(struct device *dev)
}
ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
- IRQF_DISABLED, "pkunity-rtc tick", rtc_dev);
+ 0, "pkunity-rtc tick", rtc_dev);
if (ret) {
dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
@@ -326,7 +326,7 @@ static int puv3_rtc_resume(struct platform_device *pdev)
#define puv3_rtc_resume NULL
#endif
-static struct platform_driver puv3_rtcdrv = {
+static struct platform_driver puv3_rtc_driver = {
.probe = puv3_rtc_probe,
.remove = __devexit_p(puv3_rtc_remove),
.suspend = puv3_rtc_suspend,
@@ -337,21 +337,7 @@ static struct platform_driver puv3_rtcdrv = {
}
};
-static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
-
-static int __init puv3_rtc_init(void)
-{
- printk(banner);
- return platform_driver_register(&puv3_rtcdrv);
-}
-
-static void __exit puv3_rtc_exit(void)
-{
- platform_driver_unregister(&puv3_rtcdrv);
-}
-
-module_init(puv3_rtc_init);
-module_exit(puv3_rtc_exit);
+module_platform_driver(puv3_rtc_driver);
MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
MODULE_AUTHOR("Hu Dongliang");
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 971bc8e..ce2ca85 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -229,7 +229,6 @@ static int __devexit rs5c348_remove(struct spi_device *spi)
static struct spi_driver rs5c348_driver = {
.driver = {
.name = "rtc-rs5c348",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = rs5c348_probe,
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 175067a..aef40bd 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -673,21 +673,7 @@ static struct platform_driver s3c_rtc_driver = {
},
};
-static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
-
-static int __init s3c_rtc_init(void)
-{
- printk(banner);
- return platform_driver_register(&s3c_rtc_driver);
-}
-
-static void __exit s3c_rtc_exit(void)
-{
- platform_driver_unregister(&s3c_rtc_driver);
-}
-
-module_init(s3c_rtc_init);
-module_exit(s3c_rtc_exit);
+module_platform_driver(s3c_rtc_driver);
MODULE_DESCRIPTION("Samsung S3C RTC Driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index fc1ffe9..4595d3e 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -435,18 +435,7 @@ static struct platform_driver sa1100_rtc_driver = {
},
};
-static int __init sa1100_rtc_init(void)
-{
- return platform_driver_register(&sa1100_rtc_driver);
-}
-
-static void __exit sa1100_rtc_exit(void)
-{
- platform_driver_unregister(&sa1100_rtc_driver);
-}
-
-module_init(sa1100_rtc_init);
-module_exit(sa1100_rtc_exit);
+module_platform_driver(sa1100_rtc_driver);
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index 893bac2..19a28a6 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -516,17 +516,7 @@ static struct platform_driver spear_rtc_driver = {
},
};
-static int __init rtc_init(void)
-{
- return platform_driver_register(&spear_rtc_driver);
-}
-module_init(rtc_init);
-
-static void __exit rtc_exit(void)
-{
- platform_driver_unregister(&spear_rtc_driver);
-}
-module_exit(rtc_exit);
+module_platform_driver(spear_rtc_driver);
MODULE_ALIAS("platform:rtc-spear");
MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index ed3e9b5..7621116 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -370,18 +370,7 @@ static struct platform_driver stk17ta8_rtc_driver = {
},
};
-static __init int stk17ta8_init(void)
-{
- return platform_driver_register(&stk17ta8_rtc_driver);
-}
-
-static __exit void stk17ta8_exit(void)
-{
- platform_driver_unregister(&stk17ta8_rtc_driver);
-}
-
-module_init(stk17ta8_init);
-module_exit(stk17ta8_exit);
+module_platform_driver(stk17ta8_rtc_driver);
MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>");
MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver");
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 7315068..1028786 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -276,18 +276,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
},
};
-static int __init stmp3xxx_rtc_init(void)
-{
- return platform_driver_register(&stmp3xxx_rtcdrv);
-}
-
-static void __exit stmp3xxx_rtc_exit(void)
-{
- platform_driver_unregister(&stmp3xxx_rtcdrv);
-}
-
-module_init(stmp3xxx_rtc_init);
-module_exit(stmp3xxx_rtc_exit);
+module_platform_driver(stmp3xxx_rtcdrv);
MODULE_DESCRIPTION("STMP3xxx RTC Driver");
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 20687d5..d43b4f6 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -550,6 +550,11 @@ static int twl_rtc_resume(struct platform_device *pdev)
#define twl_rtc_resume NULL
#endif
+static const struct of_device_id twl_rtc_of_match[] = {
+ {.compatible = "ti,twl4030-rtc", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, twl_rtc_of_match);
MODULE_ALIAS("platform:twl_rtc");
static struct platform_driver twl4030rtc_driver = {
@@ -559,8 +564,9 @@ static struct platform_driver twl4030rtc_driver = {
.suspend = twl_rtc_suspend,
.resume = twl_rtc_resume,
.driver = {
- .owner = THIS_MODULE,
- .name = "twl_rtc",
+ .owner = THIS_MODULE,
+ .name = "twl_rtc",
+ .of_match_table = twl_rtc_of_match,
},
};
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index f71c3ce..bca5d67 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -393,18 +393,7 @@ static struct platform_driver rtc_device_driver = {
},
};
-static __init int v3020_init(void)
-{
- return platform_driver_register(&rtc_device_driver);
-}
-
-static __exit void v3020_exit(void)
-{
- platform_driver_unregister(&rtc_device_driver);
-}
-
-module_init(v3020_init);
-module_exit(v3020_exit);
+module_platform_driver(rtc_device_driver);
MODULE_DESCRIPTION("V3020 RTC");
MODULE_AUTHOR("Raphael Assenat");
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index c5698cd..fcbfdda 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -405,15 +405,4 @@ static struct platform_driver rtc_platform_driver = {
},
};
-static int __init vr41xx_rtc_init(void)
-{
- return platform_driver_register(&rtc_platform_driver);
-}
-
-static void __exit vr41xx_rtc_exit(void)
-{
- platform_driver_unregister(&rtc_platform_driver);
-}
-
-module_init(vr41xx_rtc_init);
-module_exit(vr41xx_rtc_exit);
+module_platform_driver(rtc_platform_driver);
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index f93f412..9e94fb1 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -311,17 +311,7 @@ static struct platform_driver vt8500_rtc_driver = {
},
};
-static int __init vt8500_rtc_init(void)
-{
- return platform_driver_register(&vt8500_rtc_driver);
-}
-module_init(vt8500_rtc_init);
-
-static void __exit vt8500_rtc_exit(void)
-{
- platform_driver_unregister(&vt8500_rtc_driver);
-}
-module_exit(vt8500_rtc_exit);
+module_platform_driver(vt8500_rtc_driver);
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)");
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index bdc909b..3b6e6a6 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -324,15 +324,6 @@ static irqreturn_t wm831x_alm_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static irqreturn_t wm831x_per_irq(int irq, void *data)
-{
- struct wm831x_rtc *wm831x_rtc = data;
-
- rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF);
-
- return IRQ_HANDLED;
-}
-
static const struct rtc_class_ops wm831x_rtc_ops = {
.read_time = wm831x_rtc_readtime,
.set_mmss = wm831x_rtc_set_mmss,
@@ -405,11 +396,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_rtc *wm831x_rtc;
- int per_irq = platform_get_irq_byname(pdev, "PER");
int alm_irq = platform_get_irq_byname(pdev, "ALM");
int ret = 0;
- wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL);
+ wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL);
if (wm831x_rtc == NULL)
return -ENOMEM;
@@ -433,14 +423,6 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
goto err;
}
- ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq,
- IRQF_TRIGGER_RISING, "RTC period",
- wm831x_rtc);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
- per_irq, ret);
- }
-
ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq,
IRQF_TRIGGER_RISING, "RTC alarm",
wm831x_rtc);
@@ -452,20 +434,16 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
return 0;
err:
- kfree(wm831x_rtc);
return ret;
}
static int __devexit wm831x_rtc_remove(struct platform_device *pdev)
{
struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev);
- int per_irq = platform_get_irq_byname(pdev, "PER");
int alm_irq = platform_get_irq_byname(pdev, "ALM");
free_irq(alm_irq, wm831x_rtc);
- free_irq(per_irq, wm831x_rtc);
rtc_device_unregister(wm831x_rtc->rtc);
- kfree(wm831x_rtc);
return 0;
}
@@ -490,17 +468,7 @@ static struct platform_driver wm831x_rtc_driver = {
},
};
-static int __init wm831x_rtc_init(void)
-{
- return platform_driver_register(&wm831x_rtc_driver);
-}
-module_init(wm831x_rtc_init);
-
-static void __exit wm831x_rtc_exit(void)
-{
- platform_driver_unregister(&wm831x_rtc_driver);
-}
-module_exit(wm831x_rtc_exit);
+module_platform_driver(wm831x_rtc_driver);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs");
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index 6642142..c2e52d1 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -486,17 +486,7 @@ static struct platform_driver wm8350_rtc_driver = {
},
};
-static int __init wm8350_rtc_init(void)
-{
- return platform_driver_register(&wm8350_rtc_driver);
-}
-module_init(wm8350_rtc_init);
-
-static void __exit wm8350_rtc_exit(void)
-{
- platform_driver_unregister(&wm8350_rtc_driver);
-}
-module_exit(wm8350_rtc_exit);
+module_platform_driver(wm8350_rtc_driver);
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_DESCRIPTION("RTC driver for the WM8350");
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index e5cb924..f3b8bb8 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -75,7 +75,7 @@ static LIST_HEAD(raw3270_devices);
static int raw3270_registered;
/* Module parameters */
-static int tubxcorrect = 0;
+static bool tubxcorrect = 0;
module_param(tubxcorrect, bool, 0);
/*
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 11312f4..2211277 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -28,9 +28,9 @@
#define MAX_CMDLEN 240
#define MIN_INTERVAL 15
static char vmwdt_cmd[MAX_CMDLEN] = "IPL";
-static int vmwdt_conceal;
+static bool vmwdt_conceal;
-static int vmwdt_nowayout = WATCHDOG_NOWAYOUT;
+static bool vmwdt_nowayout = WATCHDOG_NOWAYOUT;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 2985eb4..204ca72 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -98,7 +98,7 @@ enum cmb_format {
* enum cmb_format.
*/
static int format = CMF_AUTODETECT;
-module_param(format, bool, 0444);
+module_param(format, bint, 0444);
/**
* struct cmb_operations - functions to use depending on cmb_format
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 8af868b..7bc1955 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -198,7 +198,7 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
goto out;
vq = vring_new_virtqueue(config->num, KVM_S390_VIRTIO_RING_ALIGN,
- vdev, (void *) config->address,
+ vdev, true, (void *) config->address,
kvm_notify, callback, name);
if (!vq) {
err = -ENOMEM;
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 195823a..ed119ce 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -102,7 +102,7 @@ static int setup_dmaspeed[MAXBOARDS] __initdata = { -1, -1, -1, -1 };
*/
#if defined(MODULE)
-static int isapnp = 0;
+static bool isapnp = 0;
static int aha1542[] = {0x330, 11, 4, -1};
module_param_array(aha1542, int, NULL, 0);
module_param(isapnp, bool, 0);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index f5b718d..13aeca3 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -546,7 +546,7 @@ static struct ParameterData __devinitdata cfg_data[] = {
* command line overrides will be used. If set to 1 then safe and
* slow settings will be used.
*/
-static int use_safe_settings = 0;
+static bool use_safe_settings = 0;
module_param_named(safe, use_safe_settings, bool, 0);
MODULE_PARM_DESC(safe, "Use safe and slow settings only. Default: false");
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fd860d9..67b169b 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -7638,8 +7638,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
**/
static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
ENTER;
- pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+ if (ioa_cfg->cfg_locked)
+ pci_cfg_access_unlock(ioa_cfg->pdev);
+ ioa_cfg->cfg_locked = 0;
ipr_cmd->job_step = ipr_reset_restore_cfg_space;
LEAVE;
return IPR_RC_JOB_CONTINUE;
@@ -7660,8 +7664,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
int rc = PCIBIOS_SUCCESSFUL;
ENTER;
- pci_block_user_cfg_access(ioa_cfg->pdev);
-
if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO)
writel(IPR_UPROCI_SIS64_START_BIST,
ioa_cfg->regs.set_uproc_interrupt_reg32);
@@ -7673,7 +7675,9 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
rc = IPR_RC_JOB_RETURN;
} else {
- pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+ if (ioa_cfg->cfg_locked)
+ pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev);
+ ioa_cfg->cfg_locked = 0;
ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
rc = IPR_RC_JOB_CONTINUE;
}
@@ -7716,7 +7720,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
struct pci_dev *pdev = ioa_cfg->pdev;
ENTER;
- pci_block_user_cfg_access(pdev);
pci_set_pcie_reset_state(pdev, pcie_warm_reset);
ipr_cmd->job_step = ipr_reset_slot_reset_done;
ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
@@ -7725,6 +7728,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
}
/**
+ * ipr_reset_block_config_access_wait - Wait for permission to block config access
+ * @ipr_cmd: ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA.
+ *
+ * Return value:
+ * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ int rc = IPR_RC_JOB_CONTINUE;
+
+ if (pci_cfg_access_trylock(ioa_cfg->pdev)) {
+ ioa_cfg->cfg_locked = 1;
+ ipr_cmd->job_step = ioa_cfg->reset;
+ } else {
+ if (ipr_cmd->u.time_left) {
+ rc = IPR_RC_JOB_RETURN;
+ ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+ ipr_reset_start_timer(ipr_cmd,
+ IPR_CHECK_FOR_RESET_TIMEOUT);
+ } else {
+ ipr_cmd->job_step = ioa_cfg->reset;
+ dev_err(&ioa_cfg->pdev->dev,
+ "Timed out waiting to lock config access. Resetting anyway.\n");
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * ipr_reset_block_config_access - Block config access to the IOA
+ * @ipr_cmd: ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA
+ *
+ * Return value:
+ * IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd)
+{
+ ipr_cmd->ioa_cfg->cfg_locked = 0;
+ ipr_cmd->job_step = ipr_reset_block_config_access_wait;
+ ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
+ return IPR_RC_JOB_CONTINUE;
+}
+
+/**
* ipr_reset_allowed - Query whether or not IOA can be reset
* @ioa_cfg: ioa config struct
*
@@ -7763,7 +7816,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
} else {
- ipr_cmd->job_step = ioa_cfg->reset;
+ ipr_cmd->job_step = ipr_reset_block_config_access;
rc = IPR_RC_JOB_CONTINUE;
}
@@ -7796,7 +7849,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32);
ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
} else {
- ipr_cmd->job_step = ioa_cfg->reset;
+ ipr_cmd->job_step = ipr_reset_block_config_access;
}
ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index ac84736..b13f9cc 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1387,6 +1387,7 @@ struct ipr_ioa_cfg {
u8 msi_received:1;
u8 sis64:1;
u8 dump_timeout:1;
+ u8 cfg_locked:1;
u8 revid;
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index f6a50c9..0029249 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -59,11 +59,11 @@ MODULE_PARM_DESC(trans_mode, "transfer mode (0: BIOS(default) 1: Async 2: Ultra2
#define ASYNC_MODE 1
#define ULTRA20M_MODE 2
-static int auto_param = 0; /* default: ON */
+static bool auto_param = 0; /* default: ON */
module_param (auto_param, bool, 0);
MODULE_PARM_DESC(auto_param, "AutoParameter mode (0: ON(default) 1: OFF)");
-static int disc_priv = 1; /* default: OFF */
+static bool disc_priv = 1; /* default: OFF */
module_param (disc_priv, bool, 0);
MODULE_PARM_DESC(disc_priv, "disconnection privilege mode (0: ON 1: OFF(default))");
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index ca86721..b61a753 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -70,7 +70,7 @@ module_param(nsp_burst_mode, int, 0);
MODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))");
/* Release IO ports after configuration? */
-static int free_ports = 0;
+static bool free_ports = 0;
module_param(free_ports, bool, 0);
MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index 44f76e8..c77628a 100644
--- a/drivers/scsi/scsi_netlink.c
+++ b/drivers/scsi/scsi_netlink.c
@@ -112,7 +112,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
goto next_msg;
}
- if (security_netlink_recv(skb, CAP_SYS_ADMIN)) {
+ if (!capable(CAP_SYS_ADMIN)) {
err = -EPERM;
goto next_msg;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b3c6d95..89da43f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
kfree(sdev);
goto out;
}
- blk_get_queue(sdev->request_queue);
+ WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
sdev->request_queue->queuedata = sdev;
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7b3f807..c691fb5 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1075,6 +1075,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
"cmd=0x%x\n", disk->disk_name, cmd));
+ error = scsi_verify_blk_ioctl(bdev, cmd);
+ if (error < 0)
+ return error;
+
/*
* If we are in the middle of error recovery, don't let anyone
* else try and use this device. Also, if error recovery fails, it
@@ -1097,7 +1101,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
error = scsi_ioctl(sdp, cmd, p);
break;
default:
- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
+ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
if (error != -ENOTTY)
break;
error = scsi_ioctl(sdp, cmd, p);
@@ -1267,6 +1271,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
+ int ret;
+
+ ret = scsi_verify_blk_ioctl(bdev, cmd);
+ if (ret < 0)
+ return ret;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -1278,8 +1287,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
return -ENODEV;
if (sdev->host->hostt->compat_ioctl) {
- int ret;
-
ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
return ret;
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index 67e272a..7139ad2 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -7,11 +7,4 @@ obj-$(CONFIG_HAVE_CLK) += clk/
obj-$(CONFIG_MAPLE) += maple/
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_GENERIC_GPIO) += pfc.o
-
-#
-# For the moment we only use this framework for ARM-based SH/R-Mobile
-# platforms and generic SH. SH-based SH-Mobile platforms are still using
-# an older framework that is pending up-porting, at which point this
-# special casing can go away.
-#
-obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o
+obj-y += pm_runtime.o
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index db257a3..7715de2 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk)
*/
if (!clk->parent) {
clk->mapping = &dummy_mapping;
- return 0;
+ goto out;
}
/*
@@ -384,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk)
}
clk->mapping = mapping;
+out:
+ clk->mapped_reg = clk->mapping->base;
+ clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys;
return 0;
}
@@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk)
/* Nothing to do */
if (mapping == &dummy_mapping)
- return;
+ goto out;
kref_put(&mapping->ref, clk_destroy_mapping);
clk->mapping = NULL;
+out:
+ clk->mapped_reg = NULL;
}
int clk_register(struct clk *clk)
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 82dd6fb..45fee36 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -15,15 +15,15 @@
static int sh_clk_mstp32_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
return 0;
}
static void sh_clk_mstp32_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
}
static struct clk_ops sh_clk_mstp32_clk_ops = {
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, NULL);
- idx = __raw_readl(clk->enable_reg) & 0x003f;
+ idx = ioread32(clk->mapped_reg) & 0x003f;
return clk->freq_table[idx].frequency;
}
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
if (ret < 0)
return ret;
- value = __raw_readl(clk->enable_reg) &
+ value = ioread32(clk->mapped_reg) &
~(((1 << clk->src_width) - 1) << clk->src_shift);
- __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+ iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
/* Rebuild the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x3f;
value |= idx;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
return 0;
}
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk)
ret = sh_clk_div6_set_rate(clk, clk->rate);
if (ret == 0) {
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x100; /* clear stop bit to enable clock */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
return ret;
}
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk)
{
unsigned long value;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value |= 0x100; /* stop clock */
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
static struct clk_ops sh_clk_div6_clk_ops = {
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = {
.set_parent = sh_clk_div6_set_parent,
};
+static int __init sh_clk_init_parent(struct clk *clk)
+{
+ u32 val;
+
+ if (clk->parent)
+ return 0;
+
+ if (!clk->parent_table || !clk->parent_num)
+ return 0;
+
+ if (!clk->src_width) {
+ pr_err("sh_clk_init_parent: cannot select parent clock\n");
+ return -EINVAL;
+ }
+
+ val = (ioread32(clk->mapped_reg) >> clk->src_shift);
+ val &= (1 << clk->src_width) - 1;
+
+ if (val >= clk->parent_num) {
+ pr_err("sh_clk_init_parent: parent table size failed\n");
+ return -EINVAL;
+ }
+
+ clk->parent = clk->parent_table[val];
+ if (!clk->parent) {
+ pr_err("sh_clk_init_parent: unable to set parent");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
struct clk_ops *ops)
{
@@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
clkp->ops = ops;
clkp->freq_table = freq_table + (k * freq_table_size);
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
ret = clk_register(clkp);
+ if (ret < 0)
+ break;
+
+ ret = sh_clk_init_parent(clkp);
}
return ret;
@@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, &clk->arch_flags);
- idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+ idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
return clk->freq_table[idx].frequency;
}
@@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
*/
if (parent->flags & CLK_ENABLE_ON_INIT)
- value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+ value = ioread32(clk->mapped_reg) & ~(1 << 7);
else
- value = __raw_readl(clk->enable_reg) | (1 << 7);
+ value = ioread32(clk->mapped_reg) | (1 << 7);
ret = clk_reparent(clk, parent);
if (ret < 0)
return ret;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
/* Rebiuld the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -260,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~(0xf << clk->enable_bit);
value |= (idx << clk->enable_bit);
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
if (d4t->kick)
d4t->kick(clk);
@@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
static int sh_clk_div4_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
return 0;
}
static void sh_clk_div4_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
}
static struct clk_ops sh_clk_div4_clk_ops = {
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index e67fe17..522c6c4 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -19,6 +19,75 @@
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+static void pfc_iounmap(struct pinmux_info *pip)
+{
+ int k;
+
+ for (k = 0; k < pip->num_resources; k++)
+ if (pip->window[k].virt)
+ iounmap(pip->window[k].virt);
+
+ kfree(pip->window);
+ pip->window = NULL;
+}
+
+static int pfc_ioremap(struct pinmux_info *pip)
+{
+ struct resource *res;
+ int k;
+
+ if (!pip->num_resources)
+ return 0;
+
+ pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
+ GFP_NOWAIT);
+ if (!pip->window)
+ goto err1;
+
+ for (k = 0; k < pip->num_resources; k++) {
+ res = pip->resource + k;
+ WARN_ON(resource_type(res) != IORESOURCE_MEM);
+ pip->window[k].phys = res->start;
+ pip->window[k].size = resource_size(res);
+ pip->window[k].virt = ioremap_nocache(res->start,
+ resource_size(res));
+ if (!pip->window[k].virt)
+ goto err2;
+ }
+
+ return 0;
+
+err2:
+ pfc_iounmap(pip);
+err1:
+ return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
+ unsigned long address)
+{
+ struct pfc_window *window;
+ int k;
+
+ /* scan through physical windows and convert address */
+ for (k = 0; k < pip->num_resources; k++) {
+ window = pip->window + k;
+
+ if (address < window->phys)
+ continue;
+
+ if (address >= (window->phys + window->size))
+ continue;
+
+ return window->virt + (address - window->phys);
+ }
+
+ /* no windows defined, register must be 1:1 mapped virt:phys */
+ return (void __iomem *)address;
+}
static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
{
@@ -31,41 +100,54 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
return 1;
}
-static unsigned long gpio_read_raw_reg(unsigned long reg,
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width)
{
switch (reg_width) {
case 8:
- return __raw_readb(reg);
+ return ioread8(mapped_reg);
case 16:
- return __raw_readw(reg);
+ return ioread16(mapped_reg);
case 32:
- return __raw_readl(reg);
+ return ioread32(mapped_reg);
}
BUG();
return 0;
}
-static void gpio_write_raw_reg(unsigned long reg,
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width,
unsigned long data)
{
switch (reg_width) {
case 8:
- __raw_writeb(data, reg);
+ iowrite8(data, mapped_reg);
return;
case 16:
- __raw_writew(data, reg);
+ iowrite16(data, mapped_reg);
return;
case 32:
- __raw_writel(data, reg);
+ iowrite32(data, mapped_reg);
return;
}
BUG();
}
+static int gpio_read_bit(struct pinmux_data_reg *dr,
+ unsigned long in_pos)
+{
+ unsigned long pos;
+
+ pos = dr->reg_width - (in_pos + 1);
+
+ pr_debug("read_bit: addr = %lx, pos = %ld, "
+ "r_width = %ld\n", dr->reg, pos, dr->reg_width);
+
+ return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+}
+
static void gpio_write_bit(struct pinmux_data_reg *dr,
unsigned long in_pos, unsigned long value)
{
@@ -82,53 +164,72 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
else
clear_bit(pos, &dr->reg_shadow);
- gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+ gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
-static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos)
+static void config_reg_helper(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long in_pos,
+ void __iomem **mapped_regp,
+ unsigned long *maskp,
+ unsigned long *posp)
{
- unsigned long data, mask, pos;
+ int k;
+
+ *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
- data = 0;
- mask = (1 << field_width) - 1;
- pos = reg_width - ((in_pos + 1) * field_width);
+ if (crp->field_width) {
+ *maskp = (1 << crp->field_width) - 1;
+ *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
+ } else {
+ *maskp = (1 << crp->var_field_width[in_pos]) - 1;
+ *posp = crp->reg_width;
+ for (k = 0; k <= in_pos; k++)
+ *posp -= crp->var_field_width[k];
+ }
+}
- pr_debug("read_reg: addr = %lx, pos = %ld, "
+static int read_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field)
+{
+ void __iomem *mapped_reg;
+ unsigned long mask, pos;
+
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
+
+ pr_debug("read_reg: addr = %lx, field = %ld, "
"r_width = %ld, f_width = %ld\n",
- reg, pos, reg_width, field_width);
+ crp->reg, field, crp->reg_width, crp->field_width);
- data = gpio_read_raw_reg(reg, reg_width);
- return (data >> pos) & mask;
+ return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
}
-static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos,
- unsigned long value)
+static void write_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field, unsigned long value)
{
- unsigned long mask, pos;
+ void __iomem *mapped_reg;
+ unsigned long mask, pos, data;
- mask = (1 << field_width) - 1;
- pos = reg_width - ((in_pos + 1) * field_width);
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
- pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, "
+ pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld\n",
- reg, value, pos, reg_width, field_width);
+ crp->reg, value, field, crp->reg_width, crp->field_width);
mask = ~(mask << pos);
value = value << pos;
- switch (reg_width) {
- case 8:
- __raw_writeb((__raw_readb(reg) & mask) | value, reg);
- break;
- case 16:
- __raw_writew((__raw_readw(reg) & mask) | value, reg);
- break;
- case 32:
- __raw_writel((__raw_readl(reg) & mask) | value, reg);
- break;
- }
+ data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
+ data &= mask;
+ data |= value;
+
+ if (gpioc->unlock_reg)
+ gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
+ 32, ~data);
+
+ gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
}
static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
@@ -147,6 +248,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
if (!data_reg->reg_width)
break;
+ data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] == gpiop->enum_id) {
gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +282,8 @@ static void setup_data_regs(struct pinmux_info *gpioc)
if (!drp->reg_width)
break;
- drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+ drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
k++;
}
}
@@ -201,12 +305,13 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
}
static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
- struct pinmux_cfg_reg **crp, int *indexp,
+ struct pinmux_cfg_reg **crp,
+ int *fieldp, int *valuep,
unsigned long **cntp)
{
struct pinmux_cfg_reg *config_reg;
- unsigned long r_width, f_width;
- int k, n;
+ unsigned long r_width, f_width, curr_width, ncomb;
+ int k, m, n, pos, bit_pos;
k = 0;
while (1) {
@@ -217,13 +322,27 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
if (!r_width)
break;
- for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
- if (config_reg->enum_ids[n] == enum_id) {
- *crp = config_reg;
- *indexp = n;
- *cntp = &config_reg->cnt[n / (1 << f_width)];
- return 0;
+
+ pos = 0;
+ m = 0;
+ for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+ if (f_width)
+ curr_width = f_width;
+ else
+ curr_width = config_reg->var_field_width[m];
+
+ ncomb = 1 << curr_width;
+ for (n = 0; n < ncomb; n++) {
+ if (config_reg->enum_ids[pos + n] == enum_id) {
+ *crp = config_reg;
+ *fieldp = m;
+ *valuep = n;
+ *cntp = &config_reg->cnt[m];
+ return 0;
+ }
}
+ pos += ncomb;
+ m++;
}
k++;
}
@@ -261,36 +380,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
return -1;
}
-static void write_config_reg(struct pinmux_info *gpioc,
- struct pinmux_cfg_reg *crp,
- int index)
-{
- unsigned long ncomb, pos, value;
-
- ncomb = 1 << crp->field_width;
- pos = index / ncomb;
- value = index % ncomb;
-
- gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
-}
-
-static int check_config_reg(struct pinmux_info *gpioc,
- struct pinmux_cfg_reg *crp,
- int index)
-{
- unsigned long ncomb, pos, value;
-
- ncomb = 1 << crp->field_width;
- pos = index / ncomb;
- value = index % ncomb;
-
- if (gpio_read_reg(crp->reg, crp->reg_width,
- crp->field_width, pos) == value)
- return 0;
-
- return -1;
-}
-
enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
@@ -299,7 +388,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
struct pinmux_cfg_reg *cr = NULL;
pinmux_enum_t enum_id;
struct pinmux_range *range;
- int in_range, pos, index;
+ int in_range, pos, field, value;
unsigned long *cntp;
switch (pinmux_type) {
@@ -330,7 +419,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
pos = 0;
enum_id = 0;
- index = 0;
+ field = 0;
+ value = 0;
while (1) {
pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
if (pos <= 0)
@@ -377,17 +467,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
if (!in_range)
continue;
- if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
+ if (get_config_reg(gpioc, enum_id, &cr,
+ &field, &value, &cntp) != 0)
goto out_err;
switch (cfg_mode) {
case GPIO_CFG_DRYRUN:
- if (!*cntp || !check_config_reg(gpioc, cr, index))
+ if (!*cntp ||
+ (read_config_reg(gpioc, cr, field) != value))
continue;
break;
case GPIO_CFG_REQ:
- write_config_reg(gpioc, cr, index);
+ write_config_reg(gpioc, cr, field, value);
*cntp = *cntp + 1;
break;
@@ -564,7 +656,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -EINVAL;
- return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
+ return gpio_read_bit(dr, bit);
}
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -606,10 +698,15 @@ static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
+ int ret;
pr_info("%s handling gpio %d -> %d\n",
pip->name, pip->first_gpio, pip->last_gpio);
+ ret = pfc_ioremap(pip);
+ if (ret < 0)
+ return ret;
+
setup_data_regs(pip);
chip->request = sh_gpio_request;
@@ -627,12 +724,16 @@ int register_pinmux(struct pinmux_info *pip)
chip->base = pip->first_gpio;
chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
- return gpiochip_add(chip);
+ ret = gpiochip_add(chip);
+ if (ret < 0)
+ pfc_iounmap(pip);
+
+ return ret;
}
int unregister_pinmux(struct pinmux_info *pip)
{
pr_info("%s deregistering\n", pip->name);
-
+ pfc_iounmap(pip);
return gpiochip_remove(&pip->chip);
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 56abf55..3f9a47e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -87,12 +87,12 @@ config SPI_BFIN_SPORT
Enable support for a SPI bus via the Blackfin SPORT peripheral.
config SPI_AU1550
- tristate "Au1550/Au12x0 SPI Controller"
+ tristate "Au1550/Au1200/Au1300 SPI Controller"
depends on MIPS_ALCHEMY && EXPERIMENTAL
select SPI_BITBANG
help
If you say yes to this option, support will be included for the
- Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
+ PSC SPI controller found on Au1550, Au1200 and Au1300 series.
config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters"
@@ -332,8 +332,7 @@ config SPI_STMP3XXX
config SPI_TEGRA
tristate "Nvidia Tegra SPI controller"
- depends on ARCH_TEGRA
- select TEGRA_SYSTEM_DMA
+ depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
help
SPI driver for NVidia Tegra SoCs
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index e743a45..8418eb0 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -131,7 +131,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
rxchan = dws->rxchan;
/* 2. Prepare the TX dma transfer */
- txconf.direction = DMA_TO_DEVICE;
+ txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr;
txconf.dst_maxburst = LNW_DMA_MSIZE_16;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -147,13 +147,13 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
txdesc = txchan->device->device_prep_slave_sg(txchan,
&dws->tx_sgl,
1,
- DMA_TO_DEVICE,
+ DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
txdesc->callback = dw_spi_dma_done;
txdesc->callback_param = dws;
/* 3. Prepare the RX dma transfer */
- rxconf.direction = DMA_FROM_DEVICE;
+ rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = dws->dma_addr;
rxconf.src_maxburst = LNW_DMA_MSIZE_16;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -169,7 +169,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
&dws->rx_sgl,
1,
- DMA_FROM_DEVICE,
+ DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP);
rxdesc->callback = dw_spi_dma_done;
rxdesc->callback_param = dws;
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 0a282e5..d46e55c 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -551,6 +551,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
struct dma_async_tx_descriptor *txd;
enum dma_slave_buswidth buswidth;
struct dma_slave_config conf;
+ enum dma_transfer_direction slave_dirn;
struct scatterlist *sg;
struct sg_table *sgt;
struct dma_chan *chan;
@@ -573,6 +574,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
conf.src_addr = espi->sspdr_phys;
conf.src_addr_width = buswidth;
+ slave_dirn = DMA_DEV_TO_MEM;
} else {
chan = espi->dma_tx;
buf = t->tx_buf;
@@ -580,6 +582,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
conf.dst_addr = espi->sspdr_phys;
conf.dst_addr_width = buswidth;
+ slave_dirn = DMA_MEM_TO_DEV;
}
ret = dmaengine_slave_config(chan, &conf);
@@ -631,7 +634,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
return ERR_PTR(-ENOMEM);
txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
- dir, DMA_CTRL_ACK);
+ slave_dirn, DMA_CTRL_ACK);
if (!txd) {
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
return ERR_PTR(-ENOMEM);
@@ -979,7 +982,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
dma_cap_set(DMA_SLAVE, mask);
espi->dma_rx_data.port = EP93XX_DMA_SSP;
- espi->dma_rx_data.direction = DMA_FROM_DEVICE;
+ espi->dma_rx_data.direction = DMA_DEV_TO_MEM;
espi->dma_rx_data.name = "ep93xx-spi-rx";
espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
@@ -990,7 +993,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
}
espi->dma_tx_data.port = EP93XX_DMA_SSP;
- espi->dma_tx_data.direction = DMA_TO_DEVICE;
+ espi->dma_tx_data.direction = DMA_MEM_TO_DEV;
espi->dma_tx_data.name = "ep93xx-spi-tx";
espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index f1f5efb..2f9cb43 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -900,11 +900,11 @@ static int configure_dma(struct pl022 *pl022)
{
struct dma_slave_config rx_conf = {
.src_addr = SSP_DR(pl022->phybase),
- .direction = DMA_FROM_DEVICE,
+ .direction = DMA_DEV_TO_MEM,
};
struct dma_slave_config tx_conf = {
.dst_addr = SSP_DR(pl022->phybase),
- .direction = DMA_TO_DEVICE,
+ .direction = DMA_MEM_TO_DEV,
};
unsigned int pages;
int ret;
@@ -1041,7 +1041,7 @@ static int configure_dma(struct pl022 *pl022)
rxdesc = rxchan->device->device_prep_slave_sg(rxchan,
pl022->sgt_rx.sgl,
rx_sglen,
- DMA_FROM_DEVICE,
+ DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!rxdesc)
goto err_rxdesc;
@@ -1049,7 +1049,7 @@ static int configure_dma(struct pl022 *pl022)
txdesc = txchan->device->device_prep_slave_sg(txchan,
pl022->sgt_tx.sgl,
tx_sglen,
- DMA_TO_DEVICE,
+ DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc)
goto err_txdesc;
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 7086583..2a6429d 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1079,7 +1079,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
}
sg = dma->sg_rx_p;
desc_rx = dma->chan_rx->device->device_prep_slave_sg(dma->chan_rx, sg,
- num, DMA_FROM_DEVICE,
+ num, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx) {
dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
@@ -1124,7 +1124,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
}
sg = dma->sg_tx_p;
desc_tx = dma->chan_tx->device->device_prep_slave_sg(dma->chan_tx,
- sg, num, DMA_TO_DEVICE,
+ sg, num, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) {
dev_err(&data->master->dev, "%s:device_prep_slave_sg Failed\n",
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 0d18d80..9bcf87a 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -61,7 +61,7 @@ EXPORT_SYMBOL(comedi_debug);
module_param(comedi_debug, int, 0644);
#endif
-int comedi_autoconfig = 1;
+bool comedi_autoconfig = 1;
module_param(comedi_autoconfig, bool, 0444);
static int comedi_num_legacy_minors;
diff --git a/drivers/staging/comedi/comedi_fops.h b/drivers/staging/comedi/comedi_fops.h
index da4b4f5..006cf14 100644
--- a/drivers/staging/comedi/comedi_fops.h
+++ b/drivers/staging/comedi/comedi_fops.h
@@ -1,10 +1,11 @@
#ifndef _COMEDI_FOPS_H
#define _COMEDI_FOPS_H
+#include <linux/types.h>
extern struct class *comedi_class;
extern const struct file_operations comedi_fops;
-extern int comedi_autoconfig;
+extern bool comedi_autoconfig;
extern struct comedi_driver *comedi_drivers;
#endif /* _COMEDI_FOPS_H */
diff --git a/drivers/staging/media/as102/Kconfig b/drivers/staging/media/as102/Kconfig
index 5865029..28aba00 100644
--- a/drivers/staging/media/as102/Kconfig
+++ b/drivers/staging/media/as102/Kconfig
@@ -1,6 +1,7 @@
config DVB_AS102
tristate "Abilis AS102 DVB receiver"
depends on DVB_CORE && USB && I2C && INPUT
+ select FW_LOADER
help
Choose Y or M here if you have a device containing an AS102
diff --git a/drivers/staging/media/as102/Makefile b/drivers/staging/media/as102/Makefile
index e7dbb6f..1bca43e8 100644
--- a/drivers/staging/media/as102/Makefile
+++ b/drivers/staging/media/as102/Makefile
@@ -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 += -DCONFIG_AS102_USB -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/media/as102/as102_drv.c b/drivers/staging/media/as102/as102_drv.c
index 828526d..aae0505 100644
--- a/drivers/staging/media/as102/as102_drv.c
+++ b/drivers/staging/media/as102/as102_drv.c
@@ -24,7 +24,7 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kref.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/usb.h>
/* header file for Usb device driver*/
@@ -56,13 +56,11 @@ int elna_enable = 1;
module_param_named(elna_enable, elna_enable, int, 0644);
MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");
-#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-#endif
static void as102_stop_stream(struct as102_dev_t *dev)
{
- struct as102_bus_adapter_t *bus_adap;
+ struct as10x_bus_adapter_t *bus_adap;
if (dev != NULL)
bus_adap = &dev->bus_adap;
@@ -85,7 +83,7 @@ static void as102_stop_stream(struct as102_dev_t *dev)
static int as102_start_stream(struct as102_dev_t *dev)
{
- struct as102_bus_adapter_t *bus_adap;
+ struct as10x_bus_adapter_t *bus_adap;
int ret = -EFAULT;
if (dev != NULL)
@@ -111,7 +109,7 @@ static int as102_start_stream(struct as102_dev_t *dev)
static int as10x_pid_filter(struct as102_dev_t *dev,
int index, u16 pid, int onoff) {
- struct as102_bus_adapter_t *bus_adap = &dev->bus_adap;
+ struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
int ret = -EFAULT;
ENTER();
@@ -123,22 +121,22 @@ static int as10x_pid_filter(struct as102_dev_t *dev,
switch (onoff) {
case 0:
- ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
- dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
- index, pid, ret);
- break;
+ ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
+ dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
+ index, pid, ret);
+ break;
case 1:
{
- struct as10x_ts_filter filter;
+ struct as10x_ts_filter filter;
- filter.type = TS_PID_TYPE_TS;
- filter.idx = 0xFF;
- filter.pid = pid;
+ filter.type = TS_PID_TYPE_TS;
+ filter.idx = 0xFF;
+ filter.pid = pid;
- ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
- dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
- index, filter.idx, filter.pid, ret);
- break;
+ ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
+ dprintk(debug, "ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
+ index, filter.idx, filter.pid, ret);
+ break;
}
}
@@ -159,10 +157,9 @@ static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (mutex_lock_interruptible(&as102_dev->sem))
return -ERESTARTSYS;
- if (pid_filtering) {
- as10x_pid_filter(as102_dev,
- dvbdmxfeed->index, dvbdmxfeed->pid, 1);
- }
+ if (pid_filtering)
+ as10x_pid_filter(as102_dev, dvbdmxfeed->index,
+ dvbdmxfeed->pid, 1);
if (as102_dev->streaming++ == 0)
ret = as102_start_stream(as102_dev);
@@ -185,10 +182,9 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
if (--as102_dev->streaming == 0)
as102_stop_stream(as102_dev);
- if (pid_filtering) {
- as10x_pid_filter(as102_dev,
- dvbdmxfeed->index, dvbdmxfeed->pid, 0);
- }
+ if (pid_filtering)
+ as10x_pid_filter(as102_dev, dvbdmxfeed->index,
+ dvbdmxfeed->pid, 0);
mutex_unlock(&as102_dev->sem);
LEAVE();
@@ -197,27 +193,16 @@ static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
int as102_dvb_register(struct as102_dev_t *as102_dev)
{
- int ret = 0;
- ENTER();
+ struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
+ int ret;
ret = dvb_register_adapter(&as102_dev->dvb_adap,
- as102_dev->name,
- THIS_MODULE,
-#if defined(CONFIG_AS102_USB)
- &as102_dev->bus_adap.usb_dev->dev
-#elif defined(CONFIG_AS102_SPI)
- &as102_dev->bus_adap.spi_dev->dev
-#else
-#error >>> dvb_register_adapter <<<
-#endif
-#ifdef DVB_DEFINE_MOD_OPT_ADAPTER_NR
- , adapter_nr
-#endif
- );
+ as102_dev->name, THIS_MODULE,
+ dev, adapter_nr);
if (ret < 0) {
- err("%s: dvb_register_adapter() failed (errno = %d)",
- __func__, ret);
- goto failed;
+ dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
+ __func__, ret);
+ return ret;
}
as102_dev->dvb_dmx.priv = as102_dev;
@@ -235,22 +220,22 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
ret = dvb_dmx_init(&as102_dev->dvb_dmx);
if (ret < 0) {
- err("%s: dvb_dmx_init() failed (errno = %d)", __func__, ret);
- goto failed;
+ dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
+ goto edmxinit;
}
ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
if (ret < 0) {
- err("%s: dvb_dmxdev_init() failed (errno = %d)", __func__,
- ret);
- goto failed;
+ dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
+ __func__, ret);
+ goto edmxdinit;
}
ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
if (ret < 0) {
- err("%s: as102_dvb_register_frontend() failed (errno = %d)",
+ dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
__func__, ret);
- goto failed;
+ goto efereg;
}
/* init bus mutex for token locking */
@@ -259,7 +244,6 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
/* init start / stop stream mutex */
mutex_init(&as102_dev->sem);
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
/*
* try to load as102 firmware. If firmware upload failed, we'll be
* able to upload it later.
@@ -267,18 +251,21 @@ int as102_dvb_register(struct as102_dev_t *as102_dev)
if (fw_upload)
try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
"firmware_class");
-#endif
-failed:
- LEAVE();
- /* FIXME: free dvb_XXX */
+ pr_info("Registered device %s", as102_dev->name);
+ return 0;
+
+efereg:
+ dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
+edmxdinit:
+ dvb_dmx_release(&as102_dev->dvb_dmx);
+edmxinit:
+ dvb_unregister_adapter(&as102_dev->dvb_adap);
return ret;
}
void as102_dvb_unregister(struct as102_dev_t *as102_dev)
{
- ENTER();
-
/* unregister as102 frontend */
as102_dvb_unregister_fe(&as102_dev->dvb_fe);
@@ -289,28 +276,18 @@ void as102_dvb_unregister(struct as102_dev_t *as102_dev)
/* unregister dvb adapter */
dvb_unregister_adapter(&as102_dev->dvb_adap);
- LEAVE();
+ pr_info("Unregistered device %s", as102_dev->name);
}
static int __init as102_driver_init(void)
{
- int ret = 0;
-
- ENTER();
+ int ret;
/* register this driver with the low level subsystem */
-#if defined(CONFIG_AS102_USB)
ret = usb_register(&as102_usb_driver);
if (ret)
err("usb_register failed (ret = %d)", ret);
-#endif
-#if defined(CONFIG_AS102_SPI)
- ret = spi_register_driver(&as102_spi_driver);
- if (ret)
- printk(KERN_ERR "spi_register failed (ret = %d)", ret);
-#endif
- LEAVE();
return ret;
}
@@ -327,15 +304,8 @@ module_init(as102_driver_init);
*/
static void __exit as102_driver_exit(void)
{
- ENTER();
/* deregister this driver with the low level bus subsystem */
-#if defined(CONFIG_AS102_USB)
usb_deregister(&as102_usb_driver);
-#endif
-#if defined(CONFIG_AS102_SPI)
- spi_unregister_driver(&as102_spi_driver);
-#endif
- LEAVE();
}
/*
@@ -347,5 +317,3 @@ module_exit(as102_driver_exit);
MODULE_DESCRIPTION(DRIVER_FULL_NAME);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_drv.h b/drivers/staging/media/as102/as102_drv.h
index fd33f5a..957f0ed 100644
--- a/drivers/staging/media/as102/as102_drv.h
+++ b/drivers/staging/media/as102/as102_drv.h
@@ -17,38 +17,30 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#if defined(CONFIG_AS102_USB)
#include <linux/usb.h>
-extern struct usb_driver as102_usb_driver;
-#endif
-
-#if defined(CONFIG_AS102_SPI)
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/cdev.h>
-
-extern struct spi_driver as102_spi_driver;
-#endif
-
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dmxdev.h"
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dmxdev.h>
+#include "as10x_cmd.h"
+#include "as102_usb_drv.h"
#define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
#define DRIVER_NAME "as10x_usb"
extern int as102_debug;
#define debug as102_debug
+extern struct usb_driver as102_usb_driver;
+extern int elna_enable;
#define dprintk(debug, args...) \
do { if (debug) { \
- printk(KERN_DEBUG "%s: ",__FUNCTION__); \
+ pr_debug("%s: ", __func__); \
printk(args); \
} } while (0)
#ifdef TRACE
-#define ENTER() printk(">> enter %s\n", __FUNCTION__)
-#define LEAVE() printk("<< leave %s\n", __FUNCTION__)
+#define ENTER() pr_debug(">> enter %s\n", __func__)
+#define LEAVE() pr_debug("<< leave %s\n", __func__)
#else
#define ENTER()
#define LEAVE()
@@ -59,39 +51,14 @@ extern int as102_debug;
#define AS102_USB_BUF_SIZE 512
#define MAX_STREAM_URB 32
-#include "as10x_cmd.h"
-
-#if defined(CONFIG_AS102_USB)
-#include "as102_usb_drv.h"
-#endif
-
-#if defined(CONFIG_AS102_SPI)
-#include "as10x_spi_drv.h"
-#endif
-
-
-struct as102_bus_adapter_t {
-#if defined(CONFIG_AS102_USB)
+struct as10x_bus_adapter_t {
struct usb_device *usb_dev;
-#elif defined(CONFIG_AS102_SPI)
- struct spi_device *spi_dev;
- struct cdev cdev; /* spidev raw device */
-
- struct timer_list timer;
- struct completion xfer_done;
-#endif
/* bus token lock */
struct mutex lock;
/* low level interface for bus adapter */
union as10x_bus_token_t {
-#if defined(CONFIG_AS102_USB)
/* usb token */
struct as10x_usb_token_cmd_t usb;
-#endif
-#if defined(CONFIG_AS102_SPI)
- /* spi token */
- struct as10x_spi_token_cmd_t spi;
-#endif
} token;
/* token cmd xfer id */
@@ -106,7 +73,7 @@ struct as102_bus_adapter_t {
struct as102_dev_t {
const char *name;
- struct as102_bus_adapter_t bus_adap;
+ struct as10x_bus_adapter_t bus_adap;
struct list_head device_entry;
struct kref kref;
unsigned long minor;
@@ -138,5 +105,3 @@ void as102_dvb_unregister(struct as102_dev_t *dev);
int as102_dvb_register_fe(struct as102_dev_t *dev, struct dvb_frontend *fe);
int as102_dvb_unregister_fe(struct dvb_frontend *dev);
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fe.c b/drivers/staging/media/as102/as102_fe.c
index 3550f90..bdc5a38 100644
--- a/drivers/staging/media/as102/as102_fe.c
+++ b/drivers/staging/media/as102/as102_fe.c
@@ -23,17 +23,15 @@
#include "as10x_types.h"
#include "as10x_cmd.h"
-extern int elna_enable;
-
-static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *dst,
struct as10x_tps *src);
static void as102_fe_copy_tune_parameters(struct as10x_tune_args *dst,
- struct dvb_frontend_parameters *src);
+ struct dtv_frontend_properties *src);
-static int as102_fe_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params)
+static int as102_fe_set_frontend(struct dvb_frontend *fe)
{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int ret = 0;
struct as102_dev_t *dev;
struct as10x_tune_args tune_args = { 0 };
@@ -47,7 +45,7 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe,
if (mutex_lock_interruptible(&dev->bus_adap.lock))
return -EBUSY;
- as102_fe_copy_tune_parameters(&tune_args, params);
+ as102_fe_copy_tune_parameters(&tune_args, p);
/* send abilis command: SET_TUNE */
ret = as10x_cmd_set_tune(&dev->bus_adap, &tune_args);
@@ -60,8 +58,9 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe,
return (ret < 0) ? -EINVAL : 0;
}
-static int as102_fe_get_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p) {
+static int as102_fe_get_frontend(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
int ret = 0;
struct as102_dev_t *dev;
struct as10x_tps tps = { 0 };
@@ -280,9 +279,9 @@ static int as102_fe_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
}
static struct dvb_frontend_ops as102_fe_ops = {
+ .delsys = { SYS_DVBT },
.info = {
.name = "Unknown AS102 device",
- .type = FE_OFDM,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_stepsize = 166667,
@@ -346,38 +345,36 @@ int as102_dvb_register_fe(struct as102_dev_t *as102_dev,
return errno;
}
-static void as10x_fe_copy_tps_parameters(struct dvb_frontend_parameters *dst,
+static void as10x_fe_copy_tps_parameters(struct dtv_frontend_properties *fe_tps,
struct as10x_tps *as10x_tps)
{
- struct dvb_ofdm_parameters *fe_tps = &dst->u.ofdm;
-
/* extract consteallation */
- switch (as10x_tps->constellation) {
+ switch (as10x_tps->modulation) {
case CONST_QPSK:
- fe_tps->constellation = QPSK;
+ fe_tps->modulation = QPSK;
break;
case CONST_QAM16:
- fe_tps->constellation = QAM_16;
+ fe_tps->modulation = QAM_16;
break;
case CONST_QAM64:
- fe_tps->constellation = QAM_64;
+ fe_tps->modulation = QAM_64;
break;
}
/* extract hierarchy */
switch (as10x_tps->hierarchy) {
case HIER_NONE:
- fe_tps->hierarchy_information = HIERARCHY_NONE;
+ fe_tps->hierarchy = HIERARCHY_NONE;
break;
case HIER_ALPHA_1:
- fe_tps->hierarchy_information = HIERARCHY_1;
+ fe_tps->hierarchy = HIERARCHY_1;
break;
case HIER_ALPHA_2:
- fe_tps->hierarchy_information = HIERARCHY_2;
+ fe_tps->hierarchy = HIERARCHY_2;
break;
case HIER_ALPHA_4:
- fe_tps->hierarchy_information = HIERARCHY_4;
+ fe_tps->hierarchy = HIERARCHY_4;
break;
}
@@ -475,7 +472,7 @@ static uint8_t as102_fe_get_code_rate(fe_code_rate_t arg)
}
static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
- struct dvb_frontend_parameters *params)
+ struct dtv_frontend_properties *params)
{
/* set frequency */
@@ -484,21 +481,21 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
/* fix interleaving_mode */
tune_args->interleaving_mode = INTLV_NATIVE;
- switch (params->u.ofdm.bandwidth) {
- case BANDWIDTH_8_MHZ:
+ switch (params->bandwidth_hz) {
+ case 8000000:
tune_args->bandwidth = BW_8_MHZ;
break;
- case BANDWIDTH_7_MHZ:
+ case 7000000:
tune_args->bandwidth = BW_7_MHZ;
break;
- case BANDWIDTH_6_MHZ:
+ case 6000000:
tune_args->bandwidth = BW_6_MHZ;
break;
default:
tune_args->bandwidth = BW_8_MHZ;
}
- switch (params->u.ofdm.guard_interval) {
+ switch (params->guard_interval) {
case GUARD_INTERVAL_1_32:
tune_args->guard_interval = GUARD_INT_1_32;
break;
@@ -517,22 +514,22 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
break;
}
- switch (params->u.ofdm.constellation) {
+ switch (params->modulation) {
case QPSK:
- tune_args->constellation = CONST_QPSK;
+ tune_args->modulation = CONST_QPSK;
break;
case QAM_16:
- tune_args->constellation = CONST_QAM16;
+ tune_args->modulation = CONST_QAM16;
break;
case QAM_64:
- tune_args->constellation = CONST_QAM64;
+ tune_args->modulation = CONST_QAM64;
break;
default:
- tune_args->constellation = CONST_UNKNOWN;
+ tune_args->modulation = CONST_UNKNOWN;
break;
}
- switch (params->u.ofdm.transmission_mode) {
+ switch (params->transmission_mode) {
case TRANSMISSION_MODE_2K:
tune_args->transmission_mode = TRANS_MODE_2K;
break;
@@ -543,7 +540,7 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
tune_args->transmission_mode = TRANS_MODE_UNKNOWN;
}
- switch (params->u.ofdm.hierarchy_information) {
+ switch (params->hierarchy) {
case HIERARCHY_NONE:
tune_args->hierarchy = HIER_NONE;
break;
@@ -571,19 +568,19 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
* if HP/LP are both set to FEC_NONE, HP will be selected.
*/
if ((tune_args->hierarchy != HIER_NONE) &&
- ((params->u.ofdm.code_rate_LP == FEC_NONE) ||
- (params->u.ofdm.code_rate_HP == FEC_NONE))) {
+ ((params->code_rate_LP == FEC_NONE) ||
+ (params->code_rate_HP == FEC_NONE))) {
- if (params->u.ofdm.code_rate_LP == FEC_NONE) {
+ if (params->code_rate_LP == FEC_NONE) {
tune_args->hier_select = HIER_HIGH_PRIORITY;
tune_args->code_rate =
- as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+ as102_fe_get_code_rate(params->code_rate_HP);
}
- if (params->u.ofdm.code_rate_HP == FEC_NONE) {
+ if (params->code_rate_HP == FEC_NONE) {
tune_args->hier_select = HIER_LOW_PRIORITY;
tune_args->code_rate =
- as102_fe_get_code_rate(params->u.ofdm.code_rate_LP);
+ as102_fe_get_code_rate(params->code_rate_LP);
}
dprintk(debug, "\thierarchy: 0x%02x "
@@ -596,8 +593,6 @@ static void as102_fe_copy_tune_parameters(struct as10x_tune_args *tune_args,
tune_args->code_rate);
} else {
tune_args->code_rate =
- as102_fe_get_code_rate(params->u.ofdm.code_rate_HP);
+ as102_fe_get_code_rate(params->code_rate_HP);
}
}
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c
index c019df9..43ebc43 100644
--- a/drivers/staging/media/as102/as102_fw.c
+++ b/drivers/staging/media/as102/as102_fw.c
@@ -26,7 +26,6 @@
#include "as102_drv.h"
#include "as102_fw.h"
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
char as102_st_fw1[] = "as102_data1_st.hex";
char as102_st_fw2[] = "as102_data2_st.hex";
char as102_dt_fw1[] = "as102_data1_dt.hex";
@@ -59,7 +58,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
unsigned char *src, dst;
if (*fw_data++ != ':') {
- printk(KERN_ERR "invalid firmware file\n");
+ pr_err("invalid firmware file\n");
return -EFAULT;
}
@@ -102,7 +101,7 @@ static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
return (count * 2) + 2;
}
-static int as102_firmware_upload(struct as102_bus_adapter_t *bus_adap,
+static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
unsigned char *cmd,
const struct firmware *firmware) {
@@ -163,19 +162,14 @@ error:
return (errno == 0) ? total_read_bytes : errno;
}
-int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
+int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
{
int errno = -EFAULT;
const struct firmware *firmware;
unsigned char *cmd_buf = NULL;
char *fw1, *fw2;
-
-#if defined(CONFIG_AS102_USB)
struct usb_device *dev = bus_adap->usb_dev;
-#endif
-#if defined(CONFIG_AS102_SPI)
- struct spi_device *dev = bus_adap->spi_dev;
-#endif
+
ENTER();
/* select fw file to upload */
@@ -187,7 +181,6 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
fw2 = as102_st_fw2;
}
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
/* allocate buffer to store firmware upload command and data */
cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
if (cmd_buf == NULL) {
@@ -198,21 +191,21 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
/* request kernel to locate firmware file: part1 */
errno = request_firmware(&firmware, fw1, &dev->dev);
if (errno < 0) {
- printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
- DRIVER_NAME, fw1);
+ pr_err("%s: unable to locate firmware file: %s\n",
+ DRIVER_NAME, fw1);
goto error;
}
/* initiate firmware upload */
errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
if (errno < 0) {
- printk(KERN_ERR "%s: error during firmware upload part1\n",
- DRIVER_NAME);
+ pr_err("%s: error during firmware upload part1\n",
+ DRIVER_NAME);
goto error;
}
- printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
- DRIVER_NAME, fw1);
+ pr_info("%s: firmware: %s loaded with success\n",
+ DRIVER_NAME, fw1);
release_firmware(firmware);
/* wait for boot to complete */
@@ -221,31 +214,28 @@ int as102_fw_upload(struct as102_bus_adapter_t *bus_adap)
/* request kernel to locate firmware file: part2 */
errno = request_firmware(&firmware, fw2, &dev->dev);
if (errno < 0) {
- printk(KERN_ERR "%s: unable to locate firmware file: %s\n",
- DRIVER_NAME, fw2);
+ pr_err("%s: unable to locate firmware file: %s\n",
+ DRIVER_NAME, fw2);
goto error;
}
/* initiate firmware upload */
errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
if (errno < 0) {
- printk(KERN_ERR "%s: error during firmware upload part2\n",
- DRIVER_NAME);
+ pr_err("%s: error during firmware upload part2\n",
+ DRIVER_NAME);
goto error;
}
- printk(KERN_INFO "%s: fimrware: %s loaded with success\n",
- DRIVER_NAME, fw2);
+ pr_info("%s: firmware: %s loaded with success\n",
+ DRIVER_NAME, fw2);
error:
/* free data buffer */
kfree(cmd_buf);
/* release firmware if needed */
if (firmware != NULL)
release_firmware(firmware);
-#endif
+
LEAVE();
return errno;
}
-#endif
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h
index 27e5347..bd21f05 100644
--- a/drivers/staging/media/as102/as102_fw.h
+++ b/drivers/staging/media/as102/as102_fw.h
@@ -20,11 +20,10 @@
extern int dual_tuner;
-#pragma pack(1)
struct as10x_raw_fw_pkt {
unsigned char address[4];
unsigned char data[MAX_FW_PKT_SIZE - 6];
-};
+} __packed;
struct as10x_fw_pkt_t {
union {
@@ -32,11 +31,8 @@ struct as10x_fw_pkt_t {
unsigned char length[2];
} u;
struct as10x_raw_fw_pkt raw;
-};
-#pragma pack()
+} __packed;
#ifdef __KERNEL__
-int as102_fw_upload(struct as102_bus_adapter_t *bus_adap);
+int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap);
#endif
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.c b/drivers/staging/media/as102/as102_usb_drv.c
index 264be2d..d775be0 100644
--- a/drivers/staging/media/as102/as102_usb_drv.c
+++ b/drivers/staging/media/as102/as102_usb_drv.c
@@ -42,30 +42,32 @@ static struct usb_device_id as102_usb_id_table[] = {
{ USB_DEVICE(PCTV_74E_USB_VID, PCTV_74E_USB_PID) },
{ USB_DEVICE(ELGATO_EYETV_DTT_USB_VID, ELGATO_EYETV_DTT_USB_PID) },
{ USB_DEVICE(NBOX_DVBT_DONGLE_USB_VID, NBOX_DVBT_DONGLE_USB_PID) },
+ { USB_DEVICE(SKY_IT_DIGITAL_KEY_USB_VID, SKY_IT_DIGITAL_KEY_USB_PID) },
{ } /* Terminating entry */
};
/* Note that this table must always have the same number of entries as the
as102_usb_id_table struct */
-static const char *as102_device_names[] = {
+static const char * const as102_device_names[] = {
AS102_REFERENCE_DESIGN,
AS102_PCTV_74E,
AS102_ELGATO_EYETV_DTT_NAME,
AS102_NBOX_DVBT_DONGLE_NAME,
+ AS102_SKY_IT_DIGITAL_KEY_NAME,
NULL /* Terminating entry */
};
struct usb_driver as102_usb_driver = {
- .name = DRIVER_FULL_NAME,
- .probe = as102_usb_probe,
- .disconnect = as102_usb_disconnect,
- .id_table = as102_usb_id_table
+ .name = DRIVER_FULL_NAME,
+ .probe = as102_usb_probe,
+ .disconnect = as102_usb_disconnect,
+ .id_table = as102_usb_id_table
};
static const struct file_operations as102_dev_fops = {
- .owner = THIS_MODULE,
- .open = as102_open,
- .release = as102_release,
+ .owner = THIS_MODULE,
+ .open = as102_open,
+ .release = as102_release,
};
static struct usb_class_driver as102_usb_class_driver = {
@@ -74,7 +76,7 @@ static struct usb_class_driver as102_usb_class_driver = {
.minor_base = AS102_DEVICE_MAJOR,
};
-static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
+static int as102_usb_xfer_cmd(struct as10x_bus_adapter_t *bus_adap,
unsigned char *send_buf, int send_buf_len,
unsigned char *recv_buf, int recv_buf_len)
{
@@ -131,7 +133,7 @@ static int as102_usb_xfer_cmd(struct as102_bus_adapter_t *bus_adap,
return ret;
}
-static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
+static int as102_send_ep1(struct as10x_bus_adapter_t *bus_adap,
unsigned char *send_buf,
int send_buf_len,
int swap32)
@@ -154,7 +156,7 @@ static int as102_send_ep1(struct as102_bus_adapter_t *bus_adap,
return ret ? ret : actual_len;
}
-static int as102_read_ep2(struct as102_bus_adapter_t *bus_adap,
+static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap,
unsigned char *recv_buf, int recv_buf_len)
{
int ret = 0, actual_len;
@@ -337,7 +339,7 @@ static void as102_usb_disconnect(struct usb_interface *intf)
/* decrement usage counter */
kref_put(&as102_dev->kref, as102_usb_release);
- printk(KERN_INFO "%s: device has been disconnected\n", DRIVER_NAME);
+ pr_info("%s: device has been disconnected\n", DRIVER_NAME);
LEAVE();
}
@@ -351,19 +353,19 @@ static int as102_usb_probe(struct usb_interface *intf,
ENTER();
- as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
- if (as102_dev == NULL) {
- err("%s: kzalloc failed", __func__);
- return -ENOMEM;
- }
-
/* This should never actually happen */
if ((sizeof(as102_usb_id_table) / sizeof(struct usb_device_id)) !=
(sizeof(as102_device_names) / sizeof(const char *))) {
- printk(KERN_ERR "Device names table invalid size");
+ pr_err("Device names table invalid size");
return -EINVAL;
}
+ as102_dev = kzalloc(sizeof(struct as102_dev_t), GFP_KERNEL);
+ if (as102_dev == NULL) {
+ err("%s: kzalloc failed", __func__);
+ return -ENOMEM;
+ }
+
/* Assign the user-friendly device name */
for (i = 0; i < (sizeof(as102_usb_id_table) /
sizeof(struct usb_device_id)); i++) {
@@ -399,7 +401,7 @@ static int as102_usb_probe(struct usb_interface *intf,
goto failed;
}
- printk(KERN_INFO "%s: device has been detected\n", DRIVER_NAME);
+ pr_info("%s: device has been detected\n", DRIVER_NAME);
/* request buffer allocation for streaming */
ret = as102_alloc_usb_stream_buffer(as102_dev);
@@ -432,8 +434,8 @@ static int as102_open(struct inode *inode, struct file *file)
/* fetch device from usb interface */
intf = usb_find_interface(&as102_usb_driver, minor);
if (intf == NULL) {
- printk(KERN_ERR "%s: can't find device for minor %d\n",
- __func__, minor);
+ pr_err("%s: can't find device for minor %d\n",
+ __func__, minor);
ret = -ENODEV;
goto exit;
}
@@ -474,5 +476,3 @@ static int as102_release(struct inode *inode, struct file *file)
}
MODULE_DEVICE_TABLE(usb, as102_usb_id_table);
-
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as102_usb_drv.h b/drivers/staging/media/as102/as102_usb_drv.h
index fb1fc41..fc2884a 100644
--- a/drivers/staging/media/as102/as102_usb_drv.h
+++ b/drivers/staging/media/as102/as102_usb_drv.h
@@ -47,6 +47,11 @@
#define NBOX_DVBT_DONGLE_USB_VID 0x0b89
#define NBOX_DVBT_DONGLE_USB_PID 0x0007
+/* Sky Italia: Digital Key (green led) */
+#define AS102_SKY_IT_DIGITAL_KEY_NAME "Sky IT Digital Key (green led)"
+#define SKY_IT_DIGITAL_KEY_USB_VID 0x2137
+#define SKY_IT_DIGITAL_KEY_USB_PID 0x0001
+
void as102_urb_stream_irq(struct urb *urb);
struct as10x_usb_token_cmd_t {
@@ -56,4 +61,3 @@ struct as10x_usb_token_cmd_t {
struct as10x_cmd_t r;
};
#endif
-/* EOF - vim: set textwidth=80 ts=8 sw=8 sts=8 noet: */
diff --git a/drivers/staging/media/as102/as10x_cmd.c b/drivers/staging/media/as102/as10x_cmd.c
index 0dcba80..262bb94 100644
--- a/drivers/staging/media/as102/as10x_cmd.c
+++ b/drivers/staging/media/as102/as10x_cmd.c
@@ -25,35 +25,35 @@
/**
* as10x_cmd_turn_on - send turn on command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
*
* Return 0 when no error, < 0 in case of error.
*/
-int as10x_cmd_turn_on(as10x_handle_t *phandle)
+int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
{
int error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.turn_on.req));
/* fill command */
pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
- sizeof(pcmd->body.turn_on.req) +
- HEADER_SIZE,
- (uint8_t *) prsp,
- sizeof(prsp->body.turn_on.rsp) +
- HEADER_SIZE);
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
+ sizeof(pcmd->body.turn_on.req) +
+ HEADER_SIZE,
+ (uint8_t *) prsp,
+ sizeof(prsp->body.turn_on.rsp) +
+ HEADER_SIZE);
} else {
error = AS10X_CMD_ERROR;
}
@@ -71,31 +71,31 @@ out:
/**
* as10x_cmd_turn_off - send turn off command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_turn_off(as10x_handle_t *phandle)
+int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
{
int error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.turn_off.req));
/* fill command */
pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(
- phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(
+ adap, (uint8_t *) pcmd,
sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
(uint8_t *) prsp,
sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
@@ -116,23 +116,24 @@ out:
/**
* as10x_cmd_set_tune - send set tune command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @ptune: tune parameters
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
+int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
+ struct as10x_tune_args *ptune)
{
int error;
struct as10x_cmd_t *preq, *prsp;
ENTER();
- preq = phandle->cmd;
- prsp = phandle->rsp;
+ preq = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(preq, (++phandle->cmd_xid),
+ as10x_cmd_build(preq, (++adap->cmd_xid),
sizeof(preq->body.set_tune.req));
/* fill command */
@@ -140,7 +141,7 @@ int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
preq->body.set_tune.req.args.hier_select = ptune->hier_select;
- preq->body.set_tune.req.args.constellation = ptune->constellation;
+ preq->body.set_tune.req.args.modulation = ptune->modulation;
preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
preq->body.set_tune.req.args.interleaving_mode =
ptune->interleaving_mode;
@@ -150,14 +151,14 @@ int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
ptune->transmission_mode;
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
- (uint8_t *) preq,
- sizeof(preq->body.set_tune.req)
- + HEADER_SIZE,
- (uint8_t *) prsp,
- sizeof(prsp->body.set_tune.rsp)
- + HEADER_SIZE);
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
+ (uint8_t *) preq,
+ sizeof(preq->body.set_tune.req)
+ + HEADER_SIZE,
+ (uint8_t *) prsp,
+ sizeof(prsp->body.set_tune.rsp)
+ + HEADER_SIZE);
} else {
error = AS10X_CMD_ERROR;
}
@@ -175,12 +176,12 @@ out:
/**
* as10x_cmd_get_tune_status - send get tune status command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @pstatus: pointer to updated status structure of the current tune
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
struct as10x_tune_status *pstatus)
{
int error;
@@ -188,11 +189,11 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
ENTER();
- preq = phandle->cmd;
- prsp = phandle->rsp;
+ preq = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(preq, (++phandle->cmd_xid),
+ as10x_cmd_build(preq, (++adap->cmd_xid),
sizeof(preq->body.get_tune_status.req));
/* fill command */
@@ -200,9 +201,9 @@ int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(
- phandle,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(
+ adap,
(uint8_t *) preq,
sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
(uint8_t *) prsp,
@@ -232,24 +233,24 @@ out:
}
/**
- * send get TPS command to AS10x
- * @phandle: pointer to AS10x handle
+ * as10x_cmd_get_tps - send get TPS command to AS10x
+ * @adap: pointer to AS10x handle
* @ptps: pointer to TPS parameters structure
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
+int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
{
int error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.get_tps.req));
/* fill command */
@@ -257,14 +258,14 @@ int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
cpu_to_le16(CONTROL_PROC_GETTPS);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
- (uint8_t *) pcmd,
- sizeof(pcmd->body.get_tps.req) +
- HEADER_SIZE,
- (uint8_t *) prsp,
- sizeof(prsp->body.get_tps.rsp) +
- HEADER_SIZE);
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
+ (uint8_t *) pcmd,
+ sizeof(pcmd->body.get_tps.req) +
+ HEADER_SIZE,
+ (uint8_t *) prsp,
+ sizeof(prsp->body.get_tps.rsp) +
+ HEADER_SIZE);
} else {
error = AS10X_CMD_ERROR;
}
@@ -278,7 +279,7 @@ int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
goto out;
/* Response OK -> get response data */
- ptps->constellation = prsp->body.get_tps.rsp.tps.constellation;
+ ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
@@ -296,12 +297,12 @@ out:
/**
* as10x_cmd_get_demod_stats - send get demod stats command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @pdemod_stats: pointer to demod stats parameters structure
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
+int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
struct as10x_demod_stats *pdemod_stats)
{
int error;
@@ -309,11 +310,11 @@ int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.get_demod_stats.req));
/* fill command */
@@ -321,8 +322,8 @@ int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
(uint8_t *) pcmd,
sizeof(pcmd->body.get_demod_stats.req)
+ HEADER_SIZE,
@@ -360,13 +361,13 @@ out:
/**
* as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @is_ready: pointer to value indicating when impulse
* response data is ready
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
+int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
uint8_t *is_ready)
{
int error;
@@ -374,11 +375,11 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.get_impulse_rsp.req));
/* fill command */
@@ -386,8 +387,8 @@ int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
(uint8_t *) pcmd,
sizeof(pcmd->body.get_impulse_rsp.req)
+ HEADER_SIZE,
diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h
index 01a7163..4ea249e 100644
--- a/drivers/staging/media/as102/as10x_cmd.h
+++ b/drivers/staging/media/as102/as10x_cmd.h
@@ -28,459 +28,456 @@
/*********************************/
/* MACRO DEFINITIONS */
/*********************************/
-#define AS10X_CMD_ERROR -1
+#define AS10X_CMD_ERROR -1
-#define SERVICE_PROG_ID 0x0002
-#define SERVICE_PROG_VERSION 0x0001
+#define SERVICE_PROG_ID 0x0002
+#define SERVICE_PROG_VERSION 0x0001
-#define HIER_NONE 0x00
-#define HIER_LOW_PRIORITY 0x01
+#define HIER_NONE 0x00
+#define HIER_LOW_PRIORITY 0x01
#define HEADER_SIZE (sizeof(struct as10x_cmd_header_t))
/* context request types */
-#define GET_CONTEXT_DATA 1
-#define SET_CONTEXT_DATA 2
+#define GET_CONTEXT_DATA 1
+#define SET_CONTEXT_DATA 2
/* ODSP suspend modes */
-#define CFG_MODE_ODSP_RESUME 0
-#define CFG_MODE_ODSP_SUSPEND 1
+#define CFG_MODE_ODSP_RESUME 0
+#define CFG_MODE_ODSP_SUSPEND 1
/* Dump memory size */
-#define DUMP_BLOCK_SIZE_MAX 0x20
+#define DUMP_BLOCK_SIZE_MAX 0x20
/*********************************/
/* TYPE DEFINITION */
/*********************************/
-typedef enum {
- CONTROL_PROC_TURNON = 0x0001,
- CONTROL_PROC_TURNON_RSP = 0x0100,
- CONTROL_PROC_SET_REGISTER = 0x0002,
- CONTROL_PROC_SET_REGISTER_RSP = 0x0200,
- CONTROL_PROC_GET_REGISTER = 0x0003,
- CONTROL_PROC_GET_REGISTER_RSP = 0x0300,
- CONTROL_PROC_SETTUNE = 0x000A,
- CONTROL_PROC_SETTUNE_RSP = 0x0A00,
- CONTROL_PROC_GETTUNESTAT = 0x000B,
- CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00,
- CONTROL_PROC_GETTPS = 0x000D,
- CONTROL_PROC_GETTPS_RSP = 0x0D00,
- CONTROL_PROC_SETFILTER = 0x000E,
- CONTROL_PROC_SETFILTER_RSP = 0x0E00,
- CONTROL_PROC_REMOVEFILTER = 0x000F,
- CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00,
- CONTROL_PROC_GET_IMPULSE_RESP = 0x0012,
- CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200,
- CONTROL_PROC_START_STREAMING = 0x0013,
- CONTROL_PROC_START_STREAMING_RSP = 0x1300,
- CONTROL_PROC_STOP_STREAMING = 0x0014,
- CONTROL_PROC_STOP_STREAMING_RSP = 0x1400,
- CONTROL_PROC_GET_DEMOD_STATS = 0x0015,
- CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500,
- CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016,
- CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600,
- CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017,
- CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700,
- CONTROL_PROC_AGC_CHANGE_MODE = 0x0018,
- CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800,
-
- CONTROL_PROC_CONTEXT = 0x00FC,
- CONTROL_PROC_CONTEXT_RSP = 0xFC00,
- CONTROL_PROC_DUMP_MEMORY = 0x00FD,
- CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00,
- CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE,
- CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00,
- CONTROL_PROC_TURNOFF = 0x00FF,
- CONTROL_PROC_TURNOFF_RSP = 0xFF00
-} control_proc;
-
-
-#pragma pack(1)
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- } rsp;
-} TURN_ON;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t err;
- } rsp;
-} TURN_OFF;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* tune params */
- struct as10x_tune_args args;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- } rsp;
-} SET_TUNE;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- /* tune status */
- struct as10x_tune_status sts;
- } rsp;
-} GET_TUNE_STATUS;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- /* tps details */
- struct as10x_tps tps;
- } rsp;
-} GET_TPS;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- } rsp;
-} COMMON;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* PID to filter */
- uint16_t pid;
- /* stream type (MPE, PSI/SI or PES )*/
- uint8_t stream_type;
- /* PID index in filter table */
- uint8_t idx;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- /* Filter id */
- uint8_t filter_id;
- } rsp;
-} ADD_PID_FILTER;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* PID to remove */
- uint16_t pid;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* response error */
- uint8_t error;
- } rsp;
-} DEL_PID_FILTER;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- } rsp;
-} START_STREAMING;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- } rsp;
-} STOP_STREAMING;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- /* demod stats */
- struct as10x_demod_stats stats;
- } rsp;
-} GET_DEMOD_STATS;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- /* impulse response ready */
- uint8_t is_ready;
- } rsp;
-} GET_IMPULSE_RESP;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* value to write (for set context)*/
- struct as10x_register_value reg_val;
- /* context tag */
- uint16_t tag;
- /* context request type */
- uint16_t type;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* value read (for get context) */
- struct as10x_register_value reg_val;
- /* context request type */
- uint16_t type;
- /* error */
- uint8_t error;
- } rsp;
-} FW_CONTEXT;
-
-typedef union {
- /* request */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* register description */
- struct as10x_register_addr reg_addr;
- /* register content */
- struct as10x_register_value reg_val;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- } rsp;
-} SET_REGISTER;
-
-typedef union {
- /* request */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* register description */
- struct as10x_register_addr reg_addr;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- /* register content */
- struct as10x_register_value reg_val;
- } rsp;
-} GET_REGISTER;
-
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* mode */
- uint8_t mode;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- } rsp;
-} CFG_CHANGE_MODE;
+enum control_proc {
+ CONTROL_PROC_TURNON = 0x0001,
+ CONTROL_PROC_TURNON_RSP = 0x0100,
+ CONTROL_PROC_SET_REGISTER = 0x0002,
+ CONTROL_PROC_SET_REGISTER_RSP = 0x0200,
+ CONTROL_PROC_GET_REGISTER = 0x0003,
+ CONTROL_PROC_GET_REGISTER_RSP = 0x0300,
+ CONTROL_PROC_SETTUNE = 0x000A,
+ CONTROL_PROC_SETTUNE_RSP = 0x0A00,
+ CONTROL_PROC_GETTUNESTAT = 0x000B,
+ CONTROL_PROC_GETTUNESTAT_RSP = 0x0B00,
+ CONTROL_PROC_GETTPS = 0x000D,
+ CONTROL_PROC_GETTPS_RSP = 0x0D00,
+ CONTROL_PROC_SETFILTER = 0x000E,
+ CONTROL_PROC_SETFILTER_RSP = 0x0E00,
+ CONTROL_PROC_REMOVEFILTER = 0x000F,
+ CONTROL_PROC_REMOVEFILTER_RSP = 0x0F00,
+ CONTROL_PROC_GET_IMPULSE_RESP = 0x0012,
+ CONTROL_PROC_GET_IMPULSE_RESP_RSP = 0x1200,
+ CONTROL_PROC_START_STREAMING = 0x0013,
+ CONTROL_PROC_START_STREAMING_RSP = 0x1300,
+ CONTROL_PROC_STOP_STREAMING = 0x0014,
+ CONTROL_PROC_STOP_STREAMING_RSP = 0x1400,
+ CONTROL_PROC_GET_DEMOD_STATS = 0x0015,
+ CONTROL_PROC_GET_DEMOD_STATS_RSP = 0x1500,
+ CONTROL_PROC_ELNA_CHANGE_MODE = 0x0016,
+ CONTROL_PROC_ELNA_CHANGE_MODE_RSP = 0x1600,
+ CONTROL_PROC_ODSP_CHANGE_MODE = 0x0017,
+ CONTROL_PROC_ODSP_CHANGE_MODE_RSP = 0x1700,
+ CONTROL_PROC_AGC_CHANGE_MODE = 0x0018,
+ CONTROL_PROC_AGC_CHANGE_MODE_RSP = 0x1800,
+
+ CONTROL_PROC_CONTEXT = 0x00FC,
+ CONTROL_PROC_CONTEXT_RSP = 0xFC00,
+ CONTROL_PROC_DUMP_MEMORY = 0x00FD,
+ CONTROL_PROC_DUMP_MEMORY_RSP = 0xFD00,
+ CONTROL_PROC_DUMPLOG_MEMORY = 0x00FE,
+ CONTROL_PROC_DUMPLOG_MEMORY_RSP = 0xFE00,
+ CONTROL_PROC_TURNOFF = 0x00FF,
+ CONTROL_PROC_TURNOFF_RSP = 0xFF00
+};
+
+union as10x_turn_on {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_turn_off {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t err;
+ } rsp;
+} __packed;
+
+union as10x_set_tune {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* tune params */
+ struct as10x_tune_args args;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_get_tune_status {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ /* tune status */
+ struct as10x_tune_status sts;
+ } rsp;
+} __packed;
+
+union as10x_get_tps {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ /* tps details */
+ struct as10x_tps tps;
+ } rsp;
+} __packed;
+
+union as10x_common {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_add_pid_filter {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* PID to filter */
+ uint16_t pid;
+ /* stream type (MPE, PSI/SI or PES )*/
+ uint8_t stream_type;
+ /* PID index in filter table */
+ uint8_t idx;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ /* Filter id */
+ uint8_t filter_id;
+ } rsp;
+} __packed;
+
+union as10x_del_pid_filter {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* PID to remove */
+ uint16_t pid;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* response error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_start_streaming {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_stop_streaming {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_get_demod_stats {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ /* demod stats */
+ struct as10x_demod_stats stats;
+ } rsp;
+} __packed;
+
+union as10x_get_impulse_resp {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ /* impulse response ready */
+ uint8_t is_ready;
+ } rsp;
+} __packed;
+
+union as10x_fw_context {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* value to write (for set context)*/
+ struct as10x_register_value reg_val;
+ /* context tag */
+ uint16_t tag;
+ /* context request type */
+ uint16_t type;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* value read (for get context) */
+ struct as10x_register_value reg_val;
+ /* context request type */
+ uint16_t type;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_set_register {
+ /* request */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* register description */
+ struct as10x_register_addr reg_addr;
+ /* register content */
+ struct as10x_register_value reg_val;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
+
+union as10x_get_register {
+ /* request */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* register description */
+ struct as10x_register_addr reg_addr;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ /* register content */
+ struct as10x_register_value reg_val;
+ } rsp;
+} __packed;
+
+union as10x_cfg_change_mode {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* mode */
+ uint8_t mode;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ } rsp;
+} __packed;
struct as10x_cmd_header_t {
- uint16_t req_id;
- uint16_t prog;
- uint16_t version;
- uint16_t data_len;
-};
+ uint16_t req_id;
+ uint16_t prog;
+ uint16_t version;
+ uint16_t data_len;
+} __packed;
#define DUMP_BLOCK_SIZE 16
-typedef union {
- /* request */
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* dump memory type request */
- uint8_t dump_req;
- /* register description */
- struct as10x_register_addr reg_addr;
- /* nb blocks to read */
- uint16_t num_blocks;
- } req;
- /* response */
- struct {
- /* response identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- /* dump response */
- uint8_t dump_rsp;
- /* data */
- union {
- uint8_t data8[DUMP_BLOCK_SIZE];
- uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
- uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
- } u;
- } rsp;
-} DUMP_MEMORY;
-
-typedef union {
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* dump memory type request */
- uint8_t dump_req;
- } req;
- struct {
- /* request identifier */
- uint16_t proc_id;
- /* error */
- uint8_t error;
- /* dump response */
- uint8_t dump_rsp;
- /* dump data */
- uint8_t data[DUMP_BLOCK_SIZE];
- } rsp;
-} DUMPLOG_MEMORY;
-
-typedef union {
- /* request */
- struct {
- uint16_t proc_id;
- uint8_t data[64 - sizeof(struct as10x_cmd_header_t) -2 /* proc_id */];
- } req;
- /* response */
- struct {
- uint16_t proc_id;
- uint8_t error;
- uint8_t data[64 - sizeof(struct as10x_cmd_header_t) /* header */
- - 2 /* proc_id */ - 1 /* rc */];
- } rsp;
-} RAW_DATA;
+
+union as10x_dump_memory {
+ /* request */
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* dump memory type request */
+ uint8_t dump_req;
+ /* register description */
+ struct as10x_register_addr reg_addr;
+ /* nb blocks to read */
+ uint16_t num_blocks;
+ } req;
+ /* response */
+ struct {
+ /* response identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ /* dump response */
+ uint8_t dump_rsp;
+ /* data */
+ union {
+ uint8_t data8[DUMP_BLOCK_SIZE];
+ uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)];
+ uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)];
+ } u;
+ } rsp;
+} __packed;
+
+union as10x_dumplog_memory {
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* dump memory type request */
+ uint8_t dump_req;
+ } req;
+ struct {
+ /* request identifier */
+ uint16_t proc_id;
+ /* error */
+ uint8_t error;
+ /* dump response */
+ uint8_t dump_rsp;
+ /* dump data */
+ uint8_t data[DUMP_BLOCK_SIZE];
+ } rsp;
+} __packed;
+
+union as10x_raw_data {
+ /* request */
+ struct {
+ uint16_t proc_id;
+ uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
+ - 2 /* proc_id */];
+ } req;
+ /* response */
+ struct {
+ uint16_t proc_id;
+ uint8_t error;
+ uint8_t data[64 - sizeof(struct as10x_cmd_header_t)
+ - 2 /* proc_id */ - 1 /* rc */];
+ } rsp;
+} __packed;
struct as10x_cmd_t {
- /* header */
- struct as10x_cmd_header_t header;
- /* body */
- union {
- TURN_ON turn_on;
- TURN_OFF turn_off;
- SET_TUNE set_tune;
- GET_TUNE_STATUS get_tune_status;
- GET_TPS get_tps;
- COMMON common;
- ADD_PID_FILTER add_pid_filter;
- DEL_PID_FILTER del_pid_filter;
- START_STREAMING start_streaming;
- STOP_STREAMING stop_streaming;
- GET_DEMOD_STATS get_demod_stats;
- GET_IMPULSE_RESP get_impulse_rsp;
- FW_CONTEXT context;
- SET_REGISTER set_register;
- GET_REGISTER get_register;
- CFG_CHANGE_MODE cfg_change_mode;
- DUMP_MEMORY dump_memory;
- DUMPLOG_MEMORY dumplog_memory;
- RAW_DATA raw_data;
- } body;
-};
+ struct as10x_cmd_header_t header;
+ union {
+ union as10x_turn_on turn_on;
+ union as10x_turn_off turn_off;
+ union as10x_set_tune set_tune;
+ union as10x_get_tune_status get_tune_status;
+ union as10x_get_tps get_tps;
+ union as10x_common common;
+ union as10x_add_pid_filter add_pid_filter;
+ union as10x_del_pid_filter del_pid_filter;
+ union as10x_start_streaming start_streaming;
+ union as10x_stop_streaming stop_streaming;
+ union as10x_get_demod_stats get_demod_stats;
+ union as10x_get_impulse_resp get_impulse_rsp;
+ union as10x_fw_context context;
+ union as10x_set_register set_register;
+ union as10x_get_register get_register;
+ union as10x_cfg_change_mode cfg_change_mode;
+ union as10x_dump_memory dump_memory;
+ union as10x_dumplog_memory dumplog_memory;
+ union as10x_raw_data raw_data;
+ } body;
+} __packed;
struct as10x_token_cmd_t {
- /* token cmd */
- struct as10x_cmd_t c;
- /* token response */
- struct as10x_cmd_t r;
-};
-#pragma pack()
+ /* token cmd */
+ struct as10x_cmd_t c;
+ /* token response */
+ struct as10x_cmd_t r;
+} __packed;
/**************************/
@@ -491,50 +488,42 @@ void as10x_cmd_build(struct as10x_cmd_t *pcmd, uint16_t proc_id,
uint16_t cmd_len);
int as10x_rsp_parse(struct as10x_cmd_t *r, uint16_t proc_id);
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* as10x cmd */
-int as10x_cmd_turn_on(as10x_handle_t *phandle);
-int as10x_cmd_turn_off(as10x_handle_t *phandle);
+int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap);
+int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap);
-int as10x_cmd_set_tune(as10x_handle_t *phandle,
+int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
struct as10x_tune_args *ptune);
-int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
+int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
struct as10x_tune_status *pstatus);
-int as10x_cmd_get_tps(as10x_handle_t *phandle,
+int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap,
struct as10x_tps *ptps);
-int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
+int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
struct as10x_demod_stats *pdemod_stats);
-int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
+int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
uint8_t *is_ready);
/* as10x cmd stream */
-int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap,
struct as10x_ts_filter *filter);
-int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap,
uint16_t pid_value);
-int as10x_cmd_start_streaming(as10x_handle_t *phandle);
-int as10x_cmd_stop_streaming(as10x_handle_t *phandle);
+int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap);
+int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap);
/* as10x cmd cfg */
-int as10x_cmd_set_context(as10x_handle_t *phandle,
+int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap,
uint16_t tag,
uint32_t value);
-int as10x_cmd_get_context(as10x_handle_t *phandle,
+int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap,
uint16_t tag,
uint32_t *pvalue);
-int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode);
+int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode);
int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id);
-#ifdef __cplusplus
-}
-#endif
#endif
-/* EOF - vim: set textwidth=80 ts=3 sw=3 sts=3 et: */
diff --git a/drivers/staging/media/as102/as10x_cmd_cfg.c b/drivers/staging/media/as102/as10x_cmd_cfg.c
index ec6f69f..d2a4bce 100644
--- a/drivers/staging/media/as102/as10x_cmd_cfg.c
+++ b/drivers/staging/media/as102/as10x_cmd_cfg.c
@@ -28,13 +28,13 @@
/**
* as10x_cmd_get_context - Send get context command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @tag: context tag
* @pvalue: pointer where to store context value read
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
+int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
uint32_t *pvalue)
{
int error;
@@ -42,11 +42,11 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.context.req));
/* fill command */
@@ -55,14 +55,14 @@ int as10x_cmd_get_context(as10x_handle_t *phandle, uint16_t tag,
pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
- (uint8_t *) pcmd,
- sizeof(pcmd->body.context.req)
- + HEADER_SIZE,
- (uint8_t *) prsp,
- sizeof(prsp->body.context.rsp)
- + HEADER_SIZE);
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
+ (uint8_t *) pcmd,
+ sizeof(pcmd->body.context.req)
+ + HEADER_SIZE,
+ (uint8_t *) prsp,
+ sizeof(prsp->body.context.rsp)
+ + HEADER_SIZE);
} else {
error = AS10X_CMD_ERROR;
}
@@ -87,13 +87,13 @@ out:
/**
* as10x_cmd_set_context - send set context command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @tag: context tag
* @value: value to set in context
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
+int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
uint32_t value)
{
int error;
@@ -101,11 +101,11 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.context.req));
/* fill command */
@@ -116,14 +116,14 @@ int as10x_cmd_set_context(as10x_handle_t *phandle, uint16_t tag,
pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle,
- (uint8_t *) pcmd,
- sizeof(pcmd->body.context.req)
- + HEADER_SIZE,
- (uint8_t *) prsp,
- sizeof(prsp->body.context.rsp)
- + HEADER_SIZE);
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap,
+ (uint8_t *) pcmd,
+ sizeof(pcmd->body.context.req)
+ + HEADER_SIZE,
+ (uint8_t *) prsp,
+ sizeof(prsp->body.context.rsp)
+ + HEADER_SIZE);
} else {
error = AS10X_CMD_ERROR;
}
@@ -142,7 +142,7 @@ out:
/**
* as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @mode: mode selected:
* - ON : 0x0 => eLNA always ON
* - OFF : 0x1 => eLNA always OFF
@@ -151,18 +151,18 @@ out:
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
+int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode)
{
int error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.cfg_change_mode.req));
/* fill command */
@@ -171,8 +171,8 @@ int as10x_cmd_eLNA_change_mode(as10x_handle_t *phandle, uint8_t mode)
pcmd->body.cfg_change_mode.req.mode = mode;
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
sizeof(pcmd->body.cfg_change_mode.req)
+ HEADER_SIZE, (uint8_t *) prsp,
sizeof(prsp->body.cfg_change_mode.rsp)
diff --git a/drivers/staging/media/as102/as10x_cmd_stream.c b/drivers/staging/media/as102/as10x_cmd_stream.c
index 045c706..6d000f6 100644
--- a/drivers/staging/media/as102/as10x_cmd_stream.c
+++ b/drivers/staging/media/as102/as10x_cmd_stream.c
@@ -23,12 +23,12 @@
/**
* as10x_cmd_add_PID_filter - send add filter command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
* @filter: TSFilter filter for DVB-T
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_add_PID_filter(struct as10x_bus_adapter_t *adap,
struct as10x_ts_filter *filter)
{
int error;
@@ -36,11 +36,11 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.add_pid_filter.req));
/* fill command */
@@ -55,8 +55,8 @@ int as10x_cmd_add_PID_filter(as10x_handle_t *phandle,
pcmd->body.add_pid_filter.req.idx = 0xFF;
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
sizeof(pcmd->body.add_pid_filter.req)
+ HEADER_SIZE, (uint8_t *) prsp,
sizeof(prsp->body.add_pid_filter.rsp)
@@ -83,12 +83,12 @@ out:
/**
* as10x_cmd_del_PID_filter - Send delete filter command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapte
* @pid_value: PID to delete
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
+int as10x_cmd_del_PID_filter(struct as10x_bus_adapter_t *adap,
uint16_t pid_value)
{
int error;
@@ -96,11 +96,11 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.del_pid_filter.req));
/* fill command */
@@ -109,8 +109,8 @@ int as10x_cmd_del_PID_filter(as10x_handle_t *phandle,
pcmd->body.del_pid_filter.req.pid = cpu_to_le16(pid_value);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
sizeof(pcmd->body.del_pid_filter.req)
+ HEADER_SIZE, (uint8_t *) prsp,
sizeof(prsp->body.del_pid_filter.rsp)
@@ -132,22 +132,22 @@ out:
/**
* as10x_cmd_start_streaming - Send start streaming command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_start_streaming(as10x_handle_t *phandle)
+int as10x_cmd_start_streaming(struct as10x_bus_adapter_t *adap)
{
int error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.start_streaming.req));
/* fill command */
@@ -155,8 +155,8 @@ int as10x_cmd_start_streaming(as10x_handle_t *phandle)
cpu_to_le16(CONTROL_PROC_START_STREAMING);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
sizeof(pcmd->body.start_streaming.req)
+ HEADER_SIZE, (uint8_t *) prsp,
sizeof(prsp->body.start_streaming.rsp)
@@ -178,22 +178,22 @@ out:
/**
* as10x_cmd_stop_streaming - Send stop streaming command to AS10x
- * @phandle: pointer to AS10x handle
+ * @adap: pointer to AS10x bus adapter
*
* Return 0 on success or negative value in case of error.
*/
-int as10x_cmd_stop_streaming(as10x_handle_t *phandle)
+int as10x_cmd_stop_streaming(struct as10x_bus_adapter_t *adap)
{
int8_t error;
struct as10x_cmd_t *pcmd, *prsp;
ENTER();
- pcmd = phandle->cmd;
- prsp = phandle->rsp;
+ pcmd = adap->cmd;
+ prsp = adap->rsp;
/* prepare command */
- as10x_cmd_build(pcmd, (++phandle->cmd_xid),
+ as10x_cmd_build(pcmd, (++adap->cmd_xid),
sizeof(pcmd->body.stop_streaming.req));
/* fill command */
@@ -201,8 +201,8 @@ int as10x_cmd_stop_streaming(as10x_handle_t *phandle)
cpu_to_le16(CONTROL_PROC_STOP_STREAMING);
/* send command */
- if (phandle->ops->xfer_cmd) {
- error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
+ if (adap->ops->xfer_cmd) {
+ error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
sizeof(pcmd->body.stop_streaming.req)
+ HEADER_SIZE, (uint8_t *) prsp,
sizeof(prsp->body.stop_streaming.rsp)
diff --git a/drivers/staging/media/as102/as10x_handle.h b/drivers/staging/media/as102/as10x_handle.h
index 4f01a76..62b9795 100644
--- a/drivers/staging/media/as102/as10x_handle.h
+++ b/drivers/staging/media/as102/as10x_handle.h
@@ -17,41 +17,37 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __KERNEL__
-struct as102_bus_adapter_t;
+struct as10x_bus_adapter_t;
struct as102_dev_t;
-#define as10x_handle_t struct as102_bus_adapter_t
#include "as10x_cmd.h"
/* values for "mode" field */
-#define REGMODE8 8
-#define REGMODE16 16
-#define REGMODE32 32
+#define REGMODE8 8
+#define REGMODE16 16
+#define REGMODE32 32
struct as102_priv_ops_t {
- int (*upload_fw_pkt) (struct as102_bus_adapter_t *bus_adap,
+ int (*upload_fw_pkt) (struct as10x_bus_adapter_t *bus_adap,
unsigned char *buf, int buflen, int swap32);
- int (*send_cmd) (struct as102_bus_adapter_t *bus_adap,
+ int (*send_cmd) (struct as10x_bus_adapter_t *bus_adap,
unsigned char *buf, int buflen);
- int (*xfer_cmd) (struct as102_bus_adapter_t *bus_adap,
+ int (*xfer_cmd) (struct as10x_bus_adapter_t *bus_adap,
unsigned char *send_buf, int send_buf_len,
unsigned char *recv_buf, int recv_buf_len);
-/*
- int (*pid_filter) (struct as102_bus_adapter_t *bus_adap,
- int index, u16 pid, int onoff);
-*/
+
int (*start_stream) (struct as102_dev_t *dev);
void (*stop_stream) (struct as102_dev_t *dev);
- int (*reset_target) (struct as102_bus_adapter_t *bus_adap);
+ int (*reset_target) (struct as10x_bus_adapter_t *bus_adap);
- int (*read_write)(struct as102_bus_adapter_t *bus_adap, uint8_t mode,
+ int (*read_write)(struct as10x_bus_adapter_t *bus_adap, uint8_t mode,
uint32_t rd_addr, uint16_t rd_len,
uint32_t wr_addr, uint16_t wr_len);
- int (*as102_read_ep2) (struct as102_bus_adapter_t *bus_adap,
+ int (*as102_read_ep2) (struct as10x_bus_adapter_t *bus_adap,
unsigned char *recv_buf,
int recv_buf_len);
};
diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h
index 3dedb3c..fde8140 100644
--- a/drivers/staging/media/as102/as10x_types.h
+++ b/drivers/staging/media/as102/as10x_types.h
@@ -26,173 +26,169 @@
/*********************************/
/* bandwidth constant values */
-#define BW_5_MHZ 0x00
-#define BW_6_MHZ 0x01
-#define BW_7_MHZ 0x02
-#define BW_8_MHZ 0x03
+#define BW_5_MHZ 0x00
+#define BW_6_MHZ 0x01
+#define BW_7_MHZ 0x02
+#define BW_8_MHZ 0x03
/* hierarchy priority selection values */
-#define HIER_NO_PRIORITY 0x00
-#define HIER_LOW_PRIORITY 0x01
-#define HIER_HIGH_PRIORITY 0x02
+#define HIER_NO_PRIORITY 0x00
+#define HIER_LOW_PRIORITY 0x01
+#define HIER_HIGH_PRIORITY 0x02
/* constellation available values */
-#define CONST_QPSK 0x00
-#define CONST_QAM16 0x01
-#define CONST_QAM64 0x02
-#define CONST_UNKNOWN 0xFF
+#define CONST_QPSK 0x00
+#define CONST_QAM16 0x01
+#define CONST_QAM64 0x02
+#define CONST_UNKNOWN 0xFF
/* hierarchy available values */
-#define HIER_NONE 0x00
-#define HIER_ALPHA_1 0x01
-#define HIER_ALPHA_2 0x02
-#define HIER_ALPHA_4 0x03
-#define HIER_UNKNOWN 0xFF
+#define HIER_NONE 0x00
+#define HIER_ALPHA_1 0x01
+#define HIER_ALPHA_2 0x02
+#define HIER_ALPHA_4 0x03
+#define HIER_UNKNOWN 0xFF
/* interleaving available values */
-#define INTLV_NATIVE 0x00
-#define INTLV_IN_DEPTH 0x01
-#define INTLV_UNKNOWN 0xFF
+#define INTLV_NATIVE 0x00
+#define INTLV_IN_DEPTH 0x01
+#define INTLV_UNKNOWN 0xFF
/* code rate available values */
-#define CODE_RATE_1_2 0x00
-#define CODE_RATE_2_3 0x01
-#define CODE_RATE_3_4 0x02
-#define CODE_RATE_5_6 0x03
-#define CODE_RATE_7_8 0x04
-#define CODE_RATE_UNKNOWN 0xFF
+#define CODE_RATE_1_2 0x00
+#define CODE_RATE_2_3 0x01
+#define CODE_RATE_3_4 0x02
+#define CODE_RATE_5_6 0x03
+#define CODE_RATE_7_8 0x04
+#define CODE_RATE_UNKNOWN 0xFF
/* guard interval available values */
-#define GUARD_INT_1_32 0x00
-#define GUARD_INT_1_16 0x01
-#define GUARD_INT_1_8 0x02
-#define GUARD_INT_1_4 0x03
-#define GUARD_UNKNOWN 0xFF
+#define GUARD_INT_1_32 0x00
+#define GUARD_INT_1_16 0x01
+#define GUARD_INT_1_8 0x02
+#define GUARD_INT_1_4 0x03
+#define GUARD_UNKNOWN 0xFF
/* transmission mode available values */
-#define TRANS_MODE_2K 0x00
-#define TRANS_MODE_8K 0x01
-#define TRANS_MODE_4K 0x02
-#define TRANS_MODE_UNKNOWN 0xFF
+#define TRANS_MODE_2K 0x00
+#define TRANS_MODE_8K 0x01
+#define TRANS_MODE_4K 0x02
+#define TRANS_MODE_UNKNOWN 0xFF
/* DVBH signalling available values */
-#define TIMESLICING_PRESENT 0x01
-#define MPE_FEC_PRESENT 0x02
+#define TIMESLICING_PRESENT 0x01
+#define MPE_FEC_PRESENT 0x02
/* tune state available */
-#define TUNE_STATUS_NOT_TUNED 0x00
-#define TUNE_STATUS_IDLE 0x01
-#define TUNE_STATUS_LOCKING 0x02
-#define TUNE_STATUS_SIGNAL_DVB_OK 0x03
-#define TUNE_STATUS_STREAM_DETECTED 0x04
-#define TUNE_STATUS_STREAM_TUNED 0x05
-#define TUNE_STATUS_ERROR 0xFF
+#define TUNE_STATUS_NOT_TUNED 0x00
+#define TUNE_STATUS_IDLE 0x01
+#define TUNE_STATUS_LOCKING 0x02
+#define TUNE_STATUS_SIGNAL_DVB_OK 0x03
+#define TUNE_STATUS_STREAM_DETECTED 0x04
+#define TUNE_STATUS_STREAM_TUNED 0x05
+#define TUNE_STATUS_ERROR 0xFF
/* available TS FID filter types */
-#define TS_PID_TYPE_TS 0
-#define TS_PID_TYPE_PSI_SI 1
-#define TS_PID_TYPE_MPE 2
+#define TS_PID_TYPE_TS 0
+#define TS_PID_TYPE_PSI_SI 1
+#define TS_PID_TYPE_MPE 2
/* number of echos available */
-#define MAX_ECHOS 15
+#define MAX_ECHOS 15
/* Context types */
-#define CONTEXT_LNA 1010
-#define CONTEXT_ELNA_HYSTERESIS 4003
-#define CONTEXT_ELNA_GAIN 4004
-#define CONTEXT_MER_THRESHOLD 5005
-#define CONTEXT_MER_OFFSET 5006
-#define CONTEXT_IR_STATE 7000
-#define CONTEXT_TSOUT_MSB_FIRST 7004
-#define CONTEXT_TSOUT_FALLING_EDGE 7005
+#define CONTEXT_LNA 1010
+#define CONTEXT_ELNA_HYSTERESIS 4003
+#define CONTEXT_ELNA_GAIN 4004
+#define CONTEXT_MER_THRESHOLD 5005
+#define CONTEXT_MER_OFFSET 5006
+#define CONTEXT_IR_STATE 7000
+#define CONTEXT_TSOUT_MSB_FIRST 7004
+#define CONTEXT_TSOUT_FALLING_EDGE 7005
/* Configuration modes */
-#define CFG_MODE_ON 0
-#define CFG_MODE_OFF 1
-#define CFG_MODE_AUTO 2
+#define CFG_MODE_ON 0
+#define CFG_MODE_OFF 1
+#define CFG_MODE_AUTO 2
-#pragma pack(1)
struct as10x_tps {
- uint8_t constellation;
- uint8_t hierarchy;
- uint8_t interleaving_mode;
- uint8_t code_rate_HP;
- uint8_t code_rate_LP;
- uint8_t guard_interval;
- uint8_t transmission_mode;
- uint8_t DVBH_mask_HP;
- uint8_t DVBH_mask_LP;
- uint16_t cell_ID;
-};
+ uint8_t modulation;
+ uint8_t hierarchy;
+ uint8_t interleaving_mode;
+ uint8_t code_rate_HP;
+ uint8_t code_rate_LP;
+ uint8_t guard_interval;
+ uint8_t transmission_mode;
+ uint8_t DVBH_mask_HP;
+ uint8_t DVBH_mask_LP;
+ uint16_t cell_ID;
+} __packed;
struct as10x_tune_args {
- /* frequency */
- uint32_t freq;
- /* bandwidth */
- uint8_t bandwidth;
- /* hierarchy selection */
- uint8_t hier_select;
- /* constellation */
- uint8_t constellation;
- /* hierarchy */
- uint8_t hierarchy;
- /* interleaving mode */
- uint8_t interleaving_mode;
- /* code rate */
- uint8_t code_rate;
- /* guard interval */
- uint8_t guard_interval;
- /* transmission mode */
- uint8_t transmission_mode;
-};
+ /* frequency */
+ uint32_t freq;
+ /* bandwidth */
+ uint8_t bandwidth;
+ /* hierarchy selection */
+ uint8_t hier_select;
+ /* constellation */
+ uint8_t modulation;
+ /* hierarchy */
+ uint8_t hierarchy;
+ /* interleaving mode */
+ uint8_t interleaving_mode;
+ /* code rate */
+ uint8_t code_rate;
+ /* guard interval */
+ uint8_t guard_interval;
+ /* transmission mode */
+ uint8_t transmission_mode;
+} __packed;
struct as10x_tune_status {
- /* tune status */
- uint8_t tune_state;
- /* signal strength */
- int16_t signal_strength;
- /* packet error rate 10^-4 */
- uint16_t PER;
- /* bit error rate 10^-4 */
- uint16_t BER;
-};
+ /* tune status */
+ uint8_t tune_state;
+ /* signal strength */
+ int16_t signal_strength;
+ /* packet error rate 10^-4 */
+ uint16_t PER;
+ /* bit error rate 10^-4 */
+ uint16_t BER;
+} __packed;
struct as10x_demod_stats {
- /* frame counter */
- uint32_t frame_count;
- /* Bad frame counter */
- uint32_t bad_frame_count;
- /* Number of wrong bytes fixed by Reed-Solomon */
- uint32_t bytes_fixed_by_rs;
- /* Averaged MER */
- uint16_t mer;
- /* statistics calculation state indicator (started or not) */
- uint8_t has_started;
-};
+ /* frame counter */
+ uint32_t frame_count;
+ /* Bad frame counter */
+ uint32_t bad_frame_count;
+ /* Number of wrong bytes fixed by Reed-Solomon */
+ uint32_t bytes_fixed_by_rs;
+ /* Averaged MER */
+ uint16_t mer;
+ /* statistics calculation state indicator (started or not) */
+ uint8_t has_started;
+} __packed;
struct as10x_ts_filter {
- uint16_t pid; /** valid PID value 0x00 : 0x2000 */
- uint8_t type; /** Red TS_PID_TYPE_<N> values */
- uint8_t idx; /** index in filtering table */
-};
+ uint16_t pid; /* valid PID value 0x00 : 0x2000 */
+ uint8_t type; /* Red TS_PID_TYPE_<N> values */
+ uint8_t idx; /* index in filtering table */
+} __packed;
struct as10x_register_value {
- uint8_t mode;
- union {
- uint8_t value8; /* 8 bit value */
- uint16_t value16; /* 16 bit value */
- uint32_t value32; /* 32 bit value */
- }u;
-};
-
-#pragma pack()
+ uint8_t mode;
+ union {
+ uint8_t value8; /* 8 bit value */
+ uint16_t value16; /* 16 bit value */
+ uint32_t value32; /* 32 bit value */
+ } u;
+} __packed;
struct as10x_register_addr {
- /* register addr */
- uint32_t addr;
- /* register mode access */
- uint8_t mode;
+ /* register addr */
+ uint32_t addr;
+ /* register mode access */
+ uint8_t mode;
};
-
#endif
diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
index 04e93c4..280c84e 100644
--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
@@ -218,9 +218,10 @@ dt3155_start_acq(struct dt3155_priv *pd)
* driver-specific callbacks (vb2_ops)
*/
static int
-dt3155_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
- unsigned int *num_planes, unsigned long sizes[],
- void *alloc_ctxs[])
+dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+
{
struct dt3155_priv *pd = vb2_get_drv_priv(q);
void *ret;
@@ -262,12 +263,6 @@ dt3155_buf_prepare(struct vb2_buffer *vb)
}
static int
-dt3155_start_streaming(struct vb2_queue *q)
-{
- return 0;
-}
-
-static int
dt3155_stop_streaming(struct vb2_queue *q)
{
struct dt3155_priv *pd = vb2_get_drv_priv(q);
@@ -308,7 +303,6 @@ const struct vb2_ops q_ops = {
.wait_prepare = dt3155_wait_prepare,
.wait_finish = dt3155_wait_finish,
.buf_prepare = dt3155_buf_prepare,
- .start_streaming = dt3155_start_streaming,
.stop_streaming = dt3155_stop_streaming,
.buf_queue = dt3155_buf_queue,
};
@@ -914,9 +908,10 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_req_region;
pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
- if (!pd->regs)
+ if (!pd->regs) {
err = -ENOMEM;
goto err_pci_iomap;
+ }
err = dt3155_init_board(pdev);
if (err)
goto err_init_board;
diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h
index 7b256a9..a007e74 100644
--- a/drivers/staging/media/easycap/easycap.h
+++ b/drivers/staging/media/easycap/easycap.h
@@ -98,7 +98,6 @@
#define EASYCAP_DRIVER_VERSION "0.9.01"
#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
-#define USB_SKEL_MINOR_BASE 192
#define DONGLE_MANY 8
#define INPUT_MANY 6
/*---------------------------------------------------------------------------*/
@@ -324,8 +323,6 @@ struct easycap {
int lost[INPUT_MANY];
int merit[180];
- long long int dnbydt;
-
int video_interface;
int video_altsetting_on;
int video_altsetting_off;
@@ -353,7 +350,6 @@ struct easycap {
u8 *pcache;
int video_mt;
int audio_mt;
- long long audio_bytes;
u32 isequence;
int vma_many;
@@ -450,9 +446,6 @@ struct easycap {
* SOUND PROPERTIES
*/
/*---------------------------------------------------------------------------*/
-
- int audio_buffer_many;
-
int allocation_audio_urb;
int allocation_audio_page;
int allocation_audio_struct;
@@ -469,72 +462,53 @@ struct easycap {
* 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_dqbuf(struct easycap *, int);
-int submit_video_urbs(struct easycap *);
-int kill_video_urbs(struct easycap *);
-int field2frame(struct easycap *);
-int redaub(struct easycap *, void *, void *,
- int, int, u8, u8, bool);
-void easycap_testcard(struct easycap *, int);
-int fillin_formats(void);
-int newinput(struct easycap *, int);
-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);
-int adjust_volume(struct easycap *, int);
+
+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 *);
-void easycap_alsa_complete(struct urb *);
-
-int easycap_sound_setup(struct easycap *);
-int submit_audio_urbs(struct easycap *);
-int kill_audio_urbs(struct easycap *);
-void easyoss_testtone(struct easycap *, int);
-int audio_setup(struct easycap *);
+int easycap_alsa_probe(struct easycap *);
+int easycap_audio_kill_urbs(struct easycap *);
+void easycap_alsa_complete(struct urb *);
/*---------------------------------------------------------------------------*/
/*
* LOW-LEVEL FUNCTION PROTOTYPES
*/
/*---------------------------------------------------------------------------*/
-int audio_gainget(struct usb_device *);
-int audio_gainset(struct usb_device *, s8);
+int easycap_audio_gainset(struct usb_device *, s8);
+int easycap_audio_setup(struct easycap *);
-int set_interface(struct usb_device *, u16);
-int wakeup_device(struct usb_device *);
-int confirm_resolution(struct usb_device *);
-int confirm_stream(struct usb_device *);
+int easycap_wakeup_device(struct usb_device *);
-int setup_stk(struct usb_device *, bool);
-int setup_saa(struct usb_device *, bool);
-int setup_vt(struct usb_device *);
-int check_stk(struct usb_device *, bool);
-int check_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 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 read_stk(struct usb_device *, u32);
-int write_saa(struct usb_device *, u16, u16);
-int write_000(struct usb_device *, u16, u16);
-int start_100(struct usb_device *);
-int stop_100(struct usb_device *);
-int write_300(struct usb_device *);
-int read_vt(struct usb_device *, u16);
-int write_vt(struct usb_device *, u16, u16);
-int isdongle(struct easycap *);
+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 *);
/*---------------------------------------------------------------------------*/
@@ -588,7 +562,6 @@ 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 usb_driver easycap_usb_driver;
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
index c99addf..9413b37 100644
--- a/drivers/staging/media/easycap/easycap_ioctl.c
+++ b/drivers/staging/media/easycap/easycap_ioctl.c
@@ -25,7 +25,6 @@
*/
/*****************************************************************************/
-#include <linux/version.h>
#include "easycap.h"
/*--------------------------------------------------------------------------*/
@@ -125,7 +124,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
}
if (peasycap->video_isoc_streaming) {
resubmit = true;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
} else
resubmit = false;
/*--------------------------------------------------------------------------*/
@@ -331,7 +330,7 @@ int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
}
if (resubmit)
- submit_video_urbs(peasycap);
+ easycap_video_submit_urbs(peasycap);
return 0;
}
/*****************************************************************************/
@@ -558,7 +557,7 @@ int adjust_format(struct easycap *peasycap,
peasycap->bytesperpixel * peasycap->width * peasycap->height;
if (peasycap->video_isoc_streaming) {
resubmit = true;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
} else
resubmit = false;
/*---------------------------------------------------------------------------*/
@@ -622,7 +621,7 @@ int adjust_format(struct easycap *peasycap,
}
/*---------------------------------------------------------------------------*/
if (resubmit)
- submit_video_urbs(peasycap);
+ easycap_video_submit_urbs(peasycap);
return peasycap_best_format - easycap_format;
}
@@ -667,16 +666,15 @@ int adjust_brightness(struct easycap *peasycap, int value)
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("adjusting brightness to 0x%02X\n", mood);
- return 0;
- } else {
+ if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
SAM("WARNING: failed to adjust brightness "
"to 0x%02X\n", mood);
return -ENOENT;
}
- break;
+ SAM("adjusting brightness to 0x%02X\n", mood);
+ return 0;
}
i1++;
}
@@ -726,15 +724,13 @@ int adjust_contrast(struct easycap *peasycap, int value)
JOM(8, "%i=peasycap->input\n", peasycap->input);
mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
- if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
- SAM("adjusting contrast to 0x%02X\n", mood);
- return 0;
- } else {
+ if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
SAM("WARNING: failed to adjust contrast to "
"0x%02X\n", mood);
return -ENOENT;
}
- break;
+ SAM("adjusting contrast to 0x%02X\n", mood);
+ return 0;
}
i1++;
}
@@ -784,14 +780,13 @@ int adjust_saturation(struct easycap *peasycap, int value)
} 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("adjusting saturation to 0x%02X\n", mood);
- return 0;
- } else {
+ 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++;
@@ -839,13 +834,12 @@ int adjust_hue(struct easycap *peasycap, int value)
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("adjusting hue to 0x%02X\n", mood);
- return 0;
- } else {
+ 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++;
@@ -854,7 +848,7 @@ int adjust_hue(struct easycap *peasycap, int value)
return -ENOENT;
}
/*****************************************************************************/
-int adjust_volume(struct easycap *peasycap, int value)
+static int adjust_volume(struct easycap *peasycap, int value)
{
s8 mood;
int i1;
@@ -885,15 +879,13 @@ int adjust_volume(struct easycap *peasycap, int value)
mood = (16 > peasycap->volume) ? 16 :
((31 < peasycap->volume) ? 31 :
(s8) peasycap->volume);
- if (!audio_gainset(peasycap->pusb_device, mood)) {
- SAM("adjusting volume to 0x%02X\n", mood);
- return 0;
- } else {
+ if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
SAM("WARNING: failed to adjust volume to "
"0x%2X\n", mood);
return -ENOENT;
}
- break;
+ SAM("adjusting volume to 0x%02X\n", mood);
+ return 0;
}
i1++;
}
@@ -971,7 +963,7 @@ long easycap_unlocked_ioctl(struct file *file,
SAM("ERROR: peasycap->pusb_device is NULL\n");
return -EFAULT;
}
- kd = isdongle(peasycap);
+ kd = easycap_isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
SAY("ERROR: cannot lock "
@@ -986,7 +978,7 @@ long easycap_unlocked_ioctl(struct file *file,
* IF NECESSARY, BAIL OUT.
*/
/*---------------------------------------------------------------------------*/
- if (kd != isdongle(peasycap))
+ if (kd != easycap_isdongle(peasycap))
return -ERESTARTSYS;
if (!file) {
SAY("ERROR: file is NULL\n");
@@ -1226,7 +1218,7 @@ long easycap_unlocked_ioctl(struct file *file,
return -EINVAL;
}
- rc = newinput(peasycap, (int)index);
+ rc = easycap_newinput(peasycap, (int)index);
if (0 == rc) {
JOM(8, "newinput(.,%i) OK\n", (int)index);
} else {
@@ -2209,7 +2201,7 @@ long easycap_unlocked_ioctl(struct file *file,
if (!peasycap->polled) {
do {
- rcdq = easycap_dqbuf(peasycap, 0);
+ rcdq = easycap_video_dqbuf(peasycap, 0);
if (-EIO == rcdq) {
JOM(8, "returning -EIO because "
"dqbuf() returned -EIO\n");
@@ -2313,7 +2305,7 @@ long easycap_unlocked_ioctl(struct file *file,
mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
- submit_video_urbs(peasycap);
+ easycap_video_submit_urbs(peasycap);
peasycap->video_idle = 0;
peasycap->audio_idle = 0;
peasycap->video_eof = 0;
diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c
index 0385735..0380bab 100644
--- a/drivers/staging/media/easycap/easycap_low.c
+++ b/drivers/staging/media/easycap/easycap_low.c
@@ -40,6 +40,7 @@
#include "easycap.h"
+
#define GET(X, Y, Z) do { \
int __rc; \
*(Z) = (u16)0; \
@@ -59,9 +60,9 @@
/*--------------------------------------------------------------------------*/
static const struct stk1160config {
- int reg;
- int set;
-} stk1160configPAL[256] = {
+ u16 reg;
+ u16 set;
+} stk1160configPAL[] = {
{0x000, 0x0098},
{0x002, 0x0093},
@@ -103,7 +104,7 @@ static const struct stk1160config {
{0xFFF, 0xFFFF}
};
/*--------------------------------------------------------------------------*/
-static const struct stk1160config stk1160configNTSC[256] = {
+static const struct stk1160config stk1160configNTSC[] = {
{0x000, 0x0098},
{0x002, 0x0093},
@@ -146,9 +147,9 @@ static const struct stk1160config stk1160configNTSC[256] = {
};
/*--------------------------------------------------------------------------*/
static const struct saa7113config {
- int reg;
- int set;
-} saa7113configPAL[256] = {
+ u8 reg;
+ u8 set;
+} saa7113configPAL[] = {
{0x01, 0x08},
{0x02, 0x80},
{0x03, 0x33},
@@ -202,7 +203,7 @@ static const struct saa7113config {
{0xFF, 0xFF}
};
/*--------------------------------------------------------------------------*/
-static const struct saa7113config saa7113configNTSC[256] = {
+static const struct saa7113config saa7113configNTSC[] = {
{0x01, 0x08},
{0x02, 0x80},
{0x03, 0x33},
@@ -355,101 +356,6 @@ static int wait_i2c(struct usb_device *p)
}
/****************************************************************************/
-int confirm_resolution(struct usb_device *p)
-{
- u8 get0, get1, get2, get3, get4, get5, get6, get7;
-
- if (!p)
- return -ENODEV;
- GET(p, 0x0110, &get0);
- GET(p, 0x0111, &get1);
- GET(p, 0x0112, &get2);
- GET(p, 0x0113, &get3);
- GET(p, 0x0114, &get4);
- GET(p, 0x0115, &get5);
- GET(p, 0x0116, &get6);
- GET(p, 0x0117, &get7);
- JOT(8, "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X\n",
- get0, get1, get2, get3, get4, get5, get6, get7);
- JOT(8, "....cf PAL_720x526: "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X\n",
- 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
- JOT(8, "....cf PAL_704x526: "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X\n",
- 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
- JOT(8, "....cf VGA_640x480: "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X, "
- "0x%03X, 0x%03X\n",
- 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
- return 0;
-}
-/****************************************************************************/
-int confirm_stream(struct usb_device *p)
-{
- u16 get2;
- u8 igot;
-
- if (!p)
- return -ENODEV;
- GET(p, 0x0100, &igot); get2 = 0x80 & igot;
- if (0x80 == get2)
- JOT(8, "confirm_stream: OK\n");
- else
- JOT(8, "confirm_stream: STUCK\n");
- 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, ir;
- const struct saa7113config *cfg;
- if (!p)
- return -ENODEV;
- cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
- for (i = 0; cfg[i].reg != 0xFF; i++)
- ir = write_saa(p, cfg[i].reg, cfg[i].set);
- return 0;
-}
-/****************************************************************************/
-int write_000(struct usb_device *p, u16 set2, u16 set0)
-{
- u8 igot0, igot2;
-
- if (!p)
- return -ENODEV;
- GET(p, 0x0002, &igot2);
- GET(p, 0x0000, &igot0);
- SET(p, 0x0002, set2);
- SET(p, 0x0000, set0);
- return 0;
-}
-/****************************************************************************/
int write_saa(struct usb_device *p, u16 reg0, u16 set0)
{
if (!p)
@@ -470,8 +376,7 @@ int write_saa(struct usb_device *p, u16 reg0, u16 set0)
* REGISTER 504: TARGET ADDRESS ON VT1612A
*/
/*--------------------------------------------------------------------------*/
-int
-write_vt(struct usb_device *p, u16 reg0, u16 set0)
+static int write_vt(struct usb_device *p, u16 reg0, u16 set0)
{
u8 igot;
u16 got502, got503;
@@ -508,7 +413,7 @@ write_vt(struct usb_device *p, u16 reg0, u16 set0)
* REGISTER 504: TARGET ADDRESS ON VT1612A
*/
/*--------------------------------------------------------------------------*/
-int read_vt(struct usb_device *p, u16 reg0)
+static int read_vt(struct usb_device *p, u16 reg0)
{
u8 igot;
u16 got502, got503;
@@ -532,7 +437,7 @@ int read_vt(struct usb_device *p, u16 reg0)
* THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
*/
/*--------------------------------------------------------------------------*/
-int write_300(struct usb_device *p)
+static int write_300(struct usb_device *p)
{
if (!p)
return -ENODEV;
@@ -545,32 +450,36 @@ int write_300(struct usb_device *p)
return 0;
}
/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- * NOTE: THE FOLLOWING IS NOT CHECKED:
- * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL.
- */
-/*--------------------------------------------------------------------------*/
-int check_saa(struct usb_device *p, bool ntsc)
+/****************************************************************************/
+int setup_stk(struct usb_device *p, bool ntsc)
{
- int i, ir, rc = 0;
- struct saa7113config const *cfg;
+ 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);
- cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
+ 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++) {
- if (0x0F == cfg[i].reg)
- continue;
- ir = read_saa(p, cfg[i].reg);
- if (ir != cfg[i].set) {
- SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n",
- cfg[i].reg, ir, cfg[i].set);
- rc--;
- }
+ 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 (rc < -8) ? rc : 0;
+ return 0;
}
/****************************************************************************/
int merit_saa(struct usb_device *p)
@@ -609,60 +518,22 @@ int ready_saa(struct usb_device *p)
msleep(marktime);
j++;
}
+
if (max == j)
return -1;
- else {
- 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;
-}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- * NOTE: THE FOLLOWING ARE NOT CHECKED:
- * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN
- * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config....[.].set)
- */
-/*--------------------------------------------------------------------------*/
-int check_stk(struct usb_device *p, bool ntsc)
-{
- int i, ir;
- const struct stk1160config *cfg;
-
- if (!p)
- return -ENODEV;
- cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
-
- for (i = 0; 0xFFF != cfg[i].reg; i++) {
- if (0x000 == cfg[i].reg || 0x002 == cfg[i].reg)
- continue;
-
- ir = read_stk(p, cfg[i].reg);
- if (0x100 == cfg[i].reg) {
- if ((ir != (0xFF & cfg[i].set)) &&
- (ir != (0x80 | (0xFF & cfg[i].set))) &&
- (0xFFFF != cfg[i].set)) {
- SAY("STK reg[0x%03X]=0x%02X expected 0x%02X\n",
- cfg[i].reg, ir, cfg[i].set);
- }
- continue;
- }
- if ((ir != (0xFF & cfg[i].set)) && (0xFFFF != cfg[i].set))
- SAY("STK register 0x%03X has 0x%02X,expected 0x%02X\n",
- cfg[i].reg, ir, cfg[i].set);
+ 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;
}
@@ -682,7 +553,7 @@ int read_saa(struct usb_device *p, u16 reg0)
return igot;
}
/****************************************************************************/
-int read_stk(struct usb_device *p, u32 reg0)
+static int read_stk(struct usb_device *p, u32 reg0)
{
u8 igot;
@@ -692,27 +563,7 @@ int read_stk(struct usb_device *p, u32 reg0)
GET(p, reg0, &igot);
return igot;
}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE
- *
- * CVBS+S-VIDEO 0 or 1 CVBS 1
- * FOUR-CVBS 0 or 1 CVBS1 1
- * FOUR-CVBS 2 CVBS2 2
- * FOUR-CVBS 3 CVBS3 3
- * FOUR-CVBS 4 CVBS4 4
- * CVBS+S-VIDEO 5 S-VIDEO 5
- *
- * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED:
- *
- * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED)
- * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT)
- *
-*/
-/*---------------------------------------------------------------------------*/
-int
-select_input(struct usb_device *p, int input, int mode)
+int select_input(struct usb_device *p, int input, int mode)
{
int ir;
@@ -877,10 +728,11 @@ int stop_100(struct usb_device *p)
/****************************************************************************/
/****************************************************************************/
/*****************************************************************************/
-int wakeup_device(struct usb_device *pusb_device)
+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,
@@ -888,8 +740,7 @@ int wakeup_device(struct usb_device *pusb_device)
0, NULL, 0, 50000);
}
/*****************************************************************************/
-int
-audio_setup(struct easycap *peasycap)
+int easycap_audio_setup(struct easycap *peasycap)
{
struct usb_device *pusb_device;
u8 buffer[1];
@@ -970,7 +821,7 @@ audio_setup(struct easycap *peasycap)
* SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
*/
/*---------------------------------------------------------------------------*/
- if (0 != audio_gainset(pusb_device, peasycap->gain))
+ if (easycap_audio_gainset(pusb_device, peasycap->gain))
SAY("ERROR: audio_gainset() failed\n");
check_vt(pusb_device);
return 0;
@@ -1047,7 +898,7 @@ int check_vt(struct usb_device *pusb_device)
* 31 12.0 22.5 34.5
*/
/*---------------------------------------------------------------------------*/
-int audio_gainset(struct usb_device *pusb_device, s8 loud)
+int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud)
{
int igot;
u8 tmp;
@@ -1115,15 +966,3 @@ int audio_gainset(struct usb_device *pusb_device, s8 loud)
return 0;
}
/*****************************************************************************/
-int audio_gainget(struct usb_device *pusb_device)
-{
- int igot;
-
- if (!pusb_device)
- return -ENODEV;
- igot = read_vt(pusb_device, 0x001C);
- if (0 > igot)
- SAY("ERROR: failed to read VT1612A register 0x1C\n");
- return igot;
-}
-/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c
index a45c0b5..8ff5f38 100644
--- a/drivers/staging/media/easycap/easycap_main.c
+++ b/drivers/staging/media/easycap/easycap_main.c
@@ -66,6 +66,10 @@ 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)
{
@@ -109,23 +113,13 @@ const char *strerror(int err)
#undef ERRNOSTR
}
-/*---------------------------------------------------------------------------*/
-/*
- * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
- *
- * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
- * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
- * THIS IS THE CASE FOR OpenSUSE.
- */
-/*---------------------------------------------------------------------------*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
*/
/*---------------------------------------------------------------------------*/
-int isdongle(struct easycap *peasycap)
+int easycap_isdongle(struct easycap *peasycap)
{
int k;
if (!peasycap)
@@ -161,14 +155,13 @@ static int easycap_open(struct inode *inode, struct file *file)
if (!peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
return -EFAULT;
- } else {
- JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
}
+
+ JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
+
file->private_data = peasycap;
- rc = wakeup_device(peasycap->pusb_device);
- if (0 == rc)
- JOM(8, "wakeup_device() OK\n");
- else {
+ 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");
@@ -176,6 +169,7 @@ static int easycap_open(struct inode *inode, struct file *file)
SAM("ERROR: wakeup_device() rc = %i\n", rc);
return rc;
}
+ JOM(8, "wakeup_device() OK\n");
peasycap->input = 0;
rc = reset(peasycap);
if (rc) {
@@ -303,7 +297,7 @@ static int reset(struct easycap *peasycap)
peasycap->saturation = -8192;
peasycap->hue = -8192;
- rc = newinput(peasycap, input);
+ rc = easycap_newinput(peasycap, input);
if (rc) {
SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
@@ -364,8 +358,7 @@ static int reset(struct easycap *peasycap)
* SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
*/
/*---------------------------------------------------------------------------*/
-int
-newinput(struct easycap *peasycap, int input)
+int easycap_newinput(struct easycap *peasycap, int input)
{
int rc, k, m, mood, off;
int inputnow, video_idlenow, audio_idlenow;
@@ -397,7 +390,7 @@ newinput(struct easycap *peasycap, int input)
peasycap->audio_idle = 1;
if (peasycap->video_isoc_streaming) {
resubmit = true;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
} else {
resubmit = false;
}
@@ -532,7 +525,7 @@ newinput(struct easycap *peasycap, int input)
return -EFAULT;
}
if (resubmit)
- submit_video_urbs(peasycap);
+ easycap_video_submit_urbs(peasycap);
peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
peasycap->video_idle = video_idlenow;
@@ -542,7 +535,7 @@ newinput(struct easycap *peasycap, int input)
return 0;
}
/*****************************************************************************/
-int submit_video_urbs(struct easycap *peasycap)
+int easycap_video_submit_urbs(struct easycap *peasycap)
{
struct data_urb *pdata_urb;
struct urb *purb;
@@ -616,43 +609,53 @@ int submit_video_urbs(struct easycap *peasycap)
peasycap->video_eof = 1;
}
- if (isbad) {
- JOM(4, "attempting cleanup instead of submitting\n");
- list_for_each(plist_head, (peasycap->purb_video_head)) {
- pdata_urb = list_entry(plist_head,
- struct data_urb, list_head);
- if (pdata_urb) {
- purb = pdata_urb->purb;
- if (purb)
- usb_kill_urb(purb);
- }
- }
- peasycap->video_isoc_streaming = 0;
- } else {
+ if (isbad)
+ easycap_video_kill_urbs(peasycap);
+ else
peasycap->video_isoc_streaming = 1;
- JOM(4, "submitted %i video urbs\n", m);
- }
} else {
JOM(4, "already streaming video urbs\n");
}
return 0;
}
/*****************************************************************************/
-int kill_video_urbs(struct easycap *peasycap)
+int easycap_audio_kill_urbs(struct easycap *peasycap)
{
int m;
struct list_head *plist_head;
struct data_urb *pdata_urb;
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
+ if (!peasycap->audio_isoc_streaming)
+ return 0;
+
+ if (!peasycap->purb_audio_head) {
+ SAM("ERROR: peasycap->purb_audio_head is NULL\n");
return -EFAULT;
}
- if (!peasycap->video_isoc_streaming) {
- JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
- peasycap->video_isoc_streaming);
- return 0;
+
+ 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;
@@ -690,8 +693,8 @@ static int videodev_release(struct video_device *pvideo_device)
SAY("ending unsuccessfully\n");
return -EFAULT;
}
- if (0 != kill_video_urbs(peasycap)) {
- SAM("ERROR: kill_video_urbs() failed\n");
+ if (easycap_video_kill_urbs(peasycap)) {
+ SAM("ERROR: easycap_video_kill_urbs() failed\n");
return -EFAULT;
}
JOM(4, "ending successfully\n");
@@ -727,27 +730,22 @@ static void easycap_delete(struct kref *pkref)
SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
return;
}
- kd = isdongle(peasycap);
+ kd = easycap_isdongle(peasycap);
/*---------------------------------------------------------------------------*/
/*
* FREE VIDEO.
*/
/*---------------------------------------------------------------------------*/
if (peasycap->purb_video_head) {
- JOM(4, "freeing video urbs\n");
m = 0;
- list_for_each(plist_head, (peasycap->purb_video_head)) {
+ list_for_each(plist_head, peasycap->purb_video_head) {
pdata_urb = list_entry(plist_head,
struct data_urb, list_head);
- if (!pdata_urb) {
- JOM(4, "ERROR: pdata_urb is NULL\n");
- } else {
- if (pdata_urb->purb) {
- usb_free_urb(pdata_urb->purb);
- pdata_urb->purb = NULL;
- peasycap->allocation_video_urb -= 1;
- m++;
- }
+ if (pdata_urb && pdata_urb->purb) {
+ usb_free_urb(pdata_urb->purb);
+ pdata_urb->purb = NULL;
+ peasycap->allocation_video_urb--;
+ m++;
}
}
@@ -763,7 +761,6 @@ static void easycap_delete(struct kref *pkref)
peasycap->allocation_video_struct -=
sizeof(struct data_urb);
kfree(pdata_urb);
- pdata_urb = NULL;
m++;
}
}
@@ -828,15 +825,11 @@ static void easycap_delete(struct kref *pkref)
list_for_each(plist_head, (peasycap->purb_audio_head)) {
pdata_urb = list_entry(plist_head,
struct data_urb, list_head);
- if (!pdata_urb)
- JOM(4, "ERROR: pdata_urb is NULL\n");
- else {
- if (pdata_urb->purb) {
- usb_free_urb(pdata_urb->purb);
- pdata_urb->purb = NULL;
- peasycap->allocation_audio_urb -= 1;
- m++;
- }
+ 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);
@@ -851,7 +844,6 @@ static void easycap_delete(struct kref *pkref)
peasycap->allocation_audio_struct -=
sizeof(struct data_urb);
kfree(pdata_urb);
- pdata_urb = NULL;
m++;
}
}
@@ -940,7 +932,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
- kd = isdongle(peasycap);
+ 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);
@@ -952,7 +944,7 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
* peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
* IF NECESSARY, BAIL OUT.
*/
- if (kd != isdongle(peasycap)) {
+ if (kd != easycap_isdongle(peasycap)) {
mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
@@ -980,21 +972,21 @@ static unsigned int easycap_poll(struct file *file, poll_table *wait)
*/
return -ERESTARTSYS;
/*---------------------------------------------------------------------------*/
- rc = easycap_dqbuf(peasycap, 0);
+ rc = easycap_video_dqbuf(peasycap, 0);
peasycap->polled = 1;
mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
- if (0 == rc)
- return POLLIN | POLLRDNORM;
- else
+ if (rc)
return POLLERR;
- }
+
+ return POLLIN | POLLRDNORM;
+}
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
*/
/*---------------------------------------------------------------------------*/
-int easycap_dqbuf(struct easycap *peasycap, int mode)
+int easycap_video_dqbuf(struct easycap *peasycap, int mode)
{
int input, ifield, miss, rc;
@@ -1080,7 +1072,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
JOM(8, " ... failed returning -EIO\n");
peasycap->video_eof = 1;
peasycap->audio_eof = 1;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
return -EIO;
}
peasycap->status = 0;
@@ -1090,7 +1082,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
#endif /*PERSEVERE*/
peasycap->video_eof = 1;
peasycap->audio_eof = 1;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
JOM(8, "returning -EIO\n");
return -EIO;
}
@@ -1143,7 +1135,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
JOM(8, " ... failed returning -EIO\n");
peasycap->video_eof = 1;
peasycap->audio_eof = 1;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
return -EIO;
}
peasycap->status = 0;
@@ -1153,7 +1145,7 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
#endif /*PERSEVERE*/
peasycap->video_eof = 1;
peasycap->audio_eof = 1;
- kill_video_urbs(peasycap);
+ easycap_video_kill_urbs(peasycap);
JOM(8, "returning -EIO\n");
return -EIO;
}
@@ -1207,12 +1199,9 @@ int easycap_dqbuf(struct easycap *peasycap, int mode)
* WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
* odd==false IS TRANSFERRED TO THE FRAME BUFFER.
*
- * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
- * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
*/
/*---------------------------------------------------------------------------*/
-int
-field2frame(struct easycap *peasycap)
+static int field2frame(struct easycap *peasycap)
{
void *pex, *pad;
@@ -1221,7 +1210,7 @@ field2frame(struct easycap *peasycap)
int rc, bytesperpixel, multiplier;
int much, more, over, rump, caches, input;
u8 mask, margin;
- bool odd, isuy, decimatepixel, offerfields, badinput;
+ bool odd, isuy, decimatepixel, badinput;
if (!peasycap) {
SAY("ERROR: peasycap is NULL\n");
@@ -1237,8 +1226,6 @@ field2frame(struct easycap *peasycap)
peasycap->field_buffer[peasycap->field_read][0].input,
peasycap->field_read, peasycap->frame_fill);
JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
- if (peasycap->offerfields)
- JOM(8, "===== offerfields\n");
/*---------------------------------------------------------------------------*/
/*
@@ -1260,7 +1247,6 @@ field2frame(struct easycap *peasycap)
#endif /*EASYCAP_TESTCARD*/
/*---------------------------------------------------------------------------*/
- offerfields = peasycap->offerfields;
bytesperpixel = peasycap->bytesperpixel;
decimatepixel = peasycap->decimatepixel;
@@ -1601,9 +1587,9 @@ field2frame(struct easycap *peasycap)
* REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
*/
/*---------------------------------------------------------------------------*/
-int
-redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
- u8 mask, u8 margin, bool isuy)
+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;
@@ -2855,20 +2841,7 @@ static void easycap_complete(struct urb *purb)
}
return;
}
-static const struct file_operations easycap_fops = {
- .owner = THIS_MODULE,
- .open = easycap_open,
- .unlocked_ioctl = easycap_unlocked_ioctl,
- .poll = easycap_poll,
- .mmap = easycap_mmap,
- .llseek = no_llseek,
-};
-static const struct usb_class_driver easycap_class = {
- .name = "usb/easycap%d",
- .fops = &easycap_fops,
- .minor_base = USB_SKEL_MINOR_BASE,
-};
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+
static const struct v4l2_file_operations v4l2_fops = {
.owner = THIS_MODULE,
.open = easycap_open_noinode,
@@ -2917,6 +2890,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAY("ERROR: usb_host_interface not found\n");
return -EFAULT;
}
+
interface = &alt->desc;
if (!interface) {
SAY("ERROR: intf_descriptor is NULL\n");
@@ -2976,44 +2950,31 @@ static int easycap_usb_probe(struct usb_interface *intf,
if (mutex_lock_interruptible(&mutex_dongle)) {
SAY("ERROR: cannot down mutex_dongle\n");
return -ERESTARTSYS;
- } else {
-/*---------------------------------------------------------------------------*/
- /*
- * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
- * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
- *
- * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
- * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
- * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
- */
-/*---------------------------------------------------------------------------*/
- for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
- if ((!easycapdc60_dongle[ndong].peasycap) &&
- (!mutex_is_locked(&easycapdc60_dongle
- [ndong].mutex_video)) &&
- (!mutex_is_locked(&easycapdc60_dongle
- [ndong].mutex_audio))) {
- easycapdc60_dongle[ndong].peasycap = peasycap;
- peasycap->isdongle = ndong;
- JOM(8, "intf[%i]: peasycap-->easycap"
- "_dongle[%i].peasycap\n",
- bInterfaceNumber, ndong);
- break;
- }
- }
- if (DONGLE_MANY <= ndong) {
- SAM("ERROR: too many dongles\n");
- mutex_unlock(&mutex_dongle);
- return -ENOMEM;
+ }
+
+ for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+ if ((!easycapdc60_dongle[ndong].peasycap) &&
+ (!mutex_is_locked(&easycapdc60_dongle
+ [ndong].mutex_video)) &&
+ (!mutex_is_locked(&easycapdc60_dongle
+ [ndong].mutex_audio))) {
+ easycapdc60_dongle[ndong].peasycap = peasycap;
+ peasycap->isdongle = ndong;
+ JOM(8, "intf[%i]: peasycap-->easycap"
+ "_dongle[%i].peasycap\n",
+ bInterfaceNumber, ndong);
+ break;
}
+ }
+
+ if (DONGLE_MANY <= ndong) {
+ SAM("ERROR: too many dongles\n");
mutex_unlock(&mutex_dongle);
+ return -ENOMEM;
}
+ mutex_unlock(&mutex_dongle);
+
peasycap->allocation_video_struct = sizeof(struct easycap);
- peasycap->allocation_video_page = 0;
- peasycap->allocation_video_urb = 0;
- peasycap->allocation_audio_struct = 0;
- peasycap->allocation_audio_page = 0;
- peasycap->allocation_audio_urb = 0;
/*---------------------------------------------------------------------------*/
/*
@@ -3023,7 +2984,6 @@ static int easycap_usb_probe(struct usb_interface *intf,
peasycap->pusb_device = usbdev;
peasycap->pusb_interface = intf;
- peasycap->ilk = 0;
peasycap->microphone = false;
peasycap->video_interface = -1;
@@ -3042,38 +3002,21 @@ static int easycap_usb_probe(struct usb_interface *intf,
peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
- for (k = 0; k < INPUT_MANY; k++)
- peasycap->lost[k] = 0;
- peasycap->skip = 0;
- peasycap->skipped = 0;
- peasycap->offerfields = 0;
/*---------------------------------------------------------------------------*/
/*
* DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
*/
/*---------------------------------------------------------------------------*/
- rc = fillin_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);
-/*---------------------------------------------------------------------------*/
-/*
- * ... AND POPULATE easycap.inputset[]
-*/
-/*---------------------------------------------------------------------------*/
- /* FIXME: maybe we just use memset 0 */
+
+ /* ... AND POPULATE easycap.inputset[] */
+
inputset = peasycap->inputset;
- for (k = 0; k < INPUT_MANY; k++) {
- inputset[k].input_ok = 0;
- inputset[k].standard_offset_ok = 0;
- inputset[k].format_offset_ok = 0;
- inputset[k].brightness_ok = 0;
- inputset[k].contrast_ok = 0;
- inputset[k].saturation_ok = 0;
- inputset[k].hue_ok = 0;
- }
fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
m = 0;
@@ -3390,11 +3333,10 @@ static int easycap_usb_probe(struct usb_interface *intf,
if (!isokalt) {
SAM("ERROR: no viable video_altsetting_on\n");
return -ENOENT;
- } else {
- peasycap->video_altsetting_on = okalt[isokalt - 1];
- JOM(4, "%i=video_altsetting_on <====\n",
- peasycap->video_altsetting_on);
}
+ peasycap->video_altsetting_on = okalt[isokalt - 1];
+ JOM(4, "%i=video_altsetting_on <====\n",
+ peasycap->video_altsetting_on);
/*---------------------------------------------------------------------------*/
/*
* DECIDE THE VIDEO STREAMING PARAMETERS
@@ -3480,8 +3422,9 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAM("ERROR: Could not allocate frame "
"buffer %i page %i\n", k, m);
return -ENOMEM;
- } else
- peasycap->allocation_video_page += 1;
+ }
+
+ peasycap->allocation_video_page += 1;
peasycap->frame_buffer[k][m].pgo = pbuf;
}
peasycap->frame_buffer[k][m].pto =
@@ -3510,11 +3453,11 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAM("ERROR: Could not allocate field"
" buffer %i page %i\n", k, m);
return -ENOMEM;
- }
- else
- peasycap->allocation_video_page += 1;
- peasycap->field_buffer[k][m].pgo = pbuf;
}
+
+ peasycap->allocation_video_page += 1;
+ peasycap->field_buffer[k][m].pgo = pbuf;
+ }
peasycap->field_buffer[k][m].pto =
peasycap->field_buffer[k][m].pgo;
}
@@ -3538,9 +3481,9 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAM("ERROR: Could not allocate isoc video buffer "
"%i\n", k);
return -ENOMEM;
- } else
- peasycap->allocation_video_page +=
- BIT(VIDEO_ISOC_ORDER);
+ }
+ peasycap->allocation_video_page +=
+ BIT(VIDEO_ISOC_ORDER);
peasycap->video_isoc_buffer[k].pgo = pbuf;
peasycap->video_isoc_buffer[k].pto =
@@ -3569,15 +3512,17 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAM("ERROR: usb_alloc_urb returned NULL for buffer "
"%i\n", k);
return -ENOMEM;
- } else
- peasycap->allocation_video_urb += 1;
+ }
+
+ peasycap->allocation_video_urb += 1;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
if (!pdata_urb) {
SAM("ERROR: Could not allocate struct data_urb.\n");
return -ENOMEM;
- } else
- peasycap->allocation_video_struct +=
+ }
+
+ peasycap->allocation_video_struct +=
sizeof(struct data_urb);
pdata_urb->purb = purb;
@@ -3694,13 +3639,12 @@ static int easycap_usb_probe(struct usb_interface *intf,
err("Not able to register with videodev");
videodev_release(&(peasycap->video_device));
return -ENODEV;
- } else {
- (peasycap->registered_video)++;
- SAM("registered with videodev: %i=minor\n",
- peasycap->video_device.minor);
- peasycap->minor = peasycap->video_device.minor;
}
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
+ peasycap->registered_video++;
+ SAM("registered with videodev: %i=minor\n",
+ peasycap->video_device.minor);
+ peasycap->minor = peasycap->video_device.minor;
break;
}
@@ -3734,11 +3678,10 @@ static int easycap_usb_probe(struct usb_interface *intf,
if (!isokalt) {
SAM("ERROR: no viable audio_altsetting_on\n");
return -ENOENT;
- } else {
- peasycap->audio_altsetting_on = okalt[isokalt - 1];
- JOM(4, "%i=audio_altsetting_on <====\n",
- peasycap->audio_altsetting_on);
}
+ 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);
@@ -3847,8 +3790,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
SAM("ERROR: Could not allocate isoc audio buffer "
"%i\n", k);
return -ENOMEM;
- } else
- peasycap->allocation_audio_page +=
+ }
+ peasycap->allocation_audio_page +=
BIT(AUDIO_ISOC_ORDER);
peasycap->audio_isoc_buffer[k].pgo = pbuf;
@@ -3996,12 +3939,9 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
{
struct usb_host_interface *pusb_host_interface;
struct usb_interface_descriptor *pusb_interface_descriptor;
- u8 bInterfaceNumber;
struct easycap *peasycap;
-
- struct list_head *plist_head;
- struct data_urb *pdata_urb;
- int minor, m, kd;
+ int minor, kd;
+ u8 bInterfaceNumber;
JOT(4, "\n");
@@ -4036,45 +3976,14 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
peasycap->audio_eof = 1;
wake_up_interruptible(&(peasycap->wq_video));
wake_up_interruptible(&(peasycap->wq_audio));
-/*---------------------------------------------------------------------------*/
+
switch (bInterfaceNumber) {
- case 0: {
- if (peasycap->purb_video_head) {
- 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) {
- if (pdata_urb->purb) {
- usb_kill_urb(pdata_urb->purb);
- m++;
- }
- }
- }
- JOM(4, "%i video urbs killed\n", m);
- }
+ case 0:
+ easycap_video_kill_urbs(peasycap);
break;
- }
-/*---------------------------------------------------------------------------*/
- case 2: {
- if (peasycap->purb_audio_head) {
- JOM(4, "killing 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) {
- if (pdata_urb->purb) {
- usb_kill_urb(pdata_urb->purb);
- m++;
- }
- }
- }
- JOM(4, "%i audio urbs killed\n", m);
- }
+ case 2:
+ easycap_audio_kill_urbs(peasycap);
break;
- }
default:
break;
}
@@ -4087,7 +3996,7 @@ static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
* AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
*/
/*--------------------------------------------------------------------------*/
- kd = isdongle(peasycap);
+ kd = easycap_isdongle(peasycap);
switch (bInterfaceNumber) {
case 0: {
if (0 <= kd && DONGLE_MANY > kd) {
@@ -4212,7 +4121,7 @@ static struct usb_device_id easycap_usb_device_id_table[] = {
};
MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
-struct usb_driver easycap_usb_driver = {
+static struct usb_driver easycap_usb_driver = {
.name = "easycap",
.id_table = easycap_usb_device_id_table,
.probe = easycap_usb_probe,
diff --git a/drivers/staging/media/easycap/easycap_settings.c b/drivers/staging/media/easycap/easycap_settings.c
index 70f59b1..3f5f5b3 100644
--- a/drivers/staging/media/easycap/easycap_settings.c
+++ b/drivers/staging/media/easycap/easycap_settings.c
@@ -313,7 +313,7 @@ const struct easycap_standard easycap_standard[] = {
struct easycap_format easycap_format[1 + SETTINGS_MANY];
-int fillin_formats(void)
+int easycap_video_fillin_formats(void)
{
const char *name1, *name2, *name3, *name4;
struct v4l2_format *fmt;
diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c
index b22bb39..8c8bcae 100644
--- a/drivers/staging/media/easycap/easycap_sound.c
+++ b/drivers/staging/media/easycap/easycap_sound.c
@@ -56,6 +56,141 @@ static const struct snd_pcm_hardware alsa_hardware = {
};
+/*---------------------------------------------------------------------------*/
+/*
+ * 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;
+}
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
@@ -64,8 +199,7 @@ static const struct snd_pcm_hardware alsa_hardware = {
* IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
*/
/*---------------------------------------------------------------------------*/
-void
-easycap_alsa_complete(struct urb *purb)
+void easycap_alsa_complete(struct urb *purb)
{
struct easycap *peasycap;
struct snd_pcm_substream *pss;
@@ -458,7 +592,6 @@ static int easycap_alsa_ack(struct snd_pcm_substream *pss)
static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
{
struct easycap *peasycap;
- int retval;
JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
SNDRV_PCM_TRIGGER_STOP);
@@ -481,7 +614,7 @@ static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
break;
}
default:
- retval = -EINVAL;
+ return -EINVAL;
}
return 0;
}
@@ -615,202 +748,3 @@ int easycap_alsa_probe(struct easycap *peasycap)
return 0;
}
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * COMMON AUDIO INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-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 = 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 = wakeup_device(peasycap->pusb_device);
- JOM(8, "wakeup_device() returned %i\n", rc);
-
- peasycap->audio_eof = 0;
- peasycap->audio_idle = 0;
-
- submit_audio_urbs(peasycap);
-
- JOM(4, "finished initialization\n");
- return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * SUBMIT ALL AUDIO URBS.
- */
-/*---------------------------------------------------------------------------*/
-int
-submit_audio_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_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) {
- JOM(4, "attempting cleanup instead of submitting\n");
- 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);
- }
- peasycap->audio_isoc_streaming = 0;
- } else {
- peasycap->audio_isoc_streaming = m;
- JOM(4, "submitted %i audio urbs\n", m);
- }
-
- return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- * KILL ALL AUDIO URBS.
- */
-/*---------------------------------------------------------------------------*/
-int
-kill_audio_urbs(struct easycap *peasycap)
-{
- int m;
- struct list_head *plist_head;
- struct data_urb *pdata_urb;
-
- if (!peasycap) {
- SAY("ERROR: peasycap is NULL\n");
- return -EFAULT;
- }
-
- if (!peasycap->audio_isoc_streaming) {
- JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
- 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;
- JOM(4, "killing 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_kill_urb(pdata_urb->purb);
- m++;
- }
- }
- JOM(4, "%i audio urbs killed\n", m);
-
- return 0;
-}
-/*****************************************************************************/
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index b7175fe..70e006b 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -1054,7 +1054,13 @@ static int go7007_usb_probe(struct usb_interface *intf,
else
go->hpi_ops = &go7007_usb_onboard_hpi_ops;
go->hpi_context = usb;
- usb_fill_int_urb(usb->intr_urb, usb->usbdev,
+ if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
+ usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
+ usb_rcvbulkpipe(usb->usbdev, 4),
+ usb->intr_urb->transfer_buffer, 2*sizeof(u16),
+ go7007_usb_readinterrupt_complete, go);
+ else
+ usb_fill_int_urb(usb->intr_urb, usb->usbdev,
usb_rcvintpipe(usb->usbdev, 4),
usb->intr_urb->transfer_buffer, 2*sizeof(u16),
go7007_usb_readinterrupt_complete, go, 8);
diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c
index deac938..d071c838 100644
--- a/drivers/staging/media/go7007/snd-go7007.c
+++ b/drivers/staging/media/go7007/snd-go7007.c
@@ -38,7 +38,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
module_param_array(id, charp, NULL, 0444);
diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c
index c5a0d27..4d20e9f 100644
--- a/drivers/staging/media/lirc/lirc_bt829.c
+++ b/drivers/staging/media/lirc/lirc_bt829.c
@@ -53,7 +53,7 @@ static unsigned char do_get_bits(void);
#define DRIVER_NAME "lirc_bt829"
-static int debug;
+static bool debug;
#define dprintk(fmt, args...) \
do { \
if (debug) \
diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c
index 6cd4cd6..7a25017 100644
--- a/drivers/staging/media/lirc/lirc_igorplugusb.c
+++ b/drivers/staging/media/lirc/lirc_igorplugusb.c
@@ -62,9 +62,9 @@
/* debugging support */
#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
+static bool debug = 1;
#else
-static int debug;
+static bool debug;
#endif
#define dprintk(fmt, args...) \
diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c
index f682180..5f7f8cd 100644
--- a/drivers/staging/media/lirc/lirc_imon.c
+++ b/drivers/staging/media/lirc/lirc_imon.c
@@ -63,7 +63,7 @@ static int display_open(struct inode *inode, struct file *file);
static int display_close(struct inode *inode, struct file *file);
/* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos);
/* LIRC driver function prototypes */
@@ -369,7 +369,7 @@ static int send_packet(struct imon_context *context)
* than 32 bytes are provided spaces will be appended to
* generate a full screen.
*/
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos)
{
int i;
diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
index 792aac0..dd2bca7 100644
--- a/drivers/staging/media/lirc/lirc_parallel.c
+++ b/drivers/staging/media/lirc/lirc_parallel.c
@@ -63,8 +63,8 @@
/*** Global Variables ***/
-static int debug;
-static int check_pselecd;
+static bool debug;
+static bool check_pselecd;
unsigned int irq = LIRC_IRQ;
unsigned int io = LIRC_PORT;
@@ -752,4 +752,4 @@ module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging messages");
module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Check for printer (default: 0)");
+MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
index 8a060a8..8dd8897 100644
--- a/drivers/staging/media/lirc/lirc_serial.c
+++ b/drivers/staging/media/lirc/lirc_serial.c
@@ -107,13 +107,13 @@ struct lirc_serial {
static int type;
static int io;
static int irq;
-static int iommap;
+static bool iommap;
static int ioshift;
-static int softcarrier = 1;
-static int share_irq;
-static int debug;
+static bool softcarrier = 1;
+static bool share_irq;
+static bool debug;
static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
-static int txsense; /* 0 = active high, 1 = active low */
+static bool txsense; /* 0 = active high, 1 = active low */
#define dprintk(fmt, args...) \
do { \
@@ -773,7 +773,7 @@ static int hardware_init_port(void)
/* we fail, there's nothing here */
printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test "
"failed, cannot continue\n");
- return -EINVAL;
+ return -ENODEV;
}
@@ -836,25 +836,22 @@ static int hardware_init_port(void)
return 0;
}
-static int init_port(void)
+static int __devinit lirc_serial_probe(struct platform_device *dev)
{
int i, nlow, nhigh, result;
result = request_irq(irq, irq_handler,
(share_irq ? IRQF_SHARED : 0),
LIRC_DRIVER_NAME, (void *)&hardware);
-
- switch (result) {
- case -EBUSY:
- printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
- return -EBUSY;
- case -EINVAL:
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": Bad irq number or handler\n");
- return -EINVAL;
- default:
- break;
- };
+ if (result < 0) {
+ if (result == -EBUSY)
+ printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n",
+ irq);
+ else if (result == -EINVAL)
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": Bad irq number or handler\n");
+ return result;
+ }
/* Reserve io region. */
/*
@@ -875,11 +872,13 @@ static int init_port(void)
": or compile the serial port driver as module and\n");
printk(KERN_WARNING LIRC_DRIVER_NAME
": make sure this module is loaded first\n");
- return -EBUSY;
+ result = -EBUSY;
+ goto exit_free_irq;
}
- if (hardware_init_port() < 0)
- return -EINVAL;
+ result = hardware_init_port();
+ if (result < 0)
+ goto exit_release_region;
/* Initialize pulse/space widths */
init_timing_params(duty_cycle, freq);
@@ -911,6 +910,28 @@ static int init_port(void)
dprintk("Interrupt %d, port %04x obtained\n", irq, io);
return 0;
+
+exit_release_region:
+ if (iommap != 0)
+ release_mem_region(iommap, 8 << ioshift);
+ else
+ release_region(io, 8);
+exit_free_irq:
+ free_irq(irq, (void *)&hardware);
+
+ return result;
+}
+
+static int __devexit lirc_serial_remove(struct platform_device *dev)
+{
+ free_irq(irq, (void *)&hardware);
+
+ if (iommap != 0)
+ release_mem_region(iommap, 8 << ioshift);
+ else
+ release_region(io, 8);
+
+ return 0;
}
static int set_use_inc(void *data)
@@ -955,7 +976,7 @@ static ssize_t lirc_write(struct file *file, const char *buf,
int *wbuf;
if (!(hardware[type].features & LIRC_CAN_SEND_PULSE))
- return -EBADF;
+ return -EPERM;
count = n / sizeof(int);
if (n % sizeof(int) || count % 2 == 0)
@@ -1006,11 +1027,11 @@ static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
return result;
/* only LIRC_MODE_PULSE supported */
if (value != LIRC_MODE_PULSE)
- return -ENOSYS;
+ return -EINVAL;
break;
case LIRC_GET_LENGTH:
- return -ENOSYS;
+ return -ENOIOCTLCMD;
break;
case LIRC_SET_SEND_DUTY_CYCLE:
@@ -1076,16 +1097,6 @@ static struct lirc_driver driver = {
static struct platform_device *lirc_serial_dev;
-static int __devinit lirc_serial_probe(struct platform_device *dev)
-{
- return 0;
-}
-
-static int __devexit lirc_serial_remove(struct platform_device *dev)
-{
- return 0;
-}
-
static int lirc_serial_suspend(struct platform_device *dev,
pm_message_t state)
{
@@ -1111,11 +1122,11 @@ static void lirc_serial_exit(void);
static int lirc_serial_resume(struct platform_device *dev)
{
unsigned long flags;
+ int result;
- if (hardware_init_port() < 0) {
- lirc_serial_exit();
- return -EINVAL;
- }
+ result = hardware_init_port();
+ if (result < 0)
+ return result;
spin_lock_irqsave(&hardware[type].lock, flags);
/* Enable Interrupt */
@@ -1148,7 +1159,7 @@ static int __init lirc_serial_init(void)
/* Init read buffer. */
result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
if (result < 0)
- return -ENOMEM;
+ return result;
result = platform_driver_register(&lirc_serial_driver);
if (result) {
@@ -1188,10 +1199,6 @@ static int __init lirc_serial_init_module(void)
{
int result;
- result = lirc_serial_init();
- if (result)
- return result;
-
switch (type) {
case LIRC_HOMEBREW:
case LIRC_IRDEO:
@@ -1211,8 +1218,7 @@ static int __init lirc_serial_init_module(void)
break;
#endif
default:
- result = -EINVAL;
- goto exit_serial_exit;
+ return -EINVAL;
}
if (!softcarrier) {
switch (type) {
@@ -1228,37 +1234,26 @@ static int __init lirc_serial_init_module(void)
}
}
- result = init_port();
- if (result < 0)
- goto exit_serial_exit;
+ result = lirc_serial_init();
+ if (result)
+ return result;
+
driver.features = hardware[type].features;
driver.dev = &lirc_serial_dev->dev;
driver.minor = lirc_register_driver(&driver);
if (driver.minor < 0) {
printk(KERN_ERR LIRC_DRIVER_NAME
": register_chrdev failed!\n");
- result = -EIO;
- goto exit_release;
+ lirc_serial_exit();
+ return driver.minor;
}
return 0;
-exit_release:
- release_region(io, 8);
-exit_serial_exit:
- lirc_serial_exit();
- return result;
}
static void __exit lirc_serial_exit_module(void)
{
- lirc_serial_exit();
-
- free_irq(irq, (void *)&hardware);
-
- if (iommap != 0)
- release_mem_region(iommap, 8 << ioshift);
- else
- release_region(io, 8);
lirc_unregister_driver(driver.minor);
+ lirc_serial_exit();
dprintk("cleaned up module\n");
}
diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c
index 6903d39..c94382b 100644
--- a/drivers/staging/media/lirc/lirc_sir.c
+++ b/drivers/staging/media/lirc/lirc_sir.c
@@ -173,7 +173,7 @@ static DEFINE_SPINLOCK(hardware_lock);
static int rx_buf[RBUF_LEN];
static unsigned int rx_tail, rx_head;
-static int debug;
+static bool debug;
#define dprintk(fmt, args...) \
do { \
if (debug) \
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 0302d82..76ea4a8 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -155,8 +155,8 @@ static struct mutex tx_data_lock;
#define zilog_info(s, args...) printk(KERN_INFO KBUILD_MODNAME ": " s, ## args)
/* module parameters */
-static int debug; /* debug output */
-static int tx_only; /* only handle the IR Tx function */
+static bool debug; /* debug output */
+static bool tx_only; /* only handle the IR Tx function */
static int minor = -1; /* minor number */
#define dprintk(fmt, args...) \
diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/staging/media/solo6x10/Makefile
index 72816cf..337e38c 100644
--- a/drivers/staging/media/solo6x10/Makefile
+++ b/drivers/staging/media/solo6x10/Makefile
@@ -1,3 +1,3 @@
solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o
-obj-$(CONFIG_SOLO6X10) := solo6x10.o
+obj-$(CONFIG_SOLO6X10) += solo6x10.o
diff --git a/drivers/staging/media/solo6x10/jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
index 50defec..50defec 100644
--- a/drivers/staging/media/solo6x10/jpeg.h
+++ b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index bee7280..f8f0da9 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -26,7 +26,7 @@
#include <media/videobuf-dma-sg.h>
#include "solo6x10.h"
#include "tw28.h"
-#include "jpeg.h"
+#include "solo6x10-jpeg.h"
#define MIN_VID_BUFFERS 4
#define FRAME_BUF_SIZE (128 * 1024)
diff --git a/drivers/staging/octeon/Makefile b/drivers/staging/octeon/Makefile
index fc850ba..9012dee 100644
--- a/drivers/staging/octeon/Makefile
+++ b/drivers/staging/octeon/Makefile
@@ -20,9 +20,4 @@ octeon-ethernet-y += ethernet-sgmii.o
octeon-ethernet-y += ethernet-spi.o
octeon-ethernet-y += ethernet-tx.o
octeon-ethernet-y += ethernet-xaui.o
-octeon-ethernet-y += cvmx-pko.o cvmx-spi.o cvmx-cmd-queue.o \
- cvmx-helper-board.o cvmx-helper.o cvmx-helper-xaui.o \
- cvmx-helper-rgmii.o cvmx-helper-sgmii.o cvmx-helper-npi.o \
- cvmx-helper-loop.o cvmx-helper-spi.o cvmx-helper-util.o \
- cvmx-interrupt-decodes.o cvmx-interrupt-rsl.o
diff --git a/drivers/staging/octeon/cvmx-address.h b/drivers/staging/octeon/cvmx-address.h
deleted file mode 100644
index 3c74d82..0000000
--- a/drivers/staging/octeon/cvmx-address.h
+++ /dev/null
@@ -1,274 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2009 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * Typedefs and defines for working with Octeon physical addresses.
- *
- */
-#ifndef __CVMX_ADDRESS_H__
-#define __CVMX_ADDRESS_H__
-
-#if 0
-typedef enum {
- CVMX_MIPS_SPACE_XKSEG = 3LL,
- CVMX_MIPS_SPACE_XKPHYS = 2LL,
- CVMX_MIPS_SPACE_XSSEG = 1LL,
- CVMX_MIPS_SPACE_XUSEG = 0LL
-} cvmx_mips_space_t;
-#endif
-
-typedef enum {
- CVMX_MIPS_XKSEG_SPACE_KSEG0 = 0LL,
- CVMX_MIPS_XKSEG_SPACE_KSEG1 = 1LL,
- CVMX_MIPS_XKSEG_SPACE_SSEG = 2LL,
- CVMX_MIPS_XKSEG_SPACE_KSEG3 = 3LL
-} cvmx_mips_xkseg_space_t;
-
-/* decodes <14:13> of a kseg3 window address */
-typedef enum {
- CVMX_ADD_WIN_SCR = 0L,
- /* see cvmx_add_win_dma_dec_t for further decode */
- CVMX_ADD_WIN_DMA = 1L,
- CVMX_ADD_WIN_UNUSED = 2L,
- CVMX_ADD_WIN_UNUSED2 = 3L
-} cvmx_add_win_dec_t;
-
-/* decode within DMA space */
-typedef enum {
- /*
- * Add store data to the write buffer entry, allocating it if
- * necessary.
- */
- CVMX_ADD_WIN_DMA_ADD = 0L,
- /* send out the write buffer entry to DRAM */
- CVMX_ADD_WIN_DMA_SENDMEM = 1L,
- /* store data must be normal DRAM memory space address in this case */
- /* send out the write buffer entry as an IOBDMA command */
- CVMX_ADD_WIN_DMA_SENDDMA = 2L,
- /* see CVMX_ADD_WIN_DMA_SEND_DEC for data contents */
- /* send out the write buffer entry as an IO write */
- CVMX_ADD_WIN_DMA_SENDIO = 3L,
- /* store data must be normal IO space address in this case */
- /* send out a single-tick command on the NCB bus */
- CVMX_ADD_WIN_DMA_SENDSINGLE = 4L,
- /* no write buffer data needed/used */
-} cvmx_add_win_dma_dec_t;
-
-/*
- * Physical Address Decode
- *
- * Octeon-I HW never interprets this X (<39:36> reserved
- * for future expansion), software should set to 0.
- *
- * - 0x0 XXX0 0000 0000 to DRAM Cached
- * - 0x0 XXX0 0FFF FFFF
- *
- * - 0x0 XXX0 1000 0000 to Boot Bus Uncached (Converted to 0x1 00X0 1000 0000
- * - 0x0 XXX0 1FFF FFFF + EJTAG to 0x1 00X0 1FFF FFFF)
- *
- * - 0x0 XXX0 2000 0000 to DRAM Cached
- * - 0x0 XXXF FFFF FFFF
- *
- * - 0x1 00X0 0000 0000 to Boot Bus Uncached
- * - 0x1 00XF FFFF FFFF
- *
- * - 0x1 01X0 0000 0000 to Other NCB Uncached
- * - 0x1 FFXF FFFF FFFF devices
- *
- * Decode of all Octeon addresses
- */
-typedef union {
-
- uint64_t u64;
- /* mapped or unmapped virtual address */
- struct {
- uint64_t R:2;
- uint64_t offset:62;
- } sva;
-
- /* mapped USEG virtual addresses (typically) */
- struct {
- uint64_t zeroes:33;
- uint64_t offset:31;
- } suseg;
-
- /* mapped or unmapped virtual address */
- struct {
- uint64_t ones:33;
- uint64_t sp:2;
- uint64_t offset:29;
- } sxkseg;
-
- /*
- * physical address accessed through xkphys unmapped virtual
- * address.
- */
- struct {
- uint64_t R:2; /* CVMX_MIPS_SPACE_XKPHYS in this case */
- uint64_t cca:3; /* ignored by octeon */
- uint64_t mbz:10;
- uint64_t pa:49; /* physical address */
- } sxkphys;
-
- /* physical address */
- struct {
- uint64_t mbz:15;
- /* if set, the address is uncached and resides on MCB bus */
- uint64_t is_io:1;
- /*
- * the hardware ignores this field when is_io==0, else
- * device ID.
- */
- uint64_t did:8;
- /* the hardware ignores <39:36> in Octeon I */
- uint64_t unaddr:4;
- uint64_t offset:36;
- } sphys;
-
- /* physical mem address */
- struct {
- /* techically, <47:40> are dont-cares */
- uint64_t zeroes:24;
- /* the hardware ignores <39:36> in Octeon I */
- uint64_t unaddr:4;
- uint64_t offset:36;
- } smem;
-
- /* physical IO address */
- struct {
- uint64_t mem_region:2;
- uint64_t mbz:13;
- /* 1 in this case */
- uint64_t is_io:1;
- /*
- * The hardware ignores this field when is_io==0, else
- * device ID.
- */
- uint64_t did:8;
- /* the hardware ignores <39:36> in Octeon I */
- uint64_t unaddr:4;
- uint64_t offset:36;
- } sio;
-
- /*
- * Scratchpad virtual address - accessed through a window at
- * the end of kseg3
- */
- struct {
- uint64_t ones:49;
- /* CVMX_ADD_WIN_SCR (0) in this case */
- cvmx_add_win_dec_t csrdec:2;
- uint64_t addr:13;
- } sscr;
-
- /* there should only be stores to IOBDMA space, no loads */
- /*
- * IOBDMA virtual address - accessed through a window at the
- * end of kseg3
- */
- struct {
- uint64_t ones:49;
- uint64_t csrdec:2; /* CVMX_ADD_WIN_DMA (1) in this case */
- uint64_t unused2:3;
- uint64_t type:3;
- uint64_t addr:7;
- } sdma;
-
- struct {
- uint64_t didspace:24;
- uint64_t unused:40;
- } sfilldidspace;
-
-} cvmx_addr_t;
-
-/* These macros for used by 32 bit applications */
-
-#define CVMX_MIPS32_SPACE_KSEG0 1l
-#define CVMX_ADD_SEG32(segment, add) \
- (((int32_t)segment << 31) | (int32_t)(add))
-
-/*
- * Currently all IOs are performed using XKPHYS addressing. Linux uses
- * the CvmMemCtl register to enable XKPHYS addressing to IO space from
- * user mode. Future OSes may need to change the upper bits of IO
- * addresses. The following define controls the upper two bits for all
- * IO addresses generated by the simple executive library.
- */
-#define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS
-
-/* These macros simplify the process of creating common IO addresses */
-#define CVMX_ADD_SEG(segment, add) ((((uint64_t)segment) << 62) | (add))
-#ifndef CVMX_ADD_IO_SEG
-#define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add))
-#endif
-#define CVMX_ADDR_DIDSPACE(did) (((CVMX_IO_SEG) << 22) | ((1ULL) << 8) | (did))
-#define CVMX_ADDR_DID(did) (CVMX_ADDR_DIDSPACE(did) << 40)
-#define CVMX_FULL_DID(did, subdid) (((did) << 3) | (subdid))
-
- /* from include/ncb_rsl_id.v */
-#define CVMX_OCT_DID_MIS 0ULL /* misc stuff */
-#define CVMX_OCT_DID_GMX0 1ULL
-#define CVMX_OCT_DID_GMX1 2ULL
-#define CVMX_OCT_DID_PCI 3ULL
-#define CVMX_OCT_DID_KEY 4ULL
-#define CVMX_OCT_DID_FPA 5ULL
-#define CVMX_OCT_DID_DFA 6ULL
-#define CVMX_OCT_DID_ZIP 7ULL
-#define CVMX_OCT_DID_RNG 8ULL
-#define CVMX_OCT_DID_IPD 9ULL
-#define CVMX_OCT_DID_PKT 10ULL
-#define CVMX_OCT_DID_TIM 11ULL
-#define CVMX_OCT_DID_TAG 12ULL
- /* the rest are not on the IO bus */
-#define CVMX_OCT_DID_L2C 16ULL
-#define CVMX_OCT_DID_LMC 17ULL
-#define CVMX_OCT_DID_SPX0 18ULL
-#define CVMX_OCT_DID_SPX1 19ULL
-#define CVMX_OCT_DID_PIP 20ULL
-#define CVMX_OCT_DID_ASX0 22ULL
-#define CVMX_OCT_DID_ASX1 23ULL
-#define CVMX_OCT_DID_IOB 30ULL
-
-#define CVMX_OCT_DID_PKT_SEND CVMX_FULL_DID(CVMX_OCT_DID_PKT, 2ULL)
-#define CVMX_OCT_DID_TAG_SWTAG CVMX_FULL_DID(CVMX_OCT_DID_TAG, 0ULL)
-#define CVMX_OCT_DID_TAG_TAG1 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 1ULL)
-#define CVMX_OCT_DID_TAG_TAG2 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 2ULL)
-#define CVMX_OCT_DID_TAG_TAG3 CVMX_FULL_DID(CVMX_OCT_DID_TAG, 3ULL)
-#define CVMX_OCT_DID_TAG_NULL_RD CVMX_FULL_DID(CVMX_OCT_DID_TAG, 4ULL)
-#define CVMX_OCT_DID_TAG_CSR CVMX_FULL_DID(CVMX_OCT_DID_TAG, 7ULL)
-#define CVMX_OCT_DID_FAU_FAI CVMX_FULL_DID(CVMX_OCT_DID_IOB, 0ULL)
-#define CVMX_OCT_DID_TIM_CSR CVMX_FULL_DID(CVMX_OCT_DID_TIM, 0ULL)
-#define CVMX_OCT_DID_KEY_RW CVMX_FULL_DID(CVMX_OCT_DID_KEY, 0ULL)
-#define CVMX_OCT_DID_PCI_6 CVMX_FULL_DID(CVMX_OCT_DID_PCI, 6ULL)
-#define CVMX_OCT_DID_MIS_BOO CVMX_FULL_DID(CVMX_OCT_DID_MIS, 0ULL)
-#define CVMX_OCT_DID_PCI_RML CVMX_FULL_DID(CVMX_OCT_DID_PCI, 0ULL)
-#define CVMX_OCT_DID_IPD_CSR CVMX_FULL_DID(CVMX_OCT_DID_IPD, 7ULL)
-#define CVMX_OCT_DID_DFA_CSR CVMX_FULL_DID(CVMX_OCT_DID_DFA, 7ULL)
-#define CVMX_OCT_DID_MIS_CSR CVMX_FULL_DID(CVMX_OCT_DID_MIS, 7ULL)
-#define CVMX_OCT_DID_ZIP_CSR CVMX_FULL_DID(CVMX_OCT_DID_ZIP, 0ULL)
-
-#endif /* __CVMX_ADDRESS_H__ */
diff --git a/drivers/staging/octeon/cvmx-asxx-defs.h b/drivers/staging/octeon/cvmx-asxx-defs.h
deleted file mode 100644
index 91415a8..0000000
--- a/drivers/staging/octeon/cvmx-asxx-defs.h
+++ /dev/null
@@ -1,475 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_ASXX_DEFS_H__
-#define __CVMX_ASXX_DEFS_H__
-
-#define CVMX_ASXX_GMII_RX_CLK_SET(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000180ull + (((block_id) & 0) * 0x8000000ull))
-#define CVMX_ASXX_GMII_RX_DAT_SET(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000188ull + (((block_id) & 0) * 0x8000000ull))
-#define CVMX_ASXX_INT_EN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000018ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_INT_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000010ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_MII_RX_DAT_SET(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000190ull + (((block_id) & 0) * 0x8000000ull))
-#define CVMX_ASXX_PRT_LOOP(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000040ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_BYPASS(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000248ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_BYPASS_SETTING(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000250ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_COMP(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000220ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_DATA_DRV(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000218ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_FCRAM_MODE(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000210ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_NCTL_STRONG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000230ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_NCTL_WEAK(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000240ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_PCTL_STRONG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000228ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_PCTL_WEAK(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000238ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RLD_SETTING(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000258ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_CLK_SETX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000020ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_PRT_EN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000000ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_WOL(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000100ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_WOL_MSK(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000108ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_WOL_POWOK(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000118ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_RX_WOL_SIG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000110ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_TX_CLK_SETX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000048ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_TX_COMP_BYP(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000068ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_TX_HI_WATERX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000080ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_ASXX_TX_PRT_EN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000008ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_asxx_gmii_rx_clk_set {
- uint64_t u64;
- struct cvmx_asxx_gmii_rx_clk_set_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_gmii_rx_clk_set_s cn30xx;
- struct cvmx_asxx_gmii_rx_clk_set_s cn31xx;
- struct cvmx_asxx_gmii_rx_clk_set_s cn50xx;
-};
-
-union cvmx_asxx_gmii_rx_dat_set {
- uint64_t u64;
- struct cvmx_asxx_gmii_rx_dat_set_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_gmii_rx_dat_set_s cn30xx;
- struct cvmx_asxx_gmii_rx_dat_set_s cn31xx;
- struct cvmx_asxx_gmii_rx_dat_set_s cn50xx;
-};
-
-union cvmx_asxx_int_en {
- uint64_t u64;
- struct cvmx_asxx_int_en_s {
- uint64_t reserved_12_63:52;
- uint64_t txpsh:4;
- uint64_t txpop:4;
- uint64_t ovrflw:4;
- } s;
- struct cvmx_asxx_int_en_cn30xx {
- uint64_t reserved_11_63:53;
- uint64_t txpsh:3;
- uint64_t reserved_7_7:1;
- uint64_t txpop:3;
- uint64_t reserved_3_3:1;
- uint64_t ovrflw:3;
- } cn30xx;
- struct cvmx_asxx_int_en_cn30xx cn31xx;
- struct cvmx_asxx_int_en_s cn38xx;
- struct cvmx_asxx_int_en_s cn38xxp2;
- struct cvmx_asxx_int_en_cn30xx cn50xx;
- struct cvmx_asxx_int_en_s cn58xx;
- struct cvmx_asxx_int_en_s cn58xxp1;
-};
-
-union cvmx_asxx_int_reg {
- uint64_t u64;
- struct cvmx_asxx_int_reg_s {
- uint64_t reserved_12_63:52;
- uint64_t txpsh:4;
- uint64_t txpop:4;
- uint64_t ovrflw:4;
- } s;
- struct cvmx_asxx_int_reg_cn30xx {
- uint64_t reserved_11_63:53;
- uint64_t txpsh:3;
- uint64_t reserved_7_7:1;
- uint64_t txpop:3;
- uint64_t reserved_3_3:1;
- uint64_t ovrflw:3;
- } cn30xx;
- struct cvmx_asxx_int_reg_cn30xx cn31xx;
- struct cvmx_asxx_int_reg_s cn38xx;
- struct cvmx_asxx_int_reg_s cn38xxp2;
- struct cvmx_asxx_int_reg_cn30xx cn50xx;
- struct cvmx_asxx_int_reg_s cn58xx;
- struct cvmx_asxx_int_reg_s cn58xxp1;
-};
-
-union cvmx_asxx_mii_rx_dat_set {
- uint64_t u64;
- struct cvmx_asxx_mii_rx_dat_set_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_mii_rx_dat_set_s cn30xx;
- struct cvmx_asxx_mii_rx_dat_set_s cn50xx;
-};
-
-union cvmx_asxx_prt_loop {
- uint64_t u64;
- struct cvmx_asxx_prt_loop_s {
- uint64_t reserved_8_63:56;
- uint64_t ext_loop:4;
- uint64_t int_loop:4;
- } s;
- struct cvmx_asxx_prt_loop_cn30xx {
- uint64_t reserved_7_63:57;
- uint64_t ext_loop:3;
- uint64_t reserved_3_3:1;
- uint64_t int_loop:3;
- } cn30xx;
- struct cvmx_asxx_prt_loop_cn30xx cn31xx;
- struct cvmx_asxx_prt_loop_s cn38xx;
- struct cvmx_asxx_prt_loop_s cn38xxp2;
- struct cvmx_asxx_prt_loop_cn30xx cn50xx;
- struct cvmx_asxx_prt_loop_s cn58xx;
- struct cvmx_asxx_prt_loop_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_bypass {
- uint64_t u64;
- struct cvmx_asxx_rld_bypass_s {
- uint64_t reserved_1_63:63;
- uint64_t bypass:1;
- } s;
- struct cvmx_asxx_rld_bypass_s cn38xx;
- struct cvmx_asxx_rld_bypass_s cn38xxp2;
- struct cvmx_asxx_rld_bypass_s cn58xx;
- struct cvmx_asxx_rld_bypass_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_bypass_setting {
- uint64_t u64;
- struct cvmx_asxx_rld_bypass_setting_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_rld_bypass_setting_s cn38xx;
- struct cvmx_asxx_rld_bypass_setting_s cn38xxp2;
- struct cvmx_asxx_rld_bypass_setting_s cn58xx;
- struct cvmx_asxx_rld_bypass_setting_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_comp {
- uint64_t u64;
- struct cvmx_asxx_rld_comp_s {
- uint64_t reserved_9_63:55;
- uint64_t pctl:5;
- uint64_t nctl:4;
- } s;
- struct cvmx_asxx_rld_comp_cn38xx {
- uint64_t reserved_8_63:56;
- uint64_t pctl:4;
- uint64_t nctl:4;
- } cn38xx;
- struct cvmx_asxx_rld_comp_cn38xx cn38xxp2;
- struct cvmx_asxx_rld_comp_s cn58xx;
- struct cvmx_asxx_rld_comp_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_data_drv {
- uint64_t u64;
- struct cvmx_asxx_rld_data_drv_s {
- uint64_t reserved_8_63:56;
- uint64_t pctl:4;
- uint64_t nctl:4;
- } s;
- struct cvmx_asxx_rld_data_drv_s cn38xx;
- struct cvmx_asxx_rld_data_drv_s cn38xxp2;
- struct cvmx_asxx_rld_data_drv_s cn58xx;
- struct cvmx_asxx_rld_data_drv_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_fcram_mode {
- uint64_t u64;
- struct cvmx_asxx_rld_fcram_mode_s {
- uint64_t reserved_1_63:63;
- uint64_t mode:1;
- } s;
- struct cvmx_asxx_rld_fcram_mode_s cn38xx;
- struct cvmx_asxx_rld_fcram_mode_s cn38xxp2;
-};
-
-union cvmx_asxx_rld_nctl_strong {
- uint64_t u64;
- struct cvmx_asxx_rld_nctl_strong_s {
- uint64_t reserved_5_63:59;
- uint64_t nctl:5;
- } s;
- struct cvmx_asxx_rld_nctl_strong_s cn38xx;
- struct cvmx_asxx_rld_nctl_strong_s cn38xxp2;
- struct cvmx_asxx_rld_nctl_strong_s cn58xx;
- struct cvmx_asxx_rld_nctl_strong_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_nctl_weak {
- uint64_t u64;
- struct cvmx_asxx_rld_nctl_weak_s {
- uint64_t reserved_5_63:59;
- uint64_t nctl:5;
- } s;
- struct cvmx_asxx_rld_nctl_weak_s cn38xx;
- struct cvmx_asxx_rld_nctl_weak_s cn38xxp2;
- struct cvmx_asxx_rld_nctl_weak_s cn58xx;
- struct cvmx_asxx_rld_nctl_weak_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_pctl_strong {
- uint64_t u64;
- struct cvmx_asxx_rld_pctl_strong_s {
- uint64_t reserved_5_63:59;
- uint64_t pctl:5;
- } s;
- struct cvmx_asxx_rld_pctl_strong_s cn38xx;
- struct cvmx_asxx_rld_pctl_strong_s cn38xxp2;
- struct cvmx_asxx_rld_pctl_strong_s cn58xx;
- struct cvmx_asxx_rld_pctl_strong_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_pctl_weak {
- uint64_t u64;
- struct cvmx_asxx_rld_pctl_weak_s {
- uint64_t reserved_5_63:59;
- uint64_t pctl:5;
- } s;
- struct cvmx_asxx_rld_pctl_weak_s cn38xx;
- struct cvmx_asxx_rld_pctl_weak_s cn38xxp2;
- struct cvmx_asxx_rld_pctl_weak_s cn58xx;
- struct cvmx_asxx_rld_pctl_weak_s cn58xxp1;
-};
-
-union cvmx_asxx_rld_setting {
- uint64_t u64;
- struct cvmx_asxx_rld_setting_s {
- uint64_t reserved_13_63:51;
- uint64_t dfaset:5;
- uint64_t dfalag:1;
- uint64_t dfalead:1;
- uint64_t dfalock:1;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_rld_setting_cn38xx {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } cn38xx;
- struct cvmx_asxx_rld_setting_cn38xx cn38xxp2;
- struct cvmx_asxx_rld_setting_s cn58xx;
- struct cvmx_asxx_rld_setting_s cn58xxp1;
-};
-
-union cvmx_asxx_rx_clk_setx {
- uint64_t u64;
- struct cvmx_asxx_rx_clk_setx_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_rx_clk_setx_s cn30xx;
- struct cvmx_asxx_rx_clk_setx_s cn31xx;
- struct cvmx_asxx_rx_clk_setx_s cn38xx;
- struct cvmx_asxx_rx_clk_setx_s cn38xxp2;
- struct cvmx_asxx_rx_clk_setx_s cn50xx;
- struct cvmx_asxx_rx_clk_setx_s cn58xx;
- struct cvmx_asxx_rx_clk_setx_s cn58xxp1;
-};
-
-union cvmx_asxx_rx_prt_en {
- uint64_t u64;
- struct cvmx_asxx_rx_prt_en_s {
- uint64_t reserved_4_63:60;
- uint64_t prt_en:4;
- } s;
- struct cvmx_asxx_rx_prt_en_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t prt_en:3;
- } cn30xx;
- struct cvmx_asxx_rx_prt_en_cn30xx cn31xx;
- struct cvmx_asxx_rx_prt_en_s cn38xx;
- struct cvmx_asxx_rx_prt_en_s cn38xxp2;
- struct cvmx_asxx_rx_prt_en_cn30xx cn50xx;
- struct cvmx_asxx_rx_prt_en_s cn58xx;
- struct cvmx_asxx_rx_prt_en_s cn58xxp1;
-};
-
-union cvmx_asxx_rx_wol {
- uint64_t u64;
- struct cvmx_asxx_rx_wol_s {
- uint64_t reserved_2_63:62;
- uint64_t status:1;
- uint64_t enable:1;
- } s;
- struct cvmx_asxx_rx_wol_s cn38xx;
- struct cvmx_asxx_rx_wol_s cn38xxp2;
-};
-
-union cvmx_asxx_rx_wol_msk {
- uint64_t u64;
- struct cvmx_asxx_rx_wol_msk_s {
- uint64_t msk:64;
- } s;
- struct cvmx_asxx_rx_wol_msk_s cn38xx;
- struct cvmx_asxx_rx_wol_msk_s cn38xxp2;
-};
-
-union cvmx_asxx_rx_wol_powok {
- uint64_t u64;
- struct cvmx_asxx_rx_wol_powok_s {
- uint64_t reserved_1_63:63;
- uint64_t powerok:1;
- } s;
- struct cvmx_asxx_rx_wol_powok_s cn38xx;
- struct cvmx_asxx_rx_wol_powok_s cn38xxp2;
-};
-
-union cvmx_asxx_rx_wol_sig {
- uint64_t u64;
- struct cvmx_asxx_rx_wol_sig_s {
- uint64_t reserved_32_63:32;
- uint64_t sig:32;
- } s;
- struct cvmx_asxx_rx_wol_sig_s cn38xx;
- struct cvmx_asxx_rx_wol_sig_s cn38xxp2;
-};
-
-union cvmx_asxx_tx_clk_setx {
- uint64_t u64;
- struct cvmx_asxx_tx_clk_setx_s {
- uint64_t reserved_5_63:59;
- uint64_t setting:5;
- } s;
- struct cvmx_asxx_tx_clk_setx_s cn30xx;
- struct cvmx_asxx_tx_clk_setx_s cn31xx;
- struct cvmx_asxx_tx_clk_setx_s cn38xx;
- struct cvmx_asxx_tx_clk_setx_s cn38xxp2;
- struct cvmx_asxx_tx_clk_setx_s cn50xx;
- struct cvmx_asxx_tx_clk_setx_s cn58xx;
- struct cvmx_asxx_tx_clk_setx_s cn58xxp1;
-};
-
-union cvmx_asxx_tx_comp_byp {
- uint64_t u64;
- struct cvmx_asxx_tx_comp_byp_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_asxx_tx_comp_byp_cn30xx {
- uint64_t reserved_9_63:55;
- uint64_t bypass:1;
- uint64_t pctl:4;
- uint64_t nctl:4;
- } cn30xx;
- struct cvmx_asxx_tx_comp_byp_cn30xx cn31xx;
- struct cvmx_asxx_tx_comp_byp_cn38xx {
- uint64_t reserved_8_63:56;
- uint64_t pctl:4;
- uint64_t nctl:4;
- } cn38xx;
- struct cvmx_asxx_tx_comp_byp_cn38xx cn38xxp2;
- struct cvmx_asxx_tx_comp_byp_cn50xx {
- uint64_t reserved_17_63:47;
- uint64_t bypass:1;
- uint64_t reserved_13_15:3;
- uint64_t pctl:5;
- uint64_t reserved_5_7:3;
- uint64_t nctl:5;
- } cn50xx;
- struct cvmx_asxx_tx_comp_byp_cn58xx {
- uint64_t reserved_13_63:51;
- uint64_t pctl:5;
- uint64_t reserved_5_7:3;
- uint64_t nctl:5;
- } cn58xx;
- struct cvmx_asxx_tx_comp_byp_cn58xx cn58xxp1;
-};
-
-union cvmx_asxx_tx_hi_waterx {
- uint64_t u64;
- struct cvmx_asxx_tx_hi_waterx_s {
- uint64_t reserved_4_63:60;
- uint64_t mark:4;
- } s;
- struct cvmx_asxx_tx_hi_waterx_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t mark:3;
- } cn30xx;
- struct cvmx_asxx_tx_hi_waterx_cn30xx cn31xx;
- struct cvmx_asxx_tx_hi_waterx_s cn38xx;
- struct cvmx_asxx_tx_hi_waterx_s cn38xxp2;
- struct cvmx_asxx_tx_hi_waterx_cn30xx cn50xx;
- struct cvmx_asxx_tx_hi_waterx_s cn58xx;
- struct cvmx_asxx_tx_hi_waterx_s cn58xxp1;
-};
-
-union cvmx_asxx_tx_prt_en {
- uint64_t u64;
- struct cvmx_asxx_tx_prt_en_s {
- uint64_t reserved_4_63:60;
- uint64_t prt_en:4;
- } s;
- struct cvmx_asxx_tx_prt_en_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t prt_en:3;
- } cn30xx;
- struct cvmx_asxx_tx_prt_en_cn30xx cn31xx;
- struct cvmx_asxx_tx_prt_en_s cn38xx;
- struct cvmx_asxx_tx_prt_en_s cn38xxp2;
- struct cvmx_asxx_tx_prt_en_cn30xx cn50xx;
- struct cvmx_asxx_tx_prt_en_s cn58xx;
- struct cvmx_asxx_tx_prt_en_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-cmd-queue.c b/drivers/staging/octeon/cvmx-cmd-queue.c
deleted file mode 100644
index e9809d3..0000000
--- a/drivers/staging/octeon/cvmx-cmd-queue.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Support functions for managing command queues used for
- * various hardware blocks.
- */
-
-#include <linux/kernel.h>
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-#include "cvmx-fpa.h"
-#include "cvmx-cmd-queue.h"
-
-#include <asm/octeon/cvmx-npei-defs.h>
-#include <asm/octeon/cvmx-pexp-defs.h>
-#include "cvmx-pko-defs.h"
-
-/**
- * This application uses this pointer to access the global queue
- * state. It points to a bootmem named block.
- */
-__cvmx_cmd_queue_all_state_t *__cvmx_cmd_queue_state_ptr;
-
-/**
- * Initialize the Global queue state pointer.
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-static cvmx_cmd_queue_result_t __cvmx_cmd_queue_init_state_ptr(void)
-{
- char *alloc_name = "cvmx_cmd_queues";
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
- extern uint64_t octeon_reserve32_memory;
-#endif
-
- if (likely(__cvmx_cmd_queue_state_ptr))
- return CVMX_CMD_QUEUE_SUCCESS;
-
-#if defined(CONFIG_CAVIUM_RESERVE32) && CONFIG_CAVIUM_RESERVE32
- if (octeon_reserve32_memory)
- __cvmx_cmd_queue_state_ptr =
- cvmx_bootmem_alloc_named_range(sizeof(*__cvmx_cmd_queue_state_ptr),
- octeon_reserve32_memory,
- octeon_reserve32_memory +
- (CONFIG_CAVIUM_RESERVE32 <<
- 20) - 1, 128, alloc_name);
- else
-#endif
- __cvmx_cmd_queue_state_ptr =
- cvmx_bootmem_alloc_named(sizeof(*__cvmx_cmd_queue_state_ptr),
- 128,
- alloc_name);
- if (__cvmx_cmd_queue_state_ptr)
- memset(__cvmx_cmd_queue_state_ptr, 0,
- sizeof(*__cvmx_cmd_queue_state_ptr));
- else {
- struct cvmx_bootmem_named_block_desc *block_desc =
- cvmx_bootmem_find_named_block(alloc_name);
- if (block_desc)
- __cvmx_cmd_queue_state_ptr =
- cvmx_phys_to_ptr(block_desc->base_addr);
- else {
- cvmx_dprintf
- ("ERROR: cvmx_cmd_queue_initialize: Unable to get named block %s.\n",
- alloc_name);
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
- }
- return CVMX_CMD_QUEUE_SUCCESS;
-}
-
-/**
- * Initialize a command queue for use. The initial FPA buffer is
- * allocated and the hardware unit is configured to point to the
- * new command queue.
- *
- * @queue_id: Hardware command queue to initialize.
- * @max_depth: Maximum outstanding commands that can be queued.
- * @fpa_pool: FPA pool the command queues should come from.
- * @pool_size: Size of each buffer in the FPA pool (bytes)
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id,
- int max_depth, int fpa_pool,
- int pool_size)
-{
- __cvmx_cmd_queue_state_t *qstate;
- cvmx_cmd_queue_result_t result = __cvmx_cmd_queue_init_state_ptr();
- if (result != CVMX_CMD_QUEUE_SUCCESS)
- return result;
-
- qstate = __cvmx_cmd_queue_get_state(queue_id);
- if (qstate == NULL)
- return CVMX_CMD_QUEUE_INVALID_PARAM;
-
- /*
- * We artificially limit max_depth to 1<<20 words. It is an
- * arbitrary limit.
- */
- if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH) {
- if ((max_depth < 0) || (max_depth > 1 << 20))
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- } else if (max_depth != 0)
- return CVMX_CMD_QUEUE_INVALID_PARAM;
-
- if ((fpa_pool < 0) || (fpa_pool > 7))
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- if ((pool_size < 128) || (pool_size > 65536))
- return CVMX_CMD_QUEUE_INVALID_PARAM;
-
- /* See if someone else has already initialized the queue */
- if (qstate->base_ptr_div128) {
- if (max_depth != (int)qstate->max_depth) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
- "Queue already initialized with different "
- "max_depth (%d).\n",
- (int)qstate->max_depth);
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
- if (fpa_pool != qstate->fpa_pool) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
- "Queue already initialized with different "
- "FPA pool (%u).\n",
- qstate->fpa_pool);
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
- if ((pool_size >> 3) - 1 != qstate->pool_size_m1) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
- "Queue already initialized with different "
- "FPA pool size (%u).\n",
- (qstate->pool_size_m1 + 1) << 3);
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
- CVMX_SYNCWS;
- return CVMX_CMD_QUEUE_ALREADY_SETUP;
- } else {
- union cvmx_fpa_ctl_status status;
- void *buffer;
-
- status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS);
- if (!status.s.enb) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
- "FPA is not enabled.\n");
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
- buffer = cvmx_fpa_alloc(fpa_pool);
- if (buffer == NULL) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_initialize: "
- "Unable to allocate initial buffer.\n");
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
-
- memset(qstate, 0, sizeof(*qstate));
- qstate->max_depth = max_depth;
- qstate->fpa_pool = fpa_pool;
- qstate->pool_size_m1 = (pool_size >> 3) - 1;
- qstate->base_ptr_div128 = cvmx_ptr_to_phys(buffer) / 128;
- /*
- * We zeroed the now serving field so we need to also
- * zero the ticket.
- */
- __cvmx_cmd_queue_state_ptr->
- ticket[__cvmx_cmd_queue_get_index(queue_id)] = 0;
- CVMX_SYNCWS;
- return CVMX_CMD_QUEUE_SUCCESS;
- }
-}
-
-/**
- * Shutdown a queue a free it's command buffers to the FPA. The
- * hardware connected to the queue must be stopped before this
- * function is called.
- *
- * @queue_id: Queue to shutdown
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id)
-{
- __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
- if (qptr == NULL) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Unable to "
- "get queue information.\n");
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
-
- if (cvmx_cmd_queue_length(queue_id) > 0) {
- cvmx_dprintf("ERROR: cvmx_cmd_queue_shutdown: Queue still "
- "has data in it.\n");
- return CVMX_CMD_QUEUE_FULL;
- }
-
- __cvmx_cmd_queue_lock(queue_id, qptr);
- if (qptr->base_ptr_div128) {
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t) qptr->base_ptr_div128 << 7),
- qptr->fpa_pool, 0);
- qptr->base_ptr_div128 = 0;
- }
- __cvmx_cmd_queue_unlock(qptr);
-
- return CVMX_CMD_QUEUE_SUCCESS;
-}
-
-/**
- * Return the number of command words pending in the queue. This
- * function may be relatively slow for some hardware units.
- *
- * @queue_id: Hardware command queue to query
- *
- * Returns Number of outstanding commands
- */
-int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id)
-{
- if (CVMX_ENABLE_PARAMETER_CHECKING) {
- if (__cvmx_cmd_queue_get_state(queue_id) == NULL)
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
-
- /*
- * The cast is here so gcc with check that all values in the
- * cvmx_cmd_queue_id_t enumeration are here.
- */
- switch ((cvmx_cmd_queue_id_t) (queue_id & 0xff0000)) {
- case CVMX_CMD_QUEUE_PKO_BASE:
- /*
- * FIXME: Need atomic lock on
- * CVMX_PKO_REG_READ_IDX. Right now we are normally
- * called with the queue lock, so that is a SLIGHT
- * amount of protection.
- */
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue_id & 0xffff);
- if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- union cvmx_pko_mem_debug9 debug9;
- debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9);
- return debug9.cn38xx.doorbell;
- } else {
- union cvmx_pko_mem_debug8 debug8;
- debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8);
- return debug8.cn58xx.doorbell;
- }
- case CVMX_CMD_QUEUE_ZIP:
- case CVMX_CMD_QUEUE_DFA:
- case CVMX_CMD_QUEUE_RAID:
- /* FIXME: Implement other lengths */
- return 0;
- case CVMX_CMD_QUEUE_DMA_BASE:
- {
- union cvmx_npei_dmax_counts dmax_counts;
- dmax_counts.u64 =
- cvmx_read_csr(CVMX_PEXP_NPEI_DMAX_COUNTS
- (queue_id & 0x7));
- return dmax_counts.s.dbell;
- }
- case CVMX_CMD_QUEUE_END:
- return CVMX_CMD_QUEUE_INVALID_PARAM;
- }
- return CVMX_CMD_QUEUE_INVALID_PARAM;
-}
-
-/**
- * Return the command buffer to be written to. The purpose of this
- * function is to allow CVMX routine access t othe low level buffer
- * for initial hardware setup. User applications should not call this
- * function directly.
- *
- * @queue_id: Command queue to query
- *
- * Returns Command buffer or NULL on failure
- */
-void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id)
-{
- __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
- if (qptr && qptr->base_ptr_div128)
- return cvmx_phys_to_ptr((uint64_t) qptr->base_ptr_div128 << 7);
- else
- return NULL;
-}
diff --git a/drivers/staging/octeon/cvmx-cmd-queue.h b/drivers/staging/octeon/cvmx-cmd-queue.h
deleted file mode 100644
index 614653b..0000000
--- a/drivers/staging/octeon/cvmx-cmd-queue.h
+++ /dev/null
@@ -1,617 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Support functions for managing command queues used for
- * various hardware blocks.
- *
- * The common command queue infrastructure abstracts out the
- * software necessary for adding to Octeon's chained queue
- * structures. These structures are used for commands to the
- * PKO, ZIP, DFA, RAID, and DMA engine blocks. Although each
- * hardware unit takes commands and CSRs of different types,
- * they all use basic linked command buffers to store the
- * pending request. In general, users of the CVMX API don't
- * call cvmx-cmd-queue functions directly. Instead the hardware
- * unit specific wrapper should be used. The wrappers perform
- * unit specific validation and CSR writes to submit the
- * commands.
- *
- * Even though most software will never directly interact with
- * cvmx-cmd-queue, knowledge of its internal working can help
- * in diagnosing performance problems and help with debugging.
- *
- * Command queue pointers are stored in a global named block
- * called "cvmx_cmd_queues". Except for the PKO queues, each
- * hardware queue is stored in its own cache line to reduce SMP
- * contention on spin locks. The PKO queues are stored such that
- * every 16th queue is next to each other in memory. This scheme
- * allows for queues being in separate cache lines when there
- * are low number of queues per port. With 16 queues per port,
- * the first queue for each port is in the same cache area. The
- * second queues for each port are in another area, etc. This
- * allows software to implement very efficient lockless PKO with
- * 16 queues per port using a minimum of cache lines per core.
- * All queues for a given core will be isolated in the same
- * cache area.
- *
- * In addition to the memory pointer layout, cvmx-cmd-queue
- * provides an optimized fair ll/sc locking mechanism for the
- * queues. The lock uses a "ticket / now serving" model to
- * maintain fair order on contended locks. In addition, it uses
- * predicted locking time to limit cache contention. When a core
- * know it must wait in line for a lock, it spins on the
- * internal cycle counter to completely eliminate any causes of
- * bus traffic.
- *
- */
-
-#ifndef __CVMX_CMD_QUEUE_H__
-#define __CVMX_CMD_QUEUE_H__
-
-#include <linux/prefetch.h>
-
-#include "cvmx-fpa.h"
-/**
- * By default we disable the max depth support. Most programs
- * don't use it and it slows down the command queue processing
- * significantly.
- */
-#ifndef CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH
-#define CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH 0
-#endif
-
-/**
- * Enumeration representing all hardware blocks that use command
- * queues. Each hardware block has up to 65536 sub identifiers for
- * multiple command queues. Not all chips support all hardware
- * units.
- */
-typedef enum {
- CVMX_CMD_QUEUE_PKO_BASE = 0x00000,
-
-#define CVMX_CMD_QUEUE_PKO(queue) \
- ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_PKO_BASE + (0xffff&(queue))))
-
- CVMX_CMD_QUEUE_ZIP = 0x10000,
- CVMX_CMD_QUEUE_DFA = 0x20000,
- CVMX_CMD_QUEUE_RAID = 0x30000,
- CVMX_CMD_QUEUE_DMA_BASE = 0x40000,
-
-#define CVMX_CMD_QUEUE_DMA(queue) \
- ((cvmx_cmd_queue_id_t)(CVMX_CMD_QUEUE_DMA_BASE + (0xffff&(queue))))
-
- CVMX_CMD_QUEUE_END = 0x50000,
-} cvmx_cmd_queue_id_t;
-
-/**
- * Command write operations can fail if the command queue needs
- * a new buffer and the associated FPA pool is empty. It can also
- * fail if the number of queued command words reaches the maximum
- * set at initialization.
- */
-typedef enum {
- CVMX_CMD_QUEUE_SUCCESS = 0,
- CVMX_CMD_QUEUE_NO_MEMORY = -1,
- CVMX_CMD_QUEUE_FULL = -2,
- CVMX_CMD_QUEUE_INVALID_PARAM = -3,
- CVMX_CMD_QUEUE_ALREADY_SETUP = -4,
-} cvmx_cmd_queue_result_t;
-
-typedef struct {
- /* You have lock when this is your ticket */
- uint8_t now_serving;
- uint64_t unused1:24;
- /* Maximum outstanding command words */
- uint32_t max_depth;
- /* FPA pool buffers come from */
- uint64_t fpa_pool:3;
- /* Top of command buffer pointer shifted 7 */
- uint64_t base_ptr_div128:29;
- uint64_t unused2:6;
- /* FPA buffer size in 64bit words minus 1 */
- uint64_t pool_size_m1:13;
- /* Number of commands already used in buffer */
- uint64_t index:13;
-} __cvmx_cmd_queue_state_t;
-
-/**
- * This structure contains the global state of all command queues.
- * It is stored in a bootmem named block and shared by all
- * applications running on Octeon. Tickets are stored in a differnet
- * cahce line that queue information to reduce the contention on the
- * ll/sc used to get a ticket. If this is not the case, the update
- * of queue state causes the ll/sc to fail quite often.
- */
-typedef struct {
- uint64_t ticket[(CVMX_CMD_QUEUE_END >> 16) * 256];
- __cvmx_cmd_queue_state_t state[(CVMX_CMD_QUEUE_END >> 16) * 256];
-} __cvmx_cmd_queue_all_state_t;
-
-/**
- * Initialize a command queue for use. The initial FPA buffer is
- * allocated and the hardware unit is configured to point to the
- * new command queue.
- *
- * @queue_id: Hardware command queue to initialize.
- * @max_depth: Maximum outstanding commands that can be queued.
- * @fpa_pool: FPA pool the command queues should come from.
- * @pool_size: Size of each buffer in the FPA pool (bytes)
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-cvmx_cmd_queue_result_t cvmx_cmd_queue_initialize(cvmx_cmd_queue_id_t queue_id,
- int max_depth, int fpa_pool,
- int pool_size);
-
-/**
- * Shutdown a queue a free it's command buffers to the FPA. The
- * hardware connected to the queue must be stopped before this
- * function is called.
- *
- * @queue_id: Queue to shutdown
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-cvmx_cmd_queue_result_t cvmx_cmd_queue_shutdown(cvmx_cmd_queue_id_t queue_id);
-
-/**
- * Return the number of command words pending in the queue. This
- * function may be relatively slow for some hardware units.
- *
- * @queue_id: Hardware command queue to query
- *
- * Returns Number of outstanding commands
- */
-int cvmx_cmd_queue_length(cvmx_cmd_queue_id_t queue_id);
-
-/**
- * Return the command buffer to be written to. The purpose of this
- * function is to allow CVMX routine access t othe low level buffer
- * for initial hardware setup. User applications should not call this
- * function directly.
- *
- * @queue_id: Command queue to query
- *
- * Returns Command buffer or NULL on failure
- */
-void *cvmx_cmd_queue_buffer(cvmx_cmd_queue_id_t queue_id);
-
-/**
- * Get the index into the state arrays for the supplied queue id.
- *
- * @queue_id: Queue ID to get an index for
- *
- * Returns Index into the state arrays
- */
-static inline int __cvmx_cmd_queue_get_index(cvmx_cmd_queue_id_t queue_id)
-{
- /*
- * Warning: This code currently only works with devices that
- * have 256 queues or less. Devices with more than 16 queues
- * are laid out in memory to allow cores quick access to
- * every 16th queue. This reduces cache thrashing when you are
- * running 16 queues per port to support lockless operation.
- */
- int unit = queue_id >> 16;
- int q = (queue_id >> 4) & 0xf;
- int core = queue_id & 0xf;
- return unit * 256 + core * 16 + q;
-}
-
-/**
- * Lock the supplied queue so nobody else is updating it at the same
- * time as us.
- *
- * @queue_id: Queue ID to lock
- * @qptr: Pointer to the queue's global state
- */
-static inline void __cvmx_cmd_queue_lock(cvmx_cmd_queue_id_t queue_id,
- __cvmx_cmd_queue_state_t *qptr)
-{
- extern __cvmx_cmd_queue_all_state_t
- *__cvmx_cmd_queue_state_ptr;
- int tmp;
- int my_ticket;
- prefetch(qptr);
- asm volatile (
- ".set push\n"
- ".set noreorder\n"
- "1:\n"
- /* Atomic add one to ticket_ptr */
- "ll %[my_ticket], %[ticket_ptr]\n"
- /* and store the original value */
- "li %[ticket], 1\n"
- /* in my_ticket */
- "baddu %[ticket], %[my_ticket]\n"
- "sc %[ticket], %[ticket_ptr]\n"
- "beqz %[ticket], 1b\n"
- " nop\n"
- /* Load the current now_serving ticket */
- "lbu %[ticket], %[now_serving]\n"
- "2:\n"
- /* Jump out if now_serving == my_ticket */
- "beq %[ticket], %[my_ticket], 4f\n"
- /* Find out how many tickets are in front of me */
- " subu %[ticket], %[my_ticket], %[ticket]\n"
- /* Use tickets in front of me minus one to delay */
- "subu %[ticket], 1\n"
- /* Delay will be ((tickets in front)-1)*32 loops */
- "cins %[ticket], %[ticket], 5, 7\n"
- "3:\n"
- /* Loop here until our ticket might be up */
- "bnez %[ticket], 3b\n"
- " subu %[ticket], 1\n"
- /* Jump back up to check out ticket again */
- "b 2b\n"
- /* Load the current now_serving ticket */
- " lbu %[ticket], %[now_serving]\n"
- "4:\n"
- ".set pop\n" :
- [ticket_ptr] "=m"(__cvmx_cmd_queue_state_ptr->ticket[__cvmx_cmd_queue_get_index(queue_id)]),
- [now_serving] "=m"(qptr->now_serving), [ticket] "=r"(tmp),
- [my_ticket] "=r"(my_ticket)
- );
-}
-
-/**
- * Unlock the queue, flushing all writes.
- *
- * @qptr: Queue to unlock
- */
-static inline void __cvmx_cmd_queue_unlock(__cvmx_cmd_queue_state_t *qptr)
-{
- qptr->now_serving++;
- CVMX_SYNCWS;
-}
-
-/**
- * Get the queue state structure for the given queue id
- *
- * @queue_id: Queue id to get
- *
- * Returns Queue structure or NULL on failure
- */
-static inline __cvmx_cmd_queue_state_t
- *__cvmx_cmd_queue_get_state(cvmx_cmd_queue_id_t queue_id)
-{
- extern __cvmx_cmd_queue_all_state_t
- *__cvmx_cmd_queue_state_ptr;
- return &__cvmx_cmd_queue_state_ptr->
- state[__cvmx_cmd_queue_get_index(queue_id)];
-}
-
-/**
- * Write an arbitrary number of command words to a command queue.
- * This is a generic function; the fixed number of command word
- * functions yield higher performance.
- *
- * @queue_id: Hardware command queue to write to
- * @use_locking:
- * Use internal locking to ensure exclusive access for queue
- * updates. If you don't use this locking you must ensure
- * exclusivity some other way. Locking is strongly recommended.
- * @cmd_count: Number of command words to write
- * @cmds: Array of commands to write
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write(cvmx_cmd_queue_id_t
- queue_id,
- int use_locking,
- int cmd_count,
- uint64_t *cmds)
-{
- __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
-
- /* Make sure nobody else is updating the same queue */
- if (likely(use_locking))
- __cvmx_cmd_queue_lock(queue_id, qptr);
-
- /*
- * If a max queue length was specified then make sure we don't
- * exceed it. If any part of the command would be below the
- * limit we allow it.
- */
- if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) {
- if (unlikely
- (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_FULL;
- }
- }
-
- /*
- * Normally there is plenty of room in the current buffer for
- * the command.
- */
- if (likely(qptr->index + cmd_count < qptr->pool_size_m1)) {
- uint64_t *ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- ptr += qptr->index;
- qptr->index += cmd_count;
- while (cmd_count--)
- *ptr++ = *cmds++;
- } else {
- uint64_t *ptr;
- int count;
- /*
- * We need a new command buffer. Fail if there isn't
- * one available.
- */
- uint64_t *new_buffer =
- (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool);
- if (unlikely(new_buffer == NULL)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
- ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- /*
- * Figure out how many command words will fit in this
- * buffer. One location will be needed for the next
- * buffer pointer.
- */
- count = qptr->pool_size_m1 - qptr->index;
- ptr += qptr->index;
- cmd_count -= count;
- while (count--)
- *ptr++ = *cmds++;
- *ptr = cvmx_ptr_to_phys(new_buffer);
- /*
- * The current buffer is full and has a link to the
- * next buffer. Time to write the rest of the commands
- * into the new buffer.
- */
- qptr->base_ptr_div128 = *ptr >> 7;
- qptr->index = cmd_count;
- ptr = new_buffer;
- while (cmd_count--)
- *ptr++ = *cmds++;
- }
-
- /* All updates are complete. Release the lock and return */
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_SUCCESS;
-}
-
-/**
- * Simple function to write two command words to a command
- * queue.
- *
- * @queue_id: Hardware command queue to write to
- * @use_locking:
- * Use internal locking to ensure exclusive access for queue
- * updates. If you don't use this locking you must ensure
- * exclusivity some other way. Locking is strongly recommended.
- * @cmd1: Command
- * @cmd2: Command
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write2(cvmx_cmd_queue_id_t
- queue_id,
- int use_locking,
- uint64_t cmd1,
- uint64_t cmd2)
-{
- __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
-
- /* Make sure nobody else is updating the same queue */
- if (likely(use_locking))
- __cvmx_cmd_queue_lock(queue_id, qptr);
-
- /*
- * If a max queue length was specified then make sure we don't
- * exceed it. If any part of the command would be below the
- * limit we allow it.
- */
- if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) {
- if (unlikely
- (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_FULL;
- }
- }
-
- /*
- * Normally there is plenty of room in the current buffer for
- * the command.
- */
- if (likely(qptr->index + 2 < qptr->pool_size_m1)) {
- uint64_t *ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- ptr += qptr->index;
- qptr->index += 2;
- ptr[0] = cmd1;
- ptr[1] = cmd2;
- } else {
- uint64_t *ptr;
- /*
- * Figure out how many command words will fit in this
- * buffer. One location will be needed for the next
- * buffer pointer.
- */
- int count = qptr->pool_size_m1 - qptr->index;
- /*
- * We need a new command buffer. Fail if there isn't
- * one available.
- */
- uint64_t *new_buffer =
- (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool);
- if (unlikely(new_buffer == NULL)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
- count--;
- ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- ptr += qptr->index;
- *ptr++ = cmd1;
- if (likely(count))
- *ptr++ = cmd2;
- *ptr = cvmx_ptr_to_phys(new_buffer);
- /*
- * The current buffer is full and has a link to the
- * next buffer. Time to write the rest of the commands
- * into the new buffer.
- */
- qptr->base_ptr_div128 = *ptr >> 7;
- qptr->index = 0;
- if (unlikely(count == 0)) {
- qptr->index = 1;
- new_buffer[0] = cmd2;
- }
- }
-
- /* All updates are complete. Release the lock and return */
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_SUCCESS;
-}
-
-/**
- * Simple function to write three command words to a command
- * queue.
- *
- * @queue_id: Hardware command queue to write to
- * @use_locking:
- * Use internal locking to ensure exclusive access for queue
- * updates. If you don't use this locking you must ensure
- * exclusivity some other way. Locking is strongly recommended.
- * @cmd1: Command
- * @cmd2: Command
- * @cmd3: Command
- *
- * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
- */
-static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write3(cvmx_cmd_queue_id_t
- queue_id,
- int use_locking,
- uint64_t cmd1,
- uint64_t cmd2,
- uint64_t cmd3)
-{
- __cvmx_cmd_queue_state_t *qptr = __cvmx_cmd_queue_get_state(queue_id);
-
- /* Make sure nobody else is updating the same queue */
- if (likely(use_locking))
- __cvmx_cmd_queue_lock(queue_id, qptr);
-
- /*
- * If a max queue length was specified then make sure we don't
- * exceed it. If any part of the command would be below the
- * limit we allow it.
- */
- if (CVMX_CMD_QUEUE_ENABLE_MAX_DEPTH && unlikely(qptr->max_depth)) {
- if (unlikely
- (cvmx_cmd_queue_length(queue_id) > (int)qptr->max_depth)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_FULL;
- }
- }
-
- /*
- * Normally there is plenty of room in the current buffer for
- * the command.
- */
- if (likely(qptr->index + 3 < qptr->pool_size_m1)) {
- uint64_t *ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- ptr += qptr->index;
- qptr->index += 3;
- ptr[0] = cmd1;
- ptr[1] = cmd2;
- ptr[2] = cmd3;
- } else {
- uint64_t *ptr;
- /*
- * Figure out how many command words will fit in this
- * buffer. One location will be needed for the next
- * buffer pointer
- */
- int count = qptr->pool_size_m1 - qptr->index;
- /*
- * We need a new command buffer. Fail if there isn't
- * one available
- */
- uint64_t *new_buffer =
- (uint64_t *) cvmx_fpa_alloc(qptr->fpa_pool);
- if (unlikely(new_buffer == NULL)) {
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_NO_MEMORY;
- }
- count--;
- ptr =
- (uint64_t *) cvmx_phys_to_ptr((uint64_t) qptr->
- base_ptr_div128 << 7);
- ptr += qptr->index;
- *ptr++ = cmd1;
- if (count) {
- *ptr++ = cmd2;
- if (count > 1)
- *ptr++ = cmd3;
- }
- *ptr = cvmx_ptr_to_phys(new_buffer);
- /*
- * The current buffer is full and has a link to the
- * next buffer. Time to write the rest of the commands
- * into the new buffer.
- */
- qptr->base_ptr_div128 = *ptr >> 7;
- qptr->index = 0;
- ptr = new_buffer;
- if (count == 0) {
- *ptr++ = cmd2;
- qptr->index++;
- }
- if (count < 2) {
- *ptr++ = cmd3;
- qptr->index++;
- }
- }
-
- /* All updates are complete. Release the lock and return */
- if (likely(use_locking))
- __cvmx_cmd_queue_unlock(qptr);
- return CVMX_CMD_QUEUE_SUCCESS;
-}
-
-#endif /* __CVMX_CMD_QUEUE_H__ */
diff --git a/drivers/staging/octeon/cvmx-config.h b/drivers/staging/octeon/cvmx-config.h
deleted file mode 100644
index 078a520..0000000
--- a/drivers/staging/octeon/cvmx-config.h
+++ /dev/null
@@ -1,169 +0,0 @@
-#ifndef __CVMX_CONFIG_H__
-#define __CVMX_CONFIG_H__
-
-/************************* Config Specific Defines ************************/
-#define CVMX_LLM_NUM_PORTS 1
-#define CVMX_NULL_POINTER_PROTECT 1
-#define CVMX_ENABLE_DEBUG_PRINTS 1
-/* PKO queues per port for interface 0 (ports 0-15) */
-#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 1
-/* PKO queues per port for interface 1 (ports 16-31) */
-#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 1
-/* Limit on the number of PKO ports enabled for interface 0 */
-#define CVMX_PKO_MAX_PORTS_INTERFACE0 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0
-/* Limit on the number of PKO ports enabled for interface 1 */
-#define CVMX_PKO_MAX_PORTS_INTERFACE1 CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1
-/* PKO queues per port for PCI (ports 32-35) */
-#define CVMX_PKO_QUEUES_PER_PORT_PCI 1
-/* PKO queues per port for Loop devices (ports 36-39) */
-#define CVMX_PKO_QUEUES_PER_PORT_LOOP 1
-
-/************************* FPA allocation *********************************/
-/* Pool sizes in bytes, must be multiple of a cache line */
-#define CVMX_FPA_POOL_0_SIZE (16 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_1_SIZE (1 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_2_SIZE (8 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_3_SIZE (0 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_4_SIZE (0 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_5_SIZE (0 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_6_SIZE (0 * CVMX_CACHE_LINE_SIZE)
-#define CVMX_FPA_POOL_7_SIZE (0 * CVMX_CACHE_LINE_SIZE)
-
-/* Pools in use */
-/* Packet buffers */
-#define CVMX_FPA_PACKET_POOL (0)
-#define CVMX_FPA_PACKET_POOL_SIZE CVMX_FPA_POOL_0_SIZE
-/* Work queue entrys */
-#define CVMX_FPA_WQE_POOL (1)
-#define CVMX_FPA_WQE_POOL_SIZE CVMX_FPA_POOL_1_SIZE
-/* PKO queue command buffers */
-#define CVMX_FPA_OUTPUT_BUFFER_POOL (2)
-#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE CVMX_FPA_POOL_2_SIZE
-
-/************************* FAU allocation ********************************/
-/* The fetch and add registers are allocated here. They are arranged
- * in order of descending size so that all alignment constraints are
- * automatically met. The enums are linked so that the following enum
- * continues allocating where the previous one left off, so the
- * numbering within each enum always starts with zero. The macros
- * take care of the address increment size, so the values entered
- * always increase by 1. FAU registers are accessed with byte
- * addresses.
- */
-
-#define CVMX_FAU_REG_64_ADDR(x) ((x << 3) + CVMX_FAU_REG_64_START)
-typedef enum {
- CVMX_FAU_REG_64_START = 0,
- CVMX_FAU_REG_64_END = CVMX_FAU_REG_64_ADDR(0),
-} cvmx_fau_reg_64_t;
-
-#define CVMX_FAU_REG_32_ADDR(x) ((x << 2) + CVMX_FAU_REG_32_START)
-typedef enum {
- CVMX_FAU_REG_32_START = CVMX_FAU_REG_64_END,
- CVMX_FAU_REG_32_END = CVMX_FAU_REG_32_ADDR(0),
-} cvmx_fau_reg_32_t;
-
-#define CVMX_FAU_REG_16_ADDR(x) ((x << 1) + CVMX_FAU_REG_16_START)
-typedef enum {
- CVMX_FAU_REG_16_START = CVMX_FAU_REG_32_END,
- CVMX_FAU_REG_16_END = CVMX_FAU_REG_16_ADDR(0),
-} cvmx_fau_reg_16_t;
-
-#define CVMX_FAU_REG_8_ADDR(x) ((x) + CVMX_FAU_REG_8_START)
-typedef enum {
- CVMX_FAU_REG_8_START = CVMX_FAU_REG_16_END,
- CVMX_FAU_REG_8_END = CVMX_FAU_REG_8_ADDR(0),
-} cvmx_fau_reg_8_t;
-
-/*
- * The name CVMX_FAU_REG_AVAIL_BASE is provided to indicate the first
- * available FAU address that is not allocated in cvmx-config.h. This
- * is 64 bit aligned.
- */
-#define CVMX_FAU_REG_AVAIL_BASE ((CVMX_FAU_REG_8_END + 0x7) & (~0x7ULL))
-#define CVMX_FAU_REG_END (2048)
-
-/********************** scratch memory allocation *************************/
-/* Scratchpad memory allocation. Note that these are byte memory
- * addresses. Some uses of scratchpad (IOBDMA for example) require
- * the use of 8-byte aligned addresses, so proper alignment needs to
- * be taken into account.
- */
-/* Generic scratch iobdma area */
-#define CVMX_SCR_SCRATCH (0)
-/* First location available after cvmx-config.h allocated region. */
-#define CVMX_SCR_REG_AVAIL_BASE (8)
-
-/*
- * CVMX_HELPER_FIRST_MBUFF_SKIP is the number of bytes to reserve
- * before the beginning of the packet. If necessary, override the
- * default here. See the IPD section of the hardware manual for MBUFF
- * SKIP details.
- */
-#define CVMX_HELPER_FIRST_MBUFF_SKIP 184
-
-/*
- * CVMX_HELPER_NOT_FIRST_MBUFF_SKIP is the number of bytes to reserve
- * in each chained packet element. If necessary, override the default
- * here.
- */
-#define CVMX_HELPER_NOT_FIRST_MBUFF_SKIP 0
-
-/*
- * CVMX_HELPER_ENABLE_BACK_PRESSURE controls whether back pressure is
- * enabled for all input ports. This controls if IPD sends
- * backpressure to all ports if Octeon's FPA pools don't have enough
- * packet or work queue entries. Even when this is off, it is still
- * possible to get backpressure from individual hardware ports. When
- * configuring backpressure, also check
- * CVMX_HELPER_DISABLE_*_BACKPRESSURE below. If necessary, override
- * the default here.
- */
-#define CVMX_HELPER_ENABLE_BACK_PRESSURE 1
-
-/*
- * CVMX_HELPER_ENABLE_IPD controls if the IPD is enabled in the helper
- * function. Once it is enabled the hardware starts accepting
- * packets. You might want to skip the IPD enable if configuration
- * changes are need from the default helper setup. If necessary,
- * override the default here.
- */
-#define CVMX_HELPER_ENABLE_IPD 0
-
-/*
- * CVMX_HELPER_INPUT_TAG_TYPE selects the type of tag that the IPD assigns
- * to incoming packets.
- */
-#define CVMX_HELPER_INPUT_TAG_TYPE CVMX_POW_TAG_TYPE_ORDERED
-
-#define CVMX_ENABLE_PARAMETER_CHECKING 0
-
-/*
- * The following select which fields are used by the PIP to generate
- * the tag on INPUT
- * 0: don't include
- * 1: include
- */
-#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP 0
-#define CVMX_HELPER_INPUT_TAG_IPV6_DST_IP 0
-#define CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT 0
-#define CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT 0
-#define CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER 0
-#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP 0
-#define CVMX_HELPER_INPUT_TAG_IPV4_DST_IP 0
-#define CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT 0
-#define CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT 0
-#define CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL 0
-#define CVMX_HELPER_INPUT_TAG_INPUT_PORT 1
-
-/* Select skip mode for input ports */
-#define CVMX_HELPER_INPUT_PORT_SKIP_MODE CVMX_PIP_PORT_CFG_MODE_SKIPL2
-
-/*
- * Force backpressure to be disabled. This overrides all other
- * backpressure configuration.
- */
-#define CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 0
-
-#endif /* __CVMX_CONFIG_H__ */
-
diff --git a/drivers/staging/octeon/cvmx-dbg-defs.h b/drivers/staging/octeon/cvmx-dbg-defs.h
deleted file mode 100644
index abbf42d..0000000
--- a/drivers/staging/octeon/cvmx-dbg-defs.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_DBG_DEFS_H__
-#define __CVMX_DBG_DEFS_H__
-
-#define CVMX_DBG_DATA \
- CVMX_ADD_IO_SEG(0x00011F00000001E8ull)
-
-union cvmx_dbg_data {
- uint64_t u64;
- struct cvmx_dbg_data_s {
- uint64_t reserved_23_63:41;
- uint64_t c_mul:5;
- uint64_t dsel_ext:1;
- uint64_t data:17;
- } s;
- struct cvmx_dbg_data_cn30xx {
- uint64_t reserved_31_63:33;
- uint64_t pll_mul:3;
- uint64_t reserved_23_27:5;
- uint64_t c_mul:5;
- uint64_t dsel_ext:1;
- uint64_t data:17;
- } cn30xx;
- struct cvmx_dbg_data_cn30xx cn31xx;
- struct cvmx_dbg_data_cn38xx {
- uint64_t reserved_29_63:35;
- uint64_t d_mul:4;
- uint64_t dclk_mul2:1;
- uint64_t cclk_div2:1;
- uint64_t c_mul:5;
- uint64_t dsel_ext:1;
- uint64_t data:17;
- } cn38xx;
- struct cvmx_dbg_data_cn38xx cn38xxp2;
- struct cvmx_dbg_data_cn30xx cn50xx;
- struct cvmx_dbg_data_cn58xx {
- uint64_t reserved_29_63:35;
- uint64_t rem:6;
- uint64_t c_mul:5;
- uint64_t dsel_ext:1;
- uint64_t data:17;
- } cn58xx;
- struct cvmx_dbg_data_cn58xx cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-fau.h b/drivers/staging/octeon/cvmx-fau.h
deleted file mode 100644
index a6939fc..0000000
--- a/drivers/staging/octeon/cvmx-fau.h
+++ /dev/null
@@ -1,597 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Interface to the hardware Fetch and Add Unit.
- */
-
-#ifndef __CVMX_FAU_H__
-#define __CVMX_FAU_H__
-
-/*
- * Octeon Fetch and Add Unit (FAU)
- */
-
-#define CVMX_FAU_LOAD_IO_ADDRESS cvmx_build_io_address(0x1e, 0)
-#define CVMX_FAU_BITS_SCRADDR 63, 56
-#define CVMX_FAU_BITS_LEN 55, 48
-#define CVMX_FAU_BITS_INEVAL 35, 14
-#define CVMX_FAU_BITS_TAGWAIT 13, 13
-#define CVMX_FAU_BITS_NOADD 13, 13
-#define CVMX_FAU_BITS_SIZE 12, 11
-#define CVMX_FAU_BITS_REGISTER 10, 0
-
-typedef enum {
- CVMX_FAU_OP_SIZE_8 = 0,
- CVMX_FAU_OP_SIZE_16 = 1,
- CVMX_FAU_OP_SIZE_32 = 2,
- CVMX_FAU_OP_SIZE_64 = 3
-} cvmx_fau_op_size_t;
-
-/**
- * Tagwait return definition. If a timeout occurs, the error
- * bit will be set. Otherwise the value of the register before
- * the update will be returned.
- */
-typedef struct {
- uint64_t error:1;
- int64_t value:63;
-} cvmx_fau_tagwait64_t;
-
-/**
- * Tagwait return definition. If a timeout occurs, the error
- * bit will be set. Otherwise the value of the register before
- * the update will be returned.
- */
-typedef struct {
- uint64_t error:1;
- int32_t value:31;
-} cvmx_fau_tagwait32_t;
-
-/**
- * Tagwait return definition. If a timeout occurs, the error
- * bit will be set. Otherwise the value of the register before
- * the update will be returned.
- */
-typedef struct {
- uint64_t error:1;
- int16_t value:15;
-} cvmx_fau_tagwait16_t;
-
-/**
- * Tagwait return definition. If a timeout occurs, the error
- * bit will be set. Otherwise the value of the register before
- * the update will be returned.
- */
-typedef struct {
- uint64_t error:1;
- int8_t value:7;
-} cvmx_fau_tagwait8_t;
-
-/**
- * Asynchronous tagwait return definition. If a timeout occurs,
- * the error bit will be set. Otherwise the value of the
- * register before the update will be returned.
- */
-typedef union {
- uint64_t u64;
- struct {
- uint64_t invalid:1;
- uint64_t data:63; /* unpredictable if invalid is set */
- } s;
-} cvmx_fau_async_tagwait_result_t;
-
-/**
- * Builds a store I/O address for writing to the FAU
- *
- * @noadd: 0 = Store value is atomically added to the current value
- * 1 = Store value is atomically written over the current value
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * - Step by 4 for 32 bit access.
- * - Step by 8 for 64 bit access.
- * Returns Address to store for atomic update
- */
-static inline uint64_t __cvmx_fau_store_address(uint64_t noadd, uint64_t reg)
-{
- return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) |
- cvmx_build_bits(CVMX_FAU_BITS_NOADD, noadd) |
- cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg);
-}
-
-/**
- * Builds a I/O address for accessing the FAU
- *
- * @tagwait: Should the atomic add wait for the current tag switch
- * operation to complete.
- * - 0 = Don't wait
- * - 1 = Wait for tag switch to complete
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * - Step by 4 for 32 bit access.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- * Note: When performing 32 and 64 bit access, only the low
- * 22 bits are available.
- * Returns Address to read from for atomic update
- */
-static inline uint64_t __cvmx_fau_atomic_address(uint64_t tagwait, uint64_t reg,
- int64_t value)
-{
- return CVMX_ADD_IO_SEG(CVMX_FAU_LOAD_IO_ADDRESS) |
- cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) |
- cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) |
- cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg);
-}
-
-/**
- * Perform an atomic 64 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Value of the register before the update
- */
-static inline int64_t cvmx_fau_fetch_and_add64(cvmx_fau_reg_64_t reg,
- int64_t value)
-{
- return cvmx_read64_int64(__cvmx_fau_atomic_address(0, reg, value));
-}
-
-/**
- * Perform an atomic 32 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Value of the register before the update
- */
-static inline int32_t cvmx_fau_fetch_and_add32(cvmx_fau_reg_32_t reg,
- int32_t value)
-{
- return cvmx_read64_int32(__cvmx_fau_atomic_address(0, reg, value));
-}
-
-/**
- * Perform an atomic 16 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to add.
- * Returns Value of the register before the update
- */
-static inline int16_t cvmx_fau_fetch_and_add16(cvmx_fau_reg_16_t reg,
- int16_t value)
-{
- return cvmx_read64_int16(__cvmx_fau_atomic_address(0, reg, value));
-}
-
-/**
- * Perform an atomic 8 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to add.
- * Returns Value of the register before the update
- */
-static inline int8_t cvmx_fau_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value)
-{
- return cvmx_read64_int8(__cvmx_fau_atomic_address(0, reg, value));
-}
-
-/**
- * Perform an atomic 64 bit add after the current tag switch
- * completes
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns If a timeout occurs, the error bit will be set. Otherwise
- * the value of the register before the update will be
- * returned
- */
-static inline cvmx_fau_tagwait64_t
-cvmx_fau_tagwait_fetch_and_add64(cvmx_fau_reg_64_t reg, int64_t value)
-{
- union {
- uint64_t i64;
- cvmx_fau_tagwait64_t t;
- } result;
- result.i64 =
- cvmx_read64_int64(__cvmx_fau_atomic_address(1, reg, value));
- return result.t;
-}
-
-/**
- * Perform an atomic 32 bit add after the current tag switch
- * completes
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns If a timeout occurs, the error bit will be set. Otherwise
- * the value of the register before the update will be
- * returned
- */
-static inline cvmx_fau_tagwait32_t
-cvmx_fau_tagwait_fetch_and_add32(cvmx_fau_reg_32_t reg, int32_t value)
-{
- union {
- uint64_t i32;
- cvmx_fau_tagwait32_t t;
- } result;
- result.i32 =
- cvmx_read64_int32(__cvmx_fau_atomic_address(1, reg, value));
- return result.t;
-}
-
-/**
- * Perform an atomic 16 bit add after the current tag switch
- * completes
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to add.
- * Returns If a timeout occurs, the error bit will be set. Otherwise
- * the value of the register before the update will be
- * returned
- */
-static inline cvmx_fau_tagwait16_t
-cvmx_fau_tagwait_fetch_and_add16(cvmx_fau_reg_16_t reg, int16_t value)
-{
- union {
- uint64_t i16;
- cvmx_fau_tagwait16_t t;
- } result;
- result.i16 =
- cvmx_read64_int16(__cvmx_fau_atomic_address(1, reg, value));
- return result.t;
-}
-
-/**
- * Perform an atomic 8 bit add after the current tag switch
- * completes
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to add.
- * Returns If a timeout occurs, the error bit will be set. Otherwise
- * the value of the register before the update will be
- * returned
- */
-static inline cvmx_fau_tagwait8_t
-cvmx_fau_tagwait_fetch_and_add8(cvmx_fau_reg_8_t reg, int8_t value)
-{
- union {
- uint64_t i8;
- cvmx_fau_tagwait8_t t;
- } result;
- result.i8 = cvmx_read64_int8(__cvmx_fau_atomic_address(1, reg, value));
- return result.t;
-}
-
-/**
- * Builds I/O data for async operations
- *
- * @scraddr: Scratch pad byte address to write to. Must be 8 byte aligned
- * @value: Signed value to add.
- * Note: When performing 32 and 64 bit access, only the low
- * 22 bits are available.
- * @tagwait: Should the atomic add wait for the current tag switch
- * operation to complete.
- * - 0 = Don't wait
- * - 1 = Wait for tag switch to complete
- * @size: The size of the operation:
- * - CVMX_FAU_OP_SIZE_8 (0) = 8 bits
- * - CVMX_FAU_OP_SIZE_16 (1) = 16 bits
- * - CVMX_FAU_OP_SIZE_32 (2) = 32 bits
- * - CVMX_FAU_OP_SIZE_64 (3) = 64 bits
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * - Step by 4 for 32 bit access.
- * - Step by 8 for 64 bit access.
- * Returns Data to write using cvmx_send_single
- */
-static inline uint64_t __cvmx_fau_iobdma_data(uint64_t scraddr, int64_t value,
- uint64_t tagwait,
- cvmx_fau_op_size_t size,
- uint64_t reg)
-{
- return CVMX_FAU_LOAD_IO_ADDRESS |
- cvmx_build_bits(CVMX_FAU_BITS_SCRADDR, scraddr >> 3) |
- cvmx_build_bits(CVMX_FAU_BITS_LEN, 1) |
- cvmx_build_bits(CVMX_FAU_BITS_INEVAL, value) |
- cvmx_build_bits(CVMX_FAU_BITS_TAGWAIT, tagwait) |
- cvmx_build_bits(CVMX_FAU_BITS_SIZE, size) |
- cvmx_build_bits(CVMX_FAU_BITS_REGISTER, reg);
-}
-
-/**
- * Perform an async atomic 64 bit add. The old value is
- * placed in the scratch memory at byte address scraddr.
- *
- * @scraddr: Scratch memory byte address to put response in.
- * Must be 8 byte aligned.
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_fetch_and_add64(uint64_t scraddr,
- cvmx_fau_reg_64_t reg,
- int64_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 0, CVMX_FAU_OP_SIZE_64, reg));
-}
-
-/**
- * Perform an async atomic 32 bit add. The old value is
- * placed in the scratch memory at byte address scraddr.
- *
- * @scraddr: Scratch memory byte address to put response in.
- * Must be 8 byte aligned.
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr,
- cvmx_fau_reg_32_t reg,
- int32_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 0, CVMX_FAU_OP_SIZE_32, reg));
-}
-
-/**
- * Perform an async atomic 16 bit add. The old value is
- * placed in the scratch memory at byte address scraddr.
- *
- * @scraddr: Scratch memory byte address to put response in.
- * Must be 8 byte aligned.
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to add.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_fetch_and_add16(uint64_t scraddr,
- cvmx_fau_reg_16_t reg,
- int16_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 0, CVMX_FAU_OP_SIZE_16, reg));
-}
-
-/**
- * Perform an async atomic 8 bit add. The old value is
- * placed in the scratch memory at byte address scraddr.
- *
- * @scraddr: Scratch memory byte address to put response in.
- * Must be 8 byte aligned.
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to add.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_fetch_and_add8(uint64_t scraddr,
- cvmx_fau_reg_8_t reg,
- int8_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 0, CVMX_FAU_OP_SIZE_8, reg));
-}
-
-/**
- * Perform an async atomic 64 bit add after the current tag
- * switch completes.
- *
- * @scraddr: Scratch memory byte address to put response in. Must be
- * 8 byte aligned. If a timeout occurs, the error bit (63)
- * will be set. Otherwise the value of the register before
- * the update will be returned
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_tagwait_fetch_and_add64(uint64_t scraddr,
- cvmx_fau_reg_64_t reg,
- int64_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 1, CVMX_FAU_OP_SIZE_64, reg));
-}
-
-/**
- * Perform an async atomic 32 bit add after the current tag
- * switch completes.
- *
- * @scraddr: Scratch memory byte address to put response in. Must be
- * 8 byte aligned. If a timeout occurs, the error bit (63)
- * will be set. Otherwise the value of the register before
- * the update will be returned
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to add.
- * Note: Only the low 22 bits are available.
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_tagwait_fetch_and_add32(uint64_t scraddr,
- cvmx_fau_reg_32_t reg,
- int32_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 1, CVMX_FAU_OP_SIZE_32, reg));
-}
-
-/**
- * Perform an async atomic 16 bit add after the current tag
- * switch completes.
- *
- * @scraddr: Scratch memory byte address to put response in. Must be
- * 8 byte aligned. If a timeout occurs, the error bit (63)
- * will be set. Otherwise the value of the register before
- * the update will be returned
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to add.
- *
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_tagwait_fetch_and_add16(uint64_t scraddr,
- cvmx_fau_reg_16_t reg,
- int16_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 1, CVMX_FAU_OP_SIZE_16, reg));
-}
-
-/**
- * Perform an async atomic 8 bit add after the current tag
- * switch completes.
- *
- * @scraddr: Scratch memory byte address to put response in. Must be
- * 8 byte aligned. If a timeout occurs, the error bit (63)
- * will be set. Otherwise the value of the register before
- * the update will be returned
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to add.
- *
- * Returns Placed in the scratch pad register
- */
-static inline void cvmx_fau_async_tagwait_fetch_and_add8(uint64_t scraddr,
- cvmx_fau_reg_8_t reg,
- int8_t value)
-{
- cvmx_send_single(__cvmx_fau_iobdma_data
- (scraddr, value, 1, CVMX_FAU_OP_SIZE_8, reg));
-}
-
-/**
- * Perform an atomic 64 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to add.
- */
-static inline void cvmx_fau_atomic_add64(cvmx_fau_reg_64_t reg, int64_t value)
-{
- cvmx_write64_int64(__cvmx_fau_store_address(0, reg), value);
-}
-
-/**
- * Perform an atomic 32 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to add.
- */
-static inline void cvmx_fau_atomic_add32(cvmx_fau_reg_32_t reg, int32_t value)
-{
- cvmx_write64_int32(__cvmx_fau_store_address(0, reg), value);
-}
-
-/**
- * Perform an atomic 16 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to add.
- */
-static inline void cvmx_fau_atomic_add16(cvmx_fau_reg_16_t reg, int16_t value)
-{
- cvmx_write64_int16(__cvmx_fau_store_address(0, reg), value);
-}
-
-/**
- * Perform an atomic 8 bit add
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to add.
- */
-static inline void cvmx_fau_atomic_add8(cvmx_fau_reg_8_t reg, int8_t value)
-{
- cvmx_write64_int8(__cvmx_fau_store_address(0, reg), value);
-}
-
-/**
- * Perform an atomic 64 bit write
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 8 for 64 bit access.
- * @value: Signed value to write.
- */
-static inline void cvmx_fau_atomic_write64(cvmx_fau_reg_64_t reg, int64_t value)
-{
- cvmx_write64_int64(__cvmx_fau_store_address(1, reg), value);
-}
-
-/**
- * Perform an atomic 32 bit write
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 4 for 32 bit access.
- * @value: Signed value to write.
- */
-static inline void cvmx_fau_atomic_write32(cvmx_fau_reg_32_t reg, int32_t value)
-{
- cvmx_write64_int32(__cvmx_fau_store_address(1, reg), value);
-}
-
-/**
- * Perform an atomic 16 bit write
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * - Step by 2 for 16 bit access.
- * @value: Signed value to write.
- */
-static inline void cvmx_fau_atomic_write16(cvmx_fau_reg_16_t reg, int16_t value)
-{
- cvmx_write64_int16(__cvmx_fau_store_address(1, reg), value);
-}
-
-/**
- * Perform an atomic 8 bit write
- *
- * @reg: FAU atomic register to access. 0 <= reg < 2048.
- * @value: Signed value to write.
- */
-static inline void cvmx_fau_atomic_write8(cvmx_fau_reg_8_t reg, int8_t value)
-{
- cvmx_write64_int8(__cvmx_fau_store_address(1, reg), value);
-}
-
-#endif /* __CVMX_FAU_H__ */
diff --git a/drivers/staging/octeon/cvmx-fpa-defs.h b/drivers/staging/octeon/cvmx-fpa-defs.h
deleted file mode 100644
index bf5546b..0000000
--- a/drivers/staging/octeon/cvmx-fpa-defs.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_FPA_DEFS_H__
-#define __CVMX_FPA_DEFS_H__
-
-#define CVMX_FPA_BIST_STATUS \
- CVMX_ADD_IO_SEG(0x00011800280000E8ull)
-#define CVMX_FPA_CTL_STATUS \
- CVMX_ADD_IO_SEG(0x0001180028000050ull)
-#define CVMX_FPA_FPF0_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000000ull)
-#define CVMX_FPA_FPF0_SIZE \
- CVMX_ADD_IO_SEG(0x0001180028000058ull)
-#define CVMX_FPA_FPF1_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000008ull)
-#define CVMX_FPA_FPF2_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000010ull)
-#define CVMX_FPA_FPF3_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000018ull)
-#define CVMX_FPA_FPF4_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000020ull)
-#define CVMX_FPA_FPF5_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000028ull)
-#define CVMX_FPA_FPF6_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000030ull)
-#define CVMX_FPA_FPF7_MARKS \
- CVMX_ADD_IO_SEG(0x0001180028000038ull)
-#define CVMX_FPA_FPFX_MARKS(offset) \
- CVMX_ADD_IO_SEG(0x0001180028000008ull + (((offset) & 7) * 8) - 8 * 1)
-#define CVMX_FPA_FPFX_SIZE(offset) \
- CVMX_ADD_IO_SEG(0x0001180028000060ull + (((offset) & 7) * 8) - 8 * 1)
-#define CVMX_FPA_INT_ENB \
- CVMX_ADD_IO_SEG(0x0001180028000048ull)
-#define CVMX_FPA_INT_SUM \
- CVMX_ADD_IO_SEG(0x0001180028000040ull)
-#define CVMX_FPA_QUE0_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x00011800280000F0ull)
-#define CVMX_FPA_QUE1_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x00011800280000F8ull)
-#define CVMX_FPA_QUE2_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000100ull)
-#define CVMX_FPA_QUE3_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000108ull)
-#define CVMX_FPA_QUE4_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000110ull)
-#define CVMX_FPA_QUE5_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000118ull)
-#define CVMX_FPA_QUE6_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000120ull)
-#define CVMX_FPA_QUE7_PAGE_INDEX \
- CVMX_ADD_IO_SEG(0x0001180028000128ull)
-#define CVMX_FPA_QUEX_AVAILABLE(offset) \
- CVMX_ADD_IO_SEG(0x0001180028000098ull + (((offset) & 7) * 8))
-#define CVMX_FPA_QUEX_PAGE_INDEX(offset) \
- CVMX_ADD_IO_SEG(0x00011800280000F0ull + (((offset) & 7) * 8))
-#define CVMX_FPA_QUE_ACT \
- CVMX_ADD_IO_SEG(0x0001180028000138ull)
-#define CVMX_FPA_QUE_EXP \
- CVMX_ADD_IO_SEG(0x0001180028000130ull)
-#define CVMX_FPA_WART_CTL \
- CVMX_ADD_IO_SEG(0x00011800280000D8ull)
-#define CVMX_FPA_WART_STATUS \
- CVMX_ADD_IO_SEG(0x00011800280000E0ull)
-
-union cvmx_fpa_bist_status {
- uint64_t u64;
- struct cvmx_fpa_bist_status_s {
- uint64_t reserved_5_63:59;
- uint64_t frd:1;
- uint64_t fpf0:1;
- uint64_t fpf1:1;
- uint64_t ffr:1;
- uint64_t fdr:1;
- } s;
- struct cvmx_fpa_bist_status_s cn30xx;
- struct cvmx_fpa_bist_status_s cn31xx;
- struct cvmx_fpa_bist_status_s cn38xx;
- struct cvmx_fpa_bist_status_s cn38xxp2;
- struct cvmx_fpa_bist_status_s cn50xx;
- struct cvmx_fpa_bist_status_s cn52xx;
- struct cvmx_fpa_bist_status_s cn52xxp1;
- struct cvmx_fpa_bist_status_s cn56xx;
- struct cvmx_fpa_bist_status_s cn56xxp1;
- struct cvmx_fpa_bist_status_s cn58xx;
- struct cvmx_fpa_bist_status_s cn58xxp1;
-};
-
-union cvmx_fpa_ctl_status {
- uint64_t u64;
- struct cvmx_fpa_ctl_status_s {
- uint64_t reserved_18_63:46;
- uint64_t reset:1;
- uint64_t use_ldt:1;
- uint64_t use_stt:1;
- uint64_t enb:1;
- uint64_t mem1_err:7;
- uint64_t mem0_err:7;
- } s;
- struct cvmx_fpa_ctl_status_s cn30xx;
- struct cvmx_fpa_ctl_status_s cn31xx;
- struct cvmx_fpa_ctl_status_s cn38xx;
- struct cvmx_fpa_ctl_status_s cn38xxp2;
- struct cvmx_fpa_ctl_status_s cn50xx;
- struct cvmx_fpa_ctl_status_s cn52xx;
- struct cvmx_fpa_ctl_status_s cn52xxp1;
- struct cvmx_fpa_ctl_status_s cn56xx;
- struct cvmx_fpa_ctl_status_s cn56xxp1;
- struct cvmx_fpa_ctl_status_s cn58xx;
- struct cvmx_fpa_ctl_status_s cn58xxp1;
-};
-
-union cvmx_fpa_fpfx_marks {
- uint64_t u64;
- struct cvmx_fpa_fpfx_marks_s {
- uint64_t reserved_22_63:42;
- uint64_t fpf_wr:11;
- uint64_t fpf_rd:11;
- } s;
- struct cvmx_fpa_fpfx_marks_s cn38xx;
- struct cvmx_fpa_fpfx_marks_s cn38xxp2;
- struct cvmx_fpa_fpfx_marks_s cn56xx;
- struct cvmx_fpa_fpfx_marks_s cn56xxp1;
- struct cvmx_fpa_fpfx_marks_s cn58xx;
- struct cvmx_fpa_fpfx_marks_s cn58xxp1;
-};
-
-union cvmx_fpa_fpfx_size {
- uint64_t u64;
- struct cvmx_fpa_fpfx_size_s {
- uint64_t reserved_11_63:53;
- uint64_t fpf_siz:11;
- } s;
- struct cvmx_fpa_fpfx_size_s cn38xx;
- struct cvmx_fpa_fpfx_size_s cn38xxp2;
- struct cvmx_fpa_fpfx_size_s cn56xx;
- struct cvmx_fpa_fpfx_size_s cn56xxp1;
- struct cvmx_fpa_fpfx_size_s cn58xx;
- struct cvmx_fpa_fpfx_size_s cn58xxp1;
-};
-
-union cvmx_fpa_fpf0_marks {
- uint64_t u64;
- struct cvmx_fpa_fpf0_marks_s {
- uint64_t reserved_24_63:40;
- uint64_t fpf_wr:12;
- uint64_t fpf_rd:12;
- } s;
- struct cvmx_fpa_fpf0_marks_s cn38xx;
- struct cvmx_fpa_fpf0_marks_s cn38xxp2;
- struct cvmx_fpa_fpf0_marks_s cn56xx;
- struct cvmx_fpa_fpf0_marks_s cn56xxp1;
- struct cvmx_fpa_fpf0_marks_s cn58xx;
- struct cvmx_fpa_fpf0_marks_s cn58xxp1;
-};
-
-union cvmx_fpa_fpf0_size {
- uint64_t u64;
- struct cvmx_fpa_fpf0_size_s {
- uint64_t reserved_12_63:52;
- uint64_t fpf_siz:12;
- } s;
- struct cvmx_fpa_fpf0_size_s cn38xx;
- struct cvmx_fpa_fpf0_size_s cn38xxp2;
- struct cvmx_fpa_fpf0_size_s cn56xx;
- struct cvmx_fpa_fpf0_size_s cn56xxp1;
- struct cvmx_fpa_fpf0_size_s cn58xx;
- struct cvmx_fpa_fpf0_size_s cn58xxp1;
-};
-
-union cvmx_fpa_int_enb {
- uint64_t u64;
- struct cvmx_fpa_int_enb_s {
- uint64_t reserved_28_63:36;
- uint64_t q7_perr:1;
- uint64_t q7_coff:1;
- uint64_t q7_und:1;
- uint64_t q6_perr:1;
- uint64_t q6_coff:1;
- uint64_t q6_und:1;
- uint64_t q5_perr:1;
- uint64_t q5_coff:1;
- uint64_t q5_und:1;
- uint64_t q4_perr:1;
- uint64_t q4_coff:1;
- uint64_t q4_und:1;
- uint64_t q3_perr:1;
- uint64_t q3_coff:1;
- uint64_t q3_und:1;
- uint64_t q2_perr:1;
- uint64_t q2_coff:1;
- uint64_t q2_und:1;
- uint64_t q1_perr:1;
- uint64_t q1_coff:1;
- uint64_t q1_und:1;
- uint64_t q0_perr:1;
- uint64_t q0_coff:1;
- uint64_t q0_und:1;
- uint64_t fed1_dbe:1;
- uint64_t fed1_sbe:1;
- uint64_t fed0_dbe:1;
- uint64_t fed0_sbe:1;
- } s;
- struct cvmx_fpa_int_enb_s cn30xx;
- struct cvmx_fpa_int_enb_s cn31xx;
- struct cvmx_fpa_int_enb_s cn38xx;
- struct cvmx_fpa_int_enb_s cn38xxp2;
- struct cvmx_fpa_int_enb_s cn50xx;
- struct cvmx_fpa_int_enb_s cn52xx;
- struct cvmx_fpa_int_enb_s cn52xxp1;
- struct cvmx_fpa_int_enb_s cn56xx;
- struct cvmx_fpa_int_enb_s cn56xxp1;
- struct cvmx_fpa_int_enb_s cn58xx;
- struct cvmx_fpa_int_enb_s cn58xxp1;
-};
-
-union cvmx_fpa_int_sum {
- uint64_t u64;
- struct cvmx_fpa_int_sum_s {
- uint64_t reserved_28_63:36;
- uint64_t q7_perr:1;
- uint64_t q7_coff:1;
- uint64_t q7_und:1;
- uint64_t q6_perr:1;
- uint64_t q6_coff:1;
- uint64_t q6_und:1;
- uint64_t q5_perr:1;
- uint64_t q5_coff:1;
- uint64_t q5_und:1;
- uint64_t q4_perr:1;
- uint64_t q4_coff:1;
- uint64_t q4_und:1;
- uint64_t q3_perr:1;
- uint64_t q3_coff:1;
- uint64_t q3_und:1;
- uint64_t q2_perr:1;
- uint64_t q2_coff:1;
- uint64_t q2_und:1;
- uint64_t q1_perr:1;
- uint64_t q1_coff:1;
- uint64_t q1_und:1;
- uint64_t q0_perr:1;
- uint64_t q0_coff:1;
- uint64_t q0_und:1;
- uint64_t fed1_dbe:1;
- uint64_t fed1_sbe:1;
- uint64_t fed0_dbe:1;
- uint64_t fed0_sbe:1;
- } s;
- struct cvmx_fpa_int_sum_s cn30xx;
- struct cvmx_fpa_int_sum_s cn31xx;
- struct cvmx_fpa_int_sum_s cn38xx;
- struct cvmx_fpa_int_sum_s cn38xxp2;
- struct cvmx_fpa_int_sum_s cn50xx;
- struct cvmx_fpa_int_sum_s cn52xx;
- struct cvmx_fpa_int_sum_s cn52xxp1;
- struct cvmx_fpa_int_sum_s cn56xx;
- struct cvmx_fpa_int_sum_s cn56xxp1;
- struct cvmx_fpa_int_sum_s cn58xx;
- struct cvmx_fpa_int_sum_s cn58xxp1;
-};
-
-union cvmx_fpa_quex_available {
- uint64_t u64;
- struct cvmx_fpa_quex_available_s {
- uint64_t reserved_29_63:35;
- uint64_t que_siz:29;
- } s;
- struct cvmx_fpa_quex_available_s cn30xx;
- struct cvmx_fpa_quex_available_s cn31xx;
- struct cvmx_fpa_quex_available_s cn38xx;
- struct cvmx_fpa_quex_available_s cn38xxp2;
- struct cvmx_fpa_quex_available_s cn50xx;
- struct cvmx_fpa_quex_available_s cn52xx;
- struct cvmx_fpa_quex_available_s cn52xxp1;
- struct cvmx_fpa_quex_available_s cn56xx;
- struct cvmx_fpa_quex_available_s cn56xxp1;
- struct cvmx_fpa_quex_available_s cn58xx;
- struct cvmx_fpa_quex_available_s cn58xxp1;
-};
-
-union cvmx_fpa_quex_page_index {
- uint64_t u64;
- struct cvmx_fpa_quex_page_index_s {
- uint64_t reserved_25_63:39;
- uint64_t pg_num:25;
- } s;
- struct cvmx_fpa_quex_page_index_s cn30xx;
- struct cvmx_fpa_quex_page_index_s cn31xx;
- struct cvmx_fpa_quex_page_index_s cn38xx;
- struct cvmx_fpa_quex_page_index_s cn38xxp2;
- struct cvmx_fpa_quex_page_index_s cn50xx;
- struct cvmx_fpa_quex_page_index_s cn52xx;
- struct cvmx_fpa_quex_page_index_s cn52xxp1;
- struct cvmx_fpa_quex_page_index_s cn56xx;
- struct cvmx_fpa_quex_page_index_s cn56xxp1;
- struct cvmx_fpa_quex_page_index_s cn58xx;
- struct cvmx_fpa_quex_page_index_s cn58xxp1;
-};
-
-union cvmx_fpa_que_act {
- uint64_t u64;
- struct cvmx_fpa_que_act_s {
- uint64_t reserved_29_63:35;
- uint64_t act_que:3;
- uint64_t act_indx:26;
- } s;
- struct cvmx_fpa_que_act_s cn30xx;
- struct cvmx_fpa_que_act_s cn31xx;
- struct cvmx_fpa_que_act_s cn38xx;
- struct cvmx_fpa_que_act_s cn38xxp2;
- struct cvmx_fpa_que_act_s cn50xx;
- struct cvmx_fpa_que_act_s cn52xx;
- struct cvmx_fpa_que_act_s cn52xxp1;
- struct cvmx_fpa_que_act_s cn56xx;
- struct cvmx_fpa_que_act_s cn56xxp1;
- struct cvmx_fpa_que_act_s cn58xx;
- struct cvmx_fpa_que_act_s cn58xxp1;
-};
-
-union cvmx_fpa_que_exp {
- uint64_t u64;
- struct cvmx_fpa_que_exp_s {
- uint64_t reserved_29_63:35;
- uint64_t exp_que:3;
- uint64_t exp_indx:26;
- } s;
- struct cvmx_fpa_que_exp_s cn30xx;
- struct cvmx_fpa_que_exp_s cn31xx;
- struct cvmx_fpa_que_exp_s cn38xx;
- struct cvmx_fpa_que_exp_s cn38xxp2;
- struct cvmx_fpa_que_exp_s cn50xx;
- struct cvmx_fpa_que_exp_s cn52xx;
- struct cvmx_fpa_que_exp_s cn52xxp1;
- struct cvmx_fpa_que_exp_s cn56xx;
- struct cvmx_fpa_que_exp_s cn56xxp1;
- struct cvmx_fpa_que_exp_s cn58xx;
- struct cvmx_fpa_que_exp_s cn58xxp1;
-};
-
-union cvmx_fpa_wart_ctl {
- uint64_t u64;
- struct cvmx_fpa_wart_ctl_s {
- uint64_t reserved_16_63:48;
- uint64_t ctl:16;
- } s;
- struct cvmx_fpa_wart_ctl_s cn30xx;
- struct cvmx_fpa_wart_ctl_s cn31xx;
- struct cvmx_fpa_wart_ctl_s cn38xx;
- struct cvmx_fpa_wart_ctl_s cn38xxp2;
- struct cvmx_fpa_wart_ctl_s cn50xx;
- struct cvmx_fpa_wart_ctl_s cn52xx;
- struct cvmx_fpa_wart_ctl_s cn52xxp1;
- struct cvmx_fpa_wart_ctl_s cn56xx;
- struct cvmx_fpa_wart_ctl_s cn56xxp1;
- struct cvmx_fpa_wart_ctl_s cn58xx;
- struct cvmx_fpa_wart_ctl_s cn58xxp1;
-};
-
-union cvmx_fpa_wart_status {
- uint64_t u64;
- struct cvmx_fpa_wart_status_s {
- uint64_t reserved_32_63:32;
- uint64_t status:32;
- } s;
- struct cvmx_fpa_wart_status_s cn30xx;
- struct cvmx_fpa_wart_status_s cn31xx;
- struct cvmx_fpa_wart_status_s cn38xx;
- struct cvmx_fpa_wart_status_s cn38xxp2;
- struct cvmx_fpa_wart_status_s cn50xx;
- struct cvmx_fpa_wart_status_s cn52xx;
- struct cvmx_fpa_wart_status_s cn52xxp1;
- struct cvmx_fpa_wart_status_s cn56xx;
- struct cvmx_fpa_wart_status_s cn56xxp1;
- struct cvmx_fpa_wart_status_s cn58xx;
- struct cvmx_fpa_wart_status_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-fpa.c b/drivers/staging/octeon/cvmx-fpa.c
deleted file mode 100644
index ad44b8b..0000000
--- a/drivers/staging/octeon/cvmx-fpa.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Support library for the hardware Free Pool Allocator.
- *
- *
- */
-
-#include "cvmx-config.h"
-#include "cvmx.h"
-#include "cvmx-fpa.h"
-#include "cvmx-ipd.h"
-
-/**
- * Current state of all the pools. Use access functions
- * instead of using it directly.
- */
-CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS];
-
-/**
- * Setup a FPA pool to control a new block of memory. The
- * buffer pointer must be a physical address.
- *
- * @pool: Pool to initialize
- * 0 <= pool < 8
- * @name: Constant character string to name this pool.
- * String is not copied.
- * @buffer: Pointer to the block of memory to use. This must be
- * accessible by all processors and external hardware.
- * @block_size: Size for each block controlled by the FPA
- * @num_blocks: Number of blocks
- *
- * Returns 0 on Success,
- * -1 on failure
- */
-int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer,
- uint64_t block_size, uint64_t num_blocks)
-{
- char *ptr;
- if (!buffer) {
- cvmx_dprintf
- ("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n");
- return -1;
- }
- if (pool >= CVMX_FPA_NUM_POOLS) {
- cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n");
- return -1;
- }
-
- if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) {
- cvmx_dprintf
- ("ERROR: cvmx_fpa_setup_pool: Block size too small.\n");
- return -1;
- }
-
- if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) {
- cvmx_dprintf
- ("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n");
- return -1;
- }
-
- cvmx_fpa_pool_info[pool].name = name;
- cvmx_fpa_pool_info[pool].size = block_size;
- cvmx_fpa_pool_info[pool].starting_element_count = num_blocks;
- cvmx_fpa_pool_info[pool].base = buffer;
-
- ptr = (char *)buffer;
- while (num_blocks--) {
- cvmx_fpa_free(ptr, pool, 0);
- ptr += block_size;
- }
- return 0;
-}
-
-/**
- * Shutdown a Memory pool and validate that it had all of
- * the buffers originally placed in it.
- *
- * @pool: Pool to shutdown
- * Returns Zero on success
- * - Positive is count of missing buffers
- * - Negative is too many buffers or corrupted pointers
- */
-uint64_t cvmx_fpa_shutdown_pool(uint64_t pool)
-{
- uint64_t errors = 0;
- uint64_t count = 0;
- uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base);
- uint64_t finish =
- base +
- cvmx_fpa_pool_info[pool].size *
- cvmx_fpa_pool_info[pool].starting_element_count;
- void *ptr;
- uint64_t address;
-
- count = 0;
- do {
- ptr = cvmx_fpa_alloc(pool);
- if (ptr)
- address = cvmx_ptr_to_phys(ptr);
- else
- address = 0;
- if (address) {
- if ((address >= base) && (address < finish) &&
- (((address -
- base) % cvmx_fpa_pool_info[pool].size) == 0)) {
- count++;
- } else {
- cvmx_dprintf
- ("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n",
- (unsigned long long)address,
- cvmx_fpa_pool_info[pool].name, (int)pool);
- errors++;
- }
- }
- } while (address);
-
-#ifdef CVMX_ENABLE_PKO_FUNCTIONS
- if (pool == 0)
- cvmx_ipd_free_ptr();
-#endif
-
- if (errors) {
- cvmx_dprintf
- ("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n",
- cvmx_fpa_pool_info[pool].name, (int)pool,
- (unsigned long long)base, (unsigned long long)finish,
- (unsigned long long)cvmx_fpa_pool_info[pool].size);
- return -errors;
- } else
- return 0;
-}
-
-uint64_t cvmx_fpa_get_block_size(uint64_t pool)
-{
- switch (pool) {
- case 0:
- return CVMX_FPA_POOL_0_SIZE;
- case 1:
- return CVMX_FPA_POOL_1_SIZE;
- case 2:
- return CVMX_FPA_POOL_2_SIZE;
- case 3:
- return CVMX_FPA_POOL_3_SIZE;
- case 4:
- return CVMX_FPA_POOL_4_SIZE;
- case 5:
- return CVMX_FPA_POOL_5_SIZE;
- case 6:
- return CVMX_FPA_POOL_6_SIZE;
- case 7:
- return CVMX_FPA_POOL_7_SIZE;
- default:
- return 0;
- }
-}
diff --git a/drivers/staging/octeon/cvmx-fpa.h b/drivers/staging/octeon/cvmx-fpa.h
deleted file mode 100644
index 1f04f96..0000000
--- a/drivers/staging/octeon/cvmx-fpa.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Interface to the hardware Free Pool Allocator.
- *
- *
- */
-
-#ifndef __CVMX_FPA_H__
-#define __CVMX_FPA_H__
-
-#include "cvmx-address.h"
-#include "cvmx-fpa-defs.h"
-
-#define CVMX_FPA_NUM_POOLS 8
-#define CVMX_FPA_MIN_BLOCK_SIZE 128
-#define CVMX_FPA_ALIGNMENT 128
-
-/**
- * Structure describing the data format used for stores to the FPA.
- */
-typedef union {
- uint64_t u64;
- struct {
- /*
- * the (64-bit word) location in scratchpad to write
- * to (if len != 0)
- */
- uint64_t scraddr:8;
- /* the number of words in the response (0 => no response) */
- uint64_t len:8;
- /* the ID of the device on the non-coherent bus */
- uint64_t did:8;
- /*
- * the address that will appear in the first tick on
- * the NCB bus.
- */
- uint64_t addr:40;
- } s;
-} cvmx_fpa_iobdma_data_t;
-
-/**
- * Structure describing the current state of a FPA pool.
- */
-typedef struct {
- /* Name it was created under */
- const char *name;
- /* Size of each block */
- uint64_t size;
- /* The base memory address of whole block */
- void *base;
- /* The number of elements in the pool at creation */
- uint64_t starting_element_count;
-} cvmx_fpa_pool_info_t;
-
-/**
- * Current state of all the pools. Use access functions
- * instead of using it directly.
- */
-extern cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS];
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-
-/**
- * Return the name of the pool
- *
- * @pool: Pool to get the name of
- * Returns The name
- */
-static inline const char *cvmx_fpa_get_name(uint64_t pool)
-{
- return cvmx_fpa_pool_info[pool].name;
-}
-
-/**
- * Return the base of the pool
- *
- * @pool: Pool to get the base of
- * Returns The base
- */
-static inline void *cvmx_fpa_get_base(uint64_t pool)
-{
- return cvmx_fpa_pool_info[pool].base;
-}
-
-/**
- * Check if a pointer belongs to an FPA pool. Return non-zero
- * if the supplied pointer is inside the memory controlled by
- * an FPA pool.
- *
- * @pool: Pool to check
- * @ptr: Pointer to check
- * Returns Non-zero if pointer is in the pool. Zero if not
- */
-static inline int cvmx_fpa_is_member(uint64_t pool, void *ptr)
-{
- return ((ptr >= cvmx_fpa_pool_info[pool].base) &&
- ((char *)ptr <
- ((char *)(cvmx_fpa_pool_info[pool].base)) +
- cvmx_fpa_pool_info[pool].size *
- cvmx_fpa_pool_info[pool].starting_element_count));
-}
-
-/**
- * Enable the FPA for use. Must be performed after any CSR
- * configuration but before any other FPA functions.
- */
-static inline void cvmx_fpa_enable(void)
-{
- union cvmx_fpa_ctl_status status;
-
- status.u64 = cvmx_read_csr(CVMX_FPA_CTL_STATUS);
- if (status.s.enb) {
- cvmx_dprintf
- ("Warning: Enabling FPA when FPA already enabled.\n");
- }
-
- /*
- * Do runtime check as we allow pass1 compiled code to run on
- * pass2 chips.
- */
- if (cvmx_octeon_is_pass1()) {
- union cvmx_fpa_fpfx_marks marks;
- int i;
- for (i = 1; i < 8; i++) {
- marks.u64 =
- cvmx_read_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull);
- marks.s.fpf_wr = 0xe0;
- cvmx_write_csr(CVMX_FPA_FPF1_MARKS + (i - 1) * 8ull,
- marks.u64);
- }
-
- /* Enforce a 10 cycle delay between config and enable */
- cvmx_wait(10);
- }
-
- /* FIXME: CVMX_FPA_CTL_STATUS read is unmodelled */
- status.u64 = 0;
- status.s.enb = 1;
- cvmx_write_csr(CVMX_FPA_CTL_STATUS, status.u64);
-}
-
-/**
- * Get a new block from the FPA
- *
- * @pool: Pool to get the block from
- * Returns Pointer to the block or NULL on failure
- */
-static inline void *cvmx_fpa_alloc(uint64_t pool)
-{
- uint64_t address =
- cvmx_read_csr(CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)));
- if (address)
- return cvmx_phys_to_ptr(address);
- else
- return NULL;
-}
-
-/**
- * Asynchronously get a new block from the FPA
- *
- * @scr_addr: Local scratch address to put response in. This is a byte address,
- * but must be 8 byte aligned.
- * @pool: Pool to get the block from
- */
-static inline void cvmx_fpa_async_alloc(uint64_t scr_addr, uint64_t pool)
-{
- cvmx_fpa_iobdma_data_t data;
-
- /*
- * Hardware only uses 64 bit aligned locations, so convert
- * from byte address to 64-bit index
- */
- data.s.scraddr = scr_addr >> 3;
- data.s.len = 1;
- data.s.did = CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool);
- data.s.addr = 0;
- cvmx_send_single(data.u64);
-}
-
-/**
- * Free a block allocated with a FPA pool. Does NOT provide memory
- * ordering in cases where the memory block was modified by the core.
- *
- * @ptr: Block to free
- * @pool: Pool to put it in
- * @num_cache_lines:
- * Cache lines to invalidate
- */
-static inline void cvmx_fpa_free_nosync(void *ptr, uint64_t pool,
- uint64_t num_cache_lines)
-{
- cvmx_addr_t newptr;
- newptr.u64 = cvmx_ptr_to_phys(ptr);
- newptr.sfilldidspace.didspace =
- CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool));
- /* Prevent GCC from reordering around free */
- barrier();
- /* value written is number of cache lines not written back */
- cvmx_write_io(newptr.u64, num_cache_lines);
-}
-
-/**
- * Free a block allocated with a FPA pool. Provides required memory
- * ordering in cases where memory block was modified by core.
- *
- * @ptr: Block to free
- * @pool: Pool to put it in
- * @num_cache_lines:
- * Cache lines to invalidate
- */
-static inline void cvmx_fpa_free(void *ptr, uint64_t pool,
- uint64_t num_cache_lines)
-{
- cvmx_addr_t newptr;
- newptr.u64 = cvmx_ptr_to_phys(ptr);
- newptr.sfilldidspace.didspace =
- CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool));
- /*
- * Make sure that any previous writes to memory go out before
- * we free this buffer. This also serves as a barrier to
- * prevent GCC from reordering operations to after the
- * free.
- */
- CVMX_SYNCWS;
- /* value written is number of cache lines not written back */
- cvmx_write_io(newptr.u64, num_cache_lines);
-}
-
-/**
- * Setup a FPA pool to control a new block of memory.
- * This can only be called once per pool. Make sure proper
- * locking enforces this.
- *
- * @pool: Pool to initialize
- * 0 <= pool < 8
- * @name: Constant character string to name this pool.
- * String is not copied.
- * @buffer: Pointer to the block of memory to use. This must be
- * accessible by all processors and external hardware.
- * @block_size: Size for each block controlled by the FPA
- * @num_blocks: Number of blocks
- *
- * Returns 0 on Success,
- * -1 on failure
- */
-extern int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer,
- uint64_t block_size, uint64_t num_blocks);
-
-/**
- * Shutdown a Memory pool and validate that it had all of
- * the buffers originally placed in it. This should only be
- * called by one processor after all hardware has finished
- * using the pool.
- *
- * @pool: Pool to shutdown
- * Returns Zero on success
- * - Positive is count of missing buffers
- * - Negative is too many buffers or corrupted pointers
- */
-extern uint64_t cvmx_fpa_shutdown_pool(uint64_t pool);
-
-/**
- * Get the size of blocks controlled by the pool
- * This is resolved to a constant at compile time.
- *
- * @pool: Pool to access
- * Returns Size of the block in bytes
- */
-uint64_t cvmx_fpa_get_block_size(uint64_t pool);
-
-#endif /* __CVM_FPA_H__ */
diff --git a/drivers/staging/octeon/cvmx-gmxx-defs.h b/drivers/staging/octeon/cvmx-gmxx-defs.h
deleted file mode 100644
index 946a43a..0000000
--- a/drivers/staging/octeon/cvmx-gmxx-defs.h
+++ /dev/null
@@ -1,2529 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_GMXX_DEFS_H__
-#define __CVMX_GMXX_DEFS_H__
-
-#define CVMX_GMXX_BAD_REG(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000518ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_BIST(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000400ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_CLK_EN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080007F0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_HG2_CONTROL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000550ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_INF_MODE(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080007F8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_NXA_ADR(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000510ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_PRTX_CBFC_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000580ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_PRTX_CFG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000010ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM0(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000180ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM1(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000188ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM2(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000190ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM3(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000198ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM4(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080001A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM5(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080001A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CAM_EN(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000108ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_ADR_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000100ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_DECISION(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000040ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_FRM_CHK(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000020ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_FRM_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000018ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_FRM_MAX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000030ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_FRM_MIN(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000028ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_IFG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000058ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_INT_EN(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000008ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_INT_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000000ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_JABBER(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000038ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_PAUSE_DROP_TIME(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000068ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_RX_INBND(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000060ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000050ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_OCTS(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000088ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_OCTS_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000098ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_OCTS_DMAC(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080000A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_OCTS_DRP(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080000B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_PKTS(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000080ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_PKTS_BAD(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080000C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_PKTS_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000090ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_PKTS_DMAC(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080000A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_STATS_PKTS_DRP(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080000B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RXX_UDD_SKP(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000048ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_BP_DROPX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000420ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_BP_OFFX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000460ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_BP_ONX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000440ull + (((offset) & 3) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_HG2_STATUS(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000548ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_PASS_EN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080005F8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_PASS_MAPX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000600ull + (((offset) & 15) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_PRTS(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000410ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_PRT_INFO(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004E8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_TX_STATUS(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080007E8ull + (((block_id) & 0) * 0x8000000ull))
-#define CVMX_GMXX_RX_XAUI_BAD_COL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000538ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_RX_XAUI_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000530ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_SMACX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000230ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_STAT_BP(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000520ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_APPEND(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000218ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_BURST(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000228ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_CBFC_XOFF(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080005A0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_CBFC_XON(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080005C0ull + (((offset) & 0) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_CLK(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000208ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000270ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_MIN_PKT(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000240ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000248ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_PAUSE_PKT_TIME(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000238ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_PAUSE_TOGO(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000258ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_PAUSE_ZERO(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000260ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_SGMII_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000300ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_SLOT(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000220ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_SOFT_PAUSE(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000250ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT0(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000280ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT1(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000288ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT2(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000290ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT3(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000298ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT4(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002A0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT5(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002A8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT6(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002B0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT7(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002B8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT8(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002C0ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STAT9(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800080002C8ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_STATS_CTL(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000268ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TXX_THRESH(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000210ull + (((offset) & 3) * 2048) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_BP(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004D0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_CLK_MSKX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000780ull + (((offset) & 1) * 8) + (((block_id) & 0) * 0x0ull))
-#define CVMX_GMXX_TX_COL_ATTEMPT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000498ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_CORRUPT(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004D8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_HG2_REG1(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000558ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_HG2_REG2(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000560ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_IFG(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000488ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_INT_EN(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000508ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_INT_REG(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000500ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_JAM(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000490ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_LFSR(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004F8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_OVR_BP(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004C8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_PAUSE_PKT_DMAC(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004A0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_PAUSE_PKT_TYPE(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004A8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_PRTS(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000480ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_SPI_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004C0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_SPI_DRAIN(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004E0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_SPI_MAX(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004B0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_SPI_ROUNDX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000680ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_SPI_THRESH(block_id) \
- CVMX_ADD_IO_SEG(0x00011800080004B8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_TX_XAUI_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000528ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_GMXX_XAUI_EXT_LOOPBACK(block_id) \
- CVMX_ADD_IO_SEG(0x0001180008000540ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_gmxx_bad_reg {
- uint64_t u64;
- struct cvmx_gmxx_bad_reg_s {
- uint64_t reserved_31_63:33;
- uint64_t inb_nxa:4;
- uint64_t statovr:1;
- uint64_t loststat:4;
- uint64_t reserved_18_21:4;
- uint64_t out_ovr:16;
- uint64_t ncb_ovr:1;
- uint64_t out_col:1;
- } s;
- struct cvmx_gmxx_bad_reg_cn30xx {
- uint64_t reserved_31_63:33;
- uint64_t inb_nxa:4;
- uint64_t statovr:1;
- uint64_t reserved_25_25:1;
- uint64_t loststat:3;
- uint64_t reserved_5_21:17;
- uint64_t out_ovr:3;
- uint64_t reserved_0_1:2;
- } cn30xx;
- struct cvmx_gmxx_bad_reg_cn30xx cn31xx;
- struct cvmx_gmxx_bad_reg_s cn38xx;
- struct cvmx_gmxx_bad_reg_s cn38xxp2;
- struct cvmx_gmxx_bad_reg_cn30xx cn50xx;
- struct cvmx_gmxx_bad_reg_cn52xx {
- uint64_t reserved_31_63:33;
- uint64_t inb_nxa:4;
- uint64_t statovr:1;
- uint64_t loststat:4;
- uint64_t reserved_6_21:16;
- uint64_t out_ovr:4;
- uint64_t reserved_0_1:2;
- } cn52xx;
- struct cvmx_gmxx_bad_reg_cn52xx cn52xxp1;
- struct cvmx_gmxx_bad_reg_cn52xx cn56xx;
- struct cvmx_gmxx_bad_reg_cn52xx cn56xxp1;
- struct cvmx_gmxx_bad_reg_s cn58xx;
- struct cvmx_gmxx_bad_reg_s cn58xxp1;
-};
-
-union cvmx_gmxx_bist {
- uint64_t u64;
- struct cvmx_gmxx_bist_s {
- uint64_t reserved_17_63:47;
- uint64_t status:17;
- } s;
- struct cvmx_gmxx_bist_cn30xx {
- uint64_t reserved_10_63:54;
- uint64_t status:10;
- } cn30xx;
- struct cvmx_gmxx_bist_cn30xx cn31xx;
- struct cvmx_gmxx_bist_cn30xx cn38xx;
- struct cvmx_gmxx_bist_cn30xx cn38xxp2;
- struct cvmx_gmxx_bist_cn50xx {
- uint64_t reserved_12_63:52;
- uint64_t status:12;
- } cn50xx;
- struct cvmx_gmxx_bist_cn52xx {
- uint64_t reserved_16_63:48;
- uint64_t status:16;
- } cn52xx;
- struct cvmx_gmxx_bist_cn52xx cn52xxp1;
- struct cvmx_gmxx_bist_cn52xx cn56xx;
- struct cvmx_gmxx_bist_cn52xx cn56xxp1;
- struct cvmx_gmxx_bist_s cn58xx;
- struct cvmx_gmxx_bist_s cn58xxp1;
-};
-
-union cvmx_gmxx_clk_en {
- uint64_t u64;
- struct cvmx_gmxx_clk_en_s {
- uint64_t reserved_1_63:63;
- uint64_t clk_en:1;
- } s;
- struct cvmx_gmxx_clk_en_s cn52xx;
- struct cvmx_gmxx_clk_en_s cn52xxp1;
- struct cvmx_gmxx_clk_en_s cn56xx;
- struct cvmx_gmxx_clk_en_s cn56xxp1;
-};
-
-union cvmx_gmxx_hg2_control {
- uint64_t u64;
- struct cvmx_gmxx_hg2_control_s {
- uint64_t reserved_19_63:45;
- uint64_t hg2tx_en:1;
- uint64_t hg2rx_en:1;
- uint64_t phys_en:1;
- uint64_t logl_en:16;
- } s;
- struct cvmx_gmxx_hg2_control_s cn52xx;
- struct cvmx_gmxx_hg2_control_s cn52xxp1;
- struct cvmx_gmxx_hg2_control_s cn56xx;
-};
-
-union cvmx_gmxx_inf_mode {
- uint64_t u64;
- struct cvmx_gmxx_inf_mode_s {
- uint64_t reserved_10_63:54;
- uint64_t speed:2;
- uint64_t reserved_6_7:2;
- uint64_t mode:2;
- uint64_t reserved_3_3:1;
- uint64_t p0mii:1;
- uint64_t en:1;
- uint64_t type:1;
- } s;
- struct cvmx_gmxx_inf_mode_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t p0mii:1;
- uint64_t en:1;
- uint64_t type:1;
- } cn30xx;
- struct cvmx_gmxx_inf_mode_cn31xx {
- uint64_t reserved_2_63:62;
- uint64_t en:1;
- uint64_t type:1;
- } cn31xx;
- struct cvmx_gmxx_inf_mode_cn31xx cn38xx;
- struct cvmx_gmxx_inf_mode_cn31xx cn38xxp2;
- struct cvmx_gmxx_inf_mode_cn30xx cn50xx;
- struct cvmx_gmxx_inf_mode_cn52xx {
- uint64_t reserved_10_63:54;
- uint64_t speed:2;
- uint64_t reserved_6_7:2;
- uint64_t mode:2;
- uint64_t reserved_2_3:2;
- uint64_t en:1;
- uint64_t type:1;
- } cn52xx;
- struct cvmx_gmxx_inf_mode_cn52xx cn52xxp1;
- struct cvmx_gmxx_inf_mode_cn52xx cn56xx;
- struct cvmx_gmxx_inf_mode_cn52xx cn56xxp1;
- struct cvmx_gmxx_inf_mode_cn31xx cn58xx;
- struct cvmx_gmxx_inf_mode_cn31xx cn58xxp1;
-};
-
-union cvmx_gmxx_nxa_adr {
- uint64_t u64;
- struct cvmx_gmxx_nxa_adr_s {
- uint64_t reserved_6_63:58;
- uint64_t prt:6;
- } s;
- struct cvmx_gmxx_nxa_adr_s cn30xx;
- struct cvmx_gmxx_nxa_adr_s cn31xx;
- struct cvmx_gmxx_nxa_adr_s cn38xx;
- struct cvmx_gmxx_nxa_adr_s cn38xxp2;
- struct cvmx_gmxx_nxa_adr_s cn50xx;
- struct cvmx_gmxx_nxa_adr_s cn52xx;
- struct cvmx_gmxx_nxa_adr_s cn52xxp1;
- struct cvmx_gmxx_nxa_adr_s cn56xx;
- struct cvmx_gmxx_nxa_adr_s cn56xxp1;
- struct cvmx_gmxx_nxa_adr_s cn58xx;
- struct cvmx_gmxx_nxa_adr_s cn58xxp1;
-};
-
-union cvmx_gmxx_prtx_cbfc_ctl {
- uint64_t u64;
- struct cvmx_gmxx_prtx_cbfc_ctl_s {
- uint64_t phys_en:16;
- uint64_t logl_en:16;
- uint64_t phys_bp:16;
- uint64_t reserved_4_15:12;
- uint64_t bck_en:1;
- uint64_t drp_en:1;
- uint64_t tx_en:1;
- uint64_t rx_en:1;
- } s;
- struct cvmx_gmxx_prtx_cbfc_ctl_s cn52xx;
- struct cvmx_gmxx_prtx_cbfc_ctl_s cn56xx;
-};
-
-union cvmx_gmxx_prtx_cfg {
- uint64_t u64;
- struct cvmx_gmxx_prtx_cfg_s {
- uint64_t reserved_14_63:50;
- uint64_t tx_idle:1;
- uint64_t rx_idle:1;
- uint64_t reserved_9_11:3;
- uint64_t speed_msb:1;
- uint64_t reserved_4_7:4;
- uint64_t slottime:1;
- uint64_t duplex:1;
- uint64_t speed:1;
- uint64_t en:1;
- } s;
- struct cvmx_gmxx_prtx_cfg_cn30xx {
- uint64_t reserved_4_63:60;
- uint64_t slottime:1;
- uint64_t duplex:1;
- uint64_t speed:1;
- uint64_t en:1;
- } cn30xx;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn31xx;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn38xx;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn38xxp2;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn50xx;
- struct cvmx_gmxx_prtx_cfg_s cn52xx;
- struct cvmx_gmxx_prtx_cfg_s cn52xxp1;
- struct cvmx_gmxx_prtx_cfg_s cn56xx;
- struct cvmx_gmxx_prtx_cfg_s cn56xxp1;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn58xx;
- struct cvmx_gmxx_prtx_cfg_cn30xx cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam0 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam0_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam0_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam0_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam0_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam0_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam0_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam1 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam1_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam1_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam1_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam1_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam1_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam1_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam2 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam2_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam2_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam2_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam2_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam2_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam2_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam3 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam3_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam3_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam3_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam3_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam3_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam3_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam4 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam4_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam4_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam4_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam4_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam4_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam4_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam5 {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam5_s {
- uint64_t adr:64;
- } s;
- struct cvmx_gmxx_rxx_adr_cam5_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam5_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam5_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam5_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam5_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_cam_en {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_cam_en_s {
- uint64_t reserved_8_63:56;
- uint64_t en:8;
- } s;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn30xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn31xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn38xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn50xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn52xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn56xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn58xx;
- struct cvmx_gmxx_rxx_adr_cam_en_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_adr_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rxx_adr_ctl_s {
- uint64_t reserved_4_63:60;
- uint64_t cam_mode:1;
- uint64_t mcst:2;
- uint64_t bcst:1;
- } s;
- struct cvmx_gmxx_rxx_adr_ctl_s cn30xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn31xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn38xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn38xxp2;
- struct cvmx_gmxx_rxx_adr_ctl_s cn50xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn52xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn52xxp1;
- struct cvmx_gmxx_rxx_adr_ctl_s cn56xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn56xxp1;
- struct cvmx_gmxx_rxx_adr_ctl_s cn58xx;
- struct cvmx_gmxx_rxx_adr_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_decision {
- uint64_t u64;
- struct cvmx_gmxx_rxx_decision_s {
- uint64_t reserved_5_63:59;
- uint64_t cnt:5;
- } s;
- struct cvmx_gmxx_rxx_decision_s cn30xx;
- struct cvmx_gmxx_rxx_decision_s cn31xx;
- struct cvmx_gmxx_rxx_decision_s cn38xx;
- struct cvmx_gmxx_rxx_decision_s cn38xxp2;
- struct cvmx_gmxx_rxx_decision_s cn50xx;
- struct cvmx_gmxx_rxx_decision_s cn52xx;
- struct cvmx_gmxx_rxx_decision_s cn52xxp1;
- struct cvmx_gmxx_rxx_decision_s cn56xx;
- struct cvmx_gmxx_rxx_decision_s cn56xxp1;
- struct cvmx_gmxx_rxx_decision_s cn58xx;
- struct cvmx_gmxx_rxx_decision_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_frm_chk {
- uint64_t u64;
- struct cvmx_gmxx_rxx_frm_chk_s {
- uint64_t reserved_10_63:54;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } s;
- struct cvmx_gmxx_rxx_frm_chk_s cn30xx;
- struct cvmx_gmxx_rxx_frm_chk_s cn31xx;
- struct cvmx_gmxx_rxx_frm_chk_s cn38xx;
- struct cvmx_gmxx_rxx_frm_chk_s cn38xxp2;
- struct cvmx_gmxx_rxx_frm_chk_cn50xx {
- uint64_t reserved_10_63:54;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_6_6:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn50xx;
- struct cvmx_gmxx_rxx_frm_chk_cn52xx {
- uint64_t reserved_9_63:55;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_5_6:2;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn52xx;
- struct cvmx_gmxx_rxx_frm_chk_cn52xx cn52xxp1;
- struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xx;
- struct cvmx_gmxx_rxx_frm_chk_cn52xx cn56xxp1;
- struct cvmx_gmxx_rxx_frm_chk_s cn58xx;
- struct cvmx_gmxx_rxx_frm_chk_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_frm_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rxx_frm_ctl_s {
- uint64_t reserved_11_63:53;
- uint64_t null_dis:1;
- uint64_t pre_align:1;
- uint64_t pad_len:1;
- uint64_t vlan_len:1;
- uint64_t pre_free:1;
- uint64_t ctl_smac:1;
- uint64_t ctl_mcst:1;
- uint64_t ctl_bck:1;
- uint64_t ctl_drp:1;
- uint64_t pre_strp:1;
- uint64_t pre_chk:1;
- } s;
- struct cvmx_gmxx_rxx_frm_ctl_cn30xx {
- uint64_t reserved_9_63:55;
- uint64_t pad_len:1;
- uint64_t vlan_len:1;
- uint64_t pre_free:1;
- uint64_t ctl_smac:1;
- uint64_t ctl_mcst:1;
- uint64_t ctl_bck:1;
- uint64_t ctl_drp:1;
- uint64_t pre_strp:1;
- uint64_t pre_chk:1;
- } cn30xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn31xx {
- uint64_t reserved_8_63:56;
- uint64_t vlan_len:1;
- uint64_t pre_free:1;
- uint64_t ctl_smac:1;
- uint64_t ctl_mcst:1;
- uint64_t ctl_bck:1;
- uint64_t ctl_drp:1;
- uint64_t pre_strp:1;
- uint64_t pre_chk:1;
- } cn31xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn38xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn31xx cn38xxp2;
- struct cvmx_gmxx_rxx_frm_ctl_cn50xx {
- uint64_t reserved_11_63:53;
- uint64_t null_dis:1;
- uint64_t pre_align:1;
- uint64_t reserved_7_8:2;
- uint64_t pre_free:1;
- uint64_t ctl_smac:1;
- uint64_t ctl_mcst:1;
- uint64_t ctl_bck:1;
- uint64_t ctl_drp:1;
- uint64_t pre_strp:1;
- uint64_t pre_chk:1;
- } cn50xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn52xxp1;
- struct cvmx_gmxx_rxx_frm_ctl_cn50xx cn56xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 {
- uint64_t reserved_10_63:54;
- uint64_t pre_align:1;
- uint64_t reserved_7_8:2;
- uint64_t pre_free:1;
- uint64_t ctl_smac:1;
- uint64_t ctl_mcst:1;
- uint64_t ctl_bck:1;
- uint64_t ctl_drp:1;
- uint64_t pre_strp:1;
- uint64_t pre_chk:1;
- } cn56xxp1;
- struct cvmx_gmxx_rxx_frm_ctl_s cn58xx;
- struct cvmx_gmxx_rxx_frm_ctl_cn30xx cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_frm_max {
- uint64_t u64;
- struct cvmx_gmxx_rxx_frm_max_s {
- uint64_t reserved_16_63:48;
- uint64_t len:16;
- } s;
- struct cvmx_gmxx_rxx_frm_max_s cn30xx;
- struct cvmx_gmxx_rxx_frm_max_s cn31xx;
- struct cvmx_gmxx_rxx_frm_max_s cn38xx;
- struct cvmx_gmxx_rxx_frm_max_s cn38xxp2;
- struct cvmx_gmxx_rxx_frm_max_s cn58xx;
- struct cvmx_gmxx_rxx_frm_max_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_frm_min {
- uint64_t u64;
- struct cvmx_gmxx_rxx_frm_min_s {
- uint64_t reserved_16_63:48;
- uint64_t len:16;
- } s;
- struct cvmx_gmxx_rxx_frm_min_s cn30xx;
- struct cvmx_gmxx_rxx_frm_min_s cn31xx;
- struct cvmx_gmxx_rxx_frm_min_s cn38xx;
- struct cvmx_gmxx_rxx_frm_min_s cn38xxp2;
- struct cvmx_gmxx_rxx_frm_min_s cn58xx;
- struct cvmx_gmxx_rxx_frm_min_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_ifg {
- uint64_t u64;
- struct cvmx_gmxx_rxx_ifg_s {
- uint64_t reserved_4_63:60;
- uint64_t ifg:4;
- } s;
- struct cvmx_gmxx_rxx_ifg_s cn30xx;
- struct cvmx_gmxx_rxx_ifg_s cn31xx;
- struct cvmx_gmxx_rxx_ifg_s cn38xx;
- struct cvmx_gmxx_rxx_ifg_s cn38xxp2;
- struct cvmx_gmxx_rxx_ifg_s cn50xx;
- struct cvmx_gmxx_rxx_ifg_s cn52xx;
- struct cvmx_gmxx_rxx_ifg_s cn52xxp1;
- struct cvmx_gmxx_rxx_ifg_s cn56xx;
- struct cvmx_gmxx_rxx_ifg_s cn56xxp1;
- struct cvmx_gmxx_rxx_ifg_s cn58xx;
- struct cvmx_gmxx_rxx_ifg_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_int_en {
- uint64_t u64;
- struct cvmx_gmxx_rxx_int_en_s {
- uint64_t reserved_29_63:35;
- uint64_t hg2cc:1;
- uint64_t hg2fld:1;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } s;
- struct cvmx_gmxx_rxx_int_en_cn30xx {
- uint64_t reserved_19_63:45;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } cn30xx;
- struct cvmx_gmxx_rxx_int_en_cn30xx cn31xx;
- struct cvmx_gmxx_rxx_int_en_cn30xx cn38xx;
- struct cvmx_gmxx_rxx_int_en_cn30xx cn38xxp2;
- struct cvmx_gmxx_rxx_int_en_cn50xx {
- uint64_t reserved_20_63:44;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_6_6:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn50xx;
- struct cvmx_gmxx_rxx_int_en_cn52xx {
- uint64_t reserved_29_63:35;
- uint64_t hg2cc:1;
- uint64_t hg2fld:1;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t reserved_16_18:3;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t reserved_9_9:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_5_6:2;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn52xx;
- struct cvmx_gmxx_rxx_int_en_cn52xx cn52xxp1;
- struct cvmx_gmxx_rxx_int_en_cn52xx cn56xx;
- struct cvmx_gmxx_rxx_int_en_cn56xxp1 {
- uint64_t reserved_27_63:37;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t reserved_16_18:3;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t reserved_9_9:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_5_6:2;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn56xxp1;
- struct cvmx_gmxx_rxx_int_en_cn58xx {
- uint64_t reserved_20_63:44;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } cn58xx;
- struct cvmx_gmxx_rxx_int_en_cn58xx cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_int_reg {
- uint64_t u64;
- struct cvmx_gmxx_rxx_int_reg_s {
- uint64_t reserved_29_63:35;
- uint64_t hg2cc:1;
- uint64_t hg2fld:1;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } s;
- struct cvmx_gmxx_rxx_int_reg_cn30xx {
- uint64_t reserved_19_63:45;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } cn30xx;
- struct cvmx_gmxx_rxx_int_reg_cn30xx cn31xx;
- struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xx;
- struct cvmx_gmxx_rxx_int_reg_cn30xx cn38xxp2;
- struct cvmx_gmxx_rxx_int_reg_cn50xx {
- uint64_t reserved_20_63:44;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_6_6:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn50xx;
- struct cvmx_gmxx_rxx_int_reg_cn52xx {
- uint64_t reserved_29_63:35;
- uint64_t hg2cc:1;
- uint64_t hg2fld:1;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t reserved_16_18:3;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t reserved_9_9:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_5_6:2;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn52xx;
- struct cvmx_gmxx_rxx_int_reg_cn52xx cn52xxp1;
- struct cvmx_gmxx_rxx_int_reg_cn52xx cn56xx;
- struct cvmx_gmxx_rxx_int_reg_cn56xxp1 {
- uint64_t reserved_27_63:37;
- uint64_t undat:1;
- uint64_t uneop:1;
- uint64_t unsop:1;
- uint64_t bad_term:1;
- uint64_t bad_seq:1;
- uint64_t rem_fault:1;
- uint64_t loc_fault:1;
- uint64_t pause_drp:1;
- uint64_t reserved_16_18:3;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t reserved_9_9:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t reserved_5_6:2;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t reserved_2_2:1;
- uint64_t carext:1;
- uint64_t reserved_0_0:1;
- } cn56xxp1;
- struct cvmx_gmxx_rxx_int_reg_cn58xx {
- uint64_t reserved_20_63:44;
- uint64_t pause_drp:1;
- uint64_t phy_dupx:1;
- uint64_t phy_spd:1;
- uint64_t phy_link:1;
- uint64_t ifgerr:1;
- uint64_t coldet:1;
- uint64_t falerr:1;
- uint64_t rsverr:1;
- uint64_t pcterr:1;
- uint64_t ovrerr:1;
- uint64_t niberr:1;
- uint64_t skperr:1;
- uint64_t rcverr:1;
- uint64_t lenerr:1;
- uint64_t alnerr:1;
- uint64_t fcserr:1;
- uint64_t jabber:1;
- uint64_t maxerr:1;
- uint64_t carext:1;
- uint64_t minerr:1;
- } cn58xx;
- struct cvmx_gmxx_rxx_int_reg_cn58xx cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_jabber {
- uint64_t u64;
- struct cvmx_gmxx_rxx_jabber_s {
- uint64_t reserved_16_63:48;
- uint64_t cnt:16;
- } s;
- struct cvmx_gmxx_rxx_jabber_s cn30xx;
- struct cvmx_gmxx_rxx_jabber_s cn31xx;
- struct cvmx_gmxx_rxx_jabber_s cn38xx;
- struct cvmx_gmxx_rxx_jabber_s cn38xxp2;
- struct cvmx_gmxx_rxx_jabber_s cn50xx;
- struct cvmx_gmxx_rxx_jabber_s cn52xx;
- struct cvmx_gmxx_rxx_jabber_s cn52xxp1;
- struct cvmx_gmxx_rxx_jabber_s cn56xx;
- struct cvmx_gmxx_rxx_jabber_s cn56xxp1;
- struct cvmx_gmxx_rxx_jabber_s cn58xx;
- struct cvmx_gmxx_rxx_jabber_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_pause_drop_time {
- uint64_t u64;
- struct cvmx_gmxx_rxx_pause_drop_time_s {
- uint64_t reserved_16_63:48;
- uint64_t status:16;
- } s;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn50xx;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn52xx;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn52xxp1;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn56xx;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn56xxp1;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn58xx;
- struct cvmx_gmxx_rxx_pause_drop_time_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_rx_inbnd {
- uint64_t u64;
- struct cvmx_gmxx_rxx_rx_inbnd_s {
- uint64_t reserved_4_63:60;
- uint64_t duplex:1;
- uint64_t speed:2;
- uint64_t status:1;
- } s;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn30xx;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn31xx;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn38xx;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn38xxp2;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn50xx;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn58xx;
- struct cvmx_gmxx_rxx_rx_inbnd_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_ctl_s {
- uint64_t reserved_1_63:63;
- uint64_t rd_clr:1;
- } s;
- struct cvmx_gmxx_rxx_stats_ctl_s cn30xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn31xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn38xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_ctl_s cn50xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn52xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_ctl_s cn56xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_ctl_s cn58xx;
- struct cvmx_gmxx_rxx_stats_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_octs {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_octs_s {
- uint64_t reserved_48_63:16;
- uint64_t cnt:48;
- } s;
- struct cvmx_gmxx_rxx_stats_octs_s cn30xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn31xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn38xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_octs_s cn50xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn52xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_octs_s cn56xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_octs_s cn58xx;
- struct cvmx_gmxx_rxx_stats_octs_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_octs_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s {
- uint64_t reserved_48_63:16;
- uint64_t cnt:48;
- } s;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn30xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn31xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn50xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xx;
- struct cvmx_gmxx_rxx_stats_octs_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_octs_dmac {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s {
- uint64_t reserved_48_63:16;
- uint64_t cnt:48;
- } s;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn30xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn31xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn50xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xx;
- struct cvmx_gmxx_rxx_stats_octs_dmac_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_octs_drp {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_octs_drp_s {
- uint64_t reserved_48_63:16;
- uint64_t cnt:48;
- } s;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn30xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn31xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn50xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xx;
- struct cvmx_gmxx_rxx_stats_octs_drp_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_pkts {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_pkts_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_gmxx_rxx_stats_pkts_s cn30xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn31xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn38xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_pkts_s cn50xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn52xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_s cn56xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_s cn58xx;
- struct cvmx_gmxx_rxx_stats_pkts_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_pkts_bad {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn30xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn31xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn50xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xx;
- struct cvmx_gmxx_rxx_stats_pkts_bad_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_pkts_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn30xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn31xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn50xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xx;
- struct cvmx_gmxx_rxx_stats_pkts_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_pkts_dmac {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn30xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn31xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn50xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xx;
- struct cvmx_gmxx_rxx_stats_pkts_dmac_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_stats_pkts_drp {
- uint64_t u64;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn30xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn31xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn38xxp2;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn50xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn52xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn56xxp1;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xx;
- struct cvmx_gmxx_rxx_stats_pkts_drp_s cn58xxp1;
-};
-
-union cvmx_gmxx_rxx_udd_skp {
- uint64_t u64;
- struct cvmx_gmxx_rxx_udd_skp_s {
- uint64_t reserved_9_63:55;
- uint64_t fcssel:1;
- uint64_t reserved_7_7:1;
- uint64_t len:7;
- } s;
- struct cvmx_gmxx_rxx_udd_skp_s cn30xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn31xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn38xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn38xxp2;
- struct cvmx_gmxx_rxx_udd_skp_s cn50xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn52xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn52xxp1;
- struct cvmx_gmxx_rxx_udd_skp_s cn56xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn56xxp1;
- struct cvmx_gmxx_rxx_udd_skp_s cn58xx;
- struct cvmx_gmxx_rxx_udd_skp_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_bp_dropx {
- uint64_t u64;
- struct cvmx_gmxx_rx_bp_dropx_s {
- uint64_t reserved_6_63:58;
- uint64_t mark:6;
- } s;
- struct cvmx_gmxx_rx_bp_dropx_s cn30xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn31xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn38xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn38xxp2;
- struct cvmx_gmxx_rx_bp_dropx_s cn50xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn52xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn52xxp1;
- struct cvmx_gmxx_rx_bp_dropx_s cn56xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn56xxp1;
- struct cvmx_gmxx_rx_bp_dropx_s cn58xx;
- struct cvmx_gmxx_rx_bp_dropx_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_bp_offx {
- uint64_t u64;
- struct cvmx_gmxx_rx_bp_offx_s {
- uint64_t reserved_6_63:58;
- uint64_t mark:6;
- } s;
- struct cvmx_gmxx_rx_bp_offx_s cn30xx;
- struct cvmx_gmxx_rx_bp_offx_s cn31xx;
- struct cvmx_gmxx_rx_bp_offx_s cn38xx;
- struct cvmx_gmxx_rx_bp_offx_s cn38xxp2;
- struct cvmx_gmxx_rx_bp_offx_s cn50xx;
- struct cvmx_gmxx_rx_bp_offx_s cn52xx;
- struct cvmx_gmxx_rx_bp_offx_s cn52xxp1;
- struct cvmx_gmxx_rx_bp_offx_s cn56xx;
- struct cvmx_gmxx_rx_bp_offx_s cn56xxp1;
- struct cvmx_gmxx_rx_bp_offx_s cn58xx;
- struct cvmx_gmxx_rx_bp_offx_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_bp_onx {
- uint64_t u64;
- struct cvmx_gmxx_rx_bp_onx_s {
- uint64_t reserved_9_63:55;
- uint64_t mark:9;
- } s;
- struct cvmx_gmxx_rx_bp_onx_s cn30xx;
- struct cvmx_gmxx_rx_bp_onx_s cn31xx;
- struct cvmx_gmxx_rx_bp_onx_s cn38xx;
- struct cvmx_gmxx_rx_bp_onx_s cn38xxp2;
- struct cvmx_gmxx_rx_bp_onx_s cn50xx;
- struct cvmx_gmxx_rx_bp_onx_s cn52xx;
- struct cvmx_gmxx_rx_bp_onx_s cn52xxp1;
- struct cvmx_gmxx_rx_bp_onx_s cn56xx;
- struct cvmx_gmxx_rx_bp_onx_s cn56xxp1;
- struct cvmx_gmxx_rx_bp_onx_s cn58xx;
- struct cvmx_gmxx_rx_bp_onx_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_hg2_status {
- uint64_t u64;
- struct cvmx_gmxx_rx_hg2_status_s {
- uint64_t reserved_48_63:16;
- uint64_t phtim2go:16;
- uint64_t xof:16;
- uint64_t lgtim2go:16;
- } s;
- struct cvmx_gmxx_rx_hg2_status_s cn52xx;
- struct cvmx_gmxx_rx_hg2_status_s cn52xxp1;
- struct cvmx_gmxx_rx_hg2_status_s cn56xx;
-};
-
-union cvmx_gmxx_rx_pass_en {
- uint64_t u64;
- struct cvmx_gmxx_rx_pass_en_s {
- uint64_t reserved_16_63:48;
- uint64_t en:16;
- } s;
- struct cvmx_gmxx_rx_pass_en_s cn38xx;
- struct cvmx_gmxx_rx_pass_en_s cn38xxp2;
- struct cvmx_gmxx_rx_pass_en_s cn58xx;
- struct cvmx_gmxx_rx_pass_en_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_pass_mapx {
- uint64_t u64;
- struct cvmx_gmxx_rx_pass_mapx_s {
- uint64_t reserved_4_63:60;
- uint64_t dprt:4;
- } s;
- struct cvmx_gmxx_rx_pass_mapx_s cn38xx;
- struct cvmx_gmxx_rx_pass_mapx_s cn38xxp2;
- struct cvmx_gmxx_rx_pass_mapx_s cn58xx;
- struct cvmx_gmxx_rx_pass_mapx_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_prt_info {
- uint64_t u64;
- struct cvmx_gmxx_rx_prt_info_s {
- uint64_t reserved_32_63:32;
- uint64_t drop:16;
- uint64_t commit:16;
- } s;
- struct cvmx_gmxx_rx_prt_info_cn30xx {
- uint64_t reserved_19_63:45;
- uint64_t drop:3;
- uint64_t reserved_3_15:13;
- uint64_t commit:3;
- } cn30xx;
- struct cvmx_gmxx_rx_prt_info_cn30xx cn31xx;
- struct cvmx_gmxx_rx_prt_info_s cn38xx;
- struct cvmx_gmxx_rx_prt_info_cn30xx cn50xx;
- struct cvmx_gmxx_rx_prt_info_cn52xx {
- uint64_t reserved_20_63:44;
- uint64_t drop:4;
- uint64_t reserved_4_15:12;
- uint64_t commit:4;
- } cn52xx;
- struct cvmx_gmxx_rx_prt_info_cn52xx cn52xxp1;
- struct cvmx_gmxx_rx_prt_info_cn52xx cn56xx;
- struct cvmx_gmxx_rx_prt_info_cn52xx cn56xxp1;
- struct cvmx_gmxx_rx_prt_info_s cn58xx;
- struct cvmx_gmxx_rx_prt_info_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_prts {
- uint64_t u64;
- struct cvmx_gmxx_rx_prts_s {
- uint64_t reserved_3_63:61;
- uint64_t prts:3;
- } s;
- struct cvmx_gmxx_rx_prts_s cn30xx;
- struct cvmx_gmxx_rx_prts_s cn31xx;
- struct cvmx_gmxx_rx_prts_s cn38xx;
- struct cvmx_gmxx_rx_prts_s cn38xxp2;
- struct cvmx_gmxx_rx_prts_s cn50xx;
- struct cvmx_gmxx_rx_prts_s cn52xx;
- struct cvmx_gmxx_rx_prts_s cn52xxp1;
- struct cvmx_gmxx_rx_prts_s cn56xx;
- struct cvmx_gmxx_rx_prts_s cn56xxp1;
- struct cvmx_gmxx_rx_prts_s cn58xx;
- struct cvmx_gmxx_rx_prts_s cn58xxp1;
-};
-
-union cvmx_gmxx_rx_tx_status {
- uint64_t u64;
- struct cvmx_gmxx_rx_tx_status_s {
- uint64_t reserved_7_63:57;
- uint64_t tx:3;
- uint64_t reserved_3_3:1;
- uint64_t rx:3;
- } s;
- struct cvmx_gmxx_rx_tx_status_s cn30xx;
- struct cvmx_gmxx_rx_tx_status_s cn31xx;
- struct cvmx_gmxx_rx_tx_status_s cn50xx;
-};
-
-union cvmx_gmxx_rx_xaui_bad_col {
- uint64_t u64;
- struct cvmx_gmxx_rx_xaui_bad_col_s {
- uint64_t reserved_40_63:24;
- uint64_t val:1;
- uint64_t state:3;
- uint64_t lane_rxc:4;
- uint64_t lane_rxd:32;
- } s;
- struct cvmx_gmxx_rx_xaui_bad_col_s cn52xx;
- struct cvmx_gmxx_rx_xaui_bad_col_s cn52xxp1;
- struct cvmx_gmxx_rx_xaui_bad_col_s cn56xx;
- struct cvmx_gmxx_rx_xaui_bad_col_s cn56xxp1;
-};
-
-union cvmx_gmxx_rx_xaui_ctl {
- uint64_t u64;
- struct cvmx_gmxx_rx_xaui_ctl_s {
- uint64_t reserved_2_63:62;
- uint64_t status:2;
- } s;
- struct cvmx_gmxx_rx_xaui_ctl_s cn52xx;
- struct cvmx_gmxx_rx_xaui_ctl_s cn52xxp1;
- struct cvmx_gmxx_rx_xaui_ctl_s cn56xx;
- struct cvmx_gmxx_rx_xaui_ctl_s cn56xxp1;
-};
-
-union cvmx_gmxx_smacx {
- uint64_t u64;
- struct cvmx_gmxx_smacx_s {
- uint64_t reserved_48_63:16;
- uint64_t smac:48;
- } s;
- struct cvmx_gmxx_smacx_s cn30xx;
- struct cvmx_gmxx_smacx_s cn31xx;
- struct cvmx_gmxx_smacx_s cn38xx;
- struct cvmx_gmxx_smacx_s cn38xxp2;
- struct cvmx_gmxx_smacx_s cn50xx;
- struct cvmx_gmxx_smacx_s cn52xx;
- struct cvmx_gmxx_smacx_s cn52xxp1;
- struct cvmx_gmxx_smacx_s cn56xx;
- struct cvmx_gmxx_smacx_s cn56xxp1;
- struct cvmx_gmxx_smacx_s cn58xx;
- struct cvmx_gmxx_smacx_s cn58xxp1;
-};
-
-union cvmx_gmxx_stat_bp {
- uint64_t u64;
- struct cvmx_gmxx_stat_bp_s {
- uint64_t reserved_17_63:47;
- uint64_t bp:1;
- uint64_t cnt:16;
- } s;
- struct cvmx_gmxx_stat_bp_s cn30xx;
- struct cvmx_gmxx_stat_bp_s cn31xx;
- struct cvmx_gmxx_stat_bp_s cn38xx;
- struct cvmx_gmxx_stat_bp_s cn38xxp2;
- struct cvmx_gmxx_stat_bp_s cn50xx;
- struct cvmx_gmxx_stat_bp_s cn52xx;
- struct cvmx_gmxx_stat_bp_s cn52xxp1;
- struct cvmx_gmxx_stat_bp_s cn56xx;
- struct cvmx_gmxx_stat_bp_s cn56xxp1;
- struct cvmx_gmxx_stat_bp_s cn58xx;
- struct cvmx_gmxx_stat_bp_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_append {
- uint64_t u64;
- struct cvmx_gmxx_txx_append_s {
- uint64_t reserved_4_63:60;
- uint64_t force_fcs:1;
- uint64_t fcs:1;
- uint64_t pad:1;
- uint64_t preamble:1;
- } s;
- struct cvmx_gmxx_txx_append_s cn30xx;
- struct cvmx_gmxx_txx_append_s cn31xx;
- struct cvmx_gmxx_txx_append_s cn38xx;
- struct cvmx_gmxx_txx_append_s cn38xxp2;
- struct cvmx_gmxx_txx_append_s cn50xx;
- struct cvmx_gmxx_txx_append_s cn52xx;
- struct cvmx_gmxx_txx_append_s cn52xxp1;
- struct cvmx_gmxx_txx_append_s cn56xx;
- struct cvmx_gmxx_txx_append_s cn56xxp1;
- struct cvmx_gmxx_txx_append_s cn58xx;
- struct cvmx_gmxx_txx_append_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_burst {
- uint64_t u64;
- struct cvmx_gmxx_txx_burst_s {
- uint64_t reserved_16_63:48;
- uint64_t burst:16;
- } s;
- struct cvmx_gmxx_txx_burst_s cn30xx;
- struct cvmx_gmxx_txx_burst_s cn31xx;
- struct cvmx_gmxx_txx_burst_s cn38xx;
- struct cvmx_gmxx_txx_burst_s cn38xxp2;
- struct cvmx_gmxx_txx_burst_s cn50xx;
- struct cvmx_gmxx_txx_burst_s cn52xx;
- struct cvmx_gmxx_txx_burst_s cn52xxp1;
- struct cvmx_gmxx_txx_burst_s cn56xx;
- struct cvmx_gmxx_txx_burst_s cn56xxp1;
- struct cvmx_gmxx_txx_burst_s cn58xx;
- struct cvmx_gmxx_txx_burst_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_cbfc_xoff {
- uint64_t u64;
- struct cvmx_gmxx_txx_cbfc_xoff_s {
- uint64_t reserved_16_63:48;
- uint64_t xoff:16;
- } s;
- struct cvmx_gmxx_txx_cbfc_xoff_s cn52xx;
- struct cvmx_gmxx_txx_cbfc_xoff_s cn56xx;
-};
-
-union cvmx_gmxx_txx_cbfc_xon {
- uint64_t u64;
- struct cvmx_gmxx_txx_cbfc_xon_s {
- uint64_t reserved_16_63:48;
- uint64_t xon:16;
- } s;
- struct cvmx_gmxx_txx_cbfc_xon_s cn52xx;
- struct cvmx_gmxx_txx_cbfc_xon_s cn56xx;
-};
-
-union cvmx_gmxx_txx_clk {
- uint64_t u64;
- struct cvmx_gmxx_txx_clk_s {
- uint64_t reserved_6_63:58;
- uint64_t clk_cnt:6;
- } s;
- struct cvmx_gmxx_txx_clk_s cn30xx;
- struct cvmx_gmxx_txx_clk_s cn31xx;
- struct cvmx_gmxx_txx_clk_s cn38xx;
- struct cvmx_gmxx_txx_clk_s cn38xxp2;
- struct cvmx_gmxx_txx_clk_s cn50xx;
- struct cvmx_gmxx_txx_clk_s cn58xx;
- struct cvmx_gmxx_txx_clk_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_ctl {
- uint64_t u64;
- struct cvmx_gmxx_txx_ctl_s {
- uint64_t reserved_2_63:62;
- uint64_t xsdef_en:1;
- uint64_t xscol_en:1;
- } s;
- struct cvmx_gmxx_txx_ctl_s cn30xx;
- struct cvmx_gmxx_txx_ctl_s cn31xx;
- struct cvmx_gmxx_txx_ctl_s cn38xx;
- struct cvmx_gmxx_txx_ctl_s cn38xxp2;
- struct cvmx_gmxx_txx_ctl_s cn50xx;
- struct cvmx_gmxx_txx_ctl_s cn52xx;
- struct cvmx_gmxx_txx_ctl_s cn52xxp1;
- struct cvmx_gmxx_txx_ctl_s cn56xx;
- struct cvmx_gmxx_txx_ctl_s cn56xxp1;
- struct cvmx_gmxx_txx_ctl_s cn58xx;
- struct cvmx_gmxx_txx_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_min_pkt {
- uint64_t u64;
- struct cvmx_gmxx_txx_min_pkt_s {
- uint64_t reserved_8_63:56;
- uint64_t min_size:8;
- } s;
- struct cvmx_gmxx_txx_min_pkt_s cn30xx;
- struct cvmx_gmxx_txx_min_pkt_s cn31xx;
- struct cvmx_gmxx_txx_min_pkt_s cn38xx;
- struct cvmx_gmxx_txx_min_pkt_s cn38xxp2;
- struct cvmx_gmxx_txx_min_pkt_s cn50xx;
- struct cvmx_gmxx_txx_min_pkt_s cn52xx;
- struct cvmx_gmxx_txx_min_pkt_s cn52xxp1;
- struct cvmx_gmxx_txx_min_pkt_s cn56xx;
- struct cvmx_gmxx_txx_min_pkt_s cn56xxp1;
- struct cvmx_gmxx_txx_min_pkt_s cn58xx;
- struct cvmx_gmxx_txx_min_pkt_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_pause_pkt_interval {
- uint64_t u64;
- struct cvmx_gmxx_txx_pause_pkt_interval_s {
- uint64_t reserved_16_63:48;
- uint64_t interval:16;
- } s;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn30xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn31xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn38xxp2;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn50xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn52xxp1;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn56xxp1;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xx;
- struct cvmx_gmxx_txx_pause_pkt_interval_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_pause_pkt_time {
- uint64_t u64;
- struct cvmx_gmxx_txx_pause_pkt_time_s {
- uint64_t reserved_16_63:48;
- uint64_t time:16;
- } s;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn30xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn31xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn38xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn38xxp2;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn50xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn52xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn52xxp1;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn56xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn56xxp1;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn58xx;
- struct cvmx_gmxx_txx_pause_pkt_time_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_pause_togo {
- uint64_t u64;
- struct cvmx_gmxx_txx_pause_togo_s {
- uint64_t reserved_32_63:32;
- uint64_t msg_time:16;
- uint64_t time:16;
- } s;
- struct cvmx_gmxx_txx_pause_togo_cn30xx {
- uint64_t reserved_16_63:48;
- uint64_t time:16;
- } cn30xx;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn31xx;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xx;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn38xxp2;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn50xx;
- struct cvmx_gmxx_txx_pause_togo_s cn52xx;
- struct cvmx_gmxx_txx_pause_togo_s cn52xxp1;
- struct cvmx_gmxx_txx_pause_togo_s cn56xx;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn56xxp1;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xx;
- struct cvmx_gmxx_txx_pause_togo_cn30xx cn58xxp1;
-};
-
-union cvmx_gmxx_txx_pause_zero {
- uint64_t u64;
- struct cvmx_gmxx_txx_pause_zero_s {
- uint64_t reserved_1_63:63;
- uint64_t send:1;
- } s;
- struct cvmx_gmxx_txx_pause_zero_s cn30xx;
- struct cvmx_gmxx_txx_pause_zero_s cn31xx;
- struct cvmx_gmxx_txx_pause_zero_s cn38xx;
- struct cvmx_gmxx_txx_pause_zero_s cn38xxp2;
- struct cvmx_gmxx_txx_pause_zero_s cn50xx;
- struct cvmx_gmxx_txx_pause_zero_s cn52xx;
- struct cvmx_gmxx_txx_pause_zero_s cn52xxp1;
- struct cvmx_gmxx_txx_pause_zero_s cn56xx;
- struct cvmx_gmxx_txx_pause_zero_s cn56xxp1;
- struct cvmx_gmxx_txx_pause_zero_s cn58xx;
- struct cvmx_gmxx_txx_pause_zero_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_sgmii_ctl {
- uint64_t u64;
- struct cvmx_gmxx_txx_sgmii_ctl_s {
- uint64_t reserved_1_63:63;
- uint64_t align:1;
- } s;
- struct cvmx_gmxx_txx_sgmii_ctl_s cn52xx;
- struct cvmx_gmxx_txx_sgmii_ctl_s cn52xxp1;
- struct cvmx_gmxx_txx_sgmii_ctl_s cn56xx;
- struct cvmx_gmxx_txx_sgmii_ctl_s cn56xxp1;
-};
-
-union cvmx_gmxx_txx_slot {
- uint64_t u64;
- struct cvmx_gmxx_txx_slot_s {
- uint64_t reserved_10_63:54;
- uint64_t slot:10;
- } s;
- struct cvmx_gmxx_txx_slot_s cn30xx;
- struct cvmx_gmxx_txx_slot_s cn31xx;
- struct cvmx_gmxx_txx_slot_s cn38xx;
- struct cvmx_gmxx_txx_slot_s cn38xxp2;
- struct cvmx_gmxx_txx_slot_s cn50xx;
- struct cvmx_gmxx_txx_slot_s cn52xx;
- struct cvmx_gmxx_txx_slot_s cn52xxp1;
- struct cvmx_gmxx_txx_slot_s cn56xx;
- struct cvmx_gmxx_txx_slot_s cn56xxp1;
- struct cvmx_gmxx_txx_slot_s cn58xx;
- struct cvmx_gmxx_txx_slot_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_soft_pause {
- uint64_t u64;
- struct cvmx_gmxx_txx_soft_pause_s {
- uint64_t reserved_16_63:48;
- uint64_t time:16;
- } s;
- struct cvmx_gmxx_txx_soft_pause_s cn30xx;
- struct cvmx_gmxx_txx_soft_pause_s cn31xx;
- struct cvmx_gmxx_txx_soft_pause_s cn38xx;
- struct cvmx_gmxx_txx_soft_pause_s cn38xxp2;
- struct cvmx_gmxx_txx_soft_pause_s cn50xx;
- struct cvmx_gmxx_txx_soft_pause_s cn52xx;
- struct cvmx_gmxx_txx_soft_pause_s cn52xxp1;
- struct cvmx_gmxx_txx_soft_pause_s cn56xx;
- struct cvmx_gmxx_txx_soft_pause_s cn56xxp1;
- struct cvmx_gmxx_txx_soft_pause_s cn58xx;
- struct cvmx_gmxx_txx_soft_pause_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat0 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat0_s {
- uint64_t xsdef:32;
- uint64_t xscol:32;
- } s;
- struct cvmx_gmxx_txx_stat0_s cn30xx;
- struct cvmx_gmxx_txx_stat0_s cn31xx;
- struct cvmx_gmxx_txx_stat0_s cn38xx;
- struct cvmx_gmxx_txx_stat0_s cn38xxp2;
- struct cvmx_gmxx_txx_stat0_s cn50xx;
- struct cvmx_gmxx_txx_stat0_s cn52xx;
- struct cvmx_gmxx_txx_stat0_s cn52xxp1;
- struct cvmx_gmxx_txx_stat0_s cn56xx;
- struct cvmx_gmxx_txx_stat0_s cn56xxp1;
- struct cvmx_gmxx_txx_stat0_s cn58xx;
- struct cvmx_gmxx_txx_stat0_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat1 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat1_s {
- uint64_t scol:32;
- uint64_t mcol:32;
- } s;
- struct cvmx_gmxx_txx_stat1_s cn30xx;
- struct cvmx_gmxx_txx_stat1_s cn31xx;
- struct cvmx_gmxx_txx_stat1_s cn38xx;
- struct cvmx_gmxx_txx_stat1_s cn38xxp2;
- struct cvmx_gmxx_txx_stat1_s cn50xx;
- struct cvmx_gmxx_txx_stat1_s cn52xx;
- struct cvmx_gmxx_txx_stat1_s cn52xxp1;
- struct cvmx_gmxx_txx_stat1_s cn56xx;
- struct cvmx_gmxx_txx_stat1_s cn56xxp1;
- struct cvmx_gmxx_txx_stat1_s cn58xx;
- struct cvmx_gmxx_txx_stat1_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat2 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat2_s {
- uint64_t reserved_48_63:16;
- uint64_t octs:48;
- } s;
- struct cvmx_gmxx_txx_stat2_s cn30xx;
- struct cvmx_gmxx_txx_stat2_s cn31xx;
- struct cvmx_gmxx_txx_stat2_s cn38xx;
- struct cvmx_gmxx_txx_stat2_s cn38xxp2;
- struct cvmx_gmxx_txx_stat2_s cn50xx;
- struct cvmx_gmxx_txx_stat2_s cn52xx;
- struct cvmx_gmxx_txx_stat2_s cn52xxp1;
- struct cvmx_gmxx_txx_stat2_s cn56xx;
- struct cvmx_gmxx_txx_stat2_s cn56xxp1;
- struct cvmx_gmxx_txx_stat2_s cn58xx;
- struct cvmx_gmxx_txx_stat2_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat3 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat3_s {
- uint64_t reserved_32_63:32;
- uint64_t pkts:32;
- } s;
- struct cvmx_gmxx_txx_stat3_s cn30xx;
- struct cvmx_gmxx_txx_stat3_s cn31xx;
- struct cvmx_gmxx_txx_stat3_s cn38xx;
- struct cvmx_gmxx_txx_stat3_s cn38xxp2;
- struct cvmx_gmxx_txx_stat3_s cn50xx;
- struct cvmx_gmxx_txx_stat3_s cn52xx;
- struct cvmx_gmxx_txx_stat3_s cn52xxp1;
- struct cvmx_gmxx_txx_stat3_s cn56xx;
- struct cvmx_gmxx_txx_stat3_s cn56xxp1;
- struct cvmx_gmxx_txx_stat3_s cn58xx;
- struct cvmx_gmxx_txx_stat3_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat4 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat4_s {
- uint64_t hist1:32;
- uint64_t hist0:32;
- } s;
- struct cvmx_gmxx_txx_stat4_s cn30xx;
- struct cvmx_gmxx_txx_stat4_s cn31xx;
- struct cvmx_gmxx_txx_stat4_s cn38xx;
- struct cvmx_gmxx_txx_stat4_s cn38xxp2;
- struct cvmx_gmxx_txx_stat4_s cn50xx;
- struct cvmx_gmxx_txx_stat4_s cn52xx;
- struct cvmx_gmxx_txx_stat4_s cn52xxp1;
- struct cvmx_gmxx_txx_stat4_s cn56xx;
- struct cvmx_gmxx_txx_stat4_s cn56xxp1;
- struct cvmx_gmxx_txx_stat4_s cn58xx;
- struct cvmx_gmxx_txx_stat4_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat5 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat5_s {
- uint64_t hist3:32;
- uint64_t hist2:32;
- } s;
- struct cvmx_gmxx_txx_stat5_s cn30xx;
- struct cvmx_gmxx_txx_stat5_s cn31xx;
- struct cvmx_gmxx_txx_stat5_s cn38xx;
- struct cvmx_gmxx_txx_stat5_s cn38xxp2;
- struct cvmx_gmxx_txx_stat5_s cn50xx;
- struct cvmx_gmxx_txx_stat5_s cn52xx;
- struct cvmx_gmxx_txx_stat5_s cn52xxp1;
- struct cvmx_gmxx_txx_stat5_s cn56xx;
- struct cvmx_gmxx_txx_stat5_s cn56xxp1;
- struct cvmx_gmxx_txx_stat5_s cn58xx;
- struct cvmx_gmxx_txx_stat5_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat6 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat6_s {
- uint64_t hist5:32;
- uint64_t hist4:32;
- } s;
- struct cvmx_gmxx_txx_stat6_s cn30xx;
- struct cvmx_gmxx_txx_stat6_s cn31xx;
- struct cvmx_gmxx_txx_stat6_s cn38xx;
- struct cvmx_gmxx_txx_stat6_s cn38xxp2;
- struct cvmx_gmxx_txx_stat6_s cn50xx;
- struct cvmx_gmxx_txx_stat6_s cn52xx;
- struct cvmx_gmxx_txx_stat6_s cn52xxp1;
- struct cvmx_gmxx_txx_stat6_s cn56xx;
- struct cvmx_gmxx_txx_stat6_s cn56xxp1;
- struct cvmx_gmxx_txx_stat6_s cn58xx;
- struct cvmx_gmxx_txx_stat6_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat7 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat7_s {
- uint64_t hist7:32;
- uint64_t hist6:32;
- } s;
- struct cvmx_gmxx_txx_stat7_s cn30xx;
- struct cvmx_gmxx_txx_stat7_s cn31xx;
- struct cvmx_gmxx_txx_stat7_s cn38xx;
- struct cvmx_gmxx_txx_stat7_s cn38xxp2;
- struct cvmx_gmxx_txx_stat7_s cn50xx;
- struct cvmx_gmxx_txx_stat7_s cn52xx;
- struct cvmx_gmxx_txx_stat7_s cn52xxp1;
- struct cvmx_gmxx_txx_stat7_s cn56xx;
- struct cvmx_gmxx_txx_stat7_s cn56xxp1;
- struct cvmx_gmxx_txx_stat7_s cn58xx;
- struct cvmx_gmxx_txx_stat7_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat8 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat8_s {
- uint64_t mcst:32;
- uint64_t bcst:32;
- } s;
- struct cvmx_gmxx_txx_stat8_s cn30xx;
- struct cvmx_gmxx_txx_stat8_s cn31xx;
- struct cvmx_gmxx_txx_stat8_s cn38xx;
- struct cvmx_gmxx_txx_stat8_s cn38xxp2;
- struct cvmx_gmxx_txx_stat8_s cn50xx;
- struct cvmx_gmxx_txx_stat8_s cn52xx;
- struct cvmx_gmxx_txx_stat8_s cn52xxp1;
- struct cvmx_gmxx_txx_stat8_s cn56xx;
- struct cvmx_gmxx_txx_stat8_s cn56xxp1;
- struct cvmx_gmxx_txx_stat8_s cn58xx;
- struct cvmx_gmxx_txx_stat8_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stat9 {
- uint64_t u64;
- struct cvmx_gmxx_txx_stat9_s {
- uint64_t undflw:32;
- uint64_t ctl:32;
- } s;
- struct cvmx_gmxx_txx_stat9_s cn30xx;
- struct cvmx_gmxx_txx_stat9_s cn31xx;
- struct cvmx_gmxx_txx_stat9_s cn38xx;
- struct cvmx_gmxx_txx_stat9_s cn38xxp2;
- struct cvmx_gmxx_txx_stat9_s cn50xx;
- struct cvmx_gmxx_txx_stat9_s cn52xx;
- struct cvmx_gmxx_txx_stat9_s cn52xxp1;
- struct cvmx_gmxx_txx_stat9_s cn56xx;
- struct cvmx_gmxx_txx_stat9_s cn56xxp1;
- struct cvmx_gmxx_txx_stat9_s cn58xx;
- struct cvmx_gmxx_txx_stat9_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_stats_ctl {
- uint64_t u64;
- struct cvmx_gmxx_txx_stats_ctl_s {
- uint64_t reserved_1_63:63;
- uint64_t rd_clr:1;
- } s;
- struct cvmx_gmxx_txx_stats_ctl_s cn30xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn31xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn38xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn38xxp2;
- struct cvmx_gmxx_txx_stats_ctl_s cn50xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn52xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn52xxp1;
- struct cvmx_gmxx_txx_stats_ctl_s cn56xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn56xxp1;
- struct cvmx_gmxx_txx_stats_ctl_s cn58xx;
- struct cvmx_gmxx_txx_stats_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_txx_thresh {
- uint64_t u64;
- struct cvmx_gmxx_txx_thresh_s {
- uint64_t reserved_9_63:55;
- uint64_t cnt:9;
- } s;
- struct cvmx_gmxx_txx_thresh_cn30xx {
- uint64_t reserved_7_63:57;
- uint64_t cnt:7;
- } cn30xx;
- struct cvmx_gmxx_txx_thresh_cn30xx cn31xx;
- struct cvmx_gmxx_txx_thresh_s cn38xx;
- struct cvmx_gmxx_txx_thresh_s cn38xxp2;
- struct cvmx_gmxx_txx_thresh_cn30xx cn50xx;
- struct cvmx_gmxx_txx_thresh_s cn52xx;
- struct cvmx_gmxx_txx_thresh_s cn52xxp1;
- struct cvmx_gmxx_txx_thresh_s cn56xx;
- struct cvmx_gmxx_txx_thresh_s cn56xxp1;
- struct cvmx_gmxx_txx_thresh_s cn58xx;
- struct cvmx_gmxx_txx_thresh_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_bp {
- uint64_t u64;
- struct cvmx_gmxx_tx_bp_s {
- uint64_t reserved_4_63:60;
- uint64_t bp:4;
- } s;
- struct cvmx_gmxx_tx_bp_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t bp:3;
- } cn30xx;
- struct cvmx_gmxx_tx_bp_cn30xx cn31xx;
- struct cvmx_gmxx_tx_bp_s cn38xx;
- struct cvmx_gmxx_tx_bp_s cn38xxp2;
- struct cvmx_gmxx_tx_bp_cn30xx cn50xx;
- struct cvmx_gmxx_tx_bp_s cn52xx;
- struct cvmx_gmxx_tx_bp_s cn52xxp1;
- struct cvmx_gmxx_tx_bp_s cn56xx;
- struct cvmx_gmxx_tx_bp_s cn56xxp1;
- struct cvmx_gmxx_tx_bp_s cn58xx;
- struct cvmx_gmxx_tx_bp_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_clk_mskx {
- uint64_t u64;
- struct cvmx_gmxx_tx_clk_mskx_s {
- uint64_t reserved_1_63:63;
- uint64_t msk:1;
- } s;
- struct cvmx_gmxx_tx_clk_mskx_s cn30xx;
- struct cvmx_gmxx_tx_clk_mskx_s cn50xx;
-};
-
-union cvmx_gmxx_tx_col_attempt {
- uint64_t u64;
- struct cvmx_gmxx_tx_col_attempt_s {
- uint64_t reserved_5_63:59;
- uint64_t limit:5;
- } s;
- struct cvmx_gmxx_tx_col_attempt_s cn30xx;
- struct cvmx_gmxx_tx_col_attempt_s cn31xx;
- struct cvmx_gmxx_tx_col_attempt_s cn38xx;
- struct cvmx_gmxx_tx_col_attempt_s cn38xxp2;
- struct cvmx_gmxx_tx_col_attempt_s cn50xx;
- struct cvmx_gmxx_tx_col_attempt_s cn52xx;
- struct cvmx_gmxx_tx_col_attempt_s cn52xxp1;
- struct cvmx_gmxx_tx_col_attempt_s cn56xx;
- struct cvmx_gmxx_tx_col_attempt_s cn56xxp1;
- struct cvmx_gmxx_tx_col_attempt_s cn58xx;
- struct cvmx_gmxx_tx_col_attempt_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_corrupt {
- uint64_t u64;
- struct cvmx_gmxx_tx_corrupt_s {
- uint64_t reserved_4_63:60;
- uint64_t corrupt:4;
- } s;
- struct cvmx_gmxx_tx_corrupt_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t corrupt:3;
- } cn30xx;
- struct cvmx_gmxx_tx_corrupt_cn30xx cn31xx;
- struct cvmx_gmxx_tx_corrupt_s cn38xx;
- struct cvmx_gmxx_tx_corrupt_s cn38xxp2;
- struct cvmx_gmxx_tx_corrupt_cn30xx cn50xx;
- struct cvmx_gmxx_tx_corrupt_s cn52xx;
- struct cvmx_gmxx_tx_corrupt_s cn52xxp1;
- struct cvmx_gmxx_tx_corrupt_s cn56xx;
- struct cvmx_gmxx_tx_corrupt_s cn56xxp1;
- struct cvmx_gmxx_tx_corrupt_s cn58xx;
- struct cvmx_gmxx_tx_corrupt_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_hg2_reg1 {
- uint64_t u64;
- struct cvmx_gmxx_tx_hg2_reg1_s {
- uint64_t reserved_16_63:48;
- uint64_t tx_xof:16;
- } s;
- struct cvmx_gmxx_tx_hg2_reg1_s cn52xx;
- struct cvmx_gmxx_tx_hg2_reg1_s cn52xxp1;
- struct cvmx_gmxx_tx_hg2_reg1_s cn56xx;
-};
-
-union cvmx_gmxx_tx_hg2_reg2 {
- uint64_t u64;
- struct cvmx_gmxx_tx_hg2_reg2_s {
- uint64_t reserved_16_63:48;
- uint64_t tx_xon:16;
- } s;
- struct cvmx_gmxx_tx_hg2_reg2_s cn52xx;
- struct cvmx_gmxx_tx_hg2_reg2_s cn52xxp1;
- struct cvmx_gmxx_tx_hg2_reg2_s cn56xx;
-};
-
-union cvmx_gmxx_tx_ifg {
- uint64_t u64;
- struct cvmx_gmxx_tx_ifg_s {
- uint64_t reserved_8_63:56;
- uint64_t ifg2:4;
- uint64_t ifg1:4;
- } s;
- struct cvmx_gmxx_tx_ifg_s cn30xx;
- struct cvmx_gmxx_tx_ifg_s cn31xx;
- struct cvmx_gmxx_tx_ifg_s cn38xx;
- struct cvmx_gmxx_tx_ifg_s cn38xxp2;
- struct cvmx_gmxx_tx_ifg_s cn50xx;
- struct cvmx_gmxx_tx_ifg_s cn52xx;
- struct cvmx_gmxx_tx_ifg_s cn52xxp1;
- struct cvmx_gmxx_tx_ifg_s cn56xx;
- struct cvmx_gmxx_tx_ifg_s cn56xxp1;
- struct cvmx_gmxx_tx_ifg_s cn58xx;
- struct cvmx_gmxx_tx_ifg_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_int_en {
- uint64_t u64;
- struct cvmx_gmxx_tx_int_en_s {
- uint64_t reserved_20_63:44;
- uint64_t late_col:4;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t ncb_nxa:1;
- uint64_t pko_nxa:1;
- } s;
- struct cvmx_gmxx_tx_int_en_cn30xx {
- uint64_t reserved_19_63:45;
- uint64_t late_col:3;
- uint64_t reserved_15_15:1;
- uint64_t xsdef:3;
- uint64_t reserved_11_11:1;
- uint64_t xscol:3;
- uint64_t reserved_5_7:3;
- uint64_t undflw:3;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn30xx;
- struct cvmx_gmxx_tx_int_en_cn31xx {
- uint64_t reserved_15_63:49;
- uint64_t xsdef:3;
- uint64_t reserved_11_11:1;
- uint64_t xscol:3;
- uint64_t reserved_5_7:3;
- uint64_t undflw:3;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn31xx;
- struct cvmx_gmxx_tx_int_en_s cn38xx;
- struct cvmx_gmxx_tx_int_en_cn38xxp2 {
- uint64_t reserved_16_63:48;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t ncb_nxa:1;
- uint64_t pko_nxa:1;
- } cn38xxp2;
- struct cvmx_gmxx_tx_int_en_cn30xx cn50xx;
- struct cvmx_gmxx_tx_int_en_cn52xx {
- uint64_t reserved_20_63:44;
- uint64_t late_col:4;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn52xx;
- struct cvmx_gmxx_tx_int_en_cn52xx cn52xxp1;
- struct cvmx_gmxx_tx_int_en_cn52xx cn56xx;
- struct cvmx_gmxx_tx_int_en_cn52xx cn56xxp1;
- struct cvmx_gmxx_tx_int_en_s cn58xx;
- struct cvmx_gmxx_tx_int_en_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_int_reg {
- uint64_t u64;
- struct cvmx_gmxx_tx_int_reg_s {
- uint64_t reserved_20_63:44;
- uint64_t late_col:4;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t ncb_nxa:1;
- uint64_t pko_nxa:1;
- } s;
- struct cvmx_gmxx_tx_int_reg_cn30xx {
- uint64_t reserved_19_63:45;
- uint64_t late_col:3;
- uint64_t reserved_15_15:1;
- uint64_t xsdef:3;
- uint64_t reserved_11_11:1;
- uint64_t xscol:3;
- uint64_t reserved_5_7:3;
- uint64_t undflw:3;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn30xx;
- struct cvmx_gmxx_tx_int_reg_cn31xx {
- uint64_t reserved_15_63:49;
- uint64_t xsdef:3;
- uint64_t reserved_11_11:1;
- uint64_t xscol:3;
- uint64_t reserved_5_7:3;
- uint64_t undflw:3;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn31xx;
- struct cvmx_gmxx_tx_int_reg_s cn38xx;
- struct cvmx_gmxx_tx_int_reg_cn38xxp2 {
- uint64_t reserved_16_63:48;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t ncb_nxa:1;
- uint64_t pko_nxa:1;
- } cn38xxp2;
- struct cvmx_gmxx_tx_int_reg_cn30xx cn50xx;
- struct cvmx_gmxx_tx_int_reg_cn52xx {
- uint64_t reserved_20_63:44;
- uint64_t late_col:4;
- uint64_t xsdef:4;
- uint64_t xscol:4;
- uint64_t reserved_6_7:2;
- uint64_t undflw:4;
- uint64_t reserved_1_1:1;
- uint64_t pko_nxa:1;
- } cn52xx;
- struct cvmx_gmxx_tx_int_reg_cn52xx cn52xxp1;
- struct cvmx_gmxx_tx_int_reg_cn52xx cn56xx;
- struct cvmx_gmxx_tx_int_reg_cn52xx cn56xxp1;
- struct cvmx_gmxx_tx_int_reg_s cn58xx;
- struct cvmx_gmxx_tx_int_reg_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_jam {
- uint64_t u64;
- struct cvmx_gmxx_tx_jam_s {
- uint64_t reserved_8_63:56;
- uint64_t jam:8;
- } s;
- struct cvmx_gmxx_tx_jam_s cn30xx;
- struct cvmx_gmxx_tx_jam_s cn31xx;
- struct cvmx_gmxx_tx_jam_s cn38xx;
- struct cvmx_gmxx_tx_jam_s cn38xxp2;
- struct cvmx_gmxx_tx_jam_s cn50xx;
- struct cvmx_gmxx_tx_jam_s cn52xx;
- struct cvmx_gmxx_tx_jam_s cn52xxp1;
- struct cvmx_gmxx_tx_jam_s cn56xx;
- struct cvmx_gmxx_tx_jam_s cn56xxp1;
- struct cvmx_gmxx_tx_jam_s cn58xx;
- struct cvmx_gmxx_tx_jam_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_lfsr {
- uint64_t u64;
- struct cvmx_gmxx_tx_lfsr_s {
- uint64_t reserved_16_63:48;
- uint64_t lfsr:16;
- } s;
- struct cvmx_gmxx_tx_lfsr_s cn30xx;
- struct cvmx_gmxx_tx_lfsr_s cn31xx;
- struct cvmx_gmxx_tx_lfsr_s cn38xx;
- struct cvmx_gmxx_tx_lfsr_s cn38xxp2;
- struct cvmx_gmxx_tx_lfsr_s cn50xx;
- struct cvmx_gmxx_tx_lfsr_s cn52xx;
- struct cvmx_gmxx_tx_lfsr_s cn52xxp1;
- struct cvmx_gmxx_tx_lfsr_s cn56xx;
- struct cvmx_gmxx_tx_lfsr_s cn56xxp1;
- struct cvmx_gmxx_tx_lfsr_s cn58xx;
- struct cvmx_gmxx_tx_lfsr_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_ovr_bp {
- uint64_t u64;
- struct cvmx_gmxx_tx_ovr_bp_s {
- uint64_t reserved_48_63:16;
- uint64_t tx_prt_bp:16;
- uint64_t reserved_12_31:20;
- uint64_t en:4;
- uint64_t bp:4;
- uint64_t ign_full:4;
- } s;
- struct cvmx_gmxx_tx_ovr_bp_cn30xx {
- uint64_t reserved_11_63:53;
- uint64_t en:3;
- uint64_t reserved_7_7:1;
- uint64_t bp:3;
- uint64_t reserved_3_3:1;
- uint64_t ign_full:3;
- } cn30xx;
- struct cvmx_gmxx_tx_ovr_bp_cn30xx cn31xx;
- struct cvmx_gmxx_tx_ovr_bp_cn38xx {
- uint64_t reserved_12_63:52;
- uint64_t en:4;
- uint64_t bp:4;
- uint64_t ign_full:4;
- } cn38xx;
- struct cvmx_gmxx_tx_ovr_bp_cn38xx cn38xxp2;
- struct cvmx_gmxx_tx_ovr_bp_cn30xx cn50xx;
- struct cvmx_gmxx_tx_ovr_bp_s cn52xx;
- struct cvmx_gmxx_tx_ovr_bp_s cn52xxp1;
- struct cvmx_gmxx_tx_ovr_bp_s cn56xx;
- struct cvmx_gmxx_tx_ovr_bp_s cn56xxp1;
- struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xx;
- struct cvmx_gmxx_tx_ovr_bp_cn38xx cn58xxp1;
-};
-
-union cvmx_gmxx_tx_pause_pkt_dmac {
- uint64_t u64;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s {
- uint64_t reserved_48_63:16;
- uint64_t dmac:48;
- } s;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn30xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn31xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn38xxp2;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn50xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn52xxp1;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn56xxp1;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xx;
- struct cvmx_gmxx_tx_pause_pkt_dmac_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_pause_pkt_type {
- uint64_t u64;
- struct cvmx_gmxx_tx_pause_pkt_type_s {
- uint64_t reserved_16_63:48;
- uint64_t type:16;
- } s;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn30xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn31xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn38xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn38xxp2;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn50xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn52xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn52xxp1;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn56xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn56xxp1;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn58xx;
- struct cvmx_gmxx_tx_pause_pkt_type_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_prts {
- uint64_t u64;
- struct cvmx_gmxx_tx_prts_s {
- uint64_t reserved_5_63:59;
- uint64_t prts:5;
- } s;
- struct cvmx_gmxx_tx_prts_s cn30xx;
- struct cvmx_gmxx_tx_prts_s cn31xx;
- struct cvmx_gmxx_tx_prts_s cn38xx;
- struct cvmx_gmxx_tx_prts_s cn38xxp2;
- struct cvmx_gmxx_tx_prts_s cn50xx;
- struct cvmx_gmxx_tx_prts_s cn52xx;
- struct cvmx_gmxx_tx_prts_s cn52xxp1;
- struct cvmx_gmxx_tx_prts_s cn56xx;
- struct cvmx_gmxx_tx_prts_s cn56xxp1;
- struct cvmx_gmxx_tx_prts_s cn58xx;
- struct cvmx_gmxx_tx_prts_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_spi_ctl {
- uint64_t u64;
- struct cvmx_gmxx_tx_spi_ctl_s {
- uint64_t reserved_2_63:62;
- uint64_t tpa_clr:1;
- uint64_t cont_pkt:1;
- } s;
- struct cvmx_gmxx_tx_spi_ctl_s cn38xx;
- struct cvmx_gmxx_tx_spi_ctl_s cn38xxp2;
- struct cvmx_gmxx_tx_spi_ctl_s cn58xx;
- struct cvmx_gmxx_tx_spi_ctl_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_spi_drain {
- uint64_t u64;
- struct cvmx_gmxx_tx_spi_drain_s {
- uint64_t reserved_16_63:48;
- uint64_t drain:16;
- } s;
- struct cvmx_gmxx_tx_spi_drain_s cn38xx;
- struct cvmx_gmxx_tx_spi_drain_s cn58xx;
- struct cvmx_gmxx_tx_spi_drain_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_spi_max {
- uint64_t u64;
- struct cvmx_gmxx_tx_spi_max_s {
- uint64_t reserved_23_63:41;
- uint64_t slice:7;
- uint64_t max2:8;
- uint64_t max1:8;
- } s;
- struct cvmx_gmxx_tx_spi_max_cn38xx {
- uint64_t reserved_16_63:48;
- uint64_t max2:8;
- uint64_t max1:8;
- } cn38xx;
- struct cvmx_gmxx_tx_spi_max_cn38xx cn38xxp2;
- struct cvmx_gmxx_tx_spi_max_s cn58xx;
- struct cvmx_gmxx_tx_spi_max_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_spi_roundx {
- uint64_t u64;
- struct cvmx_gmxx_tx_spi_roundx_s {
- uint64_t reserved_16_63:48;
- uint64_t round:16;
- } s;
- struct cvmx_gmxx_tx_spi_roundx_s cn58xx;
- struct cvmx_gmxx_tx_spi_roundx_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_spi_thresh {
- uint64_t u64;
- struct cvmx_gmxx_tx_spi_thresh_s {
- uint64_t reserved_6_63:58;
- uint64_t thresh:6;
- } s;
- struct cvmx_gmxx_tx_spi_thresh_s cn38xx;
- struct cvmx_gmxx_tx_spi_thresh_s cn38xxp2;
- struct cvmx_gmxx_tx_spi_thresh_s cn58xx;
- struct cvmx_gmxx_tx_spi_thresh_s cn58xxp1;
-};
-
-union cvmx_gmxx_tx_xaui_ctl {
- uint64_t u64;
- struct cvmx_gmxx_tx_xaui_ctl_s {
- uint64_t reserved_11_63:53;
- uint64_t hg_pause_hgi:2;
- uint64_t hg_en:1;
- uint64_t reserved_7_7:1;
- uint64_t ls_byp:1;
- uint64_t ls:2;
- uint64_t reserved_2_3:2;
- uint64_t uni_en:1;
- uint64_t dic_en:1;
- } s;
- struct cvmx_gmxx_tx_xaui_ctl_s cn52xx;
- struct cvmx_gmxx_tx_xaui_ctl_s cn52xxp1;
- struct cvmx_gmxx_tx_xaui_ctl_s cn56xx;
- struct cvmx_gmxx_tx_xaui_ctl_s cn56xxp1;
-};
-
-union cvmx_gmxx_xaui_ext_loopback {
- uint64_t u64;
- struct cvmx_gmxx_xaui_ext_loopback_s {
- uint64_t reserved_5_63:59;
- uint64_t en:1;
- uint64_t thresh:4;
- } s;
- struct cvmx_gmxx_xaui_ext_loopback_s cn52xx;
- struct cvmx_gmxx_xaui_ext_loopback_s cn52xxp1;
- struct cvmx_gmxx_xaui_ext_loopback_s cn56xx;
- struct cvmx_gmxx_xaui_ext_loopback_s cn56xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-board.c b/drivers/staging/octeon/cvmx-helper-board.c
deleted file mode 100644
index 57d35dc..0000000
--- a/drivers/staging/octeon/cvmx-helper-board.c
+++ /dev/null
@@ -1,695 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Helper functions to abstract board specific data about
- * network ports from the rest of the cvmx-helper files.
- */
-
-#include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-bootinfo.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-mdio.h"
-
-#include "cvmx-helper.h"
-#include "cvmx-helper-util.h"
-#include "cvmx-helper-board.h"
-
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-asxx-defs.h"
-
-/**
- * cvmx_override_board_link_get(int ipd_port) is a function
- * pointer. It is meant to allow customization of the process of
- * talking to a PHY to determine link speed. It is called every
- * time a PHY must be polled for link status. Users should set
- * this pointer to a function before calling any cvmx-helper
- * operations.
- */
-cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port) =
- NULL;
-
-/**
- * Return the MII PHY address associated with the given IPD
- * port. A result of -1 means there isn't a MII capable PHY
- * connected to this port. On chips supporting multiple MII
- * busses the bus number is encoded in bits <15:8>.
- *
- * This function must be modified for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It replies on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @ipd_port: Octeon IPD port to get the MII address for.
- *
- * Returns MII PHY address and bus number or -1.
- */
-int cvmx_helper_board_get_mii_address(int ipd_port)
-{
- switch (cvmx_sysinfo_get()->board_type) {
- case CVMX_BOARD_TYPE_SIM:
- /* Simulator doesn't have MII */
- return -1;
- case CVMX_BOARD_TYPE_EBT3000:
- case CVMX_BOARD_TYPE_EBT5800:
- case CVMX_BOARD_TYPE_THUNDER:
- case CVMX_BOARD_TYPE_NICPRO2:
- /* Interface 0 is SPI4, interface 1 is RGMII */
- if ((ipd_port >= 16) && (ipd_port < 20))
- return ipd_port - 16;
- else
- return -1;
- case CVMX_BOARD_TYPE_KODAMA:
- case CVMX_BOARD_TYPE_EBH3100:
- case CVMX_BOARD_TYPE_HIKARI:
- case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
- case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
- case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
- /*
- * Port 0 is WAN connected to a PHY, Port 1 is GMII
- * connected to a switch
- */
- if (ipd_port == 0)
- return 4;
- else if (ipd_port == 1)
- return 9;
- else
- return -1;
- case CVMX_BOARD_TYPE_NAC38:
- /* Board has 8 RGMII ports PHYs are 0-7 */
- if ((ipd_port >= 0) && (ipd_port < 4))
- return ipd_port;
- else if ((ipd_port >= 16) && (ipd_port < 20))
- return ipd_port - 16 + 4;
- else
- return -1;
- case CVMX_BOARD_TYPE_EBH3000:
- /* Board has dual SPI4 and no PHYs */
- return -1;
- case CVMX_BOARD_TYPE_EBH5200:
- case CVMX_BOARD_TYPE_EBH5201:
- case CVMX_BOARD_TYPE_EBT5200:
- /*
- * Board has 4 SGMII ports. The PHYs start right after the MII
- * ports MII0 = 0, MII1 = 1, SGMII = 2-5.
- */
- if ((ipd_port >= 0) && (ipd_port < 4))
- return ipd_port + 2;
- else
- return -1;
- case CVMX_BOARD_TYPE_EBH5600:
- case CVMX_BOARD_TYPE_EBH5601:
- case CVMX_BOARD_TYPE_EBH5610:
- /*
- * Board has 8 SGMII ports. 4 connect out, two connect
- * to a switch, and 2 loop to each other
- */
- if ((ipd_port >= 0) && (ipd_port < 4))
- return ipd_port + 1;
- else
- return -1;
- case CVMX_BOARD_TYPE_CUST_NB5:
- if (ipd_port == 2)
- return 4;
- else
- return -1;
- case CVMX_BOARD_TYPE_NIC_XLE_4G:
- /* Board has 4 SGMII ports. connected QLM3(interface 1) */
- if ((ipd_port >= 16) && (ipd_port < 20))
- return ipd_port - 16 + 1;
- else
- return -1;
- case CVMX_BOARD_TYPE_BBGW_REF:
- /*
- * No PHYs are connected to Octeon, everything is
- * through switch.
- */
- return -1;
-
- case CVMX_BOARD_TYPE_CUST_WSX16:
- if (ipd_port >= 0 && ipd_port <= 3)
- return ipd_port;
- else if (ipd_port >= 16 && ipd_port <= 19)
- return ipd_port - 16 + 4;
- else
- return -1;
- }
-
- /* Some unknown board. Somebody forgot to update this function... */
- cvmx_dprintf
- ("cvmx_helper_board_get_mii_address: Unknown board type %d\n",
- cvmx_sysinfo_get()->board_type);
- return -1;
-}
-
-/**
- * This function is the board specific method of determining an
- * ethernet ports link speed. Most Octeon boards have Marvell PHYs
- * and are handled by the fall through case. This function must be
- * updated for boards that don't have the normal Marvell PHYs.
- *
- * This function must be modified for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It relies on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @ipd_port: IPD input port associated with the port we want to get link
- * status for.
- *
- * Returns The ports link status. If the link isn't fully resolved, this must
- * return zero.
- */
-cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
-{
- cvmx_helper_link_info_t result;
- int phy_addr;
- int is_broadcom_phy = 0;
-
- /* Give the user a chance to override the processing of this function */
- if (cvmx_override_board_link_get)
- return cvmx_override_board_link_get(ipd_port);
-
- /* Unless we fix it later, all links are defaulted to down */
- result.u64 = 0;
-
- /*
- * This switch statement should handle all ports that either don't use
- * Marvell PHYS, or don't support in-band status.
- */
- switch (cvmx_sysinfo_get()->board_type) {
- case CVMX_BOARD_TYPE_SIM:
- /* The simulator gives you a simulated 1Gbps full duplex link */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- case CVMX_BOARD_TYPE_EBH3100:
- case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
- case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
- case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
- /* Port 1 on these boards is always Gigabit */
- if (ipd_port == 1) {
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- }
- /* Fall through to the generic code below */
- break;
- case CVMX_BOARD_TYPE_CUST_NB5:
- /* Port 1 on these boards is always Gigabit */
- if (ipd_port == 1) {
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- } else /* The other port uses a broadcom PHY */
- is_broadcom_phy = 1;
- break;
- case CVMX_BOARD_TYPE_BBGW_REF:
- /* Port 1 on these boards is always Gigabit */
- if (ipd_port == 2) {
- /* Port 2 is not hooked up */
- result.u64 = 0;
- return result;
- } else {
- /* Ports 0 and 1 connect to the switch */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- }
- break;
- }
-
- phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
- if (phy_addr != -1) {
- if (is_broadcom_phy) {
- /*
- * Below we are going to read SMI/MDIO
- * register 0x19 which works on Broadcom
- * parts
- */
- int phy_status =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- 0x19);
- switch ((phy_status >> 8) & 0x7) {
- case 0:
- result.u64 = 0;
- break;
- case 1:
- result.s.link_up = 1;
- result.s.full_duplex = 0;
- result.s.speed = 10;
- break;
- case 2:
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 10;
- break;
- case 3:
- result.s.link_up = 1;
- result.s.full_duplex = 0;
- result.s.speed = 100;
- break;
- case 4:
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 100;
- break;
- case 5:
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 100;
- break;
- case 6:
- result.s.link_up = 1;
- result.s.full_duplex = 0;
- result.s.speed = 1000;
- break;
- case 7:
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- break;
- }
- } else {
- /*
- * This code assumes we are using a Marvell
- * Gigabit PHY. All the speed information can
- * be read from register 17 in one
- * go. Somebody using a different PHY will
- * need to handle it above in the board
- * specific area.
- */
- int phy_status =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17);
-
- /*
- * If the resolve bit 11 isn't set, see if
- * autoneg is turned off (bit 12, reg 0). The
- * resolve bit doesn't get set properly when
- * autoneg is off, so force it.
- */
- if ((phy_status & (1 << 11)) == 0) {
- int auto_status =
- cvmx_mdio_read(phy_addr >> 8,
- phy_addr & 0xff, 0);
- if ((auto_status & (1 << 12)) == 0)
- phy_status |= 1 << 11;
- }
-
- /*
- * Only return a link if the PHY has finished
- * auto negotiation and set the resolved bit
- * (bit 11)
- */
- if (phy_status & (1 << 11)) {
- result.s.link_up = 1;
- result.s.full_duplex = ((phy_status >> 13) & 1);
- switch ((phy_status >> 14) & 3) {
- case 0: /* 10 Mbps */
- result.s.speed = 10;
- break;
- case 1: /* 100 Mbps */
- result.s.speed = 100;
- break;
- case 2: /* 1 Gbps */
- result.s.speed = 1000;
- break;
- case 3: /* Illegal */
- result.u64 = 0;
- break;
- }
- }
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- /*
- * We don't have a PHY address, so attempt to use
- * in-band status. It is really important that boards
- * not supporting in-band status never get
- * here. Reading broken in-band status tends to do bad
- * things
- */
- union cvmx_gmxx_rxx_rx_inbnd inband_status;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- inband_status.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface));
-
- result.s.link_up = inband_status.s.status;
- result.s.full_duplex = inband_status.s.duplex;
- switch (inband_status.s.speed) {
- case 0: /* 10 Mbps */
- result.s.speed = 10;
- break;
- case 1: /* 100 Mbps */
- result.s.speed = 100;
- break;
- case 2: /* 1 Gbps */
- result.s.speed = 1000;
- break;
- case 3: /* Illegal */
- result.u64 = 0;
- break;
- }
- } else {
- /*
- * We don't have a PHY address and we don't have
- * in-band status. There is no way to determine the
- * link speed. Return down assuming this port isn't
- * wired
- */
- result.u64 = 0;
- }
-
- /* If link is down, return all fields as zero. */
- if (!result.s.link_up)
- result.u64 = 0;
-
- return result;
-}
-
-/**
- * This function as a board specific method of changing the PHY
- * speed, duplex, and auto-negotiation. This programs the PHY and
- * not Octeon. This can be used to force Octeon's links to
- * specific settings.
- *
- * @phy_addr: The address of the PHY to program
- * @enable_autoneg:
- * Non zero if you want to enable auto-negotiation.
- * @link_info: Link speed to program. If the speed is zero and auto-negotiation
- * is enabled, all possible negotiation speeds are advertised.
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_helper_board_link_set_phy(int phy_addr,
- cvmx_helper_board_set_phy_link_flags_types_t
- link_flags,
- cvmx_helper_link_info_t link_info)
-{
-
- /* Set the flow control settings based on link_flags */
- if ((link_flags & set_phy_link_flags_flow_control_mask) !=
- set_phy_link_flags_flow_control_dont_touch) {
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
- reg_autoneg_adver.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
- reg_autoneg_adver.s.asymmetric_pause =
- (link_flags & set_phy_link_flags_flow_control_mask) ==
- set_phy_link_flags_flow_control_enable;
- reg_autoneg_adver.s.pause =
- (link_flags & set_phy_link_flags_flow_control_mask) ==
- set_phy_link_flags_flow_control_enable;
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
- reg_autoneg_adver.u16);
- }
-
- /* If speed isn't set and autoneg is on advertise all supported modes */
- if ((link_flags & set_phy_link_flags_autoneg)
- && (link_info.s.speed == 0)) {
- cvmx_mdio_phy_reg_control_t reg_control;
- cvmx_mdio_phy_reg_status_t reg_status;
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
- cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
- cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
-
- reg_status.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_STATUS);
- reg_autoneg_adver.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
- reg_autoneg_adver.s.advert_100base_t4 =
- reg_status.s.capable_100base_t4;
- reg_autoneg_adver.s.advert_10base_tx_full =
- reg_status.s.capable_10_full;
- reg_autoneg_adver.s.advert_10base_tx_half =
- reg_status.s.capable_10_half;
- reg_autoneg_adver.s.advert_100base_tx_full =
- reg_status.s.capable_100base_x_full;
- reg_autoneg_adver.s.advert_100base_tx_half =
- reg_status.s.capable_100base_x_half;
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
- reg_autoneg_adver.u16);
- if (reg_status.s.capable_extended_status) {
- reg_extended_status.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
- reg_control_1000.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL_1000);
- reg_control_1000.s.advert_1000base_t_full =
- reg_extended_status.s.capable_1000base_t_full;
- reg_control_1000.s.advert_1000base_t_half =
- reg_extended_status.s.capable_1000base_t_half;
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL_1000,
- reg_control_1000.u16);
- }
- reg_control.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL);
- reg_control.s.autoneg_enable = 1;
- reg_control.s.restart_autoneg = 1;
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
- } else if ((link_flags & set_phy_link_flags_autoneg)) {
- cvmx_mdio_phy_reg_control_t reg_control;
- cvmx_mdio_phy_reg_status_t reg_status;
- cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver;
- cvmx_mdio_phy_reg_extended_status_t reg_extended_status;
- cvmx_mdio_phy_reg_control_1000_t reg_control_1000;
-
- reg_status.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_STATUS);
- reg_autoneg_adver.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER);
- reg_autoneg_adver.s.advert_100base_t4 = 0;
- reg_autoneg_adver.s.advert_10base_tx_full = 0;
- reg_autoneg_adver.s.advert_10base_tx_half = 0;
- reg_autoneg_adver.s.advert_100base_tx_full = 0;
- reg_autoneg_adver.s.advert_100base_tx_half = 0;
- if (reg_status.s.capable_extended_status) {
- reg_extended_status.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_EXTENDED_STATUS);
- reg_control_1000.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL_1000);
- reg_control_1000.s.advert_1000base_t_full = 0;
- reg_control_1000.s.advert_1000base_t_half = 0;
- }
- switch (link_info.s.speed) {
- case 10:
- reg_autoneg_adver.s.advert_10base_tx_full =
- link_info.s.full_duplex;
- reg_autoneg_adver.s.advert_10base_tx_half =
- !link_info.s.full_duplex;
- break;
- case 100:
- reg_autoneg_adver.s.advert_100base_tx_full =
- link_info.s.full_duplex;
- reg_autoneg_adver.s.advert_100base_tx_half =
- !link_info.s.full_duplex;
- break;
- case 1000:
- reg_control_1000.s.advert_1000base_t_full =
- link_info.s.full_duplex;
- reg_control_1000.s.advert_1000base_t_half =
- !link_info.s.full_duplex;
- break;
- }
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_AUTONEG_ADVER,
- reg_autoneg_adver.u16);
- if (reg_status.s.capable_extended_status)
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL_1000,
- reg_control_1000.u16);
- reg_control.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL);
- reg_control.s.autoneg_enable = 1;
- reg_control.s.restart_autoneg = 1;
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
- } else {
- cvmx_mdio_phy_reg_control_t reg_control;
- reg_control.u16 =
- cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL);
- reg_control.s.autoneg_enable = 0;
- reg_control.s.restart_autoneg = 1;
- reg_control.s.duplex = link_info.s.full_duplex;
- if (link_info.s.speed == 1000) {
- reg_control.s.speed_msb = 1;
- reg_control.s.speed_lsb = 0;
- } else if (link_info.s.speed == 100) {
- reg_control.s.speed_msb = 0;
- reg_control.s.speed_lsb = 1;
- } else if (link_info.s.speed == 10) {
- reg_control.s.speed_msb = 0;
- reg_control.s.speed_lsb = 0;
- }
- cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff,
- CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16);
- }
- return 0;
-}
-
-/**
- * This function is called by cvmx_helper_interface_probe() after it
- * determines the number of ports Octeon can support on a specific
- * interface. This function is the per board location to override
- * this value. It is called with the number of ports Octeon might
- * support and should return the number of actual ports on the
- * board.
- *
- * This function must be modifed for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It relys on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @interface: Interface to probe
- * @supported_ports:
- * Number of ports Octeon supports.
- *
- * Returns Number of ports the actual board supports. Many times this will
- * simple be "support_ports".
- */
-int __cvmx_helper_board_interface_probe(int interface, int supported_ports)
-{
- switch (cvmx_sysinfo_get()->board_type) {
- case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
- if (interface == 0)
- return 2;
- break;
- case CVMX_BOARD_TYPE_BBGW_REF:
- if (interface == 0)
- return 2;
- break;
- case CVMX_BOARD_TYPE_NIC_XLE_4G:
- if (interface == 0)
- return 0;
- break;
- /* The 2nd interface on the EBH5600 is connected to the Marvel switch,
- which we don't support. Disable ports connected to it */
- case CVMX_BOARD_TYPE_EBH5600:
- if (interface == 1)
- return 0;
- break;
- }
- return supported_ports;
-}
-
-/**
- * Enable packet input/output from the hardware. This function is
- * called after by cvmx_helper_packet_hardware_enable() to
- * perform board specific initialization. For most boards
- * nothing is needed.
- *
- * @interface: Interface to enable
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_board_hardware_enable(int interface)
-{
- if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) {
- if (interface == 0) {
- /* Different config for switch port */
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0);
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0);
- /*
- * Boards with gigabit WAN ports need a
- * different setting that is compatible with
- * 100 Mbit settings
- */
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface),
- 0xc);
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface),
- 0xc);
- }
- } else if (cvmx_sysinfo_get()->board_type ==
- CVMX_BOARD_TYPE_CN3010_EVB_HS5) {
- /*
- * Broadcom PHYs require differnet ASX
- * clocks. Unfortunately many boards don't define a
- * new board Id and simply mangle the
- * CN3010_EVB_HS5
- */
- if (interface == 0) {
- /*
- * Some boards use a hacked up bootloader that
- * identifies them as CN3010_EVB_HS5
- * evaluation boards. This leads to all kinds
- * of configuration problems. Detect one
- * case, and print warning, while trying to do
- * the right thing.
- */
- int phy_addr = cvmx_helper_board_get_mii_address(0);
- if (phy_addr != -1) {
- int phy_identifier =
- cvmx_mdio_read(phy_addr >> 8,
- phy_addr & 0xff, 0x2);
- /* Is it a Broadcom PHY? */
- if (phy_identifier == 0x0143) {
- cvmx_dprintf("\n");
- cvmx_dprintf("ERROR:\n");
- cvmx_dprintf
- ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n");
- cvmx_dprintf
- ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n");
- cvmx_dprintf
- ("ERROR: All boards require a unique board type to identify them.\n");
- cvmx_dprintf("ERROR:\n");
- cvmx_dprintf("\n");
- cvmx_wait(1000000000);
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX
- (0, interface), 5);
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX
- (0, interface), 5);
- }
- }
- }
- }
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-board.h b/drivers/staging/octeon/cvmx-helper-board.h
deleted file mode 100644
index b465bec..0000000
--- a/drivers/staging/octeon/cvmx-helper-board.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * Helper functions to abstract board specific data about
- * network ports from the rest of the cvmx-helper files.
- *
- */
-#ifndef __CVMX_HELPER_BOARD_H__
-#define __CVMX_HELPER_BOARD_H__
-
-#include "cvmx-helper.h"
-
-typedef enum {
- set_phy_link_flags_autoneg = 0x1,
- set_phy_link_flags_flow_control_dont_touch = 0x0 << 1,
- set_phy_link_flags_flow_control_enable = 0x1 << 1,
- set_phy_link_flags_flow_control_disable = 0x2 << 1,
- set_phy_link_flags_flow_control_mask = 0x3 << 1, /* Mask for 2 bit wide flow control field */
-} cvmx_helper_board_set_phy_link_flags_types_t;
-
-/**
- * cvmx_override_board_link_get(int ipd_port) is a function
- * pointer. It is meant to allow customization of the process of
- * talking to a PHY to determine link speed. It is called every
- * time a PHY must be polled for link status. Users should set
- * this pointer to a function before calling any cvmx-helper
- * operations.
- */
-extern cvmx_helper_link_info_t(*cvmx_override_board_link_get) (int ipd_port);
-
-/**
- * Return the MII PHY address associated with the given IPD
- * port. A result of -1 means there isn't a MII capable PHY
- * connected to this port. On chips supporting multiple MII
- * busses the bus number is encoded in bits <15:8>.
- *
- * This function must be modifed for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It relys on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @ipd_port: Octeon IPD port to get the MII address for.
- *
- * Returns MII PHY address and bus number or -1.
- */
-extern int cvmx_helper_board_get_mii_address(int ipd_port);
-
-/**
- * This function as a board specific method of changing the PHY
- * speed, duplex, and autonegotiation. This programs the PHY and
- * not Octeon. This can be used to force Octeon's links to
- * specific settings.
- *
- * @phy_addr: The address of the PHY to program
- * @link_flags:
- * Flags to control autonegotiation. Bit 0 is autonegotiation
- * enable/disable to maintain backware compatibility.
- * @link_info: Link speed to program. If the speed is zero and autonegotiation
- * is enabled, all possible negotiation speeds are advertised.
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_helper_board_link_set_phy(int phy_addr,
- cvmx_helper_board_set_phy_link_flags_types_t
- link_flags,
- cvmx_helper_link_info_t link_info);
-
-/**
- * This function is the board specific method of determining an
- * ethernet ports link speed. Most Octeon boards have Marvell PHYs
- * and are handled by the fall through case. This function must be
- * updated for boards that don't have the normal Marvell PHYs.
- *
- * This function must be modifed for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It relys on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @ipd_port: IPD input port associated with the port we want to get link
- * status for.
- *
- * Returns The ports link status. If the link isn't fully resolved, this must
- * return zero.
- */
-extern cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port);
-
-/**
- * This function is called by cvmx_helper_interface_probe() after it
- * determines the number of ports Octeon can support on a specific
- * interface. This function is the per board location to override
- * this value. It is called with the number of ports Octeon might
- * support and should return the number of actual ports on the
- * board.
- *
- * This function must be modifed for every new Octeon board.
- * Internally it uses switch statements based on the cvmx_sysinfo
- * data to determine board types and revisions. It relys on the
- * fact that every Octeon board receives a unique board type
- * enumeration from the bootloader.
- *
- * @interface: Interface to probe
- * @supported_ports:
- * Number of ports Octeon supports.
- *
- * Returns Number of ports the actual board supports. Many times this will
- * simple be "support_ports".
- */
-extern int __cvmx_helper_board_interface_probe(int interface,
- int supported_ports);
-
-/**
- * Enable packet input/output from the hardware. This function is
- * called after by cvmx_helper_packet_hardware_enable() to
- * perform board specific initialization. For most boards
- * nothing is needed.
- *
- * @interface: Interface to enable
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_board_hardware_enable(int interface);
-
-#endif /* __CVMX_HELPER_BOARD_H__ */
diff --git a/drivers/staging/octeon/cvmx-helper-fpa.c b/drivers/staging/octeon/cvmx-helper-fpa.c
deleted file mode 100644
index c239e5f..0000000
--- a/drivers/staging/octeon/cvmx-helper-fpa.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Helper functions for FPA setup.
- *
- */
-#include "executive-config.h"
-#include "cvmx-config.h"
-#include "cvmx.h"
-#include "cvmx-bootmem.h"
-#include "cvmx-fpa.h"
-#include "cvmx-helper-fpa.h"
-
-/**
- * Allocate memory for and initialize a single FPA pool.
- *
- * @pool: Pool to initialize
- * @buffer_size: Size of buffers to allocate in bytes
- * @buffers: Number of buffers to put in the pool. Zero is allowed
- * @name: String name of the pool for debugging purposes
- * Returns Zero on success, non-zero on failure
- */
-static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size,
- uint64_t buffers, const char *name)
-{
- uint64_t current_num;
- void *memory;
- uint64_t align = CVMX_CACHE_LINE_SIZE;
-
- /*
- * Align the allocation so that power of 2 size buffers are
- * naturally aligned.
- */
- while (align < buffer_size)
- align = align << 1;
-
- if (buffers == 0)
- return 0;
-
- current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool));
- if (current_num) {
- cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. "
- "Skipping setup.\n",
- pool, name, (unsigned long long)current_num);
- return 0;
- }
-
- memory = cvmx_bootmem_alloc(buffer_size * buffers, align);
- if (memory == NULL) {
- cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n",
- pool, name);
- return -1;
- }
- cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers);
- return 0;
-}
-
-/**
- * Allocate memory and initialize the FPA pools using memory
- * from cvmx-bootmem. Specifying zero for the number of
- * buffers will cause that FPA pool to not be setup. This is
- * useful if you aren't using some of the hardware and want
- * to save memory. Use cvmx_helper_initialize_fpa instead of
- * this function directly.
- *
- * @pip_pool: Should always be CVMX_FPA_PACKET_POOL
- * @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE
- * @pip_buffers:
- * Number of packet buffers.
- * @wqe_pool: Should always be CVMX_FPA_WQE_POOL
- * @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE
- * @wqe_entries:
- * Number of work queue entries
- * @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL
- * @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
- * @pko_buffers:
- * PKO Command buffers. You should at minimum have two per
- * each PKO queue.
- * @tim_pool: Should always be CVMX_FPA_TIMER_POOL
- * @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE
- * @tim_buffers:
- * TIM ring buffer command queues. At least two per timer bucket
- * is recommened.
- * @dfa_pool: Should always be CVMX_FPA_DFA_POOL
- * @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE
- * @dfa_buffers:
- * DFA command buffer. A relatively small (32 for example)
- * number should work.
- * Returns Zero on success, non-zero if out of memory
- */
-static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size,
- int pip_buffers, int wqe_pool,
- int wqe_size, int wqe_entries,
- int pko_pool, int pko_size,
- int pko_buffers, int tim_pool,
- int tim_size, int tim_buffers,
- int dfa_pool, int dfa_size,
- int dfa_buffers)
-{
- int status;
-
- cvmx_fpa_enable();
-
- if ((pip_buffers > 0) && (pip_buffers <= 64))
- cvmx_dprintf
- ("Warning: %d packet buffers may not be enough for hardware"
- " prefetch. 65 or more is recommended.\n", pip_buffers);
-
- if (pip_pool >= 0) {
- status =
- __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size,
- pip_buffers,
- "Packet Buffers");
- if (status)
- return status;
- }
-
- if (wqe_pool >= 0) {
- status =
- __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size,
- wqe_entries,
- "Work Queue Entries");
- if (status)
- return status;
- }
-
- if (pko_pool >= 0) {
- status =
- __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size,
- pko_buffers,
- "PKO Command Buffers");
- if (status)
- return status;
- }
-
- if (tim_pool >= 0) {
- status =
- __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size,
- tim_buffers,
- "TIM Command Buffers");
- if (status)
- return status;
- }
-
- if (dfa_pool >= 0) {
- status =
- __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size,
- dfa_buffers,
- "DFA Command Buffers");
- if (status)
- return status;
- }
-
- return 0;
-}
-
-/**
- * Allocate memory and initialize the FPA pools using memory
- * from cvmx-bootmem. Sizes of each element in the pools is
- * controlled by the cvmx-config.h header file. Specifying
- * zero for any parameter will cause that FPA pool to not be
- * setup. This is useful if you aren't using some of the
- * hardware and want to save memory.
- *
- * @packet_buffers:
- * Number of packet buffers to allocate
- * @work_queue_entries:
- * Number of work queue entries
- * @pko_buffers:
- * PKO Command buffers. You should at minimum have two per
- * each PKO queue.
- * @tim_buffers:
- * TIM ring buffer command queues. At least two per timer bucket
- * is recommened.
- * @dfa_buffers:
- * DFA command buffer. A relatively small (32 for example)
- * number should work.
- * Returns Zero on success, non-zero if out of memory
- */
-int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries,
- int pko_buffers, int tim_buffers,
- int dfa_buffers)
-{
-#ifndef CVMX_FPA_PACKET_POOL
-#define CVMX_FPA_PACKET_POOL -1
-#define CVMX_FPA_PACKET_POOL_SIZE 0
-#endif
-#ifndef CVMX_FPA_WQE_POOL
-#define CVMX_FPA_WQE_POOL -1
-#define CVMX_FPA_WQE_POOL_SIZE 0
-#endif
-#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL
-#define CVMX_FPA_OUTPUT_BUFFER_POOL -1
-#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0
-#endif
-#ifndef CVMX_FPA_TIMER_POOL
-#define CVMX_FPA_TIMER_POOL -1
-#define CVMX_FPA_TIMER_POOL_SIZE 0
-#endif
-#ifndef CVMX_FPA_DFA_POOL
-#define CVMX_FPA_DFA_POOL -1
-#define CVMX_FPA_DFA_POOL_SIZE 0
-#endif
- return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL,
- CVMX_FPA_PACKET_POOL_SIZE,
- packet_buffers, CVMX_FPA_WQE_POOL,
- CVMX_FPA_WQE_POOL_SIZE,
- work_queue_entries,
- CVMX_FPA_OUTPUT_BUFFER_POOL,
- CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE,
- pko_buffers, CVMX_FPA_TIMER_POOL,
- CVMX_FPA_TIMER_POOL_SIZE,
- tim_buffers, CVMX_FPA_DFA_POOL,
- CVMX_FPA_DFA_POOL_SIZE,
- dfa_buffers);
-}
diff --git a/drivers/staging/octeon/cvmx-helper-fpa.h b/drivers/staging/octeon/cvmx-helper-fpa.h
deleted file mode 100644
index 5ff8c93..0000000
--- a/drivers/staging/octeon/cvmx-helper-fpa.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Helper functions for FPA setup.
- *
- */
-#ifndef __CVMX_HELPER_H_FPA__
-#define __CVMX_HELPER_H_FPA__
-
-/**
- * Allocate memory and initialize the FPA pools using memory
- * from cvmx-bootmem. Sizes of each element in the pools is
- * controlled by the cvmx-config.h header file. Specifying
- * zero for any parameter will cause that FPA pool to not be
- * setup. This is useful if you aren't using some of the
- * hardware and want to save memory.
- *
- * @packet_buffers:
- * Number of packet buffers to allocate
- * @work_queue_entries:
- * Number of work queue entries
- * @pko_buffers:
- * PKO Command buffers. You should at minimum have two per
- * each PKO queue.
- * @tim_buffers:
- * TIM ring buffer command queues. At least two per timer bucket
- * is recommened.
- * @dfa_buffers:
- * DFA command buffer. A relatively small (32 for example)
- * number should work.
- * Returns Zero on success, non-zero if out of memory
- */
-extern int cvmx_helper_initialize_fpa(int packet_buffers,
- int work_queue_entries, int pko_buffers,
- int tim_buffers, int dfa_buffers);
-
-#endif /* __CVMX_HELPER_H__ */
diff --git a/drivers/staging/octeon/cvmx-helper-loop.c b/drivers/staging/octeon/cvmx-helper-loop.c
deleted file mode 100644
index 55a571a..0000000
--- a/drivers/staging/octeon/cvmx-helper-loop.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for LOOP initialization, configuration,
- * and monitoring.
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-helper.h"
-#include "cvmx-pip-defs.h"
-
-/**
- * Probe a LOOP interface and determine the number of ports
- * connected to it. The LOOP interface should still be down
- * after this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-int __cvmx_helper_loop_probe(int interface)
-{
- union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
- int num_ports = 4;
- int port;
-
- /* We need to disable length checking so packet < 64 bytes and jumbo
- frames don't get errors */
- for (port = 0; port < num_ports; port++) {
- union cvmx_pip_prt_cfgx port_cfg;
- int ipd_port = cvmx_helper_get_ipd_port(interface, port);
- port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
- port_cfg.s.maxerr_en = 0;
- port_cfg.s.minerr_en = 0;
- cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_cfg.u64);
- }
-
- /* Disable FCS stripping for loopback ports */
- ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
- ipd_sub_port_fcs.s.port_bit2 = 0;
- cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
- return num_ports;
-}
-
-/**
- * Bringup and enable a LOOP interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_loop_enable(int interface)
-{
- /* Do nothing. */
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-loop.h b/drivers/staging/octeon/cvmx-helper-loop.h
deleted file mode 100644
index e646a6c..0000000
--- a/drivers/staging/octeon/cvmx-helper-loop.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful,
- * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Functions for LOOP initialization, configuration,
- * and monitoring.
- *
- */
-#ifndef __CVMX_HELPER_LOOP_H__
-#define __CVMX_HELPER_LOOP_H__
-
-/**
- * Probe a LOOP interface and determine the number of ports
- * connected to it. The LOOP interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-extern int __cvmx_helper_loop_probe(int interface);
-
-/**
- * Bringup and enable a LOOP interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_loop_enable(int interface);
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-npi.c b/drivers/staging/octeon/cvmx-helper-npi.c
deleted file mode 100644
index 7388a1e..0000000
--- a/drivers/staging/octeon/cvmx-helper-npi.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for NPI initialization, configuration,
- * and monitoring.
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-helper.h"
-
-#include "cvmx-pip-defs.h"
-
-/**
- * Probe a NPI interface and determine the number of ports
- * connected to it. The NPI interface should still be down
- * after this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-int __cvmx_helper_npi_probe(int interface)
-{
-#if CVMX_PKO_QUEUES_PER_PORT_PCI > 0
- if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
- return 4;
- else if (OCTEON_IS_MODEL(OCTEON_CN56XX)
- && !OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
- /* The packet engines didn't exist before pass 2 */
- return 4;
- else if (OCTEON_IS_MODEL(OCTEON_CN52XX)
- && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X))
- /* The packet engines didn't exist before pass 2 */
- return 4;
-#if 0
- /*
- * Technically CN30XX, CN31XX, and CN50XX contain packet
- * engines, but nobody ever uses them. Since this is the case,
- * we disable them here.
- */
- else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX))
- return 2;
- else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
- return 1;
-#endif
-#endif
- return 0;
-}
-
-/**
- * Bringup and enable a NPI interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_npi_enable(int interface)
-{
- /*
- * On CN50XX, CN52XX, and CN56XX we need to disable length
- * checking so packet < 64 bytes and jumbo frames don't get
- * errors.
- */
- if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
- !OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- int num_ports = cvmx_helper_ports_on_interface(interface);
- int port;
- for (port = 0; port < num_ports; port++) {
- union cvmx_pip_prt_cfgx port_cfg;
- int ipd_port =
- cvmx_helper_get_ipd_port(interface, port);
- port_cfg.u64 =
- cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
- port_cfg.s.maxerr_en = 0;
- port_cfg.s.minerr_en = 0;
- cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port),
- port_cfg.u64);
- }
- }
-
- /* Enables are controlled by the remote host, so nothing to do here */
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-npi.h b/drivers/staging/octeon/cvmx-helper-npi.h
deleted file mode 100644
index 908e7b0..0000000
--- a/drivers/staging/octeon/cvmx-helper-npi.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Functions for NPI initialization, configuration,
- * and monitoring.
- *
- */
-#ifndef __CVMX_HELPER_NPI_H__
-#define __CVMX_HELPER_NPI_H__
-
-/**
- * Probe a NPI interface and determine the number of ports
- * connected to it. The NPI interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-extern int __cvmx_helper_npi_probe(int interface);
-
-/**
- * Bringup and enable a NPI interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_npi_enable(int interface);
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-rgmii.c b/drivers/staging/octeon/cvmx-helper-rgmii.c
deleted file mode 100644
index aa2d5d7..0000000
--- a/drivers/staging/octeon/cvmx-helper-rgmii.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for RGMII/GMII/MII initialization, configuration,
- * and monitoring.
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-
-#include "cvmx-mdio.h"
-#include "cvmx-pko.h"
-#include "cvmx-helper.h"
-#include "cvmx-helper-board.h"
-
-#include <asm/octeon/cvmx-npi-defs.h>
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-asxx-defs.h"
-#include "cvmx-dbg-defs.h"
-
-void __cvmx_interrupt_gmxx_enable(int interface);
-void __cvmx_interrupt_asxx_enable(int block);
-
-/**
- * Probe RGMII ports and determine the number present
- *
- * @interface: Interface to probe
- *
- * Returns Number of RGMII/GMII/MII ports (0-4).
- */
-int __cvmx_helper_rgmii_probe(int interface)
-{
- int num_ports = 0;
- union cvmx_gmxx_inf_mode mode;
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
-
- if (mode.s.type) {
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- cvmx_dprintf("ERROR: RGMII initialize called in "
- "SPI interface\n");
- } else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
- || OCTEON_IS_MODEL(OCTEON_CN30XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- /*
- * On these chips "type" says we're in
- * GMII/MII mode. This limits us to 2 ports
- */
- num_ports = 2;
- } else {
- cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n",
- __func__);
- }
- } else {
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- num_ports = 4;
- } else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
- || OCTEON_IS_MODEL(OCTEON_CN30XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- num_ports = 3;
- } else {
- cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n",
- __func__);
- }
- }
- return num_ports;
-}
-
-/**
- * Put an RGMII interface in loopback mode. Internal packets sent
- * out will be received back again on the same port. Externally
- * received packets will echo back out.
- *
- * @port: IPD port number to loop.
- */
-void cvmx_helper_rgmii_internal_loopback(int port)
-{
- int interface = (port >> 4) & 1;
- int index = port & 0xf;
- uint64_t tmp;
-
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- gmx_cfg.u64 = 0;
- gmx_cfg.s.duplex = 1;
- gmx_cfg.s.slottime = 1;
- gmx_cfg.s.speed = 1;
- cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000);
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- tmp = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface));
- cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), (1 << index) | tmp);
- tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface));
- cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), (1 << index) | tmp);
- tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface));
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), (1 << index) | tmp);
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-}
-
-/**
- * Workaround ASX setup errata with CN38XX pass1
- *
- * @interface: Interface to setup
- * @port: Port to setup (0..3)
- * @cpu_clock_hz:
- * Chip frequency in Hertz
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_errata_asx_pass1(int interface, int port,
- int cpu_clock_hz)
-{
- /* Set hi water mark as per errata GMX-4 */
- if (cpu_clock_hz >= 325000000 && cpu_clock_hz < 375000000)
- cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 12);
- else if (cpu_clock_hz >= 375000000 && cpu_clock_hz < 437000000)
- cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 11);
- else if (cpu_clock_hz >= 437000000 && cpu_clock_hz < 550000000)
- cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 10);
- else if (cpu_clock_hz >= 550000000 && cpu_clock_hz < 687000000)
- cvmx_write_csr(CVMX_ASXX_TX_HI_WATERX(port, interface), 9);
- else
- cvmx_dprintf("Illegal clock frequency (%d). "
- "CVMX_ASXX_TX_HI_WATERX not set\n", cpu_clock_hz);
- return 0;
-}
-
-/**
- * Configure all of the ASX, GMX, and PKO regsiters required
- * to get RGMII to function on the supplied interface.
- *
- * @interface: PKO Interface to configure (0 or 1)
- *
- * Returns Zero on success
- */
-int __cvmx_helper_rgmii_enable(int interface)
-{
- int num_ports = cvmx_helper_ports_on_interface(interface);
- int port;
- struct cvmx_sysinfo *sys_info_ptr = cvmx_sysinfo_get();
- union cvmx_gmxx_inf_mode mode;
- union cvmx_asxx_tx_prt_en asx_tx;
- union cvmx_asxx_rx_prt_en asx_rx;
-
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
-
- if (mode.s.en == 0)
- return -1;
- if ((OCTEON_IS_MODEL(OCTEON_CN38XX) ||
- OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1)
- /* Ignore SPI interfaces */
- return -1;
-
- /* Configure the ASX registers needed to use the RGMII ports */
- asx_tx.u64 = 0;
- asx_tx.s.prt_en = cvmx_build_mask(num_ports);
- cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64);
-
- asx_rx.u64 = 0;
- asx_rx.s.prt_en = cvmx_build_mask(num_ports);
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64);
-
- /* Configure the GMX registers needed to use the RGMII ports */
- for (port = 0; port < num_ports; port++) {
- /* Setting of CVMX_GMXX_TXX_THRESH has been moved to
- __cvmx_helper_setup_gmx() */
-
- if (cvmx_octeon_is_pass1())
- __cvmx_helper_errata_asx_pass1(interface, port,
- sys_info_ptr->
- cpu_clock_hz);
- else {
- /*
- * Configure more flexible RGMII preamble
- * checking. Pass 1 doesn't support this
- * feature.
- */
- union cvmx_gmxx_rxx_frm_ctl frm_ctl;
- frm_ctl.u64 =
- cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
- (port, interface));
- /* New field, so must be compile time */
- frm_ctl.s.pre_free = 1;
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface),
- frm_ctl.u64);
- }
-
- /*
- * Each pause frame transmitted will ask for about 10M
- * bit times before resume. If buffer space comes
- * available before that time has expired, an XON
- * pause frame (0 time) will be transmitted to restart
- * the flow.
- */
- cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface),
- 20000);
- cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL
- (port, interface), 19000);
-
- if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface),
- 16);
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface),
- 16);
- } else {
- cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface),
- 24);
- cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface),
- 24);
- }
- }
-
- __cvmx_helper_setup_gmx(interface, num_ports);
-
- /* enable the ports now */
- for (port = 0; port < num_ports; port++) {
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port
- (interface, port));
- gmx_cfg.u64 =
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG(port, interface));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(port, interface),
- gmx_cfg.u64);
- }
- __cvmx_interrupt_asxx_enable(interface);
- __cvmx_interrupt_gmxx_enable(interface);
-
- return 0;
-}
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- union cvmx_asxx_prt_loop asxx_prt_loop;
-
- asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface));
- if (asxx_prt_loop.s.int_loop & (1 << index)) {
- /* Force 1Gbps full duplex on internal loopback */
- cvmx_helper_link_info_t result;
- result.u64 = 0;
- result.s.full_duplex = 1;
- result.s.link_up = 1;
- result.s.speed = 1000;
- return result;
- } else
- return __cvmx_helper_board_link_get(ipd_port);
-}
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_rgmii_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info)
-{
- int result = 0;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- union cvmx_gmxx_prtx_cfg original_gmx_cfg;
- union cvmx_gmxx_prtx_cfg new_gmx_cfg;
- union cvmx_pko_mem_queue_qos pko_mem_queue_qos;
- union cvmx_pko_mem_queue_qos pko_mem_queue_qos_save[16];
- union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp;
- union cvmx_gmxx_tx_ovr_bp gmx_tx_ovr_bp_save;
- int i;
-
- /* Ignore speed sets in the simulator */
- if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
- return 0;
-
- /* Read the current settings so we know the current enable state */
- original_gmx_cfg.u64 =
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- new_gmx_cfg = original_gmx_cfg;
-
- /* Disable the lowest level RX */
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface),
- cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) &
- ~(1 << index));
-
- /* Disable all queues so that TX should become idle */
- for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) {
- int queue = cvmx_pko_get_base_queue(ipd_port) + i;
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue);
- pko_mem_queue_qos.u64 = cvmx_read_csr(CVMX_PKO_MEM_QUEUE_QOS);
- pko_mem_queue_qos.s.pid = ipd_port;
- pko_mem_queue_qos.s.qid = queue;
- pko_mem_queue_qos_save[i] = pko_mem_queue_qos;
- pko_mem_queue_qos.s.qos_mask = 0;
- cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS, pko_mem_queue_qos.u64);
- }
-
- /* Disable backpressure */
- gmx_tx_ovr_bp.u64 = cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface));
- gmx_tx_ovr_bp_save = gmx_tx_ovr_bp;
- gmx_tx_ovr_bp.s.bp &= ~(1 << index);
- gmx_tx_ovr_bp.s.en |= 1 << index;
- cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp.u64);
- cvmx_read_csr(CVMX_GMXX_TX_OVR_BP(interface));
-
- /*
- * Poll the GMX state machine waiting for it to become
- * idle. Preferably we should only change speed when it is
- * idle. If it doesn't become idle we will still do the speed
- * change, but there is a slight chance that GMX will
- * lockup.
- */
- cvmx_write_csr(CVMX_NPI_DBG_SELECT,
- interface * 0x800 + index * 0x100 + 0x880);
- CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 7,
- ==, 0, 10000);
- CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data, data & 0xf,
- ==, 0, 10000);
-
- /* Disable the port before we make any changes */
- new_gmx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-
- /* Set full/half duplex */
- if (cvmx_octeon_is_pass1())
- /* Half duplex is broken for 38XX Pass 1 */
- new_gmx_cfg.s.duplex = 1;
- else if (!link_info.s.link_up)
- /* Force full duplex on down links */
- new_gmx_cfg.s.duplex = 1;
- else
- new_gmx_cfg.s.duplex = link_info.s.full_duplex;
-
- /* Set the link speed. Anything unknown is set to 1Gbps */
- if (link_info.s.speed == 10) {
- new_gmx_cfg.s.slottime = 0;
- new_gmx_cfg.s.speed = 0;
- } else if (link_info.s.speed == 100) {
- new_gmx_cfg.s.slottime = 0;
- new_gmx_cfg.s.speed = 0;
- } else {
- new_gmx_cfg.s.slottime = 1;
- new_gmx_cfg.s.speed = 1;
- }
-
- /* Adjust the clocks */
- if (link_info.s.speed == 10) {
- cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 50);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
- } else if (link_info.s.speed == 100) {
- cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 5);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x40);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
- } else {
- cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000);
- }
-
- if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- if ((link_info.s.speed == 10) || (link_info.s.speed == 100)) {
- union cvmx_gmxx_inf_mode mode;
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
-
- /*
- * Port .en .type .p0mii Configuration
- * ---- --- ----- ------ -----------------------------------------
- * X 0 X X All links are disabled.
- * 0 1 X 0 Port 0 is RGMII
- * 0 1 X 1 Port 0 is MII
- * 1 1 0 X Ports 1 and 2 are configured as RGMII ports.
- * 1 1 1 X Port 1: GMII/MII; Port 2: disabled. GMII or
- * MII port is selected by GMX_PRT1_CFG[SPEED].
- */
-
- /* In MII mode, CLK_CNT = 1. */
- if (((index == 0) && (mode.s.p0mii == 1))
- || ((index != 0) && (mode.s.type == 1))) {
- cvmx_write_csr(CVMX_GMXX_TXX_CLK
- (index, interface), 1);
- }
- }
- }
-
- /* Do a read to make sure all setup stuff is complete */
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-
- /* Save the new GMX setting without enabling the port */
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);
-
- /* Enable the lowest level RX */
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface),
- cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) | (1 <<
- index));
-
- /* Re-enable the TX path */
- for (i = 0; i < cvmx_pko_get_num_queues(ipd_port); i++) {
- int queue = cvmx_pko_get_base_queue(ipd_port) + i;
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, queue);
- cvmx_write_csr(CVMX_PKO_MEM_QUEUE_QOS,
- pko_mem_queue_qos_save[i].u64);
- }
-
- /* Restore backpressure */
- cvmx_write_csr(CVMX_GMXX_TX_OVR_BP(interface), gmx_tx_ovr_bp_save.u64);
-
- /* Restore the GMX enable state. Port config is complete */
- new_gmx_cfg.s.en = original_gmx_cfg.s.en;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), new_gmx_cfg.u64);
-
- return result;
-}
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-int __cvmx_helper_rgmii_configure_loopback(int ipd_port, int enable_internal,
- int enable_external)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- int original_enable;
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- union cvmx_asxx_prt_loop asxx_prt_loop;
-
- /* Read the current enable state and save it */
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- original_enable = gmx_cfg.s.en;
- /* Force port to be disabled */
- gmx_cfg.s.en = 0;
- if (enable_internal) {
- /* Force speed if we're doing internal loopback */
- gmx_cfg.s.duplex = 1;
- gmx_cfg.s.slottime = 1;
- gmx_cfg.s.speed = 1;
- cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000);
- }
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
-
- /* Set the loopback bits */
- asxx_prt_loop.u64 = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface));
- if (enable_internal)
- asxx_prt_loop.s.int_loop |= 1 << index;
- else
- asxx_prt_loop.s.int_loop &= ~(1 << index);
- if (enable_external)
- asxx_prt_loop.s.ext_loop |= 1 << index;
- else
- asxx_prt_loop.s.ext_loop &= ~(1 << index);
- cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), asxx_prt_loop.u64);
-
- /* Force enables in internal loopback */
- if (enable_internal) {
- uint64_t tmp;
- tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface));
- cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface),
- (1 << index) | tmp);
- tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface));
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface),
- (1 << index) | tmp);
- original_enable = 1;
- }
-
- /* Restore the enable state */
- gmx_cfg.s.en = original_enable;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-rgmii.h b/drivers/staging/octeon/cvmx-helper-rgmii.h
deleted file mode 100644
index ea26526..0000000
--- a/drivers/staging/octeon/cvmx-helper-rgmii.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Functions for RGMII/GMII/MII initialization, configuration,
- * and monitoring.
- *
- */
-#ifndef __CVMX_HELPER_RGMII_H__
-#define __CVMX_HELPER_RGMII_H__
-
-/**
- * Probe RGMII ports and determine the number present
- *
- * @interface: Interface to probe
- *
- * Returns Number of RGMII/GMII/MII ports (0-4).
- */
-extern int __cvmx_helper_rgmii_probe(int interface);
-
-/**
- * Put an RGMII interface in loopback mode. Internal packets sent
- * out will be received back again on the same port. Externally
- * received packets will echo back out.
- *
- * @port: IPD port number to loop.
- */
-extern void cvmx_helper_rgmii_internal_loopback(int port);
-
-/**
- * Configure all of the ASX, GMX, and PKO regsiters required
- * to get RGMII to function on the supplied interface.
- *
- * @interface: PKO Interface to configure (0 or 1)
- *
- * Returns Zero on success
- */
-extern int __cvmx_helper_rgmii_enable(int interface);
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-extern cvmx_helper_link_info_t __cvmx_helper_rgmii_link_get(int ipd_port);
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_rgmii_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info);
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-extern int __cvmx_helper_rgmii_configure_loopback(int ipd_port,
- int enable_internal,
- int enable_external);
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-sgmii.c b/drivers/staging/octeon/cvmx-helper-sgmii.c
deleted file mode 100644
index 6214e3b..0000000
--- a/drivers/staging/octeon/cvmx-helper-sgmii.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for SGMII initialization, configuration,
- * and monitoring.
- */
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-mdio.h"
-#include "cvmx-helper.h"
-#include "cvmx-helper-board.h"
-
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-pcsx-defs.h"
-
-void __cvmx_interrupt_gmxx_enable(int interface);
-void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block);
-void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index);
-
-/**
- * Perform initialization required only once for an SGMII port.
- *
- * @interface: Interface to init
- * @index: Index of prot on the interface
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_sgmii_hardware_init_one_time(int interface, int index)
-{
- const uint64_t clock_mhz = cvmx_sysinfo_get()->cpu_clock_hz / 1000000;
- union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg;
- union cvmx_pcsx_linkx_timer_count_reg pcsx_linkx_timer_count_reg;
- union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
-
- /* Disable GMX */
- gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmxx_prtx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
-
- /*
- * Write PCS*_LINK*_TIMER_COUNT_REG[COUNT] with the
- * appropriate value. 1000BASE-X specifies a 10ms
- * interval. SGMII specifies a 1.6ms interval.
- */
- pcs_misc_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
- pcsx_linkx_timer_count_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface));
- if (pcs_misc_ctl_reg.s.mode) {
- /* 1000BASE-X */
- pcsx_linkx_timer_count_reg.s.count =
- (10000ull * clock_mhz) >> 10;
- } else {
- /* SGMII */
- pcsx_linkx_timer_count_reg.s.count =
- (1600ull * clock_mhz) >> 10;
- }
- cvmx_write_csr(CVMX_PCSX_LINKX_TIMER_COUNT_REG(index, interface),
- pcsx_linkx_timer_count_reg.u64);
-
- /*
- * Write the advertisement register to be used as the
- * tx_Config_Reg<D15:D0> of the autonegotiation. In
- * 1000BASE-X mode, tx_Config_Reg<D15:D0> is PCS*_AN*_ADV_REG.
- * In SGMII PHY mode, tx_Config_Reg<D15:D0> is
- * PCS*_SGM*_AN_ADV_REG. In SGMII MAC mode,
- * tx_Config_Reg<D15:D0> is the fixed value 0x4001, so this
- * step can be skipped.
- */
- if (pcs_misc_ctl_reg.s.mode) {
- /* 1000BASE-X */
- union cvmx_pcsx_anx_adv_reg pcsx_anx_adv_reg;
- pcsx_anx_adv_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_ANX_ADV_REG(index, interface));
- pcsx_anx_adv_reg.s.rem_flt = 0;
- pcsx_anx_adv_reg.s.pause = 3;
- pcsx_anx_adv_reg.s.hfd = 1;
- pcsx_anx_adv_reg.s.fd = 1;
- cvmx_write_csr(CVMX_PCSX_ANX_ADV_REG(index, interface),
- pcsx_anx_adv_reg.u64);
- } else {
- union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
- pcsx_miscx_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
- if (pcsx_miscx_ctl_reg.s.mac_phy) {
- /* PHY Mode */
- union cvmx_pcsx_sgmx_an_adv_reg pcsx_sgmx_an_adv_reg;
- pcsx_sgmx_an_adv_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_SGMX_AN_ADV_REG
- (index, interface));
- pcsx_sgmx_an_adv_reg.s.link = 1;
- pcsx_sgmx_an_adv_reg.s.dup = 1;
- pcsx_sgmx_an_adv_reg.s.speed = 2;
- cvmx_write_csr(CVMX_PCSX_SGMX_AN_ADV_REG
- (index, interface),
- pcsx_sgmx_an_adv_reg.u64);
- } else {
- /* MAC Mode - Nothing to do */
- }
- }
- return 0;
-}
-
-/**
- * Initialize the SERTES link for the first time or after a loss
- * of link.
- *
- * @interface: Interface to init
- * @index: Index of prot on the interface
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_sgmii_hardware_init_link(int interface, int index)
-{
- union cvmx_pcsx_mrx_control_reg control_reg;
-
- /*
- * Take PCS through a reset sequence.
- * PCS*_MR*_CONTROL_REG[PWR_DN] should be cleared to zero.
- * Write PCS*_MR*_CONTROL_REG[RESET]=1 (while not changing the
- * value of the other PCS*_MR*_CONTROL_REG bits). Read
- * PCS*_MR*_CONTROL_REG[RESET] until it changes value to
- * zero.
- */
- control_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
- if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {
- control_reg.s.reset = 1;
- cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
- control_reg.u64);
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSX_MRX_CONTROL_REG(index, interface),
- union cvmx_pcsx_mrx_control_reg, reset, ==, 0, 10000)) {
- cvmx_dprintf("SGMII%d: Timeout waiting for port %d "
- "to finish reset\n",
- interface, index);
- return -1;
- }
- }
-
- /*
- * Write PCS*_MR*_CONTROL_REG[RST_AN]=1 to ensure a fresh
- * sgmii negotiation starts.
- */
- control_reg.s.rst_an = 1;
- control_reg.s.an_en = 1;
- control_reg.s.pwr_dn = 0;
- cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
- control_reg.u64);
-
- /*
- * Wait for PCS*_MR*_STATUS_REG[AN_CPT] to be set, indicating
- * that sgmii autonegotiation is complete. In MAC mode this
- * isn't an ethernet link, but a link between Octeon and the
- * PHY.
- */
- if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
- CVMX_WAIT_FOR_FIELD64(CVMX_PCSX_MRX_STATUS_REG(index, interface),
- union cvmx_pcsx_mrx_status_reg, an_cpt, ==, 1,
- 10000)) {
- /* cvmx_dprintf("SGMII%d: Port %d link timeout\n", interface, index); */
- return -1;
- }
- return 0;
-}
-
-/**
- * Configure an SGMII link to the specified speed after the SERTES
- * link is up.
- *
- * @interface: Interface to init
- * @index: Index of prot on the interface
- * @link_info: Link state to configure
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_sgmii_hardware_init_link_speed(int interface,
- int index,
- cvmx_helper_link_info_t
- link_info)
-{
- int is_enabled;
- union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
- union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
-
- /* Disable GMX before we make any changes. Remember the enable state */
- gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- is_enabled = gmxx_prtx_cfg.s.en;
- gmxx_prtx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
-
- /* Wait for GMX to be idle */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_GMXX_PRTX_CFG(index, interface), union cvmx_gmxx_prtx_cfg,
- rx_idle, ==, 1, 10000)
- || CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
- union cvmx_gmxx_prtx_cfg, tx_idle, ==, 1,
- 10000)) {
- cvmx_dprintf
- ("SGMII%d: Timeout waiting for port %d to be idle\n",
- interface, index);
- return -1;
- }
-
- /* Read GMX CFG again to make sure the disable completed */
- gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-
- /*
- * Get the misc control for PCS. We will need to set the
- * duplication amount.
- */
- pcsx_miscx_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
-
- /*
- * Use GMXENO to force the link down if the status we get says
- * it should be down.
- */
- pcsx_miscx_ctl_reg.s.gmxeno = !link_info.s.link_up;
-
- /* Only change the duplex setting if the link is up */
- if (link_info.s.link_up)
- gmxx_prtx_cfg.s.duplex = link_info.s.full_duplex;
-
- /* Do speed based setting for GMX */
- switch (link_info.s.speed) {
- case 10:
- gmxx_prtx_cfg.s.speed = 0;
- gmxx_prtx_cfg.s.speed_msb = 1;
- gmxx_prtx_cfg.s.slottime = 0;
- /* Setting from GMX-603 */
- pcsx_miscx_ctl_reg.s.samp_pt = 25;
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
- break;
- case 100:
- gmxx_prtx_cfg.s.speed = 0;
- gmxx_prtx_cfg.s.speed_msb = 0;
- gmxx_prtx_cfg.s.slottime = 0;
- pcsx_miscx_ctl_reg.s.samp_pt = 0x5;
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 64);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0);
- break;
- case 1000:
- gmxx_prtx_cfg.s.speed = 1;
- gmxx_prtx_cfg.s.speed_msb = 0;
- gmxx_prtx_cfg.s.slottime = 1;
- pcsx_miscx_ctl_reg.s.samp_pt = 1;
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 512);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 8192);
- break;
- default:
- break;
- }
-
- /* Write the new misc control for PCS */
- cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
- pcsx_miscx_ctl_reg.u64);
-
- /* Write the new GMX settings with the port still disabled */
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
-
- /* Read GMX CFG again to make sure the config completed */
- gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
-
- /* Restore the enabled / disabled state */
- gmxx_prtx_cfg.s.en = is_enabled;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmxx_prtx_cfg.u64);
-
- return 0;
-}
-
-/**
- * Bring up the SGMII interface to be ready for packet I/O but
- * leave I/O disabled using the GMX override. This function
- * follows the bringup documented in 10.6.3 of the manual.
- *
- * @interface: Interface to bringup
- * @num_ports: Number of ports on the interface
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_sgmii_hardware_init(int interface, int num_ports)
-{
- int index;
-
- __cvmx_helper_setup_gmx(interface, num_ports);
-
- for (index = 0; index < num_ports; index++) {
- int ipd_port = cvmx_helper_get_ipd_port(interface, index);
- __cvmx_helper_sgmii_hardware_init_one_time(interface, index);
- __cvmx_helper_sgmii_link_set(ipd_port,
- __cvmx_helper_sgmii_link_get
- (ipd_port));
-
- }
-
- return 0;
-}
-
-/**
- * Probe a SGMII interface and determine the number of ports
- * connected to it. The SGMII interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-int __cvmx_helper_sgmii_probe(int interface)
-{
- union cvmx_gmxx_inf_mode mode;
-
- /*
- * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the
- * interface needs to be enabled before IPD otherwise per port
- * backpressure may not work properly
- */
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
- mode.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
- return 4;
-}
-
-/**
- * Bringup and enable a SGMII interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_sgmii_enable(int interface)
-{
- int num_ports = cvmx_helper_ports_on_interface(interface);
- int index;
-
- __cvmx_helper_sgmii_hardware_init(interface, num_ports);
-
- for (index = 0; index < num_ports; index++) {
- union cvmx_gmxx_prtx_cfg gmxx_prtx_cfg;
- gmxx_prtx_cfg.u64 =
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
- gmxx_prtx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface),
- gmxx_prtx_cfg.u64);
- __cvmx_interrupt_pcsx_intx_en_reg_enable(index, interface);
- }
- __cvmx_interrupt_pcsxx_int_en_reg_enable(interface);
- __cvmx_interrupt_gmxx_enable(interface);
- return 0;
-}
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port)
-{
- cvmx_helper_link_info_t result;
- union cvmx_pcsx_miscx_ctl_reg pcs_misc_ctl_reg;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
-
- result.u64 = 0;
-
- if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) {
- /* The simulator gives you a simulated 1Gbps full duplex link */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- }
-
- pcsx_mrx_control_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
- if (pcsx_mrx_control_reg.s.loopbck1) {
- /* Force 1Gbps full duplex link for internal loopback */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- }
-
- pcs_misc_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
- if (pcs_misc_ctl_reg.s.mode) {
- /* 1000BASE-X */
- /* FIXME */
- } else {
- union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
- pcsx_miscx_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
- if (pcsx_miscx_ctl_reg.s.mac_phy) {
- /* PHY Mode */
- union cvmx_pcsx_mrx_status_reg pcsx_mrx_status_reg;
- union cvmx_pcsx_anx_results_reg pcsx_anx_results_reg;
-
- /*
- * Don't bother continuing if the SERTES low
- * level link is down
- */
- pcsx_mrx_status_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MRX_STATUS_REG
- (index, interface));
- if (pcsx_mrx_status_reg.s.lnk_st == 0) {
- if (__cvmx_helper_sgmii_hardware_init_link
- (interface, index) != 0)
- return result;
- }
-
- /* Read the autoneg results */
- pcsx_anx_results_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_ANX_RESULTS_REG
- (index, interface));
- if (pcsx_anx_results_reg.s.an_cpt) {
- /*
- * Auto negotiation is complete. Set
- * status accordingly.
- */
- result.s.full_duplex =
- pcsx_anx_results_reg.s.dup;
- result.s.link_up =
- pcsx_anx_results_reg.s.link_ok;
- switch (pcsx_anx_results_reg.s.spd) {
- case 0:
- result.s.speed = 10;
- break;
- case 1:
- result.s.speed = 100;
- break;
- case 2:
- result.s.speed = 1000;
- break;
- default:
- result.s.speed = 0;
- result.s.link_up = 0;
- break;
- }
- } else {
- /*
- * Auto negotiation isn't
- * complete. Return link down.
- */
- result.s.speed = 0;
- result.s.link_up = 0;
- }
- } else { /* MAC Mode */
-
- result = __cvmx_helper_board_link_get(ipd_port);
- }
- }
- return result;
-}
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_sgmii_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- __cvmx_helper_sgmii_hardware_init_link(interface, index);
- return __cvmx_helper_sgmii_hardware_init_link_speed(interface, index,
- link_info);
-}
-
-/**
- * Configure a port for internal and/or external loopback. Internal
- * loopback causes packets sent by the port to be received by
- * Octeon. External loopback causes packets received from the wire to
- * sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-int __cvmx_helper_sgmii_configure_loopback(int ipd_port, int enable_internal,
- int enable_external)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- union cvmx_pcsx_mrx_control_reg pcsx_mrx_control_reg;
- union cvmx_pcsx_miscx_ctl_reg pcsx_miscx_ctl_reg;
-
- pcsx_mrx_control_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface));
- pcsx_mrx_control_reg.s.loopbck1 = enable_internal;
- cvmx_write_csr(CVMX_PCSX_MRX_CONTROL_REG(index, interface),
- pcsx_mrx_control_reg.u64);
-
- pcsx_miscx_ctl_reg.u64 =
- cvmx_read_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface));
- pcsx_miscx_ctl_reg.s.loopbck2 = enable_external;
- cvmx_write_csr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
- pcsx_miscx_ctl_reg.u64);
-
- __cvmx_helper_sgmii_hardware_init_link(interface, index);
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-sgmii.h b/drivers/staging/octeon/cvmx-helper-sgmii.h
deleted file mode 100644
index 19b48d6..0000000
--- a/drivers/staging/octeon/cvmx-helper-sgmii.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Functions for SGMII initialization, configuration,
- * and monitoring.
- *
- */
-#ifndef __CVMX_HELPER_SGMII_H__
-#define __CVMX_HELPER_SGMII_H__
-
-/**
- * Probe a SGMII interface and determine the number of ports
- * connected to it. The SGMII interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-extern int __cvmx_helper_sgmii_probe(int interface);
-
-/**
- * Bringup and enable a SGMII interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_sgmii_enable(int interface);
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-extern cvmx_helper_link_info_t __cvmx_helper_sgmii_link_get(int ipd_port);
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_sgmii_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info);
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-extern int __cvmx_helper_sgmii_configure_loopback(int ipd_port,
- int enable_internal,
- int enable_external);
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-spi.c b/drivers/staging/octeon/cvmx-helper-spi.c
deleted file mode 100644
index 8ba6c83..0000000
--- a/drivers/staging/octeon/cvmx-helper-spi.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-void __cvmx_interrupt_gmxx_enable(int interface);
-void __cvmx_interrupt_spxx_int_msk_enable(int index);
-void __cvmx_interrupt_stxx_int_msk_enable(int index);
-
-/*
- * Functions for SPI initialization, configuration,
- * and monitoring.
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-#include "cvmx-spi.h"
-#include "cvmx-helper.h"
-
-#include "cvmx-pip-defs.h"
-#include "cvmx-pko-defs.h"
-
-/*
- * CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI
- * initialization routines wait for SPI training. You can override the
- * value using executive-config.h if necessary.
- */
-#ifndef CVMX_HELPER_SPI_TIMEOUT
-#define CVMX_HELPER_SPI_TIMEOUT 10
-#endif
-
-/**
- * Probe a SPI interface and determine the number of ports
- * connected to it. The SPI interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-int __cvmx_helper_spi_probe(int interface)
-{
- int num_ports = 0;
-
- if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
- cvmx_spi4000_is_present(interface)) {
- num_ports = 10;
- } else {
- union cvmx_pko_reg_crc_enable enable;
- num_ports = 16;
- /*
- * Unlike the SPI4000, most SPI devices don't
- * automatically put on the L2 CRC. For everything
- * except for the SPI4000 have PKO append the L2 CRC
- * to the packet.
- */
- enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE);
- enable.s.enable |= 0xffff << (interface * 16);
- cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64);
- }
- __cvmx_helper_setup_gmx(interface, num_ports);
- return num_ports;
-}
-
-/**
- * Bringup and enable a SPI interface. After this call packet I/O
- * should be fully functional. This is called with IPD enabled but
- * PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_spi_enable(int interface)
-{
- /*
- * Normally the ethernet L2 CRC is checked and stripped in the
- * GMX block. When you are using SPI, this isn' the case and
- * IPD needs to check the L2 CRC.
- */
- int num_ports = cvmx_helper_ports_on_interface(interface);
- int ipd_port;
- for (ipd_port = interface * 16; ipd_port < interface * 16 + num_ports;
- ipd_port++) {
- union cvmx_pip_prt_cfgx port_config;
- port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
- port_config.s.crc_en = 1;
- cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64);
- }
-
- if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) {
- cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX,
- CVMX_HELPER_SPI_TIMEOUT, num_ports);
- if (cvmx_spi4000_is_present(interface))
- cvmx_spi4000_initialize(interface);
- }
- __cvmx_interrupt_spxx_int_msk_enable(interface);
- __cvmx_interrupt_stxx_int_msk_enable(interface);
- __cvmx_interrupt_gmxx_enable(interface);
- return 0;
-}
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port)
-{
- cvmx_helper_link_info_t result;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
- result.u64 = 0;
-
- if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) {
- /* The simulator gives you a simulated full duplex link */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 10000;
- } else if (cvmx_spi4000_is_present(interface)) {
- union cvmx_gmxx_rxx_rx_inbnd inband =
- cvmx_spi4000_check_speed(interface, index);
- result.s.link_up = inband.s.status;
- result.s.full_duplex = inband.s.duplex;
- switch (inband.s.speed) {
- case 0: /* 10 Mbps */
- result.s.speed = 10;
- break;
- case 1: /* 100 Mbps */
- result.s.speed = 100;
- break;
- case 2: /* 1 Gbps */
- result.s.speed = 1000;
- break;
- case 3: /* Illegal */
- result.s.speed = 0;
- result.s.link_up = 0;
- break;
- }
- } else {
- /* For generic SPI we can't determine the link, just return some
- sane results */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 10000;
- }
- return result;
-}
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
-{
- /* Nothing to do. If we have a SPI4000 then the setup was already performed
- by cvmx_spi4000_check_speed(). If not then there isn't any link
- info */
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-spi.h b/drivers/staging/octeon/cvmx-helper-spi.h
deleted file mode 100644
index 69bac03..0000000
--- a/drivers/staging/octeon/cvmx-helper-spi.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for SPI initialization, configuration,
- * and monitoring.
- */
-#ifndef __CVMX_HELPER_SPI_H__
-#define __CVMX_HELPER_SPI_H__
-
-/**
- * Probe a SPI interface and determine the number of ports
- * connected to it. The SPI interface should still be down after
- * this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-extern int __cvmx_helper_spi_probe(int interface);
-
-/**
- * Bringup and enable a SPI interface. After this call packet I/O
- * should be fully functional. This is called with IPD enabled but
- * PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_spi_enable(int interface);
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-extern cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port);
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_spi_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info);
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper-util.c b/drivers/staging/octeon/cvmx-helper-util.c
deleted file mode 100644
index 131182b..0000000
--- a/drivers/staging/octeon/cvmx-helper-util.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Small helper utilities.
- */
-#include <linux/kernel.h>
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-fpa.h"
-#include "cvmx-pip.h"
-#include "cvmx-pko.h"
-#include "cvmx-ipd.h"
-#include "cvmx-spi.h"
-
-#include "cvmx-helper.h"
-#include "cvmx-helper-util.h"
-
-#include <asm/octeon/cvmx-ipd-defs.h>
-
-/**
- * Convert a interface mode into a human readable string
- *
- * @mode: Mode to convert
- *
- * Returns String
- */
-const char *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t
- mode)
-{
- switch (mode) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- return "DISABLED";
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- return "RGMII";
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- return "GMII";
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- return "SPI";
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- return "PCIE";
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- return "XAUI";
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- return "SGMII";
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- return "PICMG";
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- return "NPI";
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- return "LOOP";
- }
- return "UNKNOWN";
-}
-
-/**
- * Debug routine to dump the packet structure to the console
- *
- * @work: Work queue entry containing the packet to dump
- * Returns
- */
-int cvmx_helper_dump_packet(cvmx_wqe_t *work)
-{
- uint64_t count;
- uint64_t remaining_bytes;
- union cvmx_buf_ptr buffer_ptr;
- uint64_t start_of_buffer;
- uint8_t *data_address;
- uint8_t *end_of_data;
-
- cvmx_dprintf("Packet Length: %u\n", work->len);
- cvmx_dprintf(" Input Port: %u\n", work->ipprt);
- cvmx_dprintf(" QoS: %u\n", work->qos);
- cvmx_dprintf(" Buffers: %u\n", work->word2.s.bufs);
-
- if (work->word2.s.bufs == 0) {
- union cvmx_ipd_wqe_fpa_queue wqe_pool;
- wqe_pool.u64 = cvmx_read_csr(CVMX_IPD_WQE_FPA_QUEUE);
- buffer_ptr.u64 = 0;
- buffer_ptr.s.pool = wqe_pool.s.wqe_pool;
- buffer_ptr.s.size = 128;
- buffer_ptr.s.addr = cvmx_ptr_to_phys(work->packet_data);
- if (likely(!work->word2.s.not_IP)) {
- union cvmx_pip_ip_offset pip_ip_offset;
- pip_ip_offset.u64 = cvmx_read_csr(CVMX_PIP_IP_OFFSET);
- buffer_ptr.s.addr +=
- (pip_ip_offset.s.offset << 3) -
- work->word2.s.ip_offset;
- buffer_ptr.s.addr += (work->word2.s.is_v6 ^ 1) << 2;
- } else {
- /*
- * WARNING: This code assumes that the packet
- * is not RAW. If it was, we would use
- * PIP_GBL_CFG[RAW_SHF] instead of
- * PIP_GBL_CFG[NIP_SHF].
- */
- union cvmx_pip_gbl_cfg pip_gbl_cfg;
- pip_gbl_cfg.u64 = cvmx_read_csr(CVMX_PIP_GBL_CFG);
- buffer_ptr.s.addr += pip_gbl_cfg.s.nip_shf;
- }
- } else
- buffer_ptr = work->packet_ptr;
- remaining_bytes = work->len;
-
- while (remaining_bytes) {
- start_of_buffer =
- ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
- cvmx_dprintf(" Buffer Start:%llx\n",
- (unsigned long long)start_of_buffer);
- cvmx_dprintf(" Buffer I : %u\n", buffer_ptr.s.i);
- cvmx_dprintf(" Buffer Back: %u\n", buffer_ptr.s.back);
- cvmx_dprintf(" Buffer Pool: %u\n", buffer_ptr.s.pool);
- cvmx_dprintf(" Buffer Data: %llx\n",
- (unsigned long long)buffer_ptr.s.addr);
- cvmx_dprintf(" Buffer Size: %u\n", buffer_ptr.s.size);
-
- cvmx_dprintf("\t\t");
- data_address = (uint8_t *) cvmx_phys_to_ptr(buffer_ptr.s.addr);
- end_of_data = data_address + buffer_ptr.s.size;
- count = 0;
- while (data_address < end_of_data) {
- if (remaining_bytes == 0)
- break;
- else
- remaining_bytes--;
- cvmx_dprintf("%02x", (unsigned int)*data_address);
- data_address++;
- if (remaining_bytes && (count == 7)) {
- cvmx_dprintf("\n\t\t");
- count = 0;
- } else
- count++;
- }
- cvmx_dprintf("\n");
-
- if (remaining_bytes)
- buffer_ptr = *(union cvmx_buf_ptr *)
- cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
- }
- return 0;
-}
-
-/**
- * Setup Random Early Drop on a specific input queue
- *
- * @queue: Input queue to setup RED on (0-7)
- * @pass_thresh:
- * Packets will begin slowly dropping when there are less than
- * this many packet buffers free in FPA 0.
- * @drop_thresh:
- * All incomming packets will be dropped when there are less
- * than this many free packet buffers in FPA 0.
- * Returns Zero on success. Negative on failure
- */
-int cvmx_helper_setup_red_queue(int queue, int pass_thresh, int drop_thresh)
-{
- union cvmx_ipd_qosx_red_marks red_marks;
- union cvmx_ipd_red_quex_param red_param;
-
- /* Set RED to begin dropping packets when there are pass_thresh buffers
- left. It will linearly drop more packets until reaching drop_thresh
- buffers */
- red_marks.u64 = 0;
- red_marks.s.drop = drop_thresh;
- red_marks.s.pass = pass_thresh;
- cvmx_write_csr(CVMX_IPD_QOSX_RED_MARKS(queue), red_marks.u64);
-
- /* Use the actual queue 0 counter, not the average */
- red_param.u64 = 0;
- red_param.s.prb_con =
- (255ul << 24) / (red_marks.s.pass - red_marks.s.drop);
- red_param.s.avg_con = 1;
- red_param.s.new_con = 255;
- red_param.s.use_pcnt = 1;
- cvmx_write_csr(CVMX_IPD_RED_QUEX_PARAM(queue), red_param.u64);
- return 0;
-}
-
-/**
- * Setup Random Early Drop to automatically begin dropping packets.
- *
- * @pass_thresh:
- * Packets will begin slowly dropping when there are less than
- * this many packet buffers free in FPA 0.
- * @drop_thresh:
- * All incomming packets will be dropped when there are less
- * than this many free packet buffers in FPA 0.
- * Returns Zero on success. Negative on failure
- */
-int cvmx_helper_setup_red(int pass_thresh, int drop_thresh)
-{
- union cvmx_ipd_portx_bp_page_cnt page_cnt;
- union cvmx_ipd_bp_prt_red_end ipd_bp_prt_red_end;
- union cvmx_ipd_red_port_enable red_port_enable;
- int queue;
- int interface;
- int port;
-
- /* Disable backpressure based on queued buffers. It needs SW support */
- page_cnt.u64 = 0;
- page_cnt.s.bp_enb = 0;
- page_cnt.s.page_cnt = 100;
- for (interface = 0; interface < 2; interface++) {
- for (port = cvmx_helper_get_first_ipd_port(interface);
- port < cvmx_helper_get_last_ipd_port(interface); port++)
- cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port),
- page_cnt.u64);
- }
-
- for (queue = 0; queue < 8; queue++)
- cvmx_helper_setup_red_queue(queue, pass_thresh, drop_thresh);
-
- /* Shutoff the dropping based on the per port page count. SW isn't
- decrementing it right now */
- ipd_bp_prt_red_end.u64 = 0;
- ipd_bp_prt_red_end.s.prt_enb = 0;
- cvmx_write_csr(CVMX_IPD_BP_PRT_RED_END, ipd_bp_prt_red_end.u64);
-
- red_port_enable.u64 = 0;
- red_port_enable.s.prt_enb = 0xfffffffffull;
- red_port_enable.s.avg_dly = 10000;
- red_port_enable.s.prb_dly = 10000;
- cvmx_write_csr(CVMX_IPD_RED_PORT_ENABLE, red_port_enable.u64);
-
- return 0;
-}
-
-/**
- * Setup the common GMX settings that determine the number of
- * ports. These setting apply to almost all configurations of all
- * chips.
- *
- * @interface: Interface to configure
- * @num_ports: Number of ports on the interface
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_setup_gmx(int interface, int num_ports)
-{
- union cvmx_gmxx_tx_prts gmx_tx_prts;
- union cvmx_gmxx_rx_prts gmx_rx_prts;
- union cvmx_pko_reg_gmx_port_mode pko_mode;
- union cvmx_gmxx_txx_thresh gmx_tx_thresh;
- int index;
-
- /* Tell GMX the number of TX ports on this interface */
- gmx_tx_prts.u64 = cvmx_read_csr(CVMX_GMXX_TX_PRTS(interface));
- gmx_tx_prts.s.prts = num_ports;
- cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), gmx_tx_prts.u64);
-
- /* Tell GMX the number of RX ports on this interface. This only
- ** applies to *GMII and XAUI ports */
- if (cvmx_helper_interface_get_mode(interface) ==
- CVMX_HELPER_INTERFACE_MODE_RGMII
- || cvmx_helper_interface_get_mode(interface) ==
- CVMX_HELPER_INTERFACE_MODE_SGMII
- || cvmx_helper_interface_get_mode(interface) ==
- CVMX_HELPER_INTERFACE_MODE_GMII
- || cvmx_helper_interface_get_mode(interface) ==
- CVMX_HELPER_INTERFACE_MODE_XAUI) {
- if (num_ports > 4) {
- cvmx_dprintf("__cvmx_helper_setup_gmx: Illegal "
- "num_ports\n");
- return -1;
- }
-
- gmx_rx_prts.u64 = cvmx_read_csr(CVMX_GMXX_RX_PRTS(interface));
- gmx_rx_prts.s.prts = num_ports;
- cvmx_write_csr(CVMX_GMXX_RX_PRTS(interface), gmx_rx_prts.u64);
- }
-
- /* Skip setting CVMX_PKO_REG_GMX_PORT_MODE on 30XX, 31XX, and 50XX */
- if (!OCTEON_IS_MODEL(OCTEON_CN30XX) && !OCTEON_IS_MODEL(OCTEON_CN31XX)
- && !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- /* Tell PKO the number of ports on this interface */
- pko_mode.u64 = cvmx_read_csr(CVMX_PKO_REG_GMX_PORT_MODE);
- if (interface == 0) {
- if (num_ports == 1)
- pko_mode.s.mode0 = 4;
- else if (num_ports == 2)
- pko_mode.s.mode0 = 3;
- else if (num_ports <= 4)
- pko_mode.s.mode0 = 2;
- else if (num_ports <= 8)
- pko_mode.s.mode0 = 1;
- else
- pko_mode.s.mode0 = 0;
- } else {
- if (num_ports == 1)
- pko_mode.s.mode1 = 4;
- else if (num_ports == 2)
- pko_mode.s.mode1 = 3;
- else if (num_ports <= 4)
- pko_mode.s.mode1 = 2;
- else if (num_ports <= 8)
- pko_mode.s.mode1 = 1;
- else
- pko_mode.s.mode1 = 0;
- }
- cvmx_write_csr(CVMX_PKO_REG_GMX_PORT_MODE, pko_mode.u64);
- }
-
- /*
- * Set GMX to buffer as much data as possible before starting
- * transmit. This reduces the chances that we have a TX under
- * run due to memory contention. Any packet that fits entirely
- * in the GMX FIFO can never have an under run regardless of
- * memory load.
- */
- gmx_tx_thresh.u64 = cvmx_read_csr(CVMX_GMXX_TXX_THRESH(0, interface));
- if (OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN31XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- /* These chips have a fixed max threshold of 0x40 */
- gmx_tx_thresh.s.cnt = 0x40;
- } else {
- /* Choose the max value for the number of ports */
- if (num_ports <= 1)
- gmx_tx_thresh.s.cnt = 0x100 / 1;
- else if (num_ports == 2)
- gmx_tx_thresh.s.cnt = 0x100 / 2;
- else
- gmx_tx_thresh.s.cnt = 0x100 / 4;
- }
- /*
- * SPI and XAUI can have lots of ports but the GMX hardware
- * only ever has a max of 4.
- */
- if (num_ports > 4)
- num_ports = 4;
- for (index = 0; index < num_ports; index++)
- cvmx_write_csr(CVMX_GMXX_TXX_THRESH(index, interface),
- gmx_tx_thresh.u64);
-
- return 0;
-}
-
-/**
- * Returns the IPD/PKO port number for a port on the given
- * interface.
- *
- * @interface: Interface to use
- * @port: Port on the interface
- *
- * Returns IPD/PKO port number
- */
-int cvmx_helper_get_ipd_port(int interface, int port)
-{
- switch (interface) {
- case 0:
- return port;
- case 1:
- return port + 16;
- case 2:
- return port + 32;
- case 3:
- return port + 36;
- }
- return -1;
-}
-
-/**
- * Returns the interface number for an IPD/PKO port number.
- *
- * @ipd_port: IPD/PKO port number
- *
- * Returns Interface number
- */
-int cvmx_helper_get_interface_num(int ipd_port)
-{
- if (ipd_port < 16)
- return 0;
- else if (ipd_port < 32)
- return 1;
- else if (ipd_port < 36)
- return 2;
- else if (ipd_port < 40)
- return 3;
- else
- cvmx_dprintf("cvmx_helper_get_interface_num: Illegal IPD "
- "port number\n");
-
- return -1;
-}
-
-/**
- * Returns the interface index number for an IPD/PKO port
- * number.
- *
- * @ipd_port: IPD/PKO port number
- *
- * Returns Interface index number
- */
-int cvmx_helper_get_interface_index_num(int ipd_port)
-{
- if (ipd_port < 32)
- return ipd_port & 15;
- else if (ipd_port < 36)
- return ipd_port & 3;
- else if (ipd_port < 40)
- return ipd_port & 3;
- else
- cvmx_dprintf("cvmx_helper_get_interface_index_num: "
- "Illegal IPD port number\n");
-
- return -1;
-}
diff --git a/drivers/staging/octeon/cvmx-helper-util.h b/drivers/staging/octeon/cvmx-helper-util.h
deleted file mode 100644
index 6a6e52f..0000000
--- a/drivers/staging/octeon/cvmx-helper-util.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Small helper utilities.
- *
- */
-
-#ifndef __CVMX_HELPER_UTIL_H__
-#define __CVMX_HELPER_UTIL_H__
-
-/**
- * Convert a interface mode into a human readable string
- *
- * @mode: Mode to convert
- *
- * Returns String
- */
-extern const char
- *cvmx_helper_interface_mode_to_string(cvmx_helper_interface_mode_t mode);
-
-/**
- * Debug routine to dump the packet structure to the console
- *
- * @work: Work queue entry containing the packet to dump
- * Returns
- */
-extern int cvmx_helper_dump_packet(cvmx_wqe_t *work);
-
-/**
- * Setup Random Early Drop on a specific input queue
- *
- * @queue: Input queue to setup RED on (0-7)
- * @pass_thresh:
- * Packets will begin slowly dropping when there are less than
- * this many packet buffers free in FPA 0.
- * @drop_thresh:
- * All incomming packets will be dropped when there are less
- * than this many free packet buffers in FPA 0.
- * Returns Zero on success. Negative on failure
- */
-extern int cvmx_helper_setup_red_queue(int queue, int pass_thresh,
- int drop_thresh);
-
-/**
- * Setup Random Early Drop to automatically begin dropping packets.
- *
- * @pass_thresh:
- * Packets will begin slowly dropping when there are less than
- * this many packet buffers free in FPA 0.
- * @drop_thresh:
- * All incomming packets will be dropped when there are less
- * than this many free packet buffers in FPA 0.
- * Returns Zero on success. Negative on failure
- */
-extern int cvmx_helper_setup_red(int pass_thresh, int drop_thresh);
-
-/**
- * Get the version of the CVMX libraries.
- *
- * Returns Version string. Note this buffer is allocated statically
- * and will be shared by all callers.
- */
-extern const char *cvmx_helper_get_version(void);
-
-/**
- * Setup the common GMX settings that determine the number of
- * ports. These setting apply to almost all configurations of all
- * chips.
- *
- * @interface: Interface to configure
- * @num_ports: Number of ports on the interface
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_setup_gmx(int interface, int num_ports);
-
-/**
- * Returns the IPD/PKO port number for a port on the given
- * interface.
- *
- * @interface: Interface to use
- * @port: Port on the interface
- *
- * Returns IPD/PKO port number
- */
-extern int cvmx_helper_get_ipd_port(int interface, int port);
-
-/**
- * Returns the IPD/PKO port number for the first port on the given
- * interface.
- *
- * @interface: Interface to use
- *
- * Returns IPD/PKO port number
- */
-static inline int cvmx_helper_get_first_ipd_port(int interface)
-{
- return cvmx_helper_get_ipd_port(interface, 0);
-}
-
-/**
- * Returns the IPD/PKO port number for the last port on the given
- * interface.
- *
- * @interface: Interface to use
- *
- * Returns IPD/PKO port number
- */
-static inline int cvmx_helper_get_last_ipd_port(int interface)
-{
- extern int cvmx_helper_ports_on_interface(int interface);
-
- return cvmx_helper_get_first_ipd_port(interface) +
- cvmx_helper_ports_on_interface(interface) - 1;
-}
-
-/**
- * Free the packet buffers contained in a work queue entry.
- * The work queue entry is not freed.
- *
- * @work: Work queue entry with packet to free
- */
-static inline void cvmx_helper_free_packet_data(cvmx_wqe_t *work)
-{
- uint64_t number_buffers;
- union cvmx_buf_ptr buffer_ptr;
- union cvmx_buf_ptr next_buffer_ptr;
- uint64_t start_of_buffer;
-
- number_buffers = work->word2.s.bufs;
- if (number_buffers == 0)
- return;
- buffer_ptr = work->packet_ptr;
-
- /*
- * Since the number of buffers is not zero, we know this is
- * not a dynamic short packet. We need to check if it is a
- * packet received with IPD_CTL_STATUS[NO_WPTR]. If this is
- * true, we need to free all buffers except for the first
- * one. The caller doesn't expect their WQE pointer to be
- * freed
- */
- start_of_buffer = ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
- if (cvmx_ptr_to_phys(work) == start_of_buffer) {
- next_buffer_ptr =
- *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
- buffer_ptr = next_buffer_ptr;
- number_buffers--;
- }
-
- while (number_buffers--) {
- /*
- * Remember the back pointer is in cache lines, not
- * 64bit words
- */
- start_of_buffer =
- ((buffer_ptr.s.addr >> 7) - buffer_ptr.s.back) << 7;
- /*
- * Read pointer to next buffer before we free the
- * current buffer.
- */
- next_buffer_ptr =
- *(union cvmx_buf_ptr *) cvmx_phys_to_ptr(buffer_ptr.s.addr - 8);
- cvmx_fpa_free(cvmx_phys_to_ptr(start_of_buffer),
- buffer_ptr.s.pool, 0);
- buffer_ptr = next_buffer_ptr;
- }
-}
-
-/**
- * Returns the interface number for an IPD/PKO port number.
- *
- * @ipd_port: IPD/PKO port number
- *
- * Returns Interface number
- */
-extern int cvmx_helper_get_interface_num(int ipd_port);
-
-/**
- * Returns the interface index number for an IPD/PKO port
- * number.
- *
- * @ipd_port: IPD/PKO port number
- *
- * Returns Interface index number
- */
-extern int cvmx_helper_get_interface_index_num(int ipd_port);
-
-#endif /* __CVMX_HELPER_H__ */
diff --git a/drivers/staging/octeon/cvmx-helper-xaui.c b/drivers/staging/octeon/cvmx-helper-xaui.c
deleted file mode 100644
index a11e676..0000000
--- a/drivers/staging/octeon/cvmx-helper-xaui.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Functions for XAUI initialization, configuration,
- * and monitoring.
- *
- */
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-helper.h"
-
-#include "cvmx-pko-defs.h"
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-pcsxx-defs.h"
-
-void __cvmx_interrupt_gmxx_enable(int interface);
-void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block);
-void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index);
-/**
- * Probe a XAUI interface and determine the number of ports
- * connected to it. The XAUI interface should still be down
- * after this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-int __cvmx_helper_xaui_probe(int interface)
-{
- int i;
- union cvmx_gmxx_hg2_control gmx_hg2_control;
- union cvmx_gmxx_inf_mode mode;
-
- /*
- * Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the
- * interface needs to be enabled before IPD otherwise per port
- * backpressure may not work properly.
- */
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
- mode.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64);
-
- __cvmx_helper_setup_gmx(interface, 1);
-
- /*
- * Setup PKO to support 16 ports for HiGig2 virtual
- * ports. We're pointing all of the PKO packet ports for this
- * interface to the XAUI. This allows us to use HiGig2
- * backpressure per port.
- */
- for (i = 0; i < 16; i++) {
- union cvmx_pko_mem_port_ptrs pko_mem_port_ptrs;
- pko_mem_port_ptrs.u64 = 0;
- /*
- * We set each PKO port to have equal priority in a
- * round robin fashion.
- */
- pko_mem_port_ptrs.s.static_p = 0;
- pko_mem_port_ptrs.s.qos_mask = 0xff;
- /* All PKO ports map to the same XAUI hardware port */
- pko_mem_port_ptrs.s.eid = interface * 4;
- pko_mem_port_ptrs.s.pid = interface * 16 + i;
- cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64);
- }
-
- /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */
- gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface));
- if (gmx_hg2_control.s.hg2tx_en)
- return 16;
- else
- return 1;
-}
-
-/**
- * Bringup and enable a XAUI interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_xaui_enable(int interface)
-{
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- union cvmx_pcsxx_control1_reg xauiCtl;
- union cvmx_pcsxx_misc_ctl_reg xauiMiscCtl;
- union cvmx_gmxx_tx_xaui_ctl gmxXauiTxCtl;
- union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
- union cvmx_gmxx_tx_int_en gmx_tx_int_en;
- union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
-
- /* (1) Interface has already been enabled. */
-
- /* (2) Disable GMX. */
- xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface));
- xauiMiscCtl.s.gmxeno = 1;
- cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
-
- /* (3) Disable GMX and PCSX interrupts. */
- gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0, interface));
- cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0);
- gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface));
- cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
- pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface));
- cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
-
- /* (4) Bring up the PCSX and GMX reconciliation layer. */
- /* (4)a Set polarity and lane swapping. */
- /* (4)b */
- gmxXauiTxCtl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
- /* Enable better IFG packing and improves performance */
- gmxXauiTxCtl.s.dic_en = 1;
- gmxXauiTxCtl.s.uni_en = 0;
- cvmx_write_csr(CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64);
-
- /* (4)c Aply reset sequence */
- xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
- xauiCtl.s.lo_pwr = 0;
- xauiCtl.s.reset = 1;
- cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
-
- /* Wait for PCS to come out of reset */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSXX_CONTROL1_REG(interface), union cvmx_pcsxx_control1_reg,
- reset, ==, 0, 10000))
- return -1;
- /* Wait for PCS to be aligned */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSXX_10GBX_STATUS_REG(interface),
- union cvmx_pcsxx_10gbx_status_reg, alignd, ==, 1, 10000))
- return -1;
- /* Wait for RX to be ready */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_GMXX_RX_XAUI_CTL(interface), union cvmx_gmxx_rx_xaui_ctl,
- status, ==, 0, 10000))
- return -1;
-
- /* (6) Configure GMX */
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
- gmx_cfg.s.en = 0;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
-
- /* Wait for GMX RX to be idle */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg,
- rx_idle, ==, 1, 10000))
- return -1;
- /* Wait for GMX TX to be idle */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg,
- tx_idle, ==, 1, 10000))
- return -1;
-
- /* GMX configure */
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
- gmx_cfg.s.speed = 1;
- gmx_cfg.s.speed_msb = 0;
- gmx_cfg.s.slottime = 1;
- cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1);
- cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512);
- cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192);
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
-
- /* (7) Clear out any error state */
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0, interface),
- cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0, interface)));
- cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface),
- cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface)));
- cvmx_write_csr(CVMX_PCSXX_INT_REG(interface),
- cvmx_read_csr(CVMX_PCSXX_INT_REG(interface)));
-
- /* Wait for receive link */
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSXX_STATUS1_REG(interface), union cvmx_pcsxx_status1_reg,
- rcv_lnk, ==, 1, 10000))
- return -1;
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg,
- xmtflt, ==, 0, 10000))
- return -1;
- if (CVMX_WAIT_FOR_FIELD64
- (CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg,
- rcvflt, ==, 0, 10000))
- return -1;
-
- cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), gmx_rx_int_en.u64);
- cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
- cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64);
-
- cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0));
-
- /* (8) Enable packet reception */
- xauiMiscCtl.s.gmxeno = 0;
- cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
-
- gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
-
- __cvmx_interrupt_pcsx_intx_en_reg_enable(0, interface);
- __cvmx_interrupt_pcsx_intx_en_reg_enable(1, interface);
- __cvmx_interrupt_pcsx_intx_en_reg_enable(2, interface);
- __cvmx_interrupt_pcsx_intx_en_reg_enable(3, interface);
- __cvmx_interrupt_pcsxx_int_en_reg_enable(interface);
- __cvmx_interrupt_gmxx_enable(interface);
-
- return 0;
-}
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl;
- union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl;
- union cvmx_pcsxx_status1_reg pcsxx_status1_reg;
- cvmx_helper_link_info_t result;
-
- gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
- gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
- pcsxx_status1_reg.u64 =
- cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface));
- result.u64 = 0;
-
- /* Only return a link if both RX and TX are happy */
- if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) &&
- (pcsxx_status1_reg.s.rcv_lnk == 1)) {
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 10000;
- } else {
- /* Disable GMX and PCSX interrupts. */
- cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0);
- cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
- cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
- }
- return result;
-}
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- union cvmx_gmxx_tx_xaui_ctl gmxx_tx_xaui_ctl;
- union cvmx_gmxx_rx_xaui_ctl gmxx_rx_xaui_ctl;
-
- gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
- gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface));
-
- /* If the link shouldn't be up, then just return */
- if (!link_info.s.link_up)
- return 0;
-
- /* Do nothing if both RX and TX are happy */
- if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0))
- return 0;
-
- /* Bring the link up */
- return __cvmx_helper_xaui_enable(interface);
-}
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-extern int __cvmx_helper_xaui_configure_loopback(int ipd_port,
- int enable_internal,
- int enable_external)
-{
- int interface = cvmx_helper_get_interface_num(ipd_port);
- union cvmx_pcsxx_control1_reg pcsxx_control1_reg;
- union cvmx_gmxx_xaui_ext_loopback gmxx_xaui_ext_loopback;
-
- /* Set the internal loop */
- pcsxx_control1_reg.u64 =
- cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
- pcsxx_control1_reg.s.loopbck1 = enable_internal;
- cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface),
- pcsxx_control1_reg.u64);
-
- /* Set the external loop */
- gmxx_xaui_ext_loopback.u64 =
- cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface));
- gmxx_xaui_ext_loopback.s.en = enable_external;
- cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface),
- gmxx_xaui_ext_loopback.u64);
-
- /* Take the link through a reset */
- return __cvmx_helper_xaui_enable(interface);
-}
diff --git a/drivers/staging/octeon/cvmx-helper-xaui.h b/drivers/staging/octeon/cvmx-helper-xaui.h
deleted file mode 100644
index 4b4db2f..0000000
--- a/drivers/staging/octeon/cvmx-helper-xaui.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * @file
- *
- * Functions for XAUI initialization, configuration,
- * and monitoring.
- *
- */
-#ifndef __CVMX_HELPER_XAUI_H__
-#define __CVMX_HELPER_XAUI_H__
-
-/**
- * Probe a XAUI interface and determine the number of ports
- * connected to it. The XAUI interface should still be down
- * after this call.
- *
- * @interface: Interface to probe
- *
- * Returns Number of ports on the interface. Zero to disable.
- */
-extern int __cvmx_helper_xaui_probe(int interface);
-
-/**
- * Bringup and enable a XAUI interface. After this call packet
- * I/O should be fully functional. This is called with IPD
- * enabled but PKO disabled.
- *
- * @interface: Interface to bring up
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_xaui_enable(int interface);
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-extern cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port);
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-extern int __cvmx_helper_xaui_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info);
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-extern int __cvmx_helper_xaui_configure_loopback(int ipd_port,
- int enable_internal,
- int enable_external);
-#endif
diff --git a/drivers/staging/octeon/cvmx-helper.c b/drivers/staging/octeon/cvmx-helper.c
deleted file mode 100644
index e9c5c83..0000000
--- a/drivers/staging/octeon/cvmx-helper.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Helper functions for common, but complicated tasks.
- *
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-fpa.h"
-#include "cvmx-pip.h"
-#include "cvmx-pko.h"
-#include "cvmx-ipd.h"
-#include "cvmx-spi.h"
-#include "cvmx-helper.h"
-#include "cvmx-helper-board.h"
-
-#include "cvmx-pip-defs.h"
-#include "cvmx-smix-defs.h"
-#include "cvmx-asxx-defs.h"
-
-/**
- * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
- * priorities[16]) is a function pointer. It is meant to allow
- * customization of the PKO queue priorities based on the port
- * number. Users should set this pointer to a function before
- * calling any cvmx-helper operations.
- */
-void (*cvmx_override_pko_queue_priority) (int pko_port,
- uint64_t priorities[16]);
-
-/**
- * cvmx_override_ipd_port_setup(int ipd_port) is a function
- * pointer. It is meant to allow customization of the IPD port
- * setup before packet input/output comes online. It is called
- * after cvmx-helper does the default IPD configuration, but
- * before IPD is enabled. Users should set this pointer to a
- * function before calling any cvmx-helper operations.
- */
-void (*cvmx_override_ipd_port_setup) (int ipd_port);
-
-/* Port count per interface */
-static int interface_port_count[4] = { 0, 0, 0, 0 };
-
-/* Port last configured link info index by IPD/PKO port */
-static cvmx_helper_link_info_t
- port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
-
-/**
- * Return the number of interfaces the chip has. Each interface
- * may have multiple ports. Most chips support two interfaces,
- * but the CNX0XX and CNX1XX are exceptions. These only support
- * one interface.
- *
- * Returns Number of interfaces on chip
- */
-int cvmx_helper_get_number_of_interfaces(void)
-{
- if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
- return 4;
- else
- return 3;
-}
-
-/**
- * Return the number of ports on an interface. Depending on the
- * chip and configuration, this can be 1-16. A value of 0
- * specifies that the interface doesn't exist or isn't usable.
- *
- * @interface: Interface to get the port count for
- *
- * Returns Number of ports on interface. Can be Zero.
- */
-int cvmx_helper_ports_on_interface(int interface)
-{
- return interface_port_count[interface];
-}
-
-/**
- * Get the operating mode of an interface. Depending on the Octeon
- * chip and configuration, this function returns an enumeration
- * of the type of packet I/O supported by an interface.
- *
- * @interface: Interface to probe
- *
- * Returns Mode of the interface. Unknown or unsupported interfaces return
- * DISABLED.
- */
-cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
-{
- union cvmx_gmxx_inf_mode mode;
- if (interface == 2)
- return CVMX_HELPER_INTERFACE_MODE_NPI;
-
- if (interface == 3) {
- if (OCTEON_IS_MODEL(OCTEON_CN56XX)
- || OCTEON_IS_MODEL(OCTEON_CN52XX))
- return CVMX_HELPER_INTERFACE_MODE_LOOP;
- else
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
- }
-
- if (interface == 0
- && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
- && cvmx_sysinfo_get()->board_rev_major == 1) {
- /*
- * Lie about interface type of CN3005 board. This
- * board has a switch on port 1 like the other
- * evaluation boards, but it is connected over RGMII
- * instead of GMII. Report GMII mode so that the
- * speed is forced to 1 Gbit full duplex. Other than
- * some initial configuration (which does not use the
- * output of this function) there is no difference in
- * setup between GMII and RGMII modes.
- */
- return CVMX_HELPER_INTERFACE_MODE_GMII;
- }
-
- /* Interface 1 is always disabled on CN31XX and CN30XX */
- if ((interface == 1)
- && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
- || OCTEON_IS_MODEL(OCTEON_CN50XX)
- || OCTEON_IS_MODEL(OCTEON_CN52XX)))
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
-
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- switch (mode.cn56xx.mode) {
- case 0:
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
- case 1:
- return CVMX_HELPER_INTERFACE_MODE_XAUI;
- case 2:
- return CVMX_HELPER_INTERFACE_MODE_SGMII;
- case 3:
- return CVMX_HELPER_INTERFACE_MODE_PICMG;
- default:
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
- }
- } else {
- if (!mode.s.en)
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
-
- if (mode.s.type) {
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX))
- return CVMX_HELPER_INTERFACE_MODE_SPI;
- else
- return CVMX_HELPER_INTERFACE_MODE_GMII;
- } else
- return CVMX_HELPER_INTERFACE_MODE_RGMII;
- }
-}
-
-/**
- * Configure the IPD/PIP tagging and QoS options for a specific
- * port. This function determines the POW work queue entry
- * contents for a port. The setup performed here is controlled by
- * the defines in executive-config.h.
- *
- * @ipd_port: Port to configure. This follows the IPD numbering, not the
- * per interface numbering
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_port_setup_ipd(int ipd_port)
-{
- union cvmx_pip_prt_cfgx port_config;
- union cvmx_pip_prt_tagx tag_config;
-
- port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
- tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
-
- /* Have each port go to a different POW queue */
- port_config.s.qos = ipd_port & 0x7;
-
- /* Process the headers and place the IP header in the work queue */
- port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
-
- tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
- tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
- tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
- tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
- tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
- tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
- tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
- tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
- tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
- tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
- tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
- tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
- /* Put all packets in group 0. Other groups can be used by the app */
- tag_config.s.grp = 0;
-
- cvmx_pip_config_port(ipd_port, port_config, tag_config);
-
- /* Give the user a chance to override our setting for each port */
- if (cvmx_override_ipd_port_setup)
- cvmx_override_ipd_port_setup(ipd_port);
-
- return 0;
-}
-
-/**
- * This function probes an interface to determine the actual
- * number of hardware ports connected to it. It doesn't setup the
- * ports or enable them. The main goal here is to set the global
- * interface_port_count[interface] correctly. Hardware setup of the
- * ports will be performed later.
- *
- * @interface: Interface to probe
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_helper_interface_probe(int interface)
-{
- /* At this stage in the game we don't want packets to be moving yet.
- The following probe calls should perform hardware setup
- needed to determine port counts. Receive must still be disabled */
- switch (cvmx_helper_interface_get_mode(interface)) {
- /* These types don't support ports to IPD/PKO */
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- interface_port_count[interface] = 0;
- break;
- /* XAUI is a single high speed port */
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- interface_port_count[interface] =
- __cvmx_helper_xaui_probe(interface);
- break;
- /*
- * RGMII/GMII/MII are all treated about the same. Most
- * functions refer to these ports as RGMII.
- */
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- interface_port_count[interface] =
- __cvmx_helper_rgmii_probe(interface);
- break;
- /*
- * SPI4 can have 1-16 ports depending on the device at
- * the other end.
- */
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- interface_port_count[interface] =
- __cvmx_helper_spi_probe(interface);
- break;
- /*
- * SGMII can have 1-4 ports depending on how many are
- * hooked up.
- */
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- interface_port_count[interface] =
- __cvmx_helper_sgmii_probe(interface);
- break;
- /* PCI target Network Packet Interface */
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- interface_port_count[interface] =
- __cvmx_helper_npi_probe(interface);
- break;
- /*
- * Special loopback only ports. These are not the same
- * as other ports in loopback mode.
- */
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- interface_port_count[interface] =
- __cvmx_helper_loop_probe(interface);
- break;
- }
-
- interface_port_count[interface] =
- __cvmx_helper_board_interface_probe(interface,
- interface_port_count
- [interface]);
-
- /* Make sure all global variables propagate to other cores */
- CVMX_SYNCWS;
-
- return 0;
-}
-
-/**
- * Setup the IPD/PIP for the ports on an interface. Packet
- * classification and tagging are set for every port on the
- * interface. The number of ports on the interface must already
- * have been probed.
- *
- * @interface: Interface to setup IPD/PIP for
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_interface_setup_ipd(int interface)
-{
- int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
- int num_ports = interface_port_count[interface];
-
- while (num_ports--) {
- __cvmx_helper_port_setup_ipd(ipd_port);
- ipd_port++;
- }
- return 0;
-}
-
-/**
- * Setup global setting for IPD/PIP not related to a specific
- * interface or port. This must be called before IPD is enabled.
- *
- * Returns Zero on success, negative on failure.
- */
-static int __cvmx_helper_global_setup_ipd(void)
-{
- /* Setup the global packet input options */
- cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
- CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
- CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
- /* The +8 is to account for the next ptr */
- (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
- /* The +8 is to account for the next ptr */
- (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
- CVMX_FPA_WQE_POOL,
- CVMX_IPD_OPC_MODE_STT,
- CVMX_HELPER_ENABLE_BACK_PRESSURE);
- return 0;
-}
-
-/**
- * Setup the PKO for the ports on an interface. The number of
- * queues per port and the priority of each PKO output queue
- * is set here. PKO must be disabled when this function is called.
- *
- * @interface: Interface to setup PKO for
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_interface_setup_pko(int interface)
-{
- /*
- * Each packet output queue has an associated priority. The
- * higher the priority, the more often it can send a packet. A
- * priority of 8 means it can send in all 8 rounds of
- * contention. We're going to make each queue one less than
- * the last. The vector of priorities has been extended to
- * support CN5xxx CPUs, where up to 16 queues can be
- * associated to a port. To keep backward compatibility we
- * don't change the initial 8 priorities and replicate them in
- * the second half. With per-core PKO queues (PKO lockless
- * operation) all queues have the same priority.
- */
- uint64_t priorities[16] =
- { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
-
- /*
- * Setup the IPD/PIP and PKO for the ports discovered
- * above. Here packet classification, tagging and output
- * priorities are set.
- */
- int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
- int num_ports = interface_port_count[interface];
- while (num_ports--) {
- /*
- * Give the user a chance to override the per queue
- * priorities.
- */
- if (cvmx_override_pko_queue_priority)
- cvmx_override_pko_queue_priority(ipd_port, priorities);
-
- cvmx_pko_config_port(ipd_port,
- cvmx_pko_get_base_queue_per_core(ipd_port,
- 0),
- cvmx_pko_get_num_queues(ipd_port),
- priorities);
- ipd_port++;
- }
- return 0;
-}
-
-/**
- * Setup global setting for PKO not related to a specific
- * interface or port. This must be called before PKO is enabled.
- *
- * Returns Zero on success, negative on failure.
- */
-static int __cvmx_helper_global_setup_pko(void)
-{
- /*
- * Disable tagwait FAU timeout. This needs to be done before
- * anyone might start packet output using tags.
- */
- union cvmx_iob_fau_timeout fau_to;
- fau_to.u64 = 0;
- fau_to.s.tout_val = 0xfff;
- fau_to.s.tout_enb = 0;
- cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
- return 0;
-}
-
-/**
- * Setup global backpressure setting.
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_global_setup_backpressure(void)
-{
-#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
- /* Disable backpressure if configured to do so */
- /* Disable backpressure (pause frame) generation */
- int num_interfaces = cvmx_helper_get_number_of_interfaces();
- int interface;
- for (interface = 0; interface < num_interfaces; interface++) {
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- break;
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- cvmx_gmx_set_backpressure_override(interface, 0xf);
- break;
- }
- }
-#endif
-
- return 0;
-}
-
-/**
- * Enable packet input/output from the hardware. This function is
- * called after all internal setup is complete and IPD is enabled.
- * After this function completes, packets will be accepted from the
- * hardware ports. PKO should still be disabled to make sure packets
- * aren't sent out partially setup hardware.
- *
- * @interface: Interface to enable
- *
- * Returns Zero on success, negative on failure
- */
-static int __cvmx_helper_packet_hardware_enable(int interface)
-{
- int result = 0;
- switch (cvmx_helper_interface_get_mode(interface)) {
- /* These types don't support ports to IPD/PKO */
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- /* Nothing to do */
- break;
- /* XAUI is a single high speed port */
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- result = __cvmx_helper_xaui_enable(interface);
- break;
- /*
- * RGMII/GMII/MII are all treated about the same. Most
- * functions refer to these ports as RGMII
- */
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- result = __cvmx_helper_rgmii_enable(interface);
- break;
- /*
- * SPI4 can have 1-16 ports depending on the device at
- * the other end
- */
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- result = __cvmx_helper_spi_enable(interface);
- break;
- /*
- * SGMII can have 1-4 ports depending on how many are
- * hooked up
- */
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- result = __cvmx_helper_sgmii_enable(interface);
- break;
- /* PCI target Network Packet Interface */
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- result = __cvmx_helper_npi_enable(interface);
- break;
- /*
- * Special loopback only ports. These are not the same
- * as other ports in loopback mode
- */
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- result = __cvmx_helper_loop_enable(interface);
- break;
- }
- result |= __cvmx_helper_board_hardware_enable(interface);
- return result;
-}
-
-/**
- * Function to adjust internal IPD pointer alignments
- *
- * Returns 0 on success
- * !0 on failure
- */
-int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
-{
-#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
- (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
-#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
- (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
-#define FIX_IPD_OUTPORT 0
- /* Ports 0-15 are interface 0, 16-31 are interface 1 */
-#define INTERFACE(port) (port >> 4)
-#define INDEX(port) (port & 0xf)
- uint64_t *p64;
- cvmx_pko_command_word0_t pko_command;
- union cvmx_buf_ptr g_buffer, pkt_buffer;
- cvmx_wqe_t *work;
- int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- int retry_cnt;
- int retry_loop_cnt;
- int mtu;
- int i;
- cvmx_helper_link_info_t link_info;
-
- /* Save values for restore at end */
- uint64_t prtx_cfg =
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
- uint64_t tx_ptr_en =
- cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
- uint64_t rx_ptr_en =
- cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
- uint64_t rxx_jabber =
- cvmx_read_csr(CVMX_GMXX_RXX_JABBER
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
- uint64_t frame_max =
- cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
-
- /* Configure port to gig FDX as required for loopback mode */
- cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
-
- /*
- * Disable reception on all ports so if traffic is present it
- * will not interfere.
- */
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
-
- cvmx_wait(100000000ull);
-
- for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
- retry_cnt = 100000;
- wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
- pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
- wqe_pcnt &= 0x7f;
-
- num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
-
- if (num_segs == 0)
- goto fix_ipd_exit;
-
- num_segs += 1;
-
- size =
- FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
- ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
- (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
-
- cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
- 1 << INDEX(FIX_IPD_OUTPORT));
- CVMX_SYNC;
-
- g_buffer.u64 = 0;
- g_buffer.s.addr =
- cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
- if (g_buffer.s.addr == 0) {
- cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
- "buffer allocation failure.\n");
- goto fix_ipd_exit;
- }
-
- g_buffer.s.pool = CVMX_FPA_WQE_POOL;
- g_buffer.s.size = num_segs;
-
- pkt_buffer.u64 = 0;
- pkt_buffer.s.addr =
- cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
- if (pkt_buffer.s.addr == 0) {
- cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
- "buffer allocation failure.\n");
- goto fix_ipd_exit;
- }
- pkt_buffer.s.i = 1;
- pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
- pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
-
- p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
- p64[0] = 0xffffffffffff0000ull;
- p64[1] = 0x08004510ull;
- p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
- p64[3] = 0x3a5fc0a81073c0a8ull;
-
- for (i = 0; i < num_segs; i++) {
- if (i > 0)
- pkt_buffer.s.size =
- FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
-
- if (i == (num_segs - 1))
- pkt_buffer.s.i = 0;
-
- *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
- 8 * i) = pkt_buffer.u64;
- }
-
- /* Build the PKO command */
- pko_command.u64 = 0;
- pko_command.s.segs = num_segs;
- pko_command.s.total_bytes = size;
- pko_command.s.dontfree = 0;
- pko_command.s.gather = 1;
-
- gmx_cfg.u64 =
- cvmx_read_csr(CVMX_GMXX_PRTX_CFG
- (INDEX(FIX_IPD_OUTPORT),
- INTERFACE(FIX_IPD_OUTPORT)));
- gmx_cfg.s.en = 1;
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG
- (INDEX(FIX_IPD_OUTPORT),
- INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
- cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
- 1 << INDEX(FIX_IPD_OUTPORT));
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
- 1 << INDEX(FIX_IPD_OUTPORT));
-
- mtu =
- cvmx_read_csr(CVMX_GMXX_RXX_JABBER
- (INDEX(FIX_IPD_OUTPORT),
- INTERFACE(FIX_IPD_OUTPORT)));
- cvmx_write_csr(CVMX_GMXX_RXX_JABBER
- (INDEX(FIX_IPD_OUTPORT),
- INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
- (INDEX(FIX_IPD_OUTPORT),
- INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
-
- cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
- cvmx_pko_get_base_queue
- (FIX_IPD_OUTPORT),
- CVMX_PKO_LOCK_CMD_QUEUE);
- cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
- cvmx_pko_get_base_queue
- (FIX_IPD_OUTPORT), pko_command,
- g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
-
- CVMX_SYNC;
-
- do {
- work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
- retry_cnt--;
- } while ((work == NULL) && (retry_cnt > 0));
-
- if (!retry_cnt)
- cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
- "get_work() timeout occurred.\n");
-
- /* Free packet */
- if (work)
- cvmx_helper_free_packet_data(work);
- }
-
-fix_ipd_exit:
-
- /* Return CSR configs to saved values */
- cvmx_write_csr(CVMX_GMXX_PRTX_CFG
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
- prtx_cfg);
- cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
- tx_ptr_en);
- cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
- rx_ptr_en);
- cvmx_write_csr(CVMX_GMXX_RXX_JABBER
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
- rxx_jabber);
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
- (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
- frame_max);
- cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
- /* Set link to down so autonegotiation will set it up again */
- link_info.u64 = 0;
- cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info);
-
- /*
- * Bring the link back up as autonegotiation is not done in
- * user applications.
- */
- cvmx_helper_link_autoconf(FIX_IPD_OUTPORT);
-
- CVMX_SYNC;
- if (num_segs)
- cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
-
- return !!num_segs;
-
-}
-
-/**
- * Called after all internal packet IO paths are setup. This
- * function enables IPD/PIP and begins packet input and output.
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_helper_ipd_and_packet_input_enable(void)
-{
- int num_interfaces;
- int interface;
-
- /* Enable IPD */
- cvmx_ipd_enable();
-
- /*
- * Time to enable hardware ports packet input and output. Note
- * that at this point IPD/PIP must be fully functional and PKO
- * must be disabled
- */
- num_interfaces = cvmx_helper_get_number_of_interfaces();
- for (interface = 0; interface < num_interfaces; interface++) {
- if (cvmx_helper_ports_on_interface(interface) > 0)
- __cvmx_helper_packet_hardware_enable(interface);
- }
-
- /* Finally enable PKO now that the entire path is up and running */
- cvmx_pko_enable();
-
- if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
- || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
- && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
- __cvmx_helper_errata_fix_ipd_ptr_alignment();
- return 0;
-}
-
-/**
- * Initialize the PIP, IPD, and PKO hardware to support
- * simple priority based queues for the ethernet ports. Each
- * port is configured with a number of priority queues based
- * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
- * priority than the previous.
- *
- * Returns Zero on success, non-zero on failure
- */
-int cvmx_helper_initialize_packet_io_global(void)
-{
- int result = 0;
- int interface;
- union cvmx_l2c_cfg l2c_cfg;
- union cvmx_smix_en smix_en;
- const int num_interfaces = cvmx_helper_get_number_of_interfaces();
-
- /*
- * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
- * be disabled.
- */
- if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
- __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
-
- /*
- * Tell L2 to give the IOB statically higher priority compared
- * to the cores. This avoids conditions where IO blocks might
- * be starved under very high L2 loads.
- */
- l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
- l2c_cfg.s.lrf_arb_mode = 0;
- l2c_cfg.s.rfb_arb_mode = 0;
- cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
-
- /* Make sure SMI/MDIO is enabled so we can query PHYs */
- smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
- if (!smix_en.s.en) {
- smix_en.s.en = 1;
- cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
- }
-
- /* Newer chips actually have two SMI/MDIO interfaces */
- if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
- !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
- !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
- if (!smix_en.s.en) {
- smix_en.s.en = 1;
- cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
- }
- }
-
- cvmx_pko_initialize_global();
- for (interface = 0; interface < num_interfaces; interface++) {
- result |= cvmx_helper_interface_probe(interface);
- if (cvmx_helper_ports_on_interface(interface) > 0)
- cvmx_dprintf("Interface %d has %d ports (%s)\n",
- interface,
- cvmx_helper_ports_on_interface(interface),
- cvmx_helper_interface_mode_to_string
- (cvmx_helper_interface_get_mode
- (interface)));
- result |= __cvmx_helper_interface_setup_ipd(interface);
- result |= __cvmx_helper_interface_setup_pko(interface);
- }
-
- result |= __cvmx_helper_global_setup_ipd();
- result |= __cvmx_helper_global_setup_pko();
-
- /* Enable any flow control and backpressure */
- result |= __cvmx_helper_global_setup_backpressure();
-
-#if CVMX_HELPER_ENABLE_IPD
- result |= cvmx_helper_ipd_and_packet_input_enable();
-#endif
- return result;
-}
-
-/**
- * Does core local initialization for packet io
- *
- * Returns Zero on success, non-zero on failure
- */
-int cvmx_helper_initialize_packet_io_local(void)
-{
- return cvmx_pko_initialize_local();
-}
-
-/**
- * Auto configure an IPD/PKO port link state and speed. This
- * function basically does the equivalent of:
- * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
- *
- * @ipd_port: IPD/PKO port to auto configure
- *
- * Returns Link state after configure
- */
-cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
-{
- cvmx_helper_link_info_t link_info;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
-
- if (index >= cvmx_helper_ports_on_interface(interface)) {
- link_info.u64 = 0;
- return link_info;
- }
-
- link_info = cvmx_helper_link_get(ipd_port);
- if (link_info.u64 == port_link_info[ipd_port].u64)
- return link_info;
-
- /* If we fail to set the link speed, port_link_info will not change */
- cvmx_helper_link_set(ipd_port, link_info);
-
- /*
- * port_link_info should be the current value, which will be
- * different than expect if cvmx_helper_link_set() failed.
- */
- return port_link_info[ipd_port];
-}
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
-{
- cvmx_helper_link_info_t result;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
-
- /* The default result will be a down link unless the code below
- changes it */
- result.u64 = 0;
-
- if (index >= cvmx_helper_ports_on_interface(interface))
- return result;
-
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- /* Network links are not supported */
- break;
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- result = __cvmx_helper_xaui_link_get(ipd_port);
- break;
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- if (index == 0)
- result = __cvmx_helper_rgmii_link_get(ipd_port);
- else {
- result.s.full_duplex = 1;
- result.s.link_up = 1;
- result.s.speed = 1000;
- }
- break;
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- result = __cvmx_helper_rgmii_link_get(ipd_port);
- break;
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- result = __cvmx_helper_spi_link_get(ipd_port);
- break;
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- result = __cvmx_helper_sgmii_link_get(ipd_port);
- break;
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- /* Network links are not supported */
- break;
- }
- return result;
-}
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
-{
- int result = -1;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
-
- if (index >= cvmx_helper_ports_on_interface(interface))
- return -1;
-
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- break;
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
- break;
- /*
- * RGMII/GMII/MII are all treated about the same. Most
- * functions refer to these ports as RGMII.
- */
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
- break;
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- result = __cvmx_helper_spi_link_set(ipd_port, link_info);
- break;
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
- break;
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- break;
- }
- /* Set the port_link_info here so that the link status is updated
- no matter how cvmx_helper_link_set is called. We don't change
- the value if link_set failed */
- if (result == 0)
- port_link_info[ipd_port].u64 = link_info.u64;
- return result;
-}
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
- int enable_external)
-{
- int result = -1;
- int interface = cvmx_helper_get_interface_num(ipd_port);
- int index = cvmx_helper_get_interface_index_num(ipd_port);
-
- if (index >= cvmx_helper_ports_on_interface(interface))
- return -1;
-
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- break;
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- result =
- __cvmx_helper_xaui_configure_loopback(ipd_port,
- enable_internal,
- enable_external);
- break;
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- result =
- __cvmx_helper_rgmii_configure_loopback(ipd_port,
- enable_internal,
- enable_external);
- break;
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- result =
- __cvmx_helper_sgmii_configure_loopback(ipd_port,
- enable_internal,
- enable_external);
- break;
- }
- return result;
-}
diff --git a/drivers/staging/octeon/cvmx-helper.h b/drivers/staging/octeon/cvmx-helper.h
deleted file mode 100644
index 51916f3..0000000
--- a/drivers/staging/octeon/cvmx-helper.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Helper functions for common, but complicated tasks.
- *
- */
-
-#ifndef __CVMX_HELPER_H__
-#define __CVMX_HELPER_H__
-
-#include "cvmx-config.h"
-#include "cvmx-fpa.h"
-#include "cvmx-wqe.h"
-
-typedef enum {
- CVMX_HELPER_INTERFACE_MODE_DISABLED,
- CVMX_HELPER_INTERFACE_MODE_RGMII,
- CVMX_HELPER_INTERFACE_MODE_GMII,
- CVMX_HELPER_INTERFACE_MODE_SPI,
- CVMX_HELPER_INTERFACE_MODE_PCIE,
- CVMX_HELPER_INTERFACE_MODE_XAUI,
- CVMX_HELPER_INTERFACE_MODE_SGMII,
- CVMX_HELPER_INTERFACE_MODE_PICMG,
- CVMX_HELPER_INTERFACE_MODE_NPI,
- CVMX_HELPER_INTERFACE_MODE_LOOP,
-} cvmx_helper_interface_mode_t;
-
-typedef union {
- uint64_t u64;
- struct {
- uint64_t reserved_20_63:44;
- uint64_t link_up:1; /**< Is the physical link up? */
- uint64_t full_duplex:1; /**< 1 if the link is full duplex */
- uint64_t speed:18; /**< Speed of the link in Mbps */
- } s;
-} cvmx_helper_link_info_t;
-
-#include "cvmx-helper-fpa.h"
-
-#include <asm/octeon/cvmx-helper-errata.h>
-#include "cvmx-helper-loop.h"
-#include "cvmx-helper-npi.h"
-#include "cvmx-helper-rgmii.h"
-#include "cvmx-helper-sgmii.h"
-#include "cvmx-helper-spi.h"
-#include "cvmx-helper-util.h"
-#include "cvmx-helper-xaui.h"
-
-/**
- * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
- * priorities[16]) is a function pointer. It is meant to allow
- * customization of the PKO queue priorities based on the port
- * number. Users should set this pointer to a function before
- * calling any cvmx-helper operations.
- */
-extern void (*cvmx_override_pko_queue_priority) (int pko_port,
- uint64_t priorities[16]);
-
-/**
- * cvmx_override_ipd_port_setup(int ipd_port) is a function
- * pointer. It is meant to allow customization of the IPD port
- * setup before packet input/output comes online. It is called
- * after cvmx-helper does the default IPD configuration, but
- * before IPD is enabled. Users should set this pointer to a
- * function before calling any cvmx-helper operations.
- */
-extern void (*cvmx_override_ipd_port_setup) (int ipd_port);
-
-/**
- * This function enables the IPD and also enables the packet interfaces.
- * The packet interfaces (RGMII and SPI) must be enabled after the
- * IPD. This should be called by the user program after any additional
- * IPD configuration changes are made if CVMX_HELPER_ENABLE_IPD
- * is not set in the executive-config.h file.
- *
- * Returns 0 on success
- * -1 on failure
- */
-extern int cvmx_helper_ipd_and_packet_input_enable(void);
-
-/**
- * Initialize the PIP, IPD, and PKO hardware to support
- * simple priority based queues for the ethernet ports. Each
- * port is configured with a number of priority queues based
- * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
- * priority than the previous.
- *
- * Returns Zero on success, non-zero on failure
- */
-extern int cvmx_helper_initialize_packet_io_global(void);
-
-/**
- * Does core local initialization for packet io
- *
- * Returns Zero on success, non-zero on failure
- */
-extern int cvmx_helper_initialize_packet_io_local(void);
-
-/**
- * Returns the number of ports on the given interface.
- * The interface must be initialized before the port count
- * can be returned.
- *
- * @interface: Which interface to return port count for.
- *
- * Returns Port count for interface
- * -1 for uninitialized interface
- */
-extern int cvmx_helper_ports_on_interface(int interface);
-
-/**
- * Return the number of interfaces the chip has. Each interface
- * may have multiple ports. Most chips support two interfaces,
- * but the CNX0XX and CNX1XX are exceptions. These only support
- * one interface.
- *
- * Returns Number of interfaces on chip
- */
-extern int cvmx_helper_get_number_of_interfaces(void);
-
-/**
- * Get the operating mode of an interface. Depending on the Octeon
- * chip and configuration, this function returns an enumeration
- * of the type of packet I/O supported by an interface.
- *
- * @interface: Interface to probe
- *
- * Returns Mode of the interface. Unknown or unsupported interfaces return
- * DISABLED.
- */
-extern cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int
- interface);
-
-/**
- * Auto configure an IPD/PKO port link state and speed. This
- * function basically does the equivalent of:
- * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
- *
- * @ipd_port: IPD/PKO port to auto configure
- *
- * Returns Link state after configure
- */
-extern cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port);
-
-/**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @ipd_port: IPD/PKO port to query
- *
- * Returns Link state
- */
-extern cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port);
-
-/**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @ipd_port: IPD/PKO port to configure
- * @link_info: The new link state
- *
- * Returns Zero on success, negative on failure
- */
-extern int cvmx_helper_link_set(int ipd_port,
- cvmx_helper_link_info_t link_info);
-
-/**
- * This function probes an interface to determine the actual
- * number of hardware ports connected to it. It doesn't setup the
- * ports or enable them. The main goal here is to set the global
- * interface_port_count[interface] correctly. Hardware setup of the
- * ports will be performed later.
- *
- * @interface: Interface to probe
- *
- * Returns Zero on success, negative on failure
- */
-extern int cvmx_helper_interface_probe(int interface);
-
-/**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @ipd_port: IPD/PKO port to loopback.
- * @enable_internal:
- * Non zero if you want internal loopback
- * @enable_external:
- * Non zero if you want external loopback
- *
- * Returns Zero on success, negative on failure.
- */
-extern int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
- int enable_external);
-
-#endif /* __CVMX_HELPER_H__ */
diff --git a/drivers/staging/octeon/cvmx-interrupt-decodes.c b/drivers/staging/octeon/cvmx-interrupt-decodes.c
deleted file mode 100644
index a3337e3..0000000
--- a/drivers/staging/octeon/cvmx-interrupt-decodes.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2009 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Automatically generated functions useful for enabling
- * and decoding RSL_INT_BLOCKS interrupts.
- *
- */
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-pcsx-defs.h"
-#include "cvmx-pcsxx-defs.h"
-#include "cvmx-spxx-defs.h"
-#include "cvmx-stxx-defs.h"
-
-#ifndef PRINT_ERROR
-#define PRINT_ERROR(format, ...)
-#endif
-
-
-/**
- * __cvmx_interrupt_gmxx_rxx_int_en_enable enables all interrupt bits in cvmx_gmxx_rxx_int_en_t
- */
-void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block)
-{
- union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
- cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, block),
- cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, block)));
- gmx_rx_int_en.u64 = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN56XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_29_63 */
- gmx_rx_int_en.s.hg2cc = 1;
- gmx_rx_int_en.s.hg2fld = 1;
- gmx_rx_int_en.s.undat = 1;
- gmx_rx_int_en.s.uneop = 1;
- gmx_rx_int_en.s.unsop = 1;
- gmx_rx_int_en.s.bad_term = 1;
- gmx_rx_int_en.s.bad_seq = 1;
- gmx_rx_int_en.s.rem_fault = 1;
- gmx_rx_int_en.s.loc_fault = 1;
- gmx_rx_int_en.s.pause_drp = 1;
- /* Skipping gmx_rx_int_en.s.reserved_16_18 */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- /* Skipping gmx_rx_int_en.s.reserved_9_9 */
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /* Skipping gmx_rx_int_en.s.reserved_5_6 */
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- /* Skipping gmx_rx_int_en.s.reserved_2_2 */
- gmx_rx_int_en.s.carext = 1;
- /* Skipping gmx_rx_int_en.s.reserved_0_0 */
- }
- if (OCTEON_IS_MODEL(OCTEON_CN30XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_19_63 */
- /*gmx_rx_int_en.s.phy_dupx = 1; */
- /*gmx_rx_int_en.s.phy_spd = 1; */
- /*gmx_rx_int_en.s.phy_link = 1; */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- gmx_rx_int_en.s.niberr = 1;
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
- gmx_rx_int_en.s.alnerr = 1;
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- gmx_rx_int_en.s.maxerr = 1;
- gmx_rx_int_en.s.carext = 1;
- gmx_rx_int_en.s.minerr = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_20_63 */
- gmx_rx_int_en.s.pause_drp = 1;
- /*gmx_rx_int_en.s.phy_dupx = 1; */
- /*gmx_rx_int_en.s.phy_spd = 1; */
- /*gmx_rx_int_en.s.phy_link = 1; */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- gmx_rx_int_en.s.niberr = 1;
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /* Skipping gmx_rx_int_en.s.reserved_6_6 */
- gmx_rx_int_en.s.alnerr = 1;
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- /* Skipping gmx_rx_int_en.s.reserved_2_2 */
- gmx_rx_int_en.s.carext = 1;
- /* Skipping gmx_rx_int_en.s.reserved_0_0 */
- }
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_19_63 */
- /*gmx_rx_int_en.s.phy_dupx = 1; */
- /*gmx_rx_int_en.s.phy_spd = 1; */
- /*gmx_rx_int_en.s.phy_link = 1; */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- gmx_rx_int_en.s.niberr = 1;
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
- gmx_rx_int_en.s.alnerr = 1;
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- gmx_rx_int_en.s.maxerr = 1;
- gmx_rx_int_en.s.carext = 1;
- gmx_rx_int_en.s.minerr = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN31XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_19_63 */
- /*gmx_rx_int_en.s.phy_dupx = 1; */
- /*gmx_rx_int_en.s.phy_spd = 1; */
- /*gmx_rx_int_en.s.phy_link = 1; */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- gmx_rx_int_en.s.niberr = 1;
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
- gmx_rx_int_en.s.alnerr = 1;
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- gmx_rx_int_en.s.maxerr = 1;
- gmx_rx_int_en.s.carext = 1;
- gmx_rx_int_en.s.minerr = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_20_63 */
- gmx_rx_int_en.s.pause_drp = 1;
- /*gmx_rx_int_en.s.phy_dupx = 1; */
- /*gmx_rx_int_en.s.phy_spd = 1; */
- /*gmx_rx_int_en.s.phy_link = 1; */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- gmx_rx_int_en.s.niberr = 1;
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /*gmx_rx_int_en.s.lenerr = 1; // Length errors are handled when we get work */
- gmx_rx_int_en.s.alnerr = 1;
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- gmx_rx_int_en.s.maxerr = 1;
- gmx_rx_int_en.s.carext = 1;
- gmx_rx_int_en.s.minerr = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- /* Skipping gmx_rx_int_en.s.reserved_29_63 */
- gmx_rx_int_en.s.hg2cc = 1;
- gmx_rx_int_en.s.hg2fld = 1;
- gmx_rx_int_en.s.undat = 1;
- gmx_rx_int_en.s.uneop = 1;
- gmx_rx_int_en.s.unsop = 1;
- gmx_rx_int_en.s.bad_term = 1;
- gmx_rx_int_en.s.bad_seq = 0;
- gmx_rx_int_en.s.rem_fault = 1;
- gmx_rx_int_en.s.loc_fault = 0;
- gmx_rx_int_en.s.pause_drp = 1;
- /* Skipping gmx_rx_int_en.s.reserved_16_18 */
- /*gmx_rx_int_en.s.ifgerr = 1; */
- /*gmx_rx_int_en.s.coldet = 1; // Collsion detect */
- /*gmx_rx_int_en.s.falerr = 1; // False carrier error or extend error after slottime */
- /*gmx_rx_int_en.s.rsverr = 1; // RGMII reserved opcodes */
- /*gmx_rx_int_en.s.pcterr = 1; // Bad Preamble / Protocol */
- gmx_rx_int_en.s.ovrerr = 1;
- /* Skipping gmx_rx_int_en.s.reserved_9_9 */
- gmx_rx_int_en.s.skperr = 1;
- gmx_rx_int_en.s.rcverr = 1;
- /* Skipping gmx_rx_int_en.s.reserved_5_6 */
- /*gmx_rx_int_en.s.fcserr = 1; // FCS errors are handled when we get work */
- gmx_rx_int_en.s.jabber = 1;
- /* Skipping gmx_rx_int_en.s.reserved_2_2 */
- gmx_rx_int_en.s.carext = 1;
- /* Skipping gmx_rx_int_en.s.reserved_0_0 */
- }
- cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, block), gmx_rx_int_en.u64);
-}
-/**
- * __cvmx_interrupt_pcsx_intx_en_reg_enable enables all interrupt bits in cvmx_pcsx_intx_en_reg_t
- */
-void __cvmx_interrupt_pcsx_intx_en_reg_enable(int index, int block)
-{
- union cvmx_pcsx_intx_en_reg pcs_int_en_reg;
- cvmx_write_csr(CVMX_PCSX_INTX_REG(index, block),
- cvmx_read_csr(CVMX_PCSX_INTX_REG(index, block)));
- pcs_int_en_reg.u64 = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN56XX)) {
- /* Skipping pcs_int_en_reg.s.reserved_12_63 */
- /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */
- pcs_int_en_reg.s.sync_bad_en = 1;
- pcs_int_en_reg.s.an_bad_en = 1;
- pcs_int_en_reg.s.rxlock_en = 1;
- pcs_int_en_reg.s.rxbad_en = 1;
- /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */
- pcs_int_en_reg.s.txbad_en = 1;
- pcs_int_en_reg.s.txfifo_en = 1;
- pcs_int_en_reg.s.txfifu_en = 1;
- pcs_int_en_reg.s.an_err_en = 1;
- /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */
- /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */
- }
- if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- /* Skipping pcs_int_en_reg.s.reserved_12_63 */
- /*pcs_int_en_reg.s.dup = 1; // This happens during normal operation */
- pcs_int_en_reg.s.sync_bad_en = 1;
- pcs_int_en_reg.s.an_bad_en = 1;
- pcs_int_en_reg.s.rxlock_en = 1;
- pcs_int_en_reg.s.rxbad_en = 1;
- /*pcs_int_en_reg.s.rxerr_en = 1; // This happens during normal operation */
- pcs_int_en_reg.s.txbad_en = 1;
- pcs_int_en_reg.s.txfifo_en = 1;
- pcs_int_en_reg.s.txfifu_en = 1;
- pcs_int_en_reg.s.an_err_en = 1;
- /*pcs_int_en_reg.s.xmit_en = 1; // This happens during normal operation */
- /*pcs_int_en_reg.s.lnkspd_en = 1; // This happens during normal operation */
- }
- cvmx_write_csr(CVMX_PCSX_INTX_EN_REG(index, block), pcs_int_en_reg.u64);
-}
-/**
- * __cvmx_interrupt_pcsxx_int_en_reg_enable enables all interrupt bits in cvmx_pcsxx_int_en_reg_t
- */
-void __cvmx_interrupt_pcsxx_int_en_reg_enable(int index)
-{
- union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
- cvmx_write_csr(CVMX_PCSXX_INT_REG(index),
- cvmx_read_csr(CVMX_PCSXX_INT_REG(index)));
- pcsx_int_en_reg.u64 = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN56XX)) {
- /* Skipping pcsx_int_en_reg.s.reserved_6_63 */
- pcsx_int_en_reg.s.algnlos_en = 1;
- pcsx_int_en_reg.s.synlos_en = 1;
- pcsx_int_en_reg.s.bitlckls_en = 1;
- pcsx_int_en_reg.s.rxsynbad_en = 1;
- pcsx_int_en_reg.s.rxbad_en = 1;
- pcsx_int_en_reg.s.txflt_en = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- /* Skipping pcsx_int_en_reg.s.reserved_6_63 */
- pcsx_int_en_reg.s.algnlos_en = 1;
- pcsx_int_en_reg.s.synlos_en = 1;
- pcsx_int_en_reg.s.bitlckls_en = 0; /* Happens if XAUI module is not installed */
- pcsx_int_en_reg.s.rxsynbad_en = 1;
- pcsx_int_en_reg.s.rxbad_en = 1;
- pcsx_int_en_reg.s.txflt_en = 1;
- }
- cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(index), pcsx_int_en_reg.u64);
-}
-
-/**
- * __cvmx_interrupt_spxx_int_msk_enable enables all interrupt bits in cvmx_spxx_int_msk_t
- */
-void __cvmx_interrupt_spxx_int_msk_enable(int index)
-{
- union cvmx_spxx_int_msk spx_int_msk;
- cvmx_write_csr(CVMX_SPXX_INT_REG(index),
- cvmx_read_csr(CVMX_SPXX_INT_REG(index)));
- spx_int_msk.u64 = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
- /* Skipping spx_int_msk.s.reserved_12_63 */
- spx_int_msk.s.calerr = 1;
- spx_int_msk.s.syncerr = 1;
- spx_int_msk.s.diperr = 1;
- spx_int_msk.s.tpaovr = 1;
- spx_int_msk.s.rsverr = 1;
- spx_int_msk.s.drwnng = 1;
- spx_int_msk.s.clserr = 1;
- spx_int_msk.s.spiovr = 1;
- /* Skipping spx_int_msk.s.reserved_2_3 */
- spx_int_msk.s.abnorm = 1;
- spx_int_msk.s.prtnxa = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- /* Skipping spx_int_msk.s.reserved_12_63 */
- spx_int_msk.s.calerr = 1;
- spx_int_msk.s.syncerr = 1;
- spx_int_msk.s.diperr = 1;
- spx_int_msk.s.tpaovr = 1;
- spx_int_msk.s.rsverr = 1;
- spx_int_msk.s.drwnng = 1;
- spx_int_msk.s.clserr = 1;
- spx_int_msk.s.spiovr = 1;
- /* Skipping spx_int_msk.s.reserved_2_3 */
- spx_int_msk.s.abnorm = 1;
- spx_int_msk.s.prtnxa = 1;
- }
- cvmx_write_csr(CVMX_SPXX_INT_MSK(index), spx_int_msk.u64);
-}
-/**
- * __cvmx_interrupt_stxx_int_msk_enable enables all interrupt bits in cvmx_stxx_int_msk_t
- */
-void __cvmx_interrupt_stxx_int_msk_enable(int index)
-{
- union cvmx_stxx_int_msk stx_int_msk;
- cvmx_write_csr(CVMX_STXX_INT_REG(index),
- cvmx_read_csr(CVMX_STXX_INT_REG(index)));
- stx_int_msk.u64 = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
- /* Skipping stx_int_msk.s.reserved_8_63 */
- stx_int_msk.s.frmerr = 1;
- stx_int_msk.s.unxfrm = 1;
- stx_int_msk.s.nosync = 1;
- stx_int_msk.s.diperr = 1;
- stx_int_msk.s.datovr = 1;
- stx_int_msk.s.ovrbst = 1;
- stx_int_msk.s.calpar1 = 1;
- stx_int_msk.s.calpar0 = 1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- /* Skipping stx_int_msk.s.reserved_8_63 */
- stx_int_msk.s.frmerr = 1;
- stx_int_msk.s.unxfrm = 1;
- stx_int_msk.s.nosync = 1;
- stx_int_msk.s.diperr = 1;
- stx_int_msk.s.datovr = 1;
- stx_int_msk.s.ovrbst = 1;
- stx_int_msk.s.calpar1 = 1;
- stx_int_msk.s.calpar0 = 1;
- }
- cvmx_write_csr(CVMX_STXX_INT_MSK(index), stx_int_msk.u64);
-}
diff --git a/drivers/staging/octeon/cvmx-interrupt-rsl.c b/drivers/staging/octeon/cvmx-interrupt-rsl.c
deleted file mode 100644
index df50048..0000000
--- a/drivers/staging/octeon/cvmx-interrupt-rsl.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Utility functions to decode Octeon's RSL_INT_BLOCKS
- * interrupts into error messages.
- */
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-asxx-defs.h"
-#include "cvmx-gmxx-defs.h"
-
-#ifndef PRINT_ERROR
-#define PRINT_ERROR(format, ...)
-#endif
-
-void __cvmx_interrupt_gmxx_rxx_int_en_enable(int index, int block);
-
-/**
- * Enable ASX error interrupts that exist on CN3XXX, CN50XX, and
- * CN58XX.
- *
- * @block: Interface to enable 0-1
- */
-void __cvmx_interrupt_asxx_enable(int block)
-{
- int mask;
- union cvmx_asxx_int_en csr;
- /*
- * CN38XX and CN58XX have two interfaces with 4 ports per
- * interface. All other chips have a max of 3 ports on
- * interface 0
- */
- if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
- mask = 0xf; /* Set enables for 4 ports */
- else
- mask = 0x7; /* Set enables for 3 ports */
-
- /* Enable interface interrupts */
- csr.u64 = cvmx_read_csr(CVMX_ASXX_INT_EN(block));
- csr.s.txpsh = mask;
- csr.s.txpop = mask;
- csr.s.ovrflw = mask;
- cvmx_write_csr(CVMX_ASXX_INT_EN(block), csr.u64);
-}
-/**
- * Enable GMX error reporting for the supplied interface
- *
- * @interface: Interface to enable
- */
-void __cvmx_interrupt_gmxx_enable(int interface)
-{
- union cvmx_gmxx_inf_mode mode;
- union cvmx_gmxx_tx_int_en gmx_tx_int_en;
- int num_ports;
- int index;
-
- mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
-
- if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- if (mode.s.en) {
- switch (mode.cn56xx.mode) {
- case 1: /* XAUI */
- num_ports = 1;
- break;
- case 2: /* SGMII */
- case 3: /* PICMG */
- num_ports = 4;
- break;
- default: /* Disabled */
- num_ports = 0;
- break;
- }
- } else
- num_ports = 0;
- } else {
- if (mode.s.en) {
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- /*
- * SPI on CN38XX and CN58XX report all
- * errors through port 0. RGMII needs
- * to check all 4 ports
- */
- if (mode.s.type)
- num_ports = 1;
- else
- num_ports = 4;
- } else {
- /*
- * CN30XX, CN31XX, and CN50XX have two
- * or three ports. GMII and MII has 2,
- * RGMII has three
- */
- if (mode.s.type)
- num_ports = 2;
- else
- num_ports = 3;
- }
- } else
- num_ports = 0;
- }
-
- gmx_tx_int_en.u64 = 0;
- if (num_ports) {
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)
- || OCTEON_IS_MODEL(OCTEON_CN58XX))
- gmx_tx_int_en.s.ncb_nxa = 1;
- gmx_tx_int_en.s.pko_nxa = 1;
- }
- gmx_tx_int_en.s.undflw = (1 << num_ports) - 1;
- cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
- for (index = 0; index < num_ports; index++)
- __cvmx_interrupt_gmxx_rxx_int_en_enable(index, interface);
-}
diff --git a/drivers/staging/octeon/cvmx-ipd.h b/drivers/staging/octeon/cvmx-ipd.h
deleted file mode 100644
index 115a552..0000000
--- a/drivers/staging/octeon/cvmx-ipd.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * Interface to the hardware Input Packet Data unit.
- */
-
-#ifndef __CVMX_IPD_H__
-#define __CVMX_IPD_H__
-
-#include <asm/octeon/octeon-feature.h>
-
-#include <asm/octeon/cvmx-ipd-defs.h>
-
-enum cvmx_ipd_mode {
- CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */
- CVMX_IPD_OPC_MODE_STF = 1LL, /* All bloccks into L2 */
- CVMX_IPD_OPC_MODE_STF1_STT = 2LL, /* 1st block L2, rest DRAM */
- CVMX_IPD_OPC_MODE_STF2_STT = 3LL /* 1st, 2nd blocks L2, rest DRAM */
-};
-
-#ifndef CVMX_ENABLE_LEN_M8_FIX
-#define CVMX_ENABLE_LEN_M8_FIX 0
-#endif
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-typedef union cvmx_ipd_1st_mbuff_skip cvmx_ipd_mbuff_first_skip_t;
-typedef union cvmx_ipd_1st_next_ptr_back cvmx_ipd_first_next_ptr_back_t;
-
-typedef cvmx_ipd_mbuff_first_skip_t cvmx_ipd_mbuff_not_first_skip_t;
-typedef cvmx_ipd_first_next_ptr_back_t cvmx_ipd_second_next_ptr_back_t;
-
-/**
- * Configure IPD
- *
- * @mbuff_size: Packets buffer size in 8 byte words
- * @first_mbuff_skip:
- * Number of 8 byte words to skip in the first buffer
- * @not_first_mbuff_skip:
- * Number of 8 byte words to skip in each following buffer
- * @first_back: Must be same as first_mbuff_skip / 128
- * @second_back:
- * Must be same as not_first_mbuff_skip / 128
- * @wqe_fpa_pool:
- * FPA pool to get work entries from
- * @cache_mode:
- * @back_pres_enable_flag:
- * Enable or disable port back pressure
- */
-static inline void cvmx_ipd_config(uint64_t mbuff_size,
- uint64_t first_mbuff_skip,
- uint64_t not_first_mbuff_skip,
- uint64_t first_back,
- uint64_t second_back,
- uint64_t wqe_fpa_pool,
- enum cvmx_ipd_mode cache_mode,
- uint64_t back_pres_enable_flag)
-{
- cvmx_ipd_mbuff_first_skip_t first_skip;
- cvmx_ipd_mbuff_not_first_skip_t not_first_skip;
- union cvmx_ipd_packet_mbuff_size size;
- cvmx_ipd_first_next_ptr_back_t first_back_struct;
- cvmx_ipd_second_next_ptr_back_t second_back_struct;
- union cvmx_ipd_wqe_fpa_queue wqe_pool;
- union cvmx_ipd_ctl_status ipd_ctl_reg;
-
- first_skip.u64 = 0;
- first_skip.s.skip_sz = first_mbuff_skip;
- cvmx_write_csr(CVMX_IPD_1ST_MBUFF_SKIP, first_skip.u64);
-
- not_first_skip.u64 = 0;
- not_first_skip.s.skip_sz = not_first_mbuff_skip;
- cvmx_write_csr(CVMX_IPD_NOT_1ST_MBUFF_SKIP, not_first_skip.u64);
-
- size.u64 = 0;
- size.s.mb_size = mbuff_size;
- cvmx_write_csr(CVMX_IPD_PACKET_MBUFF_SIZE, size.u64);
-
- first_back_struct.u64 = 0;
- first_back_struct.s.back = first_back;
- cvmx_write_csr(CVMX_IPD_1st_NEXT_PTR_BACK, first_back_struct.u64);
-
- second_back_struct.u64 = 0;
- second_back_struct.s.back = second_back;
- cvmx_write_csr(CVMX_IPD_2nd_NEXT_PTR_BACK, second_back_struct.u64);
-
- wqe_pool.u64 = 0;
- wqe_pool.s.wqe_pool = wqe_fpa_pool;
- cvmx_write_csr(CVMX_IPD_WQE_FPA_QUEUE, wqe_pool.u64);
-
- ipd_ctl_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
- ipd_ctl_reg.s.opc_mode = cache_mode;
- ipd_ctl_reg.s.pbp_en = back_pres_enable_flag;
- cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_reg.u64);
-
- /* Note: the example RED code that used to be here has been moved to
- cvmx_helper_setup_red */
-}
-
-/**
- * Enable IPD
- */
-static inline void cvmx_ipd_enable(void)
-{
- union cvmx_ipd_ctl_status ipd_reg;
- ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
- if (ipd_reg.s.ipd_en) {
- cvmx_dprintf
- ("Warning: Enabling IPD when IPD already enabled.\n");
- }
- ipd_reg.s.ipd_en = 1;
-#if CVMX_ENABLE_LEN_M8_FIX
- if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
- ipd_reg.s.len_m8 = TRUE;
-#endif
- cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64);
-}
-
-/**
- * Disable IPD
- */
-static inline void cvmx_ipd_disable(void)
-{
- union cvmx_ipd_ctl_status ipd_reg;
- ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
- ipd_reg.s.ipd_en = 0;
- cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64);
-}
-
-/**
- * Supportive function for cvmx_fpa_shutdown_pool.
- */
-static inline void cvmx_ipd_free_ptr(void)
-{
- /* Only CN38XXp{1,2} cannot read pointer out of the IPD */
- if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)
- && !OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) {
- int no_wptr = 0;
- union cvmx_ipd_ptr_count ipd_ptr_count;
- ipd_ptr_count.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
-
- /* Handle Work Queue Entry in cn56xx and cn52xx */
- if (octeon_has_feature(OCTEON_FEATURE_NO_WPTR)) {
- union cvmx_ipd_ctl_status ipd_ctl_status;
- ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
- if (ipd_ctl_status.s.no_wptr)
- no_wptr = 1;
- }
-
- /* Free the prefetched WQE */
- if (ipd_ptr_count.s.wqev_cnt) {
- union cvmx_ipd_wqe_ptr_valid ipd_wqe_ptr_valid;
- ipd_wqe_ptr_valid.u64 =
- cvmx_read_csr(CVMX_IPD_WQE_PTR_VALID);
- if (no_wptr)
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t) ipd_wqe_ptr_valid.s.
- ptr << 7), CVMX_FPA_PACKET_POOL,
- 0);
- else
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t) ipd_wqe_ptr_valid.s.
- ptr << 7), CVMX_FPA_WQE_POOL, 0);
- }
-
- /* Free all WQE in the fifo */
- if (ipd_ptr_count.s.wqe_pcnt) {
- int i;
- union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl;
- ipd_pwp_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL);
- for (i = 0; i < ipd_ptr_count.s.wqe_pcnt; i++) {
- ipd_pwp_ptr_fifo_ctl.s.cena = 0;
- ipd_pwp_ptr_fifo_ctl.s.raddr =
- ipd_pwp_ptr_fifo_ctl.s.max_cnts +
- (ipd_pwp_ptr_fifo_ctl.s.wraddr +
- i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts;
- cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL,
- ipd_pwp_ptr_fifo_ctl.u64);
- ipd_pwp_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL);
- if (no_wptr)
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t)
- ipd_pwp_ptr_fifo_ctl.s.
- ptr << 7),
- CVMX_FPA_PACKET_POOL, 0);
- else
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t)
- ipd_pwp_ptr_fifo_ctl.s.
- ptr << 7),
- CVMX_FPA_WQE_POOL, 0);
- }
- ipd_pwp_ptr_fifo_ctl.s.cena = 1;
- cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL,
- ipd_pwp_ptr_fifo_ctl.u64);
- }
-
- /* Free the prefetched packet */
- if (ipd_ptr_count.s.pktv_cnt) {
- union cvmx_ipd_pkt_ptr_valid ipd_pkt_ptr_valid;
- ipd_pkt_ptr_valid.u64 =
- cvmx_read_csr(CVMX_IPD_PKT_PTR_VALID);
- cvmx_fpa_free(cvmx_phys_to_ptr
- (ipd_pkt_ptr_valid.s.ptr << 7),
- CVMX_FPA_PACKET_POOL, 0);
- }
-
- /* Free the per port prefetched packets */
- if (1) {
- int i;
- union cvmx_ipd_prc_port_ptr_fifo_ctl
- ipd_prc_port_ptr_fifo_ctl;
- ipd_prc_port_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL);
-
- for (i = 0; i < ipd_prc_port_ptr_fifo_ctl.s.max_pkt;
- i++) {
- ipd_prc_port_ptr_fifo_ctl.s.cena = 0;
- ipd_prc_port_ptr_fifo_ctl.s.raddr =
- i % ipd_prc_port_ptr_fifo_ctl.s.max_pkt;
- cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL,
- ipd_prc_port_ptr_fifo_ctl.u64);
- ipd_prc_port_ptr_fifo_ctl.u64 =
- cvmx_read_csr
- (CVMX_IPD_PRC_PORT_PTR_FIFO_CTL);
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t)
- ipd_prc_port_ptr_fifo_ctl.s.
- ptr << 7), CVMX_FPA_PACKET_POOL,
- 0);
- }
- ipd_prc_port_ptr_fifo_ctl.s.cena = 1;
- cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL,
- ipd_prc_port_ptr_fifo_ctl.u64);
- }
-
- /* Free all packets in the holding fifo */
- if (ipd_ptr_count.s.pfif_cnt) {
- int i;
- union cvmx_ipd_prc_hold_ptr_fifo_ctl
- ipd_prc_hold_ptr_fifo_ctl;
-
- ipd_prc_hold_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL);
-
- for (i = 0; i < ipd_ptr_count.s.pfif_cnt; i++) {
- ipd_prc_hold_ptr_fifo_ctl.s.cena = 0;
- ipd_prc_hold_ptr_fifo_ctl.s.raddr =
- (ipd_prc_hold_ptr_fifo_ctl.s.praddr +
- i) % ipd_prc_hold_ptr_fifo_ctl.s.max_pkt;
- cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL,
- ipd_prc_hold_ptr_fifo_ctl.u64);
- ipd_prc_hold_ptr_fifo_ctl.u64 =
- cvmx_read_csr
- (CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL);
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t)
- ipd_prc_hold_ptr_fifo_ctl.s.
- ptr << 7), CVMX_FPA_PACKET_POOL,
- 0);
- }
- ipd_prc_hold_ptr_fifo_ctl.s.cena = 1;
- cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL,
- ipd_prc_hold_ptr_fifo_ctl.u64);
- }
-
- /* Free all packets in the fifo */
- if (ipd_ptr_count.s.pkt_pcnt) {
- int i;
- union cvmx_ipd_pwp_ptr_fifo_ctl ipd_pwp_ptr_fifo_ctl;
- ipd_pwp_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL);
-
- for (i = 0; i < ipd_ptr_count.s.pkt_pcnt; i++) {
- ipd_pwp_ptr_fifo_ctl.s.cena = 0;
- ipd_pwp_ptr_fifo_ctl.s.raddr =
- (ipd_pwp_ptr_fifo_ctl.s.praddr +
- i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts;
- cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL,
- ipd_pwp_ptr_fifo_ctl.u64);
- ipd_pwp_ptr_fifo_ctl.u64 =
- cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL);
- cvmx_fpa_free(cvmx_phys_to_ptr
- ((uint64_t) ipd_pwp_ptr_fifo_ctl.
- s.ptr << 7),
- CVMX_FPA_PACKET_POOL, 0);
- }
- ipd_pwp_ptr_fifo_ctl.s.cena = 1;
- cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL,
- ipd_pwp_ptr_fifo_ctl.u64);
- }
-
- /* Reset the IPD to get all buffers out of it */
- {
- union cvmx_ipd_ctl_status ipd_ctl_status;
- ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
- ipd_ctl_status.s.reset = 1;
- cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
- }
-
- /* Reset the PIP */
- {
- union cvmx_pip_sft_rst pip_sft_rst;
- pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST);
- pip_sft_rst.s.rst = 1;
- cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64);
- }
- }
-}
-
-#endif /* __CVMX_IPD_H__ */
diff --git a/drivers/staging/octeon/cvmx-mdio.h b/drivers/staging/octeon/cvmx-mdio.h
deleted file mode 100644
index d88ab8d..0000000
--- a/drivers/staging/octeon/cvmx-mdio.h
+++ /dev/null
@@ -1,506 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3
- * clause 22 and clause 45 operations.
- *
- */
-
-#ifndef __CVMX_MIO_H__
-#define __CVMX_MIO_H__
-
-#include "cvmx-smix-defs.h"
-
-/**
- * PHY register 0 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_CONTROL 0
-typedef union {
- uint16_t u16;
- struct {
- uint16_t reset:1;
- uint16_t loopback:1;
- uint16_t speed_lsb:1;
- uint16_t autoneg_enable:1;
- uint16_t power_down:1;
- uint16_t isolate:1;
- uint16_t restart_autoneg:1;
- uint16_t duplex:1;
- uint16_t collision_test:1;
- uint16_t speed_msb:1;
- uint16_t unidirectional_enable:1;
- uint16_t reserved_0_4:5;
- } s;
-} cvmx_mdio_phy_reg_control_t;
-
-/**
- * PHY register 1 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_STATUS 1
-typedef union {
- uint16_t u16;
- struct {
- uint16_t capable_100base_t4:1;
- uint16_t capable_100base_x_full:1;
- uint16_t capable_100base_x_half:1;
- uint16_t capable_10_full:1;
- uint16_t capable_10_half:1;
- uint16_t capable_100base_t2_full:1;
- uint16_t capable_100base_t2_half:1;
- uint16_t capable_extended_status:1;
- uint16_t capable_unidirectional:1;
- uint16_t capable_mf_preamble_suppression:1;
- uint16_t autoneg_complete:1;
- uint16_t remote_fault:1;
- uint16_t capable_autoneg:1;
- uint16_t link_status:1;
- uint16_t jabber_detect:1;
- uint16_t capable_extended_registers:1;
-
- } s;
-} cvmx_mdio_phy_reg_status_t;
-
-/**
- * PHY register 2 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_ID1 2
-typedef union {
- uint16_t u16;
- struct {
- uint16_t oui_bits_3_18;
- } s;
-} cvmx_mdio_phy_reg_id1_t;
-
-/**
- * PHY register 3 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_ID2 3
-typedef union {
- uint16_t u16;
- struct {
- uint16_t oui_bits_19_24:6;
- uint16_t model:6;
- uint16_t revision:4;
- } s;
-} cvmx_mdio_phy_reg_id2_t;
-
-/**
- * PHY register 4 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4
-typedef union {
- uint16_t u16;
- struct {
- uint16_t next_page:1;
- uint16_t reserved_14:1;
- uint16_t remote_fault:1;
- uint16_t reserved_12:1;
- uint16_t asymmetric_pause:1;
- uint16_t pause:1;
- uint16_t advert_100base_t4:1;
- uint16_t advert_100base_tx_full:1;
- uint16_t advert_100base_tx_half:1;
- uint16_t advert_10base_tx_full:1;
- uint16_t advert_10base_tx_half:1;
- uint16_t selector:5;
- } s;
-} cvmx_mdio_phy_reg_autoneg_adver_t;
-
-/**
- * PHY register 5 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5
-typedef union {
- uint16_t u16;
- struct {
- uint16_t next_page:1;
- uint16_t ack:1;
- uint16_t remote_fault:1;
- uint16_t reserved_12:1;
- uint16_t asymmetric_pause:1;
- uint16_t pause:1;
- uint16_t advert_100base_t4:1;
- uint16_t advert_100base_tx_full:1;
- uint16_t advert_100base_tx_half:1;
- uint16_t advert_10base_tx_full:1;
- uint16_t advert_10base_tx_half:1;
- uint16_t selector:5;
- } s;
-} cvmx_mdio_phy_reg_link_partner_ability_t;
-
-/**
- * PHY register 6 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6
-typedef union {
- uint16_t u16;
- struct {
- uint16_t reserved_5_15:11;
- uint16_t parallel_detection_fault:1;
- uint16_t link_partner_next_page_capable:1;
- uint16_t local_next_page_capable:1;
- uint16_t page_received:1;
- uint16_t link_partner_autoneg_capable:1;
-
- } s;
-} cvmx_mdio_phy_reg_autoneg_expansion_t;
-
-/**
- * PHY register 9 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_CONTROL_1000 9
-typedef union {
- uint16_t u16;
- struct {
- uint16_t test_mode:3;
- uint16_t manual_master_slave:1;
- uint16_t master:1;
- uint16_t port_type:1;
- uint16_t advert_1000base_t_full:1;
- uint16_t advert_1000base_t_half:1;
- uint16_t reserved_0_7:8;
- } s;
-} cvmx_mdio_phy_reg_control_1000_t;
-
-/**
- * PHY register 10 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_STATUS_1000 10
-typedef union {
- uint16_t u16;
- struct {
- uint16_t master_slave_fault:1;
- uint16_t is_master:1;
- uint16_t local_receiver_ok:1;
- uint16_t remote_receiver_ok:1;
- uint16_t remote_capable_1000base_t_full:1;
- uint16_t remote_capable_1000base_t_half:1;
- uint16_t reserved_8_9:2;
- uint16_t idle_error_count:8;
- } s;
-} cvmx_mdio_phy_reg_status_1000_t;
-
-/**
- * PHY register 15 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15
-typedef union {
- uint16_t u16;
- struct {
- uint16_t capable_1000base_x_full:1;
- uint16_t capable_1000base_x_half:1;
- uint16_t capable_1000base_t_full:1;
- uint16_t capable_1000base_t_half:1;
- uint16_t reserved_0_11:12;
- } s;
-} cvmx_mdio_phy_reg_extended_status_t;
-
-/**
- * PHY register 13 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13
-typedef union {
- uint16_t u16;
- struct {
- uint16_t function:2;
- uint16_t reserved_5_13:9;
- uint16_t devad:5;
- } s;
-} cvmx_mdio_phy_reg_mmd_control_t;
-
-/**
- * PHY register 14 from the 802.3 spec
- */
-#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14
-typedef union {
- uint16_t u16;
- struct {
- uint16_t address_data:16;
- } s;
-} cvmx_mdio_phy_reg_mmd_address_data_t;
-
-/* Operating request encodings. */
-#define MDIO_CLAUSE_22_WRITE 0
-#define MDIO_CLAUSE_22_READ 1
-
-#define MDIO_CLAUSE_45_ADDRESS 0
-#define MDIO_CLAUSE_45_WRITE 1
-#define MDIO_CLAUSE_45_READ_INC 2
-#define MDIO_CLAUSE_45_READ 3
-
-/* MMD identifiers, mostly for accessing devices within XENPAK modules. */
-#define CVMX_MMD_DEVICE_PMA_PMD 1
-#define CVMX_MMD_DEVICE_WIS 2
-#define CVMX_MMD_DEVICE_PCS 3
-#define CVMX_MMD_DEVICE_PHY_XS 4
-#define CVMX_MMD_DEVICE_DTS_XS 5
-#define CVMX_MMD_DEVICE_TC 6
-#define CVMX_MMD_DEVICE_CL22_EXT 29
-#define CVMX_MMD_DEVICE_VENDOR_1 30
-#define CVMX_MMD_DEVICE_VENDOR_2 31
-
-/* Helper function to put MDIO interface into clause 45 mode */
-static inline void __cvmx_mdio_set_clause45_mode(int bus_id)
-{
- union cvmx_smix_clk smi_clk;
- /* Put bus into clause 45 mode */
- smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
- smi_clk.s.mode = 1;
- smi_clk.s.preamble = 1;
- cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
-}
-
-/* Helper function to put MDIO interface into clause 22 mode */
-static inline void __cvmx_mdio_set_clause22_mode(int bus_id)
-{
- union cvmx_smix_clk smi_clk;
- /* Put bus into clause 22 mode */
- smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
- smi_clk.s.mode = 0;
- cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
-}
-
-/**
- * Perform an MII read. This function is used to read PHY
- * registers controlling auto negotiation.
- *
- * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
- * support multiple busses.
- * @phy_id: The MII phy id
- * @location: Register location to read
- *
- * Returns Result from the read or -1 on failure
- */
-static inline int cvmx_mdio_read(int bus_id, int phy_id, int location)
-{
- union cvmx_smix_cmd smi_cmd;
- union cvmx_smix_rd_dat smi_rd;
- int timeout = 1000;
-
- if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
- __cvmx_mdio_set_clause22_mode(bus_id);
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = location;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
- } while (smi_rd.s.pending && timeout--);
-
- if (smi_rd.s.val)
- return smi_rd.s.dat;
- else
- return -1;
-}
-
-/**
- * Perform an MII write. This function is used to write PHY
- * registers controlling auto negotiation.
- *
- * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
- * support multiple busses.
- * @phy_id: The MII phy id
- * @location: Register location to write
- * @val: Value to write
- *
- * Returns -1 on error
- * 0 on success
- */
-static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val)
-{
- union cvmx_smix_cmd smi_cmd;
- union cvmx_smix_wr_dat smi_wr;
- int timeout = 1000;
-
- if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
- __cvmx_mdio_set_clause22_mode(bus_id);
-
- smi_wr.u64 = 0;
- smi_wr.s.dat = val;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = location;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
- } while (smi_wr.s.pending && --timeout);
- if (timeout <= 0)
- return -1;
-
- return 0;
-}
-
-/**
- * Perform an IEEE 802.3 clause 45 MII read. This function is used to
- * read PHY registers controlling auto negotiation.
- *
- * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
- * support multiple busses.
- * @phy_id: The MII phy id
- * @device: MDIO Managable Device (MMD) id
- * @location: Register location to read
- *
- * Returns Result from the read or -1 on failure
- */
-
-static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device,
- int location)
-{
- union cvmx_smix_cmd smi_cmd;
- union cvmx_smix_rd_dat smi_rd;
- union cvmx_smix_wr_dat smi_wr;
- int timeout = 1000;
-
- if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
- return -1;
-
- __cvmx_mdio_set_clause45_mode(bus_id);
-
- smi_wr.u64 = 0;
- smi_wr.s.dat = location;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = device;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
- } while (smi_wr.s.pending && --timeout);
- if (timeout <= 0) {
- cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
- "device %2d register %2d TIME OUT(address)\n",
- bus_id, phy_id, device, location);
- return -1;
- }
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = device;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
- } while (smi_rd.s.pending && --timeout);
-
- if (timeout <= 0) {
- cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
- "device %2d register %2d TIME OUT(data)\n",
- bus_id, phy_id, device, location);
- return -1;
- }
-
- if (smi_rd.s.val)
- return smi_rd.s.dat;
- else {
- cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
- "device %2d register %2d INVALID READ\n",
- bus_id, phy_id, device, location);
- return -1;
- }
-}
-
-/**
- * Perform an IEEE 802.3 clause 45 MII write. This function is used to
- * write PHY registers controlling auto negotiation.
- *
- * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
- * support multiple busses.
- * @phy_id: The MII phy id
- * @device: MDIO Managable Device (MMD) id
- * @location: Register location to write
- * @val: Value to write
- *
- * Returns -1 on error
- * 0 on success
- */
-static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device,
- int location, int val)
-{
- union cvmx_smix_cmd smi_cmd;
- union cvmx_smix_wr_dat smi_wr;
- int timeout = 1000;
-
- if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
- return -1;
-
- __cvmx_mdio_set_clause45_mode(bus_id);
-
- smi_wr.u64 = 0;
- smi_wr.s.dat = location;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = device;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
- } while (smi_wr.s.pending && --timeout);
- if (timeout <= 0)
- return -1;
-
- smi_wr.u64 = 0;
- smi_wr.s.dat = val;
- cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
-
- smi_cmd.u64 = 0;
- smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE;
- smi_cmd.s.phy_adr = phy_id;
- smi_cmd.s.reg_adr = device;
- cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
-
- do {
- cvmx_wait(1000);
- smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
- } while (smi_wr.s.pending && --timeout);
- if (timeout <= 0)
- return -1;
-
- return 0;
-}
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-packet.h b/drivers/staging/octeon/cvmx-packet.h
deleted file mode 100644
index 62ffe78a..0000000
--- a/drivers/staging/octeon/cvmx-packet.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * Packet buffer defines.
- */
-
-#ifndef __CVMX_PACKET_H__
-#define __CVMX_PACKET_H__
-
-/**
- * This structure defines a buffer pointer on Octeon
- */
-union cvmx_buf_ptr {
- void *ptr;
- uint64_t u64;
- struct {
- /*
- * if set, invert the "free" pick of the overall
- * packet. HW always sets this bit to 0 on inbound
- * packet
- */
- uint64_t i:1;
- /*
- * Indicates the amount to back up to get to the
- * buffer start in cache lines. In most cases this is
- * less than one complete cache line, so the value is
- * zero.
- */
- uint64_t back:4;
- /* The pool that the buffer came from / goes to */
- uint64_t pool:3;
- /* The size of the segment pointed to by addr (in bytes) */
- uint64_t size:16;
- /* Pointer to the first byte of the data, NOT buffer */
- uint64_t addr:40;
- } s;
-};
-
-#endif /* __CVMX_PACKET_H__ */
diff --git a/drivers/staging/octeon/cvmx-pcsx-defs.h b/drivers/staging/octeon/cvmx-pcsx-defs.h
deleted file mode 100644
index d45952d..0000000
--- a/drivers/staging/octeon/cvmx-pcsx-defs.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_PCSX_DEFS_H__
-#define __CVMX_PCSX_DEFS_H__
-
-#define CVMX_PCSX_ANX_ADV_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001010ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_ANX_EXT_ST_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001028ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_ANX_LP_ABIL_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001018ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_ANX_RESULTS_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001020ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_INTX_EN_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001088ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_INTX_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001080ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_LINKX_TIMER_COUNT_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001040ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_LOG_ANLX_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001090ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_MISCX_CTL_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001078ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_MRX_CONTROL_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001000ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_MRX_STATUS_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001008ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_RXX_STATES_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001058ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_RXX_SYNC_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001050ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_SGMX_AN_ADV_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001068ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_SGMX_LP_ADV_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001070ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_TXX_STATES_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001060ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSX_TX_RXX_POLARITY_REG(offset, block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0001048ull + (((offset) & 3) * 1024) + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_pcsx_anx_adv_reg {
- uint64_t u64;
- struct cvmx_pcsx_anx_adv_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t np:1;
- uint64_t reserved_14_14:1;
- uint64_t rem_flt:2;
- uint64_t reserved_9_11:3;
- uint64_t pause:2;
- uint64_t hfd:1;
- uint64_t fd:1;
- uint64_t reserved_0_4:5;
- } s;
- struct cvmx_pcsx_anx_adv_reg_s cn52xx;
- struct cvmx_pcsx_anx_adv_reg_s cn52xxp1;
- struct cvmx_pcsx_anx_adv_reg_s cn56xx;
- struct cvmx_pcsx_anx_adv_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_anx_ext_st_reg {
- uint64_t u64;
- struct cvmx_pcsx_anx_ext_st_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t thou_xfd:1;
- uint64_t thou_xhd:1;
- uint64_t thou_tfd:1;
- uint64_t thou_thd:1;
- uint64_t reserved_0_11:12;
- } s;
- struct cvmx_pcsx_anx_ext_st_reg_s cn52xx;
- struct cvmx_pcsx_anx_ext_st_reg_s cn52xxp1;
- struct cvmx_pcsx_anx_ext_st_reg_s cn56xx;
- struct cvmx_pcsx_anx_ext_st_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_anx_lp_abil_reg {
- uint64_t u64;
- struct cvmx_pcsx_anx_lp_abil_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t np:1;
- uint64_t ack:1;
- uint64_t rem_flt:2;
- uint64_t reserved_9_11:3;
- uint64_t pause:2;
- uint64_t hfd:1;
- uint64_t fd:1;
- uint64_t reserved_0_4:5;
- } s;
- struct cvmx_pcsx_anx_lp_abil_reg_s cn52xx;
- struct cvmx_pcsx_anx_lp_abil_reg_s cn52xxp1;
- struct cvmx_pcsx_anx_lp_abil_reg_s cn56xx;
- struct cvmx_pcsx_anx_lp_abil_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_anx_results_reg {
- uint64_t u64;
- struct cvmx_pcsx_anx_results_reg_s {
- uint64_t reserved_7_63:57;
- uint64_t pause:2;
- uint64_t spd:2;
- uint64_t an_cpt:1;
- uint64_t dup:1;
- uint64_t link_ok:1;
- } s;
- struct cvmx_pcsx_anx_results_reg_s cn52xx;
- struct cvmx_pcsx_anx_results_reg_s cn52xxp1;
- struct cvmx_pcsx_anx_results_reg_s cn56xx;
- struct cvmx_pcsx_anx_results_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_intx_en_reg {
- uint64_t u64;
- struct cvmx_pcsx_intx_en_reg_s {
- uint64_t reserved_12_63:52;
- uint64_t dup:1;
- uint64_t sync_bad_en:1;
- uint64_t an_bad_en:1;
- uint64_t rxlock_en:1;
- uint64_t rxbad_en:1;
- uint64_t rxerr_en:1;
- uint64_t txbad_en:1;
- uint64_t txfifo_en:1;
- uint64_t txfifu_en:1;
- uint64_t an_err_en:1;
- uint64_t xmit_en:1;
- uint64_t lnkspd_en:1;
- } s;
- struct cvmx_pcsx_intx_en_reg_s cn52xx;
- struct cvmx_pcsx_intx_en_reg_s cn52xxp1;
- struct cvmx_pcsx_intx_en_reg_s cn56xx;
- struct cvmx_pcsx_intx_en_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_intx_reg {
- uint64_t u64;
- struct cvmx_pcsx_intx_reg_s {
- uint64_t reserved_12_63:52;
- uint64_t dup:1;
- uint64_t sync_bad:1;
- uint64_t an_bad:1;
- uint64_t rxlock:1;
- uint64_t rxbad:1;
- uint64_t rxerr:1;
- uint64_t txbad:1;
- uint64_t txfifo:1;
- uint64_t txfifu:1;
- uint64_t an_err:1;
- uint64_t xmit:1;
- uint64_t lnkspd:1;
- } s;
- struct cvmx_pcsx_intx_reg_s cn52xx;
- struct cvmx_pcsx_intx_reg_s cn52xxp1;
- struct cvmx_pcsx_intx_reg_s cn56xx;
- struct cvmx_pcsx_intx_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_linkx_timer_count_reg {
- uint64_t u64;
- struct cvmx_pcsx_linkx_timer_count_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t count:16;
- } s;
- struct cvmx_pcsx_linkx_timer_count_reg_s cn52xx;
- struct cvmx_pcsx_linkx_timer_count_reg_s cn52xxp1;
- struct cvmx_pcsx_linkx_timer_count_reg_s cn56xx;
- struct cvmx_pcsx_linkx_timer_count_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_log_anlx_reg {
- uint64_t u64;
- struct cvmx_pcsx_log_anlx_reg_s {
- uint64_t reserved_4_63:60;
- uint64_t lafifovfl:1;
- uint64_t la_en:1;
- uint64_t pkt_sz:2;
- } s;
- struct cvmx_pcsx_log_anlx_reg_s cn52xx;
- struct cvmx_pcsx_log_anlx_reg_s cn52xxp1;
- struct cvmx_pcsx_log_anlx_reg_s cn56xx;
- struct cvmx_pcsx_log_anlx_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_miscx_ctl_reg {
- uint64_t u64;
- struct cvmx_pcsx_miscx_ctl_reg_s {
- uint64_t reserved_13_63:51;
- uint64_t sgmii:1;
- uint64_t gmxeno:1;
- uint64_t loopbck2:1;
- uint64_t mac_phy:1;
- uint64_t mode:1;
- uint64_t an_ovrd:1;
- uint64_t samp_pt:7;
- } s;
- struct cvmx_pcsx_miscx_ctl_reg_s cn52xx;
- struct cvmx_pcsx_miscx_ctl_reg_s cn52xxp1;
- struct cvmx_pcsx_miscx_ctl_reg_s cn56xx;
- struct cvmx_pcsx_miscx_ctl_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_mrx_control_reg {
- uint64_t u64;
- struct cvmx_pcsx_mrx_control_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t reset:1;
- uint64_t loopbck1:1;
- uint64_t spdlsb:1;
- uint64_t an_en:1;
- uint64_t pwr_dn:1;
- uint64_t reserved_10_10:1;
- uint64_t rst_an:1;
- uint64_t dup:1;
- uint64_t coltst:1;
- uint64_t spdmsb:1;
- uint64_t uni:1;
- uint64_t reserved_0_4:5;
- } s;
- struct cvmx_pcsx_mrx_control_reg_s cn52xx;
- struct cvmx_pcsx_mrx_control_reg_s cn52xxp1;
- struct cvmx_pcsx_mrx_control_reg_s cn56xx;
- struct cvmx_pcsx_mrx_control_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_mrx_status_reg {
- uint64_t u64;
- struct cvmx_pcsx_mrx_status_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t hun_t4:1;
- uint64_t hun_xfd:1;
- uint64_t hun_xhd:1;
- uint64_t ten_fd:1;
- uint64_t ten_hd:1;
- uint64_t hun_t2fd:1;
- uint64_t hun_t2hd:1;
- uint64_t ext_st:1;
- uint64_t reserved_7_7:1;
- uint64_t prb_sup:1;
- uint64_t an_cpt:1;
- uint64_t rm_flt:1;
- uint64_t an_abil:1;
- uint64_t lnk_st:1;
- uint64_t reserved_1_1:1;
- uint64_t extnd:1;
- } s;
- struct cvmx_pcsx_mrx_status_reg_s cn52xx;
- struct cvmx_pcsx_mrx_status_reg_s cn52xxp1;
- struct cvmx_pcsx_mrx_status_reg_s cn56xx;
- struct cvmx_pcsx_mrx_status_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_rxx_states_reg {
- uint64_t u64;
- struct cvmx_pcsx_rxx_states_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t rx_bad:1;
- uint64_t rx_st:5;
- uint64_t sync_bad:1;
- uint64_t sync:4;
- uint64_t an_bad:1;
- uint64_t an_st:4;
- } s;
- struct cvmx_pcsx_rxx_states_reg_s cn52xx;
- struct cvmx_pcsx_rxx_states_reg_s cn52xxp1;
- struct cvmx_pcsx_rxx_states_reg_s cn56xx;
- struct cvmx_pcsx_rxx_states_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_rxx_sync_reg {
- uint64_t u64;
- struct cvmx_pcsx_rxx_sync_reg_s {
- uint64_t reserved_2_63:62;
- uint64_t sync:1;
- uint64_t bit_lock:1;
- } s;
- struct cvmx_pcsx_rxx_sync_reg_s cn52xx;
- struct cvmx_pcsx_rxx_sync_reg_s cn52xxp1;
- struct cvmx_pcsx_rxx_sync_reg_s cn56xx;
- struct cvmx_pcsx_rxx_sync_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_sgmx_an_adv_reg {
- uint64_t u64;
- struct cvmx_pcsx_sgmx_an_adv_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t link:1;
- uint64_t ack:1;
- uint64_t reserved_13_13:1;
- uint64_t dup:1;
- uint64_t speed:2;
- uint64_t reserved_1_9:9;
- uint64_t one:1;
- } s;
- struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xx;
- struct cvmx_pcsx_sgmx_an_adv_reg_s cn52xxp1;
- struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xx;
- struct cvmx_pcsx_sgmx_an_adv_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_sgmx_lp_adv_reg {
- uint64_t u64;
- struct cvmx_pcsx_sgmx_lp_adv_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t link:1;
- uint64_t reserved_13_14:2;
- uint64_t dup:1;
- uint64_t speed:2;
- uint64_t reserved_1_9:9;
- uint64_t one:1;
- } s;
- struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xx;
- struct cvmx_pcsx_sgmx_lp_adv_reg_s cn52xxp1;
- struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xx;
- struct cvmx_pcsx_sgmx_lp_adv_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_txx_states_reg {
- uint64_t u64;
- struct cvmx_pcsx_txx_states_reg_s {
- uint64_t reserved_7_63:57;
- uint64_t xmit:2;
- uint64_t tx_bad:1;
- uint64_t ord_st:4;
- } s;
- struct cvmx_pcsx_txx_states_reg_s cn52xx;
- struct cvmx_pcsx_txx_states_reg_s cn52xxp1;
- struct cvmx_pcsx_txx_states_reg_s cn56xx;
- struct cvmx_pcsx_txx_states_reg_s cn56xxp1;
-};
-
-union cvmx_pcsx_tx_rxx_polarity_reg {
- uint64_t u64;
- struct cvmx_pcsx_tx_rxx_polarity_reg_s {
- uint64_t reserved_4_63:60;
- uint64_t rxovrd:1;
- uint64_t autorxpl:1;
- uint64_t rxplrt:1;
- uint64_t txplrt:1;
- } s;
- struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xx;
- struct cvmx_pcsx_tx_rxx_polarity_reg_s cn52xxp1;
- struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xx;
- struct cvmx_pcsx_tx_rxx_polarity_reg_s cn56xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-pcsxx-defs.h b/drivers/staging/octeon/cvmx-pcsxx-defs.h
deleted file mode 100644
index 55d120f..0000000
--- a/drivers/staging/octeon/cvmx-pcsxx-defs.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_PCSXX_DEFS_H__
-#define __CVMX_PCSXX_DEFS_H__
-
-#define CVMX_PCSXX_10GBX_STATUS_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000828ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_BIST_STATUS_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000870ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_BIT_LOCK_STATUS_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000850ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_CONTROL1_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000800ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_CONTROL2_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000818ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_INT_EN_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000860ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_INT_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000858ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_LOG_ANL_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000868ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_MISC_CTL_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000848ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_RX_SYNC_STATES_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000838ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_SPD_ABIL_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000810ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_STATUS1_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000808ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_STATUS2_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000820ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_TX_RX_POLARITY_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000840ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_PCSXX_TX_RX_STATES_REG(block_id) \
- CVMX_ADD_IO_SEG(0x00011800B0000830ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_pcsxx_10gbx_status_reg {
- uint64_t u64;
- struct cvmx_pcsxx_10gbx_status_reg_s {
- uint64_t reserved_13_63:51;
- uint64_t alignd:1;
- uint64_t pattst:1;
- uint64_t reserved_4_10:7;
- uint64_t l3sync:1;
- uint64_t l2sync:1;
- uint64_t l1sync:1;
- uint64_t l0sync:1;
- } s;
- struct cvmx_pcsxx_10gbx_status_reg_s cn52xx;
- struct cvmx_pcsxx_10gbx_status_reg_s cn52xxp1;
- struct cvmx_pcsxx_10gbx_status_reg_s cn56xx;
- struct cvmx_pcsxx_10gbx_status_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_bist_status_reg {
- uint64_t u64;
- struct cvmx_pcsxx_bist_status_reg_s {
- uint64_t reserved_1_63:63;
- uint64_t bist_status:1;
- } s;
- struct cvmx_pcsxx_bist_status_reg_s cn52xx;
- struct cvmx_pcsxx_bist_status_reg_s cn52xxp1;
- struct cvmx_pcsxx_bist_status_reg_s cn56xx;
- struct cvmx_pcsxx_bist_status_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_bit_lock_status_reg {
- uint64_t u64;
- struct cvmx_pcsxx_bit_lock_status_reg_s {
- uint64_t reserved_4_63:60;
- uint64_t bitlck3:1;
- uint64_t bitlck2:1;
- uint64_t bitlck1:1;
- uint64_t bitlck0:1;
- } s;
- struct cvmx_pcsxx_bit_lock_status_reg_s cn52xx;
- struct cvmx_pcsxx_bit_lock_status_reg_s cn52xxp1;
- struct cvmx_pcsxx_bit_lock_status_reg_s cn56xx;
- struct cvmx_pcsxx_bit_lock_status_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_control1_reg {
- uint64_t u64;
- struct cvmx_pcsxx_control1_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t reset:1;
- uint64_t loopbck1:1;
- uint64_t spdsel1:1;
- uint64_t reserved_12_12:1;
- uint64_t lo_pwr:1;
- uint64_t reserved_7_10:4;
- uint64_t spdsel0:1;
- uint64_t spd:4;
- uint64_t reserved_0_1:2;
- } s;
- struct cvmx_pcsxx_control1_reg_s cn52xx;
- struct cvmx_pcsxx_control1_reg_s cn52xxp1;
- struct cvmx_pcsxx_control1_reg_s cn56xx;
- struct cvmx_pcsxx_control1_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_control2_reg {
- uint64_t u64;
- struct cvmx_pcsxx_control2_reg_s {
- uint64_t reserved_2_63:62;
- uint64_t type:2;
- } s;
- struct cvmx_pcsxx_control2_reg_s cn52xx;
- struct cvmx_pcsxx_control2_reg_s cn52xxp1;
- struct cvmx_pcsxx_control2_reg_s cn56xx;
- struct cvmx_pcsxx_control2_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_int_en_reg {
- uint64_t u64;
- struct cvmx_pcsxx_int_en_reg_s {
- uint64_t reserved_6_63:58;
- uint64_t algnlos_en:1;
- uint64_t synlos_en:1;
- uint64_t bitlckls_en:1;
- uint64_t rxsynbad_en:1;
- uint64_t rxbad_en:1;
- uint64_t txflt_en:1;
- } s;
- struct cvmx_pcsxx_int_en_reg_s cn52xx;
- struct cvmx_pcsxx_int_en_reg_s cn52xxp1;
- struct cvmx_pcsxx_int_en_reg_s cn56xx;
- struct cvmx_pcsxx_int_en_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_int_reg {
- uint64_t u64;
- struct cvmx_pcsxx_int_reg_s {
- uint64_t reserved_6_63:58;
- uint64_t algnlos:1;
- uint64_t synlos:1;
- uint64_t bitlckls:1;
- uint64_t rxsynbad:1;
- uint64_t rxbad:1;
- uint64_t txflt:1;
- } s;
- struct cvmx_pcsxx_int_reg_s cn52xx;
- struct cvmx_pcsxx_int_reg_s cn52xxp1;
- struct cvmx_pcsxx_int_reg_s cn56xx;
- struct cvmx_pcsxx_int_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_log_anl_reg {
- uint64_t u64;
- struct cvmx_pcsxx_log_anl_reg_s {
- uint64_t reserved_7_63:57;
- uint64_t enc_mode:1;
- uint64_t drop_ln:2;
- uint64_t lafifovfl:1;
- uint64_t la_en:1;
- uint64_t pkt_sz:2;
- } s;
- struct cvmx_pcsxx_log_anl_reg_s cn52xx;
- struct cvmx_pcsxx_log_anl_reg_s cn52xxp1;
- struct cvmx_pcsxx_log_anl_reg_s cn56xx;
- struct cvmx_pcsxx_log_anl_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_misc_ctl_reg {
- uint64_t u64;
- struct cvmx_pcsxx_misc_ctl_reg_s {
- uint64_t reserved_4_63:60;
- uint64_t tx_swap:1;
- uint64_t rx_swap:1;
- uint64_t xaui:1;
- uint64_t gmxeno:1;
- } s;
- struct cvmx_pcsxx_misc_ctl_reg_s cn52xx;
- struct cvmx_pcsxx_misc_ctl_reg_s cn52xxp1;
- struct cvmx_pcsxx_misc_ctl_reg_s cn56xx;
- struct cvmx_pcsxx_misc_ctl_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_rx_sync_states_reg {
- uint64_t u64;
- struct cvmx_pcsxx_rx_sync_states_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t sync3st:4;
- uint64_t sync2st:4;
- uint64_t sync1st:4;
- uint64_t sync0st:4;
- } s;
- struct cvmx_pcsxx_rx_sync_states_reg_s cn52xx;
- struct cvmx_pcsxx_rx_sync_states_reg_s cn52xxp1;
- struct cvmx_pcsxx_rx_sync_states_reg_s cn56xx;
- struct cvmx_pcsxx_rx_sync_states_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_spd_abil_reg {
- uint64_t u64;
- struct cvmx_pcsxx_spd_abil_reg_s {
- uint64_t reserved_2_63:62;
- uint64_t tenpasst:1;
- uint64_t tengb:1;
- } s;
- struct cvmx_pcsxx_spd_abil_reg_s cn52xx;
- struct cvmx_pcsxx_spd_abil_reg_s cn52xxp1;
- struct cvmx_pcsxx_spd_abil_reg_s cn56xx;
- struct cvmx_pcsxx_spd_abil_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_status1_reg {
- uint64_t u64;
- struct cvmx_pcsxx_status1_reg_s {
- uint64_t reserved_8_63:56;
- uint64_t flt:1;
- uint64_t reserved_3_6:4;
- uint64_t rcv_lnk:1;
- uint64_t lpable:1;
- uint64_t reserved_0_0:1;
- } s;
- struct cvmx_pcsxx_status1_reg_s cn52xx;
- struct cvmx_pcsxx_status1_reg_s cn52xxp1;
- struct cvmx_pcsxx_status1_reg_s cn56xx;
- struct cvmx_pcsxx_status1_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_status2_reg {
- uint64_t u64;
- struct cvmx_pcsxx_status2_reg_s {
- uint64_t reserved_16_63:48;
- uint64_t dev:2;
- uint64_t reserved_12_13:2;
- uint64_t xmtflt:1;
- uint64_t rcvflt:1;
- uint64_t reserved_3_9:7;
- uint64_t tengb_w:1;
- uint64_t tengb_x:1;
- uint64_t tengb_r:1;
- } s;
- struct cvmx_pcsxx_status2_reg_s cn52xx;
- struct cvmx_pcsxx_status2_reg_s cn52xxp1;
- struct cvmx_pcsxx_status2_reg_s cn56xx;
- struct cvmx_pcsxx_status2_reg_s cn56xxp1;
-};
-
-union cvmx_pcsxx_tx_rx_polarity_reg {
- uint64_t u64;
- struct cvmx_pcsxx_tx_rx_polarity_reg_s {
- uint64_t reserved_10_63:54;
- uint64_t xor_rxplrt:4;
- uint64_t xor_txplrt:4;
- uint64_t rxplrt:1;
- uint64_t txplrt:1;
- } s;
- struct cvmx_pcsxx_tx_rx_polarity_reg_s cn52xx;
- struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 {
- uint64_t reserved_2_63:62;
- uint64_t rxplrt:1;
- uint64_t txplrt:1;
- } cn52xxp1;
- struct cvmx_pcsxx_tx_rx_polarity_reg_s cn56xx;
- struct cvmx_pcsxx_tx_rx_polarity_reg_cn52xxp1 cn56xxp1;
-};
-
-union cvmx_pcsxx_tx_rx_states_reg {
- uint64_t u64;
- struct cvmx_pcsxx_tx_rx_states_reg_s {
- uint64_t reserved_14_63:50;
- uint64_t term_err:1;
- uint64_t syn3bad:1;
- uint64_t syn2bad:1;
- uint64_t syn1bad:1;
- uint64_t syn0bad:1;
- uint64_t rxbad:1;
- uint64_t algn_st:3;
- uint64_t rx_st:2;
- uint64_t tx_st:3;
- } s;
- struct cvmx_pcsxx_tx_rx_states_reg_s cn52xx;
- struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 {
- uint64_t reserved_13_63:51;
- uint64_t syn3bad:1;
- uint64_t syn2bad:1;
- uint64_t syn1bad:1;
- uint64_t syn0bad:1;
- uint64_t rxbad:1;
- uint64_t algn_st:3;
- uint64_t rx_st:2;
- uint64_t tx_st:3;
- } cn52xxp1;
- struct cvmx_pcsxx_tx_rx_states_reg_s cn56xx;
- struct cvmx_pcsxx_tx_rx_states_reg_cn52xxp1 cn56xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-pip-defs.h b/drivers/staging/octeon/cvmx-pip-defs.h
deleted file mode 100644
index 5a36910..0000000
--- a/drivers/staging/octeon/cvmx-pip-defs.h
+++ /dev/null
@@ -1,1267 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_PIP_DEFS_H__
-#define __CVMX_PIP_DEFS_H__
-
-/*
- * Enumeration representing the amount of packet processing
- * and validation performed by the input hardware.
- */
-enum cvmx_pip_port_parse_mode {
- /*
- * Packet input doesn't perform any processing of the input
- * packet.
- */
- CVMX_PIP_PORT_CFG_MODE_NONE = 0ull,
- /*
- * Full packet processing is performed with pointer starting
- * at the L2 (ethernet MAC) header.
- */
- CVMX_PIP_PORT_CFG_MODE_SKIPL2 = 1ull,
- /*
- * Input packets are assumed to be IP. Results from non IP
- * packets is undefined. Pointers reference the beginning of
- * the IP header.
- */
- CVMX_PIP_PORT_CFG_MODE_SKIPIP = 2ull
-};
-
-#define CVMX_PIP_BCK_PRS \
- CVMX_ADD_IO_SEG(0x00011800A0000038ull)
-#define CVMX_PIP_BIST_STATUS \
- CVMX_ADD_IO_SEG(0x00011800A0000000ull)
-#define CVMX_PIP_CRC_CTLX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000040ull + (((offset) & 1) * 8))
-#define CVMX_PIP_CRC_IVX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000050ull + (((offset) & 1) * 8))
-#define CVMX_PIP_DEC_IPSECX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000080ull + (((offset) & 3) * 8))
-#define CVMX_PIP_DSA_SRC_GRP \
- CVMX_ADD_IO_SEG(0x00011800A0000190ull)
-#define CVMX_PIP_DSA_VID_GRP \
- CVMX_ADD_IO_SEG(0x00011800A0000198ull)
-#define CVMX_PIP_FRM_LEN_CHKX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000180ull + (((offset) & 1) * 8))
-#define CVMX_PIP_GBL_CFG \
- CVMX_ADD_IO_SEG(0x00011800A0000028ull)
-#define CVMX_PIP_GBL_CTL \
- CVMX_ADD_IO_SEG(0x00011800A0000020ull)
-#define CVMX_PIP_HG_PRI_QOS \
- CVMX_ADD_IO_SEG(0x00011800A00001A0ull)
-#define CVMX_PIP_INT_EN \
- CVMX_ADD_IO_SEG(0x00011800A0000010ull)
-#define CVMX_PIP_INT_REG \
- CVMX_ADD_IO_SEG(0x00011800A0000008ull)
-#define CVMX_PIP_IP_OFFSET \
- CVMX_ADD_IO_SEG(0x00011800A0000060ull)
-#define CVMX_PIP_PRT_CFGX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000200ull + (((offset) & 63) * 8))
-#define CVMX_PIP_PRT_TAGX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000400ull + (((offset) & 63) * 8))
-#define CVMX_PIP_QOS_DIFFX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000600ull + (((offset) & 63) * 8))
-#define CVMX_PIP_QOS_VLANX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A00000C0ull + (((offset) & 7) * 8))
-#define CVMX_PIP_QOS_WATCHX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000100ull + (((offset) & 7) * 8))
-#define CVMX_PIP_RAW_WORD \
- CVMX_ADD_IO_SEG(0x00011800A00000B0ull)
-#define CVMX_PIP_SFT_RST \
- CVMX_ADD_IO_SEG(0x00011800A0000030ull)
-#define CVMX_PIP_STAT0_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000800ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT1_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000808ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT2_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000810ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT3_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000818ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT4_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000820ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT5_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000828ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT6_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000830ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT7_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000838ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT8_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000840ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT9_PRTX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0000848ull + (((offset) & 63) * 80))
-#define CVMX_PIP_STAT_CTL \
- CVMX_ADD_IO_SEG(0x00011800A0000018ull)
-#define CVMX_PIP_STAT_INB_ERRSX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0001A10ull + (((offset) & 63) * 32))
-#define CVMX_PIP_STAT_INB_OCTSX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0001A08ull + (((offset) & 63) * 32))
-#define CVMX_PIP_STAT_INB_PKTSX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0001A00ull + (((offset) & 63) * 32))
-#define CVMX_PIP_TAG_INCX(offset) \
- CVMX_ADD_IO_SEG(0x00011800A0001800ull + (((offset) & 63) * 8))
-#define CVMX_PIP_TAG_MASK \
- CVMX_ADD_IO_SEG(0x00011800A0000070ull)
-#define CVMX_PIP_TAG_SECRET \
- CVMX_ADD_IO_SEG(0x00011800A0000068ull)
-#define CVMX_PIP_TODO_ENTRY \
- CVMX_ADD_IO_SEG(0x00011800A0000078ull)
-
-union cvmx_pip_bck_prs {
- uint64_t u64;
- struct cvmx_pip_bck_prs_s {
- uint64_t bckprs:1;
- uint64_t reserved_13_62:50;
- uint64_t hiwater:5;
- uint64_t reserved_5_7:3;
- uint64_t lowater:5;
- } s;
- struct cvmx_pip_bck_prs_s cn38xx;
- struct cvmx_pip_bck_prs_s cn38xxp2;
- struct cvmx_pip_bck_prs_s cn56xx;
- struct cvmx_pip_bck_prs_s cn56xxp1;
- struct cvmx_pip_bck_prs_s cn58xx;
- struct cvmx_pip_bck_prs_s cn58xxp1;
-};
-
-union cvmx_pip_bist_status {
- uint64_t u64;
- struct cvmx_pip_bist_status_s {
- uint64_t reserved_18_63:46;
- uint64_t bist:18;
- } s;
- struct cvmx_pip_bist_status_s cn30xx;
- struct cvmx_pip_bist_status_s cn31xx;
- struct cvmx_pip_bist_status_s cn38xx;
- struct cvmx_pip_bist_status_s cn38xxp2;
- struct cvmx_pip_bist_status_cn50xx {
- uint64_t reserved_17_63:47;
- uint64_t bist:17;
- } cn50xx;
- struct cvmx_pip_bist_status_s cn52xx;
- struct cvmx_pip_bist_status_s cn52xxp1;
- struct cvmx_pip_bist_status_s cn56xx;
- struct cvmx_pip_bist_status_s cn56xxp1;
- struct cvmx_pip_bist_status_s cn58xx;
- struct cvmx_pip_bist_status_s cn58xxp1;
-};
-
-union cvmx_pip_crc_ctlx {
- uint64_t u64;
- struct cvmx_pip_crc_ctlx_s {
- uint64_t reserved_2_63:62;
- uint64_t invres:1;
- uint64_t reflect:1;
- } s;
- struct cvmx_pip_crc_ctlx_s cn38xx;
- struct cvmx_pip_crc_ctlx_s cn38xxp2;
- struct cvmx_pip_crc_ctlx_s cn58xx;
- struct cvmx_pip_crc_ctlx_s cn58xxp1;
-};
-
-union cvmx_pip_crc_ivx {
- uint64_t u64;
- struct cvmx_pip_crc_ivx_s {
- uint64_t reserved_32_63:32;
- uint64_t iv:32;
- } s;
- struct cvmx_pip_crc_ivx_s cn38xx;
- struct cvmx_pip_crc_ivx_s cn38xxp2;
- struct cvmx_pip_crc_ivx_s cn58xx;
- struct cvmx_pip_crc_ivx_s cn58xxp1;
-};
-
-union cvmx_pip_dec_ipsecx {
- uint64_t u64;
- struct cvmx_pip_dec_ipsecx_s {
- uint64_t reserved_18_63:46;
- uint64_t tcp:1;
- uint64_t udp:1;
- uint64_t dprt:16;
- } s;
- struct cvmx_pip_dec_ipsecx_s cn30xx;
- struct cvmx_pip_dec_ipsecx_s cn31xx;
- struct cvmx_pip_dec_ipsecx_s cn38xx;
- struct cvmx_pip_dec_ipsecx_s cn38xxp2;
- struct cvmx_pip_dec_ipsecx_s cn50xx;
- struct cvmx_pip_dec_ipsecx_s cn52xx;
- struct cvmx_pip_dec_ipsecx_s cn52xxp1;
- struct cvmx_pip_dec_ipsecx_s cn56xx;
- struct cvmx_pip_dec_ipsecx_s cn56xxp1;
- struct cvmx_pip_dec_ipsecx_s cn58xx;
- struct cvmx_pip_dec_ipsecx_s cn58xxp1;
-};
-
-union cvmx_pip_dsa_src_grp {
- uint64_t u64;
- struct cvmx_pip_dsa_src_grp_s {
- uint64_t map15:4;
- uint64_t map14:4;
- uint64_t map13:4;
- uint64_t map12:4;
- uint64_t map11:4;
- uint64_t map10:4;
- uint64_t map9:4;
- uint64_t map8:4;
- uint64_t map7:4;
- uint64_t map6:4;
- uint64_t map5:4;
- uint64_t map4:4;
- uint64_t map3:4;
- uint64_t map2:4;
- uint64_t map1:4;
- uint64_t map0:4;
- } s;
- struct cvmx_pip_dsa_src_grp_s cn52xx;
- struct cvmx_pip_dsa_src_grp_s cn52xxp1;
- struct cvmx_pip_dsa_src_grp_s cn56xx;
-};
-
-union cvmx_pip_dsa_vid_grp {
- uint64_t u64;
- struct cvmx_pip_dsa_vid_grp_s {
- uint64_t map15:4;
- uint64_t map14:4;
- uint64_t map13:4;
- uint64_t map12:4;
- uint64_t map11:4;
- uint64_t map10:4;
- uint64_t map9:4;
- uint64_t map8:4;
- uint64_t map7:4;
- uint64_t map6:4;
- uint64_t map5:4;
- uint64_t map4:4;
- uint64_t map3:4;
- uint64_t map2:4;
- uint64_t map1:4;
- uint64_t map0:4;
- } s;
- struct cvmx_pip_dsa_vid_grp_s cn52xx;
- struct cvmx_pip_dsa_vid_grp_s cn52xxp1;
- struct cvmx_pip_dsa_vid_grp_s cn56xx;
-};
-
-union cvmx_pip_frm_len_chkx {
- uint64_t u64;
- struct cvmx_pip_frm_len_chkx_s {
- uint64_t reserved_32_63:32;
- uint64_t maxlen:16;
- uint64_t minlen:16;
- } s;
- struct cvmx_pip_frm_len_chkx_s cn50xx;
- struct cvmx_pip_frm_len_chkx_s cn52xx;
- struct cvmx_pip_frm_len_chkx_s cn52xxp1;
- struct cvmx_pip_frm_len_chkx_s cn56xx;
- struct cvmx_pip_frm_len_chkx_s cn56xxp1;
-};
-
-union cvmx_pip_gbl_cfg {
- uint64_t u64;
- struct cvmx_pip_gbl_cfg_s {
- uint64_t reserved_19_63:45;
- uint64_t tag_syn:1;
- uint64_t ip6_udp:1;
- uint64_t max_l2:1;
- uint64_t reserved_11_15:5;
- uint64_t raw_shf:3;
- uint64_t reserved_3_7:5;
- uint64_t nip_shf:3;
- } s;
- struct cvmx_pip_gbl_cfg_s cn30xx;
- struct cvmx_pip_gbl_cfg_s cn31xx;
- struct cvmx_pip_gbl_cfg_s cn38xx;
- struct cvmx_pip_gbl_cfg_s cn38xxp2;
- struct cvmx_pip_gbl_cfg_s cn50xx;
- struct cvmx_pip_gbl_cfg_s cn52xx;
- struct cvmx_pip_gbl_cfg_s cn52xxp1;
- struct cvmx_pip_gbl_cfg_s cn56xx;
- struct cvmx_pip_gbl_cfg_s cn56xxp1;
- struct cvmx_pip_gbl_cfg_s cn58xx;
- struct cvmx_pip_gbl_cfg_s cn58xxp1;
-};
-
-union cvmx_pip_gbl_ctl {
- uint64_t u64;
- struct cvmx_pip_gbl_ctl_s {
- uint64_t reserved_27_63:37;
- uint64_t dsa_grp_tvid:1;
- uint64_t dsa_grp_scmd:1;
- uint64_t dsa_grp_sid:1;
- uint64_t reserved_21_23:3;
- uint64_t ring_en:1;
- uint64_t reserved_17_19:3;
- uint64_t ignrs:1;
- uint64_t vs_wqe:1;
- uint64_t vs_qos:1;
- uint64_t l2_mal:1;
- uint64_t tcp_flag:1;
- uint64_t l4_len:1;
- uint64_t l4_chk:1;
- uint64_t l4_prt:1;
- uint64_t l4_mal:1;
- uint64_t reserved_6_7:2;
- uint64_t ip6_eext:2;
- uint64_t ip4_opts:1;
- uint64_t ip_hop:1;
- uint64_t ip_mal:1;
- uint64_t ip_chk:1;
- } s;
- struct cvmx_pip_gbl_ctl_cn30xx {
- uint64_t reserved_17_63:47;
- uint64_t ignrs:1;
- uint64_t vs_wqe:1;
- uint64_t vs_qos:1;
- uint64_t l2_mal:1;
- uint64_t tcp_flag:1;
- uint64_t l4_len:1;
- uint64_t l4_chk:1;
- uint64_t l4_prt:1;
- uint64_t l4_mal:1;
- uint64_t reserved_6_7:2;
- uint64_t ip6_eext:2;
- uint64_t ip4_opts:1;
- uint64_t ip_hop:1;
- uint64_t ip_mal:1;
- uint64_t ip_chk:1;
- } cn30xx;
- struct cvmx_pip_gbl_ctl_cn30xx cn31xx;
- struct cvmx_pip_gbl_ctl_cn30xx cn38xx;
- struct cvmx_pip_gbl_ctl_cn30xx cn38xxp2;
- struct cvmx_pip_gbl_ctl_cn30xx cn50xx;
- struct cvmx_pip_gbl_ctl_s cn52xx;
- struct cvmx_pip_gbl_ctl_s cn52xxp1;
- struct cvmx_pip_gbl_ctl_s cn56xx;
- struct cvmx_pip_gbl_ctl_cn56xxp1 {
- uint64_t reserved_21_63:43;
- uint64_t ring_en:1;
- uint64_t reserved_17_19:3;
- uint64_t ignrs:1;
- uint64_t vs_wqe:1;
- uint64_t vs_qos:1;
- uint64_t l2_mal:1;
- uint64_t tcp_flag:1;
- uint64_t l4_len:1;
- uint64_t l4_chk:1;
- uint64_t l4_prt:1;
- uint64_t l4_mal:1;
- uint64_t reserved_6_7:2;
- uint64_t ip6_eext:2;
- uint64_t ip4_opts:1;
- uint64_t ip_hop:1;
- uint64_t ip_mal:1;
- uint64_t ip_chk:1;
- } cn56xxp1;
- struct cvmx_pip_gbl_ctl_cn30xx cn58xx;
- struct cvmx_pip_gbl_ctl_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_hg_pri_qos {
- uint64_t u64;
- struct cvmx_pip_hg_pri_qos_s {
- uint64_t reserved_11_63:53;
- uint64_t qos:3;
- uint64_t reserved_6_7:2;
- uint64_t pri:6;
- } s;
- struct cvmx_pip_hg_pri_qos_s cn52xx;
- struct cvmx_pip_hg_pri_qos_s cn52xxp1;
- struct cvmx_pip_hg_pri_qos_s cn56xx;
-};
-
-union cvmx_pip_int_en {
- uint64_t u64;
- struct cvmx_pip_int_en_s {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } s;
- struct cvmx_pip_int_en_cn30xx {
- uint64_t reserved_9_63:55;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn30xx;
- struct cvmx_pip_int_en_cn30xx cn31xx;
- struct cvmx_pip_int_en_cn30xx cn38xx;
- struct cvmx_pip_int_en_cn30xx cn38xxp2;
- struct cvmx_pip_int_en_cn50xx {
- uint64_t reserved_12_63:52;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t reserved_1_1:1;
- uint64_t pktdrp:1;
- } cn50xx;
- struct cvmx_pip_int_en_cn52xx {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t reserved_1_1:1;
- uint64_t pktdrp:1;
- } cn52xx;
- struct cvmx_pip_int_en_cn52xx cn52xxp1;
- struct cvmx_pip_int_en_s cn56xx;
- struct cvmx_pip_int_en_cn56xxp1 {
- uint64_t reserved_12_63:52;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn56xxp1;
- struct cvmx_pip_int_en_cn58xx {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t reserved_9_11:3;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn58xx;
- struct cvmx_pip_int_en_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_int_reg {
- uint64_t u64;
- struct cvmx_pip_int_reg_s {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } s;
- struct cvmx_pip_int_reg_cn30xx {
- uint64_t reserved_9_63:55;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn30xx;
- struct cvmx_pip_int_reg_cn30xx cn31xx;
- struct cvmx_pip_int_reg_cn30xx cn38xx;
- struct cvmx_pip_int_reg_cn30xx cn38xxp2;
- struct cvmx_pip_int_reg_cn50xx {
- uint64_t reserved_12_63:52;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t reserved_1_1:1;
- uint64_t pktdrp:1;
- } cn50xx;
- struct cvmx_pip_int_reg_cn52xx {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t reserved_1_1:1;
- uint64_t pktdrp:1;
- } cn52xx;
- struct cvmx_pip_int_reg_cn52xx cn52xxp1;
- struct cvmx_pip_int_reg_s cn56xx;
- struct cvmx_pip_int_reg_cn56xxp1 {
- uint64_t reserved_12_63:52;
- uint64_t lenerr:1;
- uint64_t maxerr:1;
- uint64_t minerr:1;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn56xxp1;
- struct cvmx_pip_int_reg_cn58xx {
- uint64_t reserved_13_63:51;
- uint64_t punyerr:1;
- uint64_t reserved_9_11:3;
- uint64_t beperr:1;
- uint64_t feperr:1;
- uint64_t todoovr:1;
- uint64_t skprunt:1;
- uint64_t badtag:1;
- uint64_t prtnxa:1;
- uint64_t bckprs:1;
- uint64_t crcerr:1;
- uint64_t pktdrp:1;
- } cn58xx;
- struct cvmx_pip_int_reg_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_ip_offset {
- uint64_t u64;
- struct cvmx_pip_ip_offset_s {
- uint64_t reserved_3_63:61;
- uint64_t offset:3;
- } s;
- struct cvmx_pip_ip_offset_s cn30xx;
- struct cvmx_pip_ip_offset_s cn31xx;
- struct cvmx_pip_ip_offset_s cn38xx;
- struct cvmx_pip_ip_offset_s cn38xxp2;
- struct cvmx_pip_ip_offset_s cn50xx;
- struct cvmx_pip_ip_offset_s cn52xx;
- struct cvmx_pip_ip_offset_s cn52xxp1;
- struct cvmx_pip_ip_offset_s cn56xx;
- struct cvmx_pip_ip_offset_s cn56xxp1;
- struct cvmx_pip_ip_offset_s cn58xx;
- struct cvmx_pip_ip_offset_s cn58xxp1;
-};
-
-union cvmx_pip_prt_cfgx {
- uint64_t u64;
- struct cvmx_pip_prt_cfgx_s {
- uint64_t reserved_53_63:11;
- uint64_t pad_len:1;
- uint64_t vlan_len:1;
- uint64_t lenerr_en:1;
- uint64_t maxerr_en:1;
- uint64_t minerr_en:1;
- uint64_t grp_wat_47:4;
- uint64_t qos_wat_47:4;
- uint64_t reserved_37_39:3;
- uint64_t rawdrp:1;
- uint64_t tag_inc:2;
- uint64_t dyn_rs:1;
- uint64_t inst_hdr:1;
- uint64_t grp_wat:4;
- uint64_t hg_qos:1;
- uint64_t qos:3;
- uint64_t qos_wat:4;
- uint64_t qos_vsel:1;
- uint64_t qos_vod:1;
- uint64_t qos_diff:1;
- uint64_t qos_vlan:1;
- uint64_t reserved_13_15:3;
- uint64_t crc_en:1;
- uint64_t higig_en:1;
- uint64_t dsa_en:1;
- uint64_t mode:2;
- uint64_t reserved_7_7:1;
- uint64_t skip:7;
- } s;
- struct cvmx_pip_prt_cfgx_cn30xx {
- uint64_t reserved_37_63:27;
- uint64_t rawdrp:1;
- uint64_t tag_inc:2;
- uint64_t dyn_rs:1;
- uint64_t inst_hdr:1;
- uint64_t grp_wat:4;
- uint64_t reserved_27_27:1;
- uint64_t qos:3;
- uint64_t qos_wat:4;
- uint64_t reserved_18_19:2;
- uint64_t qos_diff:1;
- uint64_t qos_vlan:1;
- uint64_t reserved_10_15:6;
- uint64_t mode:2;
- uint64_t reserved_7_7:1;
- uint64_t skip:7;
- } cn30xx;
- struct cvmx_pip_prt_cfgx_cn30xx cn31xx;
- struct cvmx_pip_prt_cfgx_cn38xx {
- uint64_t reserved_37_63:27;
- uint64_t rawdrp:1;
- uint64_t tag_inc:2;
- uint64_t dyn_rs:1;
- uint64_t inst_hdr:1;
- uint64_t grp_wat:4;
- uint64_t reserved_27_27:1;
- uint64_t qos:3;
- uint64_t qos_wat:4;
- uint64_t reserved_18_19:2;
- uint64_t qos_diff:1;
- uint64_t qos_vlan:1;
- uint64_t reserved_13_15:3;
- uint64_t crc_en:1;
- uint64_t reserved_10_11:2;
- uint64_t mode:2;
- uint64_t reserved_7_7:1;
- uint64_t skip:7;
- } cn38xx;
- struct cvmx_pip_prt_cfgx_cn38xx cn38xxp2;
- struct cvmx_pip_prt_cfgx_cn50xx {
- uint64_t reserved_53_63:11;
- uint64_t pad_len:1;
- uint64_t vlan_len:1;
- uint64_t lenerr_en:1;
- uint64_t maxerr_en:1;
- uint64_t minerr_en:1;
- uint64_t grp_wat_47:4;
- uint64_t qos_wat_47:4;
- uint64_t reserved_37_39:3;
- uint64_t rawdrp:1;
- uint64_t tag_inc:2;
- uint64_t dyn_rs:1;
- uint64_t inst_hdr:1;
- uint64_t grp_wat:4;
- uint64_t reserved_27_27:1;
- uint64_t qos:3;
- uint64_t qos_wat:4;
- uint64_t reserved_19_19:1;
- uint64_t qos_vod:1;
- uint64_t qos_diff:1;
- uint64_t qos_vlan:1;
- uint64_t reserved_13_15:3;
- uint64_t crc_en:1;
- uint64_t reserved_10_11:2;
- uint64_t mode:2;
- uint64_t reserved_7_7:1;
- uint64_t skip:7;
- } cn50xx;
- struct cvmx_pip_prt_cfgx_s cn52xx;
- struct cvmx_pip_prt_cfgx_s cn52xxp1;
- struct cvmx_pip_prt_cfgx_s cn56xx;
- struct cvmx_pip_prt_cfgx_cn50xx cn56xxp1;
- struct cvmx_pip_prt_cfgx_cn58xx {
- uint64_t reserved_37_63:27;
- uint64_t rawdrp:1;
- uint64_t tag_inc:2;
- uint64_t dyn_rs:1;
- uint64_t inst_hdr:1;
- uint64_t grp_wat:4;
- uint64_t reserved_27_27:1;
- uint64_t qos:3;
- uint64_t qos_wat:4;
- uint64_t reserved_19_19:1;
- uint64_t qos_vod:1;
- uint64_t qos_diff:1;
- uint64_t qos_vlan:1;
- uint64_t reserved_13_15:3;
- uint64_t crc_en:1;
- uint64_t reserved_10_11:2;
- uint64_t mode:2;
- uint64_t reserved_7_7:1;
- uint64_t skip:7;
- } cn58xx;
- struct cvmx_pip_prt_cfgx_cn58xx cn58xxp1;
-};
-
-union cvmx_pip_prt_tagx {
- uint64_t u64;
- struct cvmx_pip_prt_tagx_s {
- uint64_t reserved_40_63:24;
- uint64_t grptagbase:4;
- uint64_t grptagmask:4;
- uint64_t grptag:1;
- uint64_t grptag_mskip:1;
- uint64_t tag_mode:2;
- uint64_t inc_vs:2;
- uint64_t inc_vlan:1;
- uint64_t inc_prt_flag:1;
- uint64_t ip6_dprt_flag:1;
- uint64_t ip4_dprt_flag:1;
- uint64_t ip6_sprt_flag:1;
- uint64_t ip4_sprt_flag:1;
- uint64_t ip6_nxth_flag:1;
- uint64_t ip4_pctl_flag:1;
- uint64_t ip6_dst_flag:1;
- uint64_t ip4_dst_flag:1;
- uint64_t ip6_src_flag:1;
- uint64_t ip4_src_flag:1;
- uint64_t tcp6_tag_type:2;
- uint64_t tcp4_tag_type:2;
- uint64_t ip6_tag_type:2;
- uint64_t ip4_tag_type:2;
- uint64_t non_tag_type:2;
- uint64_t grp:4;
- } s;
- struct cvmx_pip_prt_tagx_cn30xx {
- uint64_t reserved_40_63:24;
- uint64_t grptagbase:4;
- uint64_t grptagmask:4;
- uint64_t grptag:1;
- uint64_t reserved_30_30:1;
- uint64_t tag_mode:2;
- uint64_t inc_vs:2;
- uint64_t inc_vlan:1;
- uint64_t inc_prt_flag:1;
- uint64_t ip6_dprt_flag:1;
- uint64_t ip4_dprt_flag:1;
- uint64_t ip6_sprt_flag:1;
- uint64_t ip4_sprt_flag:1;
- uint64_t ip6_nxth_flag:1;
- uint64_t ip4_pctl_flag:1;
- uint64_t ip6_dst_flag:1;
- uint64_t ip4_dst_flag:1;
- uint64_t ip6_src_flag:1;
- uint64_t ip4_src_flag:1;
- uint64_t tcp6_tag_type:2;
- uint64_t tcp4_tag_type:2;
- uint64_t ip6_tag_type:2;
- uint64_t ip4_tag_type:2;
- uint64_t non_tag_type:2;
- uint64_t grp:4;
- } cn30xx;
- struct cvmx_pip_prt_tagx_cn30xx cn31xx;
- struct cvmx_pip_prt_tagx_cn30xx cn38xx;
- struct cvmx_pip_prt_tagx_cn30xx cn38xxp2;
- struct cvmx_pip_prt_tagx_s cn50xx;
- struct cvmx_pip_prt_tagx_s cn52xx;
- struct cvmx_pip_prt_tagx_s cn52xxp1;
- struct cvmx_pip_prt_tagx_s cn56xx;
- struct cvmx_pip_prt_tagx_s cn56xxp1;
- struct cvmx_pip_prt_tagx_cn30xx cn58xx;
- struct cvmx_pip_prt_tagx_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_qos_diffx {
- uint64_t u64;
- struct cvmx_pip_qos_diffx_s {
- uint64_t reserved_3_63:61;
- uint64_t qos:3;
- } s;
- struct cvmx_pip_qos_diffx_s cn30xx;
- struct cvmx_pip_qos_diffx_s cn31xx;
- struct cvmx_pip_qos_diffx_s cn38xx;
- struct cvmx_pip_qos_diffx_s cn38xxp2;
- struct cvmx_pip_qos_diffx_s cn50xx;
- struct cvmx_pip_qos_diffx_s cn52xx;
- struct cvmx_pip_qos_diffx_s cn52xxp1;
- struct cvmx_pip_qos_diffx_s cn56xx;
- struct cvmx_pip_qos_diffx_s cn56xxp1;
- struct cvmx_pip_qos_diffx_s cn58xx;
- struct cvmx_pip_qos_diffx_s cn58xxp1;
-};
-
-union cvmx_pip_qos_vlanx {
- uint64_t u64;
- struct cvmx_pip_qos_vlanx_s {
- uint64_t reserved_7_63:57;
- uint64_t qos1:3;
- uint64_t reserved_3_3:1;
- uint64_t qos:3;
- } s;
- struct cvmx_pip_qos_vlanx_cn30xx {
- uint64_t reserved_3_63:61;
- uint64_t qos:3;
- } cn30xx;
- struct cvmx_pip_qos_vlanx_cn30xx cn31xx;
- struct cvmx_pip_qos_vlanx_cn30xx cn38xx;
- struct cvmx_pip_qos_vlanx_cn30xx cn38xxp2;
- struct cvmx_pip_qos_vlanx_cn30xx cn50xx;
- struct cvmx_pip_qos_vlanx_s cn52xx;
- struct cvmx_pip_qos_vlanx_s cn52xxp1;
- struct cvmx_pip_qos_vlanx_s cn56xx;
- struct cvmx_pip_qos_vlanx_cn30xx cn56xxp1;
- struct cvmx_pip_qos_vlanx_cn30xx cn58xx;
- struct cvmx_pip_qos_vlanx_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_qos_watchx {
- uint64_t u64;
- struct cvmx_pip_qos_watchx_s {
- uint64_t reserved_48_63:16;
- uint64_t mask:16;
- uint64_t reserved_28_31:4;
- uint64_t grp:4;
- uint64_t reserved_23_23:1;
- uint64_t qos:3;
- uint64_t reserved_19_19:1;
- uint64_t match_type:3;
- uint64_t match_value:16;
- } s;
- struct cvmx_pip_qos_watchx_cn30xx {
- uint64_t reserved_48_63:16;
- uint64_t mask:16;
- uint64_t reserved_28_31:4;
- uint64_t grp:4;
- uint64_t reserved_23_23:1;
- uint64_t qos:3;
- uint64_t reserved_18_19:2;
- uint64_t match_type:2;
- uint64_t match_value:16;
- } cn30xx;
- struct cvmx_pip_qos_watchx_cn30xx cn31xx;
- struct cvmx_pip_qos_watchx_cn30xx cn38xx;
- struct cvmx_pip_qos_watchx_cn30xx cn38xxp2;
- struct cvmx_pip_qos_watchx_s cn50xx;
- struct cvmx_pip_qos_watchx_s cn52xx;
- struct cvmx_pip_qos_watchx_s cn52xxp1;
- struct cvmx_pip_qos_watchx_s cn56xx;
- struct cvmx_pip_qos_watchx_s cn56xxp1;
- struct cvmx_pip_qos_watchx_cn30xx cn58xx;
- struct cvmx_pip_qos_watchx_cn30xx cn58xxp1;
-};
-
-union cvmx_pip_raw_word {
- uint64_t u64;
- struct cvmx_pip_raw_word_s {
- uint64_t reserved_56_63:8;
- uint64_t word:56;
- } s;
- struct cvmx_pip_raw_word_s cn30xx;
- struct cvmx_pip_raw_word_s cn31xx;
- struct cvmx_pip_raw_word_s cn38xx;
- struct cvmx_pip_raw_word_s cn38xxp2;
- struct cvmx_pip_raw_word_s cn50xx;
- struct cvmx_pip_raw_word_s cn52xx;
- struct cvmx_pip_raw_word_s cn52xxp1;
- struct cvmx_pip_raw_word_s cn56xx;
- struct cvmx_pip_raw_word_s cn56xxp1;
- struct cvmx_pip_raw_word_s cn58xx;
- struct cvmx_pip_raw_word_s cn58xxp1;
-};
-
-union cvmx_pip_sft_rst {
- uint64_t u64;
- struct cvmx_pip_sft_rst_s {
- uint64_t reserved_1_63:63;
- uint64_t rst:1;
- } s;
- struct cvmx_pip_sft_rst_s cn30xx;
- struct cvmx_pip_sft_rst_s cn31xx;
- struct cvmx_pip_sft_rst_s cn38xx;
- struct cvmx_pip_sft_rst_s cn50xx;
- struct cvmx_pip_sft_rst_s cn52xx;
- struct cvmx_pip_sft_rst_s cn52xxp1;
- struct cvmx_pip_sft_rst_s cn56xx;
- struct cvmx_pip_sft_rst_s cn56xxp1;
- struct cvmx_pip_sft_rst_s cn58xx;
- struct cvmx_pip_sft_rst_s cn58xxp1;
-};
-
-union cvmx_pip_stat0_prtx {
- uint64_t u64;
- struct cvmx_pip_stat0_prtx_s {
- uint64_t drp_pkts:32;
- uint64_t drp_octs:32;
- } s;
- struct cvmx_pip_stat0_prtx_s cn30xx;
- struct cvmx_pip_stat0_prtx_s cn31xx;
- struct cvmx_pip_stat0_prtx_s cn38xx;
- struct cvmx_pip_stat0_prtx_s cn38xxp2;
- struct cvmx_pip_stat0_prtx_s cn50xx;
- struct cvmx_pip_stat0_prtx_s cn52xx;
- struct cvmx_pip_stat0_prtx_s cn52xxp1;
- struct cvmx_pip_stat0_prtx_s cn56xx;
- struct cvmx_pip_stat0_prtx_s cn56xxp1;
- struct cvmx_pip_stat0_prtx_s cn58xx;
- struct cvmx_pip_stat0_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat1_prtx {
- uint64_t u64;
- struct cvmx_pip_stat1_prtx_s {
- uint64_t reserved_48_63:16;
- uint64_t octs:48;
- } s;
- struct cvmx_pip_stat1_prtx_s cn30xx;
- struct cvmx_pip_stat1_prtx_s cn31xx;
- struct cvmx_pip_stat1_prtx_s cn38xx;
- struct cvmx_pip_stat1_prtx_s cn38xxp2;
- struct cvmx_pip_stat1_prtx_s cn50xx;
- struct cvmx_pip_stat1_prtx_s cn52xx;
- struct cvmx_pip_stat1_prtx_s cn52xxp1;
- struct cvmx_pip_stat1_prtx_s cn56xx;
- struct cvmx_pip_stat1_prtx_s cn56xxp1;
- struct cvmx_pip_stat1_prtx_s cn58xx;
- struct cvmx_pip_stat1_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat2_prtx {
- uint64_t u64;
- struct cvmx_pip_stat2_prtx_s {
- uint64_t pkts:32;
- uint64_t raw:32;
- } s;
- struct cvmx_pip_stat2_prtx_s cn30xx;
- struct cvmx_pip_stat2_prtx_s cn31xx;
- struct cvmx_pip_stat2_prtx_s cn38xx;
- struct cvmx_pip_stat2_prtx_s cn38xxp2;
- struct cvmx_pip_stat2_prtx_s cn50xx;
- struct cvmx_pip_stat2_prtx_s cn52xx;
- struct cvmx_pip_stat2_prtx_s cn52xxp1;
- struct cvmx_pip_stat2_prtx_s cn56xx;
- struct cvmx_pip_stat2_prtx_s cn56xxp1;
- struct cvmx_pip_stat2_prtx_s cn58xx;
- struct cvmx_pip_stat2_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat3_prtx {
- uint64_t u64;
- struct cvmx_pip_stat3_prtx_s {
- uint64_t bcst:32;
- uint64_t mcst:32;
- } s;
- struct cvmx_pip_stat3_prtx_s cn30xx;
- struct cvmx_pip_stat3_prtx_s cn31xx;
- struct cvmx_pip_stat3_prtx_s cn38xx;
- struct cvmx_pip_stat3_prtx_s cn38xxp2;
- struct cvmx_pip_stat3_prtx_s cn50xx;
- struct cvmx_pip_stat3_prtx_s cn52xx;
- struct cvmx_pip_stat3_prtx_s cn52xxp1;
- struct cvmx_pip_stat3_prtx_s cn56xx;
- struct cvmx_pip_stat3_prtx_s cn56xxp1;
- struct cvmx_pip_stat3_prtx_s cn58xx;
- struct cvmx_pip_stat3_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat4_prtx {
- uint64_t u64;
- struct cvmx_pip_stat4_prtx_s {
- uint64_t h65to127:32;
- uint64_t h64:32;
- } s;
- struct cvmx_pip_stat4_prtx_s cn30xx;
- struct cvmx_pip_stat4_prtx_s cn31xx;
- struct cvmx_pip_stat4_prtx_s cn38xx;
- struct cvmx_pip_stat4_prtx_s cn38xxp2;
- struct cvmx_pip_stat4_prtx_s cn50xx;
- struct cvmx_pip_stat4_prtx_s cn52xx;
- struct cvmx_pip_stat4_prtx_s cn52xxp1;
- struct cvmx_pip_stat4_prtx_s cn56xx;
- struct cvmx_pip_stat4_prtx_s cn56xxp1;
- struct cvmx_pip_stat4_prtx_s cn58xx;
- struct cvmx_pip_stat4_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat5_prtx {
- uint64_t u64;
- struct cvmx_pip_stat5_prtx_s {
- uint64_t h256to511:32;
- uint64_t h128to255:32;
- } s;
- struct cvmx_pip_stat5_prtx_s cn30xx;
- struct cvmx_pip_stat5_prtx_s cn31xx;
- struct cvmx_pip_stat5_prtx_s cn38xx;
- struct cvmx_pip_stat5_prtx_s cn38xxp2;
- struct cvmx_pip_stat5_prtx_s cn50xx;
- struct cvmx_pip_stat5_prtx_s cn52xx;
- struct cvmx_pip_stat5_prtx_s cn52xxp1;
- struct cvmx_pip_stat5_prtx_s cn56xx;
- struct cvmx_pip_stat5_prtx_s cn56xxp1;
- struct cvmx_pip_stat5_prtx_s cn58xx;
- struct cvmx_pip_stat5_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat6_prtx {
- uint64_t u64;
- struct cvmx_pip_stat6_prtx_s {
- uint64_t h1024to1518:32;
- uint64_t h512to1023:32;
- } s;
- struct cvmx_pip_stat6_prtx_s cn30xx;
- struct cvmx_pip_stat6_prtx_s cn31xx;
- struct cvmx_pip_stat6_prtx_s cn38xx;
- struct cvmx_pip_stat6_prtx_s cn38xxp2;
- struct cvmx_pip_stat6_prtx_s cn50xx;
- struct cvmx_pip_stat6_prtx_s cn52xx;
- struct cvmx_pip_stat6_prtx_s cn52xxp1;
- struct cvmx_pip_stat6_prtx_s cn56xx;
- struct cvmx_pip_stat6_prtx_s cn56xxp1;
- struct cvmx_pip_stat6_prtx_s cn58xx;
- struct cvmx_pip_stat6_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat7_prtx {
- uint64_t u64;
- struct cvmx_pip_stat7_prtx_s {
- uint64_t fcs:32;
- uint64_t h1519:32;
- } s;
- struct cvmx_pip_stat7_prtx_s cn30xx;
- struct cvmx_pip_stat7_prtx_s cn31xx;
- struct cvmx_pip_stat7_prtx_s cn38xx;
- struct cvmx_pip_stat7_prtx_s cn38xxp2;
- struct cvmx_pip_stat7_prtx_s cn50xx;
- struct cvmx_pip_stat7_prtx_s cn52xx;
- struct cvmx_pip_stat7_prtx_s cn52xxp1;
- struct cvmx_pip_stat7_prtx_s cn56xx;
- struct cvmx_pip_stat7_prtx_s cn56xxp1;
- struct cvmx_pip_stat7_prtx_s cn58xx;
- struct cvmx_pip_stat7_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat8_prtx {
- uint64_t u64;
- struct cvmx_pip_stat8_prtx_s {
- uint64_t frag:32;
- uint64_t undersz:32;
- } s;
- struct cvmx_pip_stat8_prtx_s cn30xx;
- struct cvmx_pip_stat8_prtx_s cn31xx;
- struct cvmx_pip_stat8_prtx_s cn38xx;
- struct cvmx_pip_stat8_prtx_s cn38xxp2;
- struct cvmx_pip_stat8_prtx_s cn50xx;
- struct cvmx_pip_stat8_prtx_s cn52xx;
- struct cvmx_pip_stat8_prtx_s cn52xxp1;
- struct cvmx_pip_stat8_prtx_s cn56xx;
- struct cvmx_pip_stat8_prtx_s cn56xxp1;
- struct cvmx_pip_stat8_prtx_s cn58xx;
- struct cvmx_pip_stat8_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat9_prtx {
- uint64_t u64;
- struct cvmx_pip_stat9_prtx_s {
- uint64_t jabber:32;
- uint64_t oversz:32;
- } s;
- struct cvmx_pip_stat9_prtx_s cn30xx;
- struct cvmx_pip_stat9_prtx_s cn31xx;
- struct cvmx_pip_stat9_prtx_s cn38xx;
- struct cvmx_pip_stat9_prtx_s cn38xxp2;
- struct cvmx_pip_stat9_prtx_s cn50xx;
- struct cvmx_pip_stat9_prtx_s cn52xx;
- struct cvmx_pip_stat9_prtx_s cn52xxp1;
- struct cvmx_pip_stat9_prtx_s cn56xx;
- struct cvmx_pip_stat9_prtx_s cn56xxp1;
- struct cvmx_pip_stat9_prtx_s cn58xx;
- struct cvmx_pip_stat9_prtx_s cn58xxp1;
-};
-
-union cvmx_pip_stat_ctl {
- uint64_t u64;
- struct cvmx_pip_stat_ctl_s {
- uint64_t reserved_1_63:63;
- uint64_t rdclr:1;
- } s;
- struct cvmx_pip_stat_ctl_s cn30xx;
- struct cvmx_pip_stat_ctl_s cn31xx;
- struct cvmx_pip_stat_ctl_s cn38xx;
- struct cvmx_pip_stat_ctl_s cn38xxp2;
- struct cvmx_pip_stat_ctl_s cn50xx;
- struct cvmx_pip_stat_ctl_s cn52xx;
- struct cvmx_pip_stat_ctl_s cn52xxp1;
- struct cvmx_pip_stat_ctl_s cn56xx;
- struct cvmx_pip_stat_ctl_s cn56xxp1;
- struct cvmx_pip_stat_ctl_s cn58xx;
- struct cvmx_pip_stat_ctl_s cn58xxp1;
-};
-
-union cvmx_pip_stat_inb_errsx {
- uint64_t u64;
- struct cvmx_pip_stat_inb_errsx_s {
- uint64_t reserved_16_63:48;
- uint64_t errs:16;
- } s;
- struct cvmx_pip_stat_inb_errsx_s cn30xx;
- struct cvmx_pip_stat_inb_errsx_s cn31xx;
- struct cvmx_pip_stat_inb_errsx_s cn38xx;
- struct cvmx_pip_stat_inb_errsx_s cn38xxp2;
- struct cvmx_pip_stat_inb_errsx_s cn50xx;
- struct cvmx_pip_stat_inb_errsx_s cn52xx;
- struct cvmx_pip_stat_inb_errsx_s cn52xxp1;
- struct cvmx_pip_stat_inb_errsx_s cn56xx;
- struct cvmx_pip_stat_inb_errsx_s cn56xxp1;
- struct cvmx_pip_stat_inb_errsx_s cn58xx;
- struct cvmx_pip_stat_inb_errsx_s cn58xxp1;
-};
-
-union cvmx_pip_stat_inb_octsx {
- uint64_t u64;
- struct cvmx_pip_stat_inb_octsx_s {
- uint64_t reserved_48_63:16;
- uint64_t octs:48;
- } s;
- struct cvmx_pip_stat_inb_octsx_s cn30xx;
- struct cvmx_pip_stat_inb_octsx_s cn31xx;
- struct cvmx_pip_stat_inb_octsx_s cn38xx;
- struct cvmx_pip_stat_inb_octsx_s cn38xxp2;
- struct cvmx_pip_stat_inb_octsx_s cn50xx;
- struct cvmx_pip_stat_inb_octsx_s cn52xx;
- struct cvmx_pip_stat_inb_octsx_s cn52xxp1;
- struct cvmx_pip_stat_inb_octsx_s cn56xx;
- struct cvmx_pip_stat_inb_octsx_s cn56xxp1;
- struct cvmx_pip_stat_inb_octsx_s cn58xx;
- struct cvmx_pip_stat_inb_octsx_s cn58xxp1;
-};
-
-union cvmx_pip_stat_inb_pktsx {
- uint64_t u64;
- struct cvmx_pip_stat_inb_pktsx_s {
- uint64_t reserved_32_63:32;
- uint64_t pkts:32;
- } s;
- struct cvmx_pip_stat_inb_pktsx_s cn30xx;
- struct cvmx_pip_stat_inb_pktsx_s cn31xx;
- struct cvmx_pip_stat_inb_pktsx_s cn38xx;
- struct cvmx_pip_stat_inb_pktsx_s cn38xxp2;
- struct cvmx_pip_stat_inb_pktsx_s cn50xx;
- struct cvmx_pip_stat_inb_pktsx_s cn52xx;
- struct cvmx_pip_stat_inb_pktsx_s cn52xxp1;
- struct cvmx_pip_stat_inb_pktsx_s cn56xx;
- struct cvmx_pip_stat_inb_pktsx_s cn56xxp1;
- struct cvmx_pip_stat_inb_pktsx_s cn58xx;
- struct cvmx_pip_stat_inb_pktsx_s cn58xxp1;
-};
-
-union cvmx_pip_tag_incx {
- uint64_t u64;
- struct cvmx_pip_tag_incx_s {
- uint64_t reserved_8_63:56;
- uint64_t en:8;
- } s;
- struct cvmx_pip_tag_incx_s cn30xx;
- struct cvmx_pip_tag_incx_s cn31xx;
- struct cvmx_pip_tag_incx_s cn38xx;
- struct cvmx_pip_tag_incx_s cn38xxp2;
- struct cvmx_pip_tag_incx_s cn50xx;
- struct cvmx_pip_tag_incx_s cn52xx;
- struct cvmx_pip_tag_incx_s cn52xxp1;
- struct cvmx_pip_tag_incx_s cn56xx;
- struct cvmx_pip_tag_incx_s cn56xxp1;
- struct cvmx_pip_tag_incx_s cn58xx;
- struct cvmx_pip_tag_incx_s cn58xxp1;
-};
-
-union cvmx_pip_tag_mask {
- uint64_t u64;
- struct cvmx_pip_tag_mask_s {
- uint64_t reserved_16_63:48;
- uint64_t mask:16;
- } s;
- struct cvmx_pip_tag_mask_s cn30xx;
- struct cvmx_pip_tag_mask_s cn31xx;
- struct cvmx_pip_tag_mask_s cn38xx;
- struct cvmx_pip_tag_mask_s cn38xxp2;
- struct cvmx_pip_tag_mask_s cn50xx;
- struct cvmx_pip_tag_mask_s cn52xx;
- struct cvmx_pip_tag_mask_s cn52xxp1;
- struct cvmx_pip_tag_mask_s cn56xx;
- struct cvmx_pip_tag_mask_s cn56xxp1;
- struct cvmx_pip_tag_mask_s cn58xx;
- struct cvmx_pip_tag_mask_s cn58xxp1;
-};
-
-union cvmx_pip_tag_secret {
- uint64_t u64;
- struct cvmx_pip_tag_secret_s {
- uint64_t reserved_32_63:32;
- uint64_t dst:16;
- uint64_t src:16;
- } s;
- struct cvmx_pip_tag_secret_s cn30xx;
- struct cvmx_pip_tag_secret_s cn31xx;
- struct cvmx_pip_tag_secret_s cn38xx;
- struct cvmx_pip_tag_secret_s cn38xxp2;
- struct cvmx_pip_tag_secret_s cn50xx;
- struct cvmx_pip_tag_secret_s cn52xx;
- struct cvmx_pip_tag_secret_s cn52xxp1;
- struct cvmx_pip_tag_secret_s cn56xx;
- struct cvmx_pip_tag_secret_s cn56xxp1;
- struct cvmx_pip_tag_secret_s cn58xx;
- struct cvmx_pip_tag_secret_s cn58xxp1;
-};
-
-union cvmx_pip_todo_entry {
- uint64_t u64;
- struct cvmx_pip_todo_entry_s {
- uint64_t val:1;
- uint64_t reserved_62_62:1;
- uint64_t entry:62;
- } s;
- struct cvmx_pip_todo_entry_s cn30xx;
- struct cvmx_pip_todo_entry_s cn31xx;
- struct cvmx_pip_todo_entry_s cn38xx;
- struct cvmx_pip_todo_entry_s cn38xxp2;
- struct cvmx_pip_todo_entry_s cn50xx;
- struct cvmx_pip_todo_entry_s cn52xx;
- struct cvmx_pip_todo_entry_s cn52xxp1;
- struct cvmx_pip_todo_entry_s cn56xx;
- struct cvmx_pip_todo_entry_s cn56xxp1;
- struct cvmx_pip_todo_entry_s cn58xx;
- struct cvmx_pip_todo_entry_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-pip.h b/drivers/staging/octeon/cvmx-pip.h
deleted file mode 100644
index 78dbce8..0000000
--- a/drivers/staging/octeon/cvmx-pip.h
+++ /dev/null
@@ -1,524 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Interface to the hardware Packet Input Processing unit.
- *
- */
-
-#ifndef __CVMX_PIP_H__
-#define __CVMX_PIP_H__
-
-#include "cvmx-wqe.h"
-#include "cvmx-fpa.h"
-#include "cvmx-pip-defs.h"
-
-#define CVMX_PIP_NUM_INPUT_PORTS 40
-#define CVMX_PIP_NUM_WATCHERS 4
-
-/*
- * Encodes the different error and exception codes
- */
-typedef enum {
- CVMX_PIP_L4_NO_ERR = 0ull,
- /*
- * 1 = TCP (UDP) packet not long enough to cover TCP (UDP)
- * header
- */
- CVMX_PIP_L4_MAL_ERR = 1ull,
- /* 2 = TCP/UDP checksum failure */
- CVMX_PIP_CHK_ERR = 2ull,
- /*
- * 3 = TCP/UDP length check (TCP/UDP length does not match IP
- * length).
- */
- CVMX_PIP_L4_LENGTH_ERR = 3ull,
- /* 4 = illegal TCP/UDP port (either source or dest port is zero) */
- CVMX_PIP_BAD_PRT_ERR = 4ull,
- /* 8 = TCP flags = FIN only */
- CVMX_PIP_TCP_FLG8_ERR = 8ull,
- /* 9 = TCP flags = 0 */
- CVMX_PIP_TCP_FLG9_ERR = 9ull,
- /* 10 = TCP flags = FIN+RST+* */
- CVMX_PIP_TCP_FLG10_ERR = 10ull,
- /* 11 = TCP flags = SYN+URG+* */
- CVMX_PIP_TCP_FLG11_ERR = 11ull,
- /* 12 = TCP flags = SYN+RST+* */
- CVMX_PIP_TCP_FLG12_ERR = 12ull,
- /* 13 = TCP flags = SYN+FIN+* */
- CVMX_PIP_TCP_FLG13_ERR = 13ull
-} cvmx_pip_l4_err_t;
-
-typedef enum {
-
- CVMX_PIP_IP_NO_ERR = 0ull,
- /* 1 = not IPv4 or IPv6 */
- CVMX_PIP_NOT_IP = 1ull,
- /* 2 = IPv4 header checksum violation */
- CVMX_PIP_IPV4_HDR_CHK = 2ull,
- /* 3 = malformed (packet not long enough to cover IP hdr) */
- CVMX_PIP_IP_MAL_HDR = 3ull,
- /* 4 = malformed (packet not long enough to cover len in IP hdr) */
- CVMX_PIP_IP_MAL_PKT = 4ull,
- /* 5 = TTL / hop count equal zero */
- CVMX_PIP_TTL_HOP = 5ull,
- /* 6 = IPv4 options / IPv6 early extension headers */
- CVMX_PIP_OPTS = 6ull
-} cvmx_pip_ip_exc_t;
-
-/**
- * NOTES
- * late collision (data received before collision)
- * late collisions cannot be detected by the receiver
- * they would appear as JAM bits which would appear as bad FCS
- * or carrier extend error which is CVMX_PIP_EXTEND_ERR
- */
-typedef enum {
- /* No error */
- CVMX_PIP_RX_NO_ERR = 0ull,
- /* RGM+SPI 1 = partially received packet (buffering/bandwidth
- * not adequate) */
- CVMX_PIP_PARTIAL_ERR = 1ull,
- /* RGM+SPI 2 = receive packet too large and truncated */
- CVMX_PIP_JABBER_ERR = 2ull,
- /*
- * RGM 3 = max frame error (pkt len > max frame len) (with FCS
- * error)
- */
- CVMX_PIP_OVER_FCS_ERR = 3ull,
- /* RGM+SPI 4 = max frame error (pkt len > max frame len) */
- CVMX_PIP_OVER_ERR = 4ull,
- /*
- * RGM 5 = nibble error (data not byte multiple - 100M and 10M
- * only)
- */
- CVMX_PIP_ALIGN_ERR = 5ull,
- /*
- * RGM 6 = min frame error (pkt len < min frame len) (with FCS
- * error)
- */
- CVMX_PIP_UNDER_FCS_ERR = 6ull,
- /* RGM 7 = FCS error */
- CVMX_PIP_GMX_FCS_ERR = 7ull,
- /* RGM+SPI 8 = min frame error (pkt len < min frame len) */
- CVMX_PIP_UNDER_ERR = 8ull,
- /* RGM 9 = Frame carrier extend error */
- CVMX_PIP_EXTEND_ERR = 9ull,
- /*
- * RGM 10 = length mismatch (len did not match len in L2
- * length/type)
- */
- CVMX_PIP_LENGTH_ERR = 10ull,
- /* RGM 11 = Frame error (some or all data bits marked err) */
- CVMX_PIP_DAT_ERR = 11ull,
- /* SPI 11 = DIP4 error */
- CVMX_PIP_DIP_ERR = 11ull,
- /*
- * RGM 12 = packet was not large enough to pass the skipper -
- * no inspection could occur.
- */
- CVMX_PIP_SKIP_ERR = 12ull,
- /*
- * RGM 13 = studder error (data not repeated - 100M and 10M
- * only)
- */
- CVMX_PIP_NIBBLE_ERR = 13ull,
- /* RGM+SPI 16 = FCS error */
- CVMX_PIP_PIP_FCS = 16L,
- /*
- * RGM+SPI+PCI 17 = packet was not large enough to pass the
- * skipper - no inspection could occur.
- */
- CVMX_PIP_PIP_SKIP_ERR = 17L,
- /*
- * RGM+SPI+PCI 18 = malformed l2 (packet not long enough to
- * cover L2 hdr).
- */
- CVMX_PIP_PIP_L2_MAL_HDR = 18L
- /*
- * NOTES: xx = late collision (data received before collision)
- * late collisions cannot be detected by the receiver
- * they would appear as JAM bits which would appear as
- * bad FCS or carrier extend error which is
- * CVMX_PIP_EXTEND_ERR
- */
-} cvmx_pip_rcv_err_t;
-
-/**
- * This defines the err_code field errors in the work Q entry
- */
-typedef union {
- cvmx_pip_l4_err_t l4_err;
- cvmx_pip_ip_exc_t ip_exc;
- cvmx_pip_rcv_err_t rcv_err;
-} cvmx_pip_err_t;
-
-/**
- * Status statistics for a port
- */
-typedef struct {
- /* Inbound octets marked to be dropped by the IPD */
- uint32_t dropped_octets;
- /* Inbound packets marked to be dropped by the IPD */
- uint32_t dropped_packets;
- /* RAW PCI Packets received by PIP per port */
- uint32_t pci_raw_packets;
- /* Number of octets processed by PIP */
- uint32_t octets;
- /* Number of packets processed by PIP */
- uint32_t packets;
- /*
- * Number of indentified L2 multicast packets. Does not
- * include broadcast packets. Only includes packets whose
- * parse mode is SKIP_TO_L2
- */
- uint32_t multicast_packets;
- /*
- * Number of indentified L2 broadcast packets. Does not
- * include multicast packets. Only includes packets whose
- * parse mode is SKIP_TO_L2
- */
- uint32_t broadcast_packets;
- /* Number of 64B packets */
- uint32_t len_64_packets;
- /* Number of 65-127B packets */
- uint32_t len_65_127_packets;
- /* Number of 128-255B packets */
- uint32_t len_128_255_packets;
- /* Number of 256-511B packets */
- uint32_t len_256_511_packets;
- /* Number of 512-1023B packets */
- uint32_t len_512_1023_packets;
- /* Number of 1024-1518B packets */
- uint32_t len_1024_1518_packets;
- /* Number of 1519-max packets */
- uint32_t len_1519_max_packets;
- /* Number of packets with FCS or Align opcode errors */
- uint32_t fcs_align_err_packets;
- /* Number of packets with length < min */
- uint32_t runt_packets;
- /* Number of packets with length < min and FCS error */
- uint32_t runt_crc_packets;
- /* Number of packets with length > max */
- uint32_t oversize_packets;
- /* Number of packets with length > max and FCS error */
- uint32_t oversize_crc_packets;
- /* Number of packets without GMX/SPX/PCI errors received by PIP */
- uint32_t inb_packets;
- /*
- * Total number of octets from all packets received by PIP,
- * including CRC
- */
- uint64_t inb_octets;
- /* Number of packets with GMX/SPX/PCI errors received by PIP */
- uint16_t inb_errors;
-} cvmx_pip_port_status_t;
-
-/**
- * Definition of the PIP custom header that can be prepended
- * to a packet by external hardware.
- */
-typedef union {
- uint64_t u64;
- struct {
- /*
- * Documented as R - Set if the Packet is RAWFULL. If
- * set, this header must be the full 8 bytes.
- */
- uint64_t rawfull:1;
- /* Must be zero */
- uint64_t reserved0:5;
- /* PIP parse mode for this packet */
- uint64_t parse_mode:2;
- /* Must be zero */
- uint64_t reserved1:1;
- /*
- * Skip amount, including this header, to the
- * beginning of the packet
- */
- uint64_t skip_len:7;
- /* Must be zero */
- uint64_t reserved2:6;
- /* POW input queue for this packet */
- uint64_t qos:3;
- /* POW input group for this packet */
- uint64_t grp:4;
- /*
- * Flag to store this packet in the work queue entry,
- * if possible
- */
- uint64_t rs:1;
- /* POW input tag type */
- uint64_t tag_type:2;
- /* POW input tag */
- uint64_t tag:32;
- } s;
-} cvmx_pip_pkt_inst_hdr_t;
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-
-/**
- * Configure an ethernet input port
- *
- * @port_num: Port number to configure
- * @port_cfg: Port hardware configuration
- * @port_tag_cfg:
- * Port POW tagging configuration
- */
-static inline void cvmx_pip_config_port(uint64_t port_num,
- union cvmx_pip_prt_cfgx port_cfg,
- union cvmx_pip_prt_tagx port_tag_cfg)
-{
- cvmx_write_csr(CVMX_PIP_PRT_CFGX(port_num), port_cfg.u64);
- cvmx_write_csr(CVMX_PIP_PRT_TAGX(port_num), port_tag_cfg.u64);
-}
-#if 0
-/**
- * @deprecated This function is a thin wrapper around the Pass1 version
- * of the CVMX_PIP_QOS_WATCHX CSR; Pass2 has added a field for
- * setting the group that is incompatible with this function,
- * the preferred upgrade path is to use the CSR directly.
- *
- * Configure the global QoS packet watchers. Each watcher is
- * capable of matching a field in a packet to determine the
- * QoS queue for scheduling.
- *
- * @watcher: Watcher number to configure (0 - 3).
- * @match_type: Watcher match type
- * @match_value:
- * Value the watcher will match against
- * @qos: QoS queue for packets matching this watcher
- */
-static inline void cvmx_pip_config_watcher(uint64_t watcher,
- cvmx_pip_qos_watch_types match_type,
- uint64_t match_value, uint64_t qos)
-{
- cvmx_pip_port_watcher_cfg_t watcher_config;
-
- watcher_config.u64 = 0;
- watcher_config.s.match_type = match_type;
- watcher_config.s.match_value = match_value;
- watcher_config.s.qos = qos;
-
- cvmx_write_csr(CVMX_PIP_QOS_WATCHX(watcher), watcher_config.u64);
-}
-#endif
-/**
- * Configure the VLAN priority to QoS queue mapping.
- *
- * @vlan_priority:
- * VLAN priority (0-7)
- * @qos: QoS queue for packets matching this watcher
- */
-static inline void cvmx_pip_config_vlan_qos(uint64_t vlan_priority,
- uint64_t qos)
-{
- union cvmx_pip_qos_vlanx pip_qos_vlanx;
- pip_qos_vlanx.u64 = 0;
- pip_qos_vlanx.s.qos = qos;
- cvmx_write_csr(CVMX_PIP_QOS_VLANX(vlan_priority), pip_qos_vlanx.u64);
-}
-
-/**
- * Configure the Diffserv to QoS queue mapping.
- *
- * @diffserv: Diffserv field value (0-63)
- * @qos: QoS queue for packets matching this watcher
- */
-static inline void cvmx_pip_config_diffserv_qos(uint64_t diffserv, uint64_t qos)
-{
- union cvmx_pip_qos_diffx pip_qos_diffx;
- pip_qos_diffx.u64 = 0;
- pip_qos_diffx.s.qos = qos;
- cvmx_write_csr(CVMX_PIP_QOS_DIFFX(diffserv), pip_qos_diffx.u64);
-}
-
-/**
- * Get the status counters for a port.
- *
- * @port_num: Port number to get statistics for.
- * @clear: Set to 1 to clear the counters after they are read
- * @status: Where to put the results.
- */
-static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear,
- cvmx_pip_port_status_t *status)
-{
- union cvmx_pip_stat_ctl pip_stat_ctl;
- union cvmx_pip_stat0_prtx stat0;
- union cvmx_pip_stat1_prtx stat1;
- union cvmx_pip_stat2_prtx stat2;
- union cvmx_pip_stat3_prtx stat3;
- union cvmx_pip_stat4_prtx stat4;
- union cvmx_pip_stat5_prtx stat5;
- union cvmx_pip_stat6_prtx stat6;
- union cvmx_pip_stat7_prtx stat7;
- union cvmx_pip_stat8_prtx stat8;
- union cvmx_pip_stat9_prtx stat9;
- union cvmx_pip_stat_inb_pktsx pip_stat_inb_pktsx;
- union cvmx_pip_stat_inb_octsx pip_stat_inb_octsx;
- union cvmx_pip_stat_inb_errsx pip_stat_inb_errsx;
-
- pip_stat_ctl.u64 = 0;
- pip_stat_ctl.s.rdclr = clear;
- cvmx_write_csr(CVMX_PIP_STAT_CTL, pip_stat_ctl.u64);
-
- stat0.u64 = cvmx_read_csr(CVMX_PIP_STAT0_PRTX(port_num));
- stat1.u64 = cvmx_read_csr(CVMX_PIP_STAT1_PRTX(port_num));
- stat2.u64 = cvmx_read_csr(CVMX_PIP_STAT2_PRTX(port_num));
- stat3.u64 = cvmx_read_csr(CVMX_PIP_STAT3_PRTX(port_num));
- stat4.u64 = cvmx_read_csr(CVMX_PIP_STAT4_PRTX(port_num));
- stat5.u64 = cvmx_read_csr(CVMX_PIP_STAT5_PRTX(port_num));
- stat6.u64 = cvmx_read_csr(CVMX_PIP_STAT6_PRTX(port_num));
- stat7.u64 = cvmx_read_csr(CVMX_PIP_STAT7_PRTX(port_num));
- stat8.u64 = cvmx_read_csr(CVMX_PIP_STAT8_PRTX(port_num));
- stat9.u64 = cvmx_read_csr(CVMX_PIP_STAT9_PRTX(port_num));
- pip_stat_inb_pktsx.u64 =
- cvmx_read_csr(CVMX_PIP_STAT_INB_PKTSX(port_num));
- pip_stat_inb_octsx.u64 =
- cvmx_read_csr(CVMX_PIP_STAT_INB_OCTSX(port_num));
- pip_stat_inb_errsx.u64 =
- cvmx_read_csr(CVMX_PIP_STAT_INB_ERRSX(port_num));
-
- status->dropped_octets = stat0.s.drp_octs;
- status->dropped_packets = stat0.s.drp_pkts;
- status->octets = stat1.s.octs;
- status->pci_raw_packets = stat2.s.raw;
- status->packets = stat2.s.pkts;
- status->multicast_packets = stat3.s.mcst;
- status->broadcast_packets = stat3.s.bcst;
- status->len_64_packets = stat4.s.h64;
- status->len_65_127_packets = stat4.s.h65to127;
- status->len_128_255_packets = stat5.s.h128to255;
- status->len_256_511_packets = stat5.s.h256to511;
- status->len_512_1023_packets = stat6.s.h512to1023;
- status->len_1024_1518_packets = stat6.s.h1024to1518;
- status->len_1519_max_packets = stat7.s.h1519;
- status->fcs_align_err_packets = stat7.s.fcs;
- status->runt_packets = stat8.s.undersz;
- status->runt_crc_packets = stat8.s.frag;
- status->oversize_packets = stat9.s.oversz;
- status->oversize_crc_packets = stat9.s.jabber;
- status->inb_packets = pip_stat_inb_pktsx.s.pkts;
- status->inb_octets = pip_stat_inb_octsx.s.octs;
- status->inb_errors = pip_stat_inb_errsx.s.errs;
-
- if (cvmx_octeon_is_pass1()) {
- /*
- * Kludge to fix Octeon Pass 1 errata - Drop counts
- * don't work.
- */
- if (status->inb_packets > status->packets)
- status->dropped_packets =
- status->inb_packets - status->packets;
- else
- status->dropped_packets = 0;
- if (status->inb_octets - status->inb_packets * 4 >
- status->octets)
- status->dropped_octets =
- status->inb_octets - status->inb_packets * 4 -
- status->octets;
- else
- status->dropped_octets = 0;
- }
-}
-
-/**
- * Configure the hardware CRC engine
- *
- * @interface: Interface to configure (0 or 1)
- * @invert_result:
- * Invert the result of the CRC
- * @reflect: Reflect
- * @initialization_vector:
- * CRC initialization vector
- */
-static inline void cvmx_pip_config_crc(uint64_t interface,
- uint64_t invert_result, uint64_t reflect,
- uint32_t initialization_vector)
-{
- if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) {
- union cvmx_pip_crc_ctlx config;
- union cvmx_pip_crc_ivx pip_crc_ivx;
-
- config.u64 = 0;
- config.s.invres = invert_result;
- config.s.reflect = reflect;
- cvmx_write_csr(CVMX_PIP_CRC_CTLX(interface), config.u64);
-
- pip_crc_ivx.u64 = 0;
- pip_crc_ivx.s.iv = initialization_vector;
- cvmx_write_csr(CVMX_PIP_CRC_IVX(interface), pip_crc_ivx.u64);
- }
-}
-
-/**
- * Clear all bits in a tag mask. This should be called on
- * startup before any calls to cvmx_pip_tag_mask_set. Each bit
- * set in the final mask represent a byte used in the packet for
- * tag generation.
- *
- * @mask_index: Which tag mask to clear (0..3)
- */
-static inline void cvmx_pip_tag_mask_clear(uint64_t mask_index)
-{
- uint64_t index;
- union cvmx_pip_tag_incx pip_tag_incx;
- pip_tag_incx.u64 = 0;
- pip_tag_incx.s.en = 0;
- for (index = mask_index * 16; index < (mask_index + 1) * 16; index++)
- cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64);
-}
-
-/**
- * Sets a range of bits in the tag mask. The tag mask is used
- * when the cvmx_pip_port_tag_cfg_t tag_mode is non zero.
- * There are four separate masks that can be configured.
- *
- * @mask_index: Which tag mask to modify (0..3)
- * @offset: Offset into the bitmask to set bits at. Use the GCC macro
- * offsetof() to determine the offsets into packet headers.
- * For example, offsetof(ethhdr, protocol) returns the offset
- * of the ethernet protocol field. The bitmask selects which
- * bytes to include the the tag, with bit offset X selecting
- * byte at offset X from the beginning of the packet data.
- * @len: Number of bytes to include. Usually this is the sizeof()
- * the field.
- */
-static inline void cvmx_pip_tag_mask_set(uint64_t mask_index, uint64_t offset,
- uint64_t len)
-{
- while (len--) {
- union cvmx_pip_tag_incx pip_tag_incx;
- uint64_t index = mask_index * 16 + offset / 8;
- pip_tag_incx.u64 = cvmx_read_csr(CVMX_PIP_TAG_INCX(index));
- pip_tag_incx.s.en |= 0x80 >> (offset & 0x7);
- cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64);
- offset++;
- }
-}
-
-#endif /* __CVMX_PIP_H__ */
diff --git a/drivers/staging/octeon/cvmx-pko-defs.h b/drivers/staging/octeon/cvmx-pko-defs.h
deleted file mode 100644
index 50e779c..0000000
--- a/drivers/staging/octeon/cvmx-pko-defs.h
+++ /dev/null
@@ -1,1133 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_PKO_DEFS_H__
-#define __CVMX_PKO_DEFS_H__
-
-#define CVMX_PKO_MEM_COUNT0 \
- CVMX_ADD_IO_SEG(0x0001180050001080ull)
-#define CVMX_PKO_MEM_COUNT1 \
- CVMX_ADD_IO_SEG(0x0001180050001088ull)
-#define CVMX_PKO_MEM_DEBUG0 \
- CVMX_ADD_IO_SEG(0x0001180050001100ull)
-#define CVMX_PKO_MEM_DEBUG1 \
- CVMX_ADD_IO_SEG(0x0001180050001108ull)
-#define CVMX_PKO_MEM_DEBUG10 \
- CVMX_ADD_IO_SEG(0x0001180050001150ull)
-#define CVMX_PKO_MEM_DEBUG11 \
- CVMX_ADD_IO_SEG(0x0001180050001158ull)
-#define CVMX_PKO_MEM_DEBUG12 \
- CVMX_ADD_IO_SEG(0x0001180050001160ull)
-#define CVMX_PKO_MEM_DEBUG13 \
- CVMX_ADD_IO_SEG(0x0001180050001168ull)
-#define CVMX_PKO_MEM_DEBUG14 \
- CVMX_ADD_IO_SEG(0x0001180050001170ull)
-#define CVMX_PKO_MEM_DEBUG2 \
- CVMX_ADD_IO_SEG(0x0001180050001110ull)
-#define CVMX_PKO_MEM_DEBUG3 \
- CVMX_ADD_IO_SEG(0x0001180050001118ull)
-#define CVMX_PKO_MEM_DEBUG4 \
- CVMX_ADD_IO_SEG(0x0001180050001120ull)
-#define CVMX_PKO_MEM_DEBUG5 \
- CVMX_ADD_IO_SEG(0x0001180050001128ull)
-#define CVMX_PKO_MEM_DEBUG6 \
- CVMX_ADD_IO_SEG(0x0001180050001130ull)
-#define CVMX_PKO_MEM_DEBUG7 \
- CVMX_ADD_IO_SEG(0x0001180050001138ull)
-#define CVMX_PKO_MEM_DEBUG8 \
- CVMX_ADD_IO_SEG(0x0001180050001140ull)
-#define CVMX_PKO_MEM_DEBUG9 \
- CVMX_ADD_IO_SEG(0x0001180050001148ull)
-#define CVMX_PKO_MEM_PORT_PTRS \
- CVMX_ADD_IO_SEG(0x0001180050001010ull)
-#define CVMX_PKO_MEM_PORT_QOS \
- CVMX_ADD_IO_SEG(0x0001180050001018ull)
-#define CVMX_PKO_MEM_PORT_RATE0 \
- CVMX_ADD_IO_SEG(0x0001180050001020ull)
-#define CVMX_PKO_MEM_PORT_RATE1 \
- CVMX_ADD_IO_SEG(0x0001180050001028ull)
-#define CVMX_PKO_MEM_QUEUE_PTRS \
- CVMX_ADD_IO_SEG(0x0001180050001000ull)
-#define CVMX_PKO_MEM_QUEUE_QOS \
- CVMX_ADD_IO_SEG(0x0001180050001008ull)
-#define CVMX_PKO_REG_BIST_RESULT \
- CVMX_ADD_IO_SEG(0x0001180050000080ull)
-#define CVMX_PKO_REG_CMD_BUF \
- CVMX_ADD_IO_SEG(0x0001180050000010ull)
-#define CVMX_PKO_REG_CRC_CTLX(offset) \
- CVMX_ADD_IO_SEG(0x0001180050000028ull + (((offset) & 1) * 8))
-#define CVMX_PKO_REG_CRC_ENABLE \
- CVMX_ADD_IO_SEG(0x0001180050000020ull)
-#define CVMX_PKO_REG_CRC_IVX(offset) \
- CVMX_ADD_IO_SEG(0x0001180050000038ull + (((offset) & 1) * 8))
-#define CVMX_PKO_REG_DEBUG0 \
- CVMX_ADD_IO_SEG(0x0001180050000098ull)
-#define CVMX_PKO_REG_DEBUG1 \
- CVMX_ADD_IO_SEG(0x00011800500000A0ull)
-#define CVMX_PKO_REG_DEBUG2 \
- CVMX_ADD_IO_SEG(0x00011800500000A8ull)
-#define CVMX_PKO_REG_DEBUG3 \
- CVMX_ADD_IO_SEG(0x00011800500000B0ull)
-#define CVMX_PKO_REG_ENGINE_INFLIGHT \
- CVMX_ADD_IO_SEG(0x0001180050000050ull)
-#define CVMX_PKO_REG_ENGINE_THRESH \
- CVMX_ADD_IO_SEG(0x0001180050000058ull)
-#define CVMX_PKO_REG_ERROR \
- CVMX_ADD_IO_SEG(0x0001180050000088ull)
-#define CVMX_PKO_REG_FLAGS \
- CVMX_ADD_IO_SEG(0x0001180050000000ull)
-#define CVMX_PKO_REG_GMX_PORT_MODE \
- CVMX_ADD_IO_SEG(0x0001180050000018ull)
-#define CVMX_PKO_REG_INT_MASK \
- CVMX_ADD_IO_SEG(0x0001180050000090ull)
-#define CVMX_PKO_REG_QUEUE_MODE \
- CVMX_ADD_IO_SEG(0x0001180050000048ull)
-#define CVMX_PKO_REG_QUEUE_PTRS1 \
- CVMX_ADD_IO_SEG(0x0001180050000100ull)
-#define CVMX_PKO_REG_READ_IDX \
- CVMX_ADD_IO_SEG(0x0001180050000008ull)
-
-union cvmx_pko_mem_count0 {
- uint64_t u64;
- struct cvmx_pko_mem_count0_s {
- uint64_t reserved_32_63:32;
- uint64_t count:32;
- } s;
- struct cvmx_pko_mem_count0_s cn30xx;
- struct cvmx_pko_mem_count0_s cn31xx;
- struct cvmx_pko_mem_count0_s cn38xx;
- struct cvmx_pko_mem_count0_s cn38xxp2;
- struct cvmx_pko_mem_count0_s cn50xx;
- struct cvmx_pko_mem_count0_s cn52xx;
- struct cvmx_pko_mem_count0_s cn52xxp1;
- struct cvmx_pko_mem_count0_s cn56xx;
- struct cvmx_pko_mem_count0_s cn56xxp1;
- struct cvmx_pko_mem_count0_s cn58xx;
- struct cvmx_pko_mem_count0_s cn58xxp1;
-};
-
-union cvmx_pko_mem_count1 {
- uint64_t u64;
- struct cvmx_pko_mem_count1_s {
- uint64_t reserved_48_63:16;
- uint64_t count:48;
- } s;
- struct cvmx_pko_mem_count1_s cn30xx;
- struct cvmx_pko_mem_count1_s cn31xx;
- struct cvmx_pko_mem_count1_s cn38xx;
- struct cvmx_pko_mem_count1_s cn38xxp2;
- struct cvmx_pko_mem_count1_s cn50xx;
- struct cvmx_pko_mem_count1_s cn52xx;
- struct cvmx_pko_mem_count1_s cn52xxp1;
- struct cvmx_pko_mem_count1_s cn56xx;
- struct cvmx_pko_mem_count1_s cn56xxp1;
- struct cvmx_pko_mem_count1_s cn58xx;
- struct cvmx_pko_mem_count1_s cn58xxp1;
-};
-
-union cvmx_pko_mem_debug0 {
- uint64_t u64;
- struct cvmx_pko_mem_debug0_s {
- uint64_t fau:28;
- uint64_t cmd:14;
- uint64_t segs:6;
- uint64_t size:16;
- } s;
- struct cvmx_pko_mem_debug0_s cn30xx;
- struct cvmx_pko_mem_debug0_s cn31xx;
- struct cvmx_pko_mem_debug0_s cn38xx;
- struct cvmx_pko_mem_debug0_s cn38xxp2;
- struct cvmx_pko_mem_debug0_s cn50xx;
- struct cvmx_pko_mem_debug0_s cn52xx;
- struct cvmx_pko_mem_debug0_s cn52xxp1;
- struct cvmx_pko_mem_debug0_s cn56xx;
- struct cvmx_pko_mem_debug0_s cn56xxp1;
- struct cvmx_pko_mem_debug0_s cn58xx;
- struct cvmx_pko_mem_debug0_s cn58xxp1;
-};
-
-union cvmx_pko_mem_debug1 {
- uint64_t u64;
- struct cvmx_pko_mem_debug1_s {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t ptr:40;
- } s;
- struct cvmx_pko_mem_debug1_s cn30xx;
- struct cvmx_pko_mem_debug1_s cn31xx;
- struct cvmx_pko_mem_debug1_s cn38xx;
- struct cvmx_pko_mem_debug1_s cn38xxp2;
- struct cvmx_pko_mem_debug1_s cn50xx;
- struct cvmx_pko_mem_debug1_s cn52xx;
- struct cvmx_pko_mem_debug1_s cn52xxp1;
- struct cvmx_pko_mem_debug1_s cn56xx;
- struct cvmx_pko_mem_debug1_s cn56xxp1;
- struct cvmx_pko_mem_debug1_s cn58xx;
- struct cvmx_pko_mem_debug1_s cn58xxp1;
-};
-
-union cvmx_pko_mem_debug10 {
- uint64_t u64;
- struct cvmx_pko_mem_debug10_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug10_cn30xx {
- uint64_t fau:28;
- uint64_t cmd:14;
- uint64_t segs:6;
- uint64_t size:16;
- } cn30xx;
- struct cvmx_pko_mem_debug10_cn30xx cn31xx;
- struct cvmx_pko_mem_debug10_cn30xx cn38xx;
- struct cvmx_pko_mem_debug10_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug10_cn50xx {
- uint64_t reserved_49_63:15;
- uint64_t ptrs1:17;
- uint64_t reserved_17_31:15;
- uint64_t ptrs2:17;
- } cn50xx;
- struct cvmx_pko_mem_debug10_cn50xx cn52xx;
- struct cvmx_pko_mem_debug10_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug10_cn50xx cn56xx;
- struct cvmx_pko_mem_debug10_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug10_cn50xx cn58xx;
- struct cvmx_pko_mem_debug10_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug11 {
- uint64_t u64;
- struct cvmx_pko_mem_debug11_s {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t reserved_0_39:40;
- } s;
- struct cvmx_pko_mem_debug11_cn30xx {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t ptr:40;
- } cn30xx;
- struct cvmx_pko_mem_debug11_cn30xx cn31xx;
- struct cvmx_pko_mem_debug11_cn30xx cn38xx;
- struct cvmx_pko_mem_debug11_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug11_cn50xx {
- uint64_t reserved_23_63:41;
- uint64_t maj:1;
- uint64_t uid:3;
- uint64_t sop:1;
- uint64_t len:1;
- uint64_t chk:1;
- uint64_t cnt:13;
- uint64_t mod:3;
- } cn50xx;
- struct cvmx_pko_mem_debug11_cn50xx cn52xx;
- struct cvmx_pko_mem_debug11_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug11_cn50xx cn56xx;
- struct cvmx_pko_mem_debug11_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug11_cn50xx cn58xx;
- struct cvmx_pko_mem_debug11_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug12 {
- uint64_t u64;
- struct cvmx_pko_mem_debug12_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug12_cn30xx {
- uint64_t data:64;
- } cn30xx;
- struct cvmx_pko_mem_debug12_cn30xx cn31xx;
- struct cvmx_pko_mem_debug12_cn30xx cn38xx;
- struct cvmx_pko_mem_debug12_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug12_cn50xx {
- uint64_t fau:28;
- uint64_t cmd:14;
- uint64_t segs:6;
- uint64_t size:16;
- } cn50xx;
- struct cvmx_pko_mem_debug12_cn50xx cn52xx;
- struct cvmx_pko_mem_debug12_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug12_cn50xx cn56xx;
- struct cvmx_pko_mem_debug12_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug12_cn50xx cn58xx;
- struct cvmx_pko_mem_debug12_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug13 {
- uint64_t u64;
- struct cvmx_pko_mem_debug13_s {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t reserved_0_55:56;
- } s;
- struct cvmx_pko_mem_debug13_cn30xx {
- uint64_t reserved_51_63:13;
- uint64_t widx:17;
- uint64_t ridx2:17;
- uint64_t widx2:17;
- } cn30xx;
- struct cvmx_pko_mem_debug13_cn30xx cn31xx;
- struct cvmx_pko_mem_debug13_cn30xx cn38xx;
- struct cvmx_pko_mem_debug13_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug13_cn50xx {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t ptr:40;
- } cn50xx;
- struct cvmx_pko_mem_debug13_cn50xx cn52xx;
- struct cvmx_pko_mem_debug13_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug13_cn50xx cn56xx;
- struct cvmx_pko_mem_debug13_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug13_cn50xx cn58xx;
- struct cvmx_pko_mem_debug13_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug14 {
- uint64_t u64;
- struct cvmx_pko_mem_debug14_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug14_cn30xx {
- uint64_t reserved_17_63:47;
- uint64_t ridx:17;
- } cn30xx;
- struct cvmx_pko_mem_debug14_cn30xx cn31xx;
- struct cvmx_pko_mem_debug14_cn30xx cn38xx;
- struct cvmx_pko_mem_debug14_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug14_cn52xx {
- uint64_t data:64;
- } cn52xx;
- struct cvmx_pko_mem_debug14_cn52xx cn52xxp1;
- struct cvmx_pko_mem_debug14_cn52xx cn56xx;
- struct cvmx_pko_mem_debug14_cn52xx cn56xxp1;
-};
-
-union cvmx_pko_mem_debug2 {
- uint64_t u64;
- struct cvmx_pko_mem_debug2_s {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t ptr:40;
- } s;
- struct cvmx_pko_mem_debug2_s cn30xx;
- struct cvmx_pko_mem_debug2_s cn31xx;
- struct cvmx_pko_mem_debug2_s cn38xx;
- struct cvmx_pko_mem_debug2_s cn38xxp2;
- struct cvmx_pko_mem_debug2_s cn50xx;
- struct cvmx_pko_mem_debug2_s cn52xx;
- struct cvmx_pko_mem_debug2_s cn52xxp1;
- struct cvmx_pko_mem_debug2_s cn56xx;
- struct cvmx_pko_mem_debug2_s cn56xxp1;
- struct cvmx_pko_mem_debug2_s cn58xx;
- struct cvmx_pko_mem_debug2_s cn58xxp1;
-};
-
-union cvmx_pko_mem_debug3 {
- uint64_t u64;
- struct cvmx_pko_mem_debug3_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug3_cn30xx {
- uint64_t i:1;
- uint64_t back:4;
- uint64_t pool:3;
- uint64_t size:16;
- uint64_t ptr:40;
- } cn30xx;
- struct cvmx_pko_mem_debug3_cn30xx cn31xx;
- struct cvmx_pko_mem_debug3_cn30xx cn38xx;
- struct cvmx_pko_mem_debug3_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug3_cn50xx {
- uint64_t data:64;
- } cn50xx;
- struct cvmx_pko_mem_debug3_cn50xx cn52xx;
- struct cvmx_pko_mem_debug3_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug3_cn50xx cn56xx;
- struct cvmx_pko_mem_debug3_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug3_cn50xx cn58xx;
- struct cvmx_pko_mem_debug3_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug4 {
- uint64_t u64;
- struct cvmx_pko_mem_debug4_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug4_cn30xx {
- uint64_t data:64;
- } cn30xx;
- struct cvmx_pko_mem_debug4_cn30xx cn31xx;
- struct cvmx_pko_mem_debug4_cn30xx cn38xx;
- struct cvmx_pko_mem_debug4_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug4_cn50xx {
- uint64_t cmnd_segs:3;
- uint64_t cmnd_siz:16;
- uint64_t cmnd_off:6;
- uint64_t uid:3;
- uint64_t dread_sop:1;
- uint64_t init_dwrite:1;
- uint64_t chk_once:1;
- uint64_t chk_mode:1;
- uint64_t active:1;
- uint64_t static_p:1;
- uint64_t qos:3;
- uint64_t qcb_ridx:5;
- uint64_t qid_off_max:4;
- uint64_t qid_off:4;
- uint64_t qid_base:8;
- uint64_t wait:1;
- uint64_t minor:2;
- uint64_t major:3;
- } cn50xx;
- struct cvmx_pko_mem_debug4_cn52xx {
- uint64_t curr_siz:8;
- uint64_t curr_off:16;
- uint64_t cmnd_segs:6;
- uint64_t cmnd_siz:16;
- uint64_t cmnd_off:6;
- uint64_t uid:2;
- uint64_t dread_sop:1;
- uint64_t init_dwrite:1;
- uint64_t chk_once:1;
- uint64_t chk_mode:1;
- uint64_t wait:1;
- uint64_t minor:2;
- uint64_t major:3;
- } cn52xx;
- struct cvmx_pko_mem_debug4_cn52xx cn52xxp1;
- struct cvmx_pko_mem_debug4_cn52xx cn56xx;
- struct cvmx_pko_mem_debug4_cn52xx cn56xxp1;
- struct cvmx_pko_mem_debug4_cn50xx cn58xx;
- struct cvmx_pko_mem_debug4_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug5 {
- uint64_t u64;
- struct cvmx_pko_mem_debug5_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_mem_debug5_cn30xx {
- uint64_t dwri_mod:1;
- uint64_t dwri_sop:1;
- uint64_t dwri_len:1;
- uint64_t dwri_cnt:13;
- uint64_t cmnd_siz:16;
- uint64_t uid:1;
- uint64_t xfer_wor:1;
- uint64_t xfer_dwr:1;
- uint64_t cbuf_fre:1;
- uint64_t reserved_27_27:1;
- uint64_t chk_mode:1;
- uint64_t active:1;
- uint64_t qos:3;
- uint64_t qcb_ridx:5;
- uint64_t qid_off:3;
- uint64_t qid_base:7;
- uint64_t wait:1;
- uint64_t minor:2;
- uint64_t major:4;
- } cn30xx;
- struct cvmx_pko_mem_debug5_cn30xx cn31xx;
- struct cvmx_pko_mem_debug5_cn30xx cn38xx;
- struct cvmx_pko_mem_debug5_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug5_cn50xx {
- uint64_t curr_ptr:29;
- uint64_t curr_siz:16;
- uint64_t curr_off:16;
- uint64_t cmnd_segs:3;
- } cn50xx;
- struct cvmx_pko_mem_debug5_cn52xx {
- uint64_t reserved_54_63:10;
- uint64_t nxt_inflt:6;
- uint64_t curr_ptr:40;
- uint64_t curr_siz:8;
- } cn52xx;
- struct cvmx_pko_mem_debug5_cn52xx cn52xxp1;
- struct cvmx_pko_mem_debug5_cn52xx cn56xx;
- struct cvmx_pko_mem_debug5_cn52xx cn56xxp1;
- struct cvmx_pko_mem_debug5_cn50xx cn58xx;
- struct cvmx_pko_mem_debug5_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug6 {
- uint64_t u64;
- struct cvmx_pko_mem_debug6_s {
- uint64_t reserved_37_63:27;
- uint64_t qid_offres:4;
- uint64_t qid_offths:4;
- uint64_t preempter:1;
- uint64_t preemptee:1;
- uint64_t preempted:1;
- uint64_t active:1;
- uint64_t statc:1;
- uint64_t qos:3;
- uint64_t qcb_ridx:5;
- uint64_t qid_offmax:4;
- uint64_t reserved_0_11:12;
- } s;
- struct cvmx_pko_mem_debug6_cn30xx {
- uint64_t reserved_11_63:53;
- uint64_t qid_offm:3;
- uint64_t static_p:1;
- uint64_t work_min:3;
- uint64_t dwri_chk:1;
- uint64_t dwri_uid:1;
- uint64_t dwri_mod:2;
- } cn30xx;
- struct cvmx_pko_mem_debug6_cn30xx cn31xx;
- struct cvmx_pko_mem_debug6_cn30xx cn38xx;
- struct cvmx_pko_mem_debug6_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug6_cn50xx {
- uint64_t reserved_11_63:53;
- uint64_t curr_ptr:11;
- } cn50xx;
- struct cvmx_pko_mem_debug6_cn52xx {
- uint64_t reserved_37_63:27;
- uint64_t qid_offres:4;
- uint64_t qid_offths:4;
- uint64_t preempter:1;
- uint64_t preemptee:1;
- uint64_t preempted:1;
- uint64_t active:1;
- uint64_t statc:1;
- uint64_t qos:3;
- uint64_t qcb_ridx:5;
- uint64_t qid_offmax:4;
- uint64_t qid_off:4;
- uint64_t qid_base:8;
- } cn52xx;
- struct cvmx_pko_mem_debug6_cn52xx cn52xxp1;
- struct cvmx_pko_mem_debug6_cn52xx cn56xx;
- struct cvmx_pko_mem_debug6_cn52xx cn56xxp1;
- struct cvmx_pko_mem_debug6_cn50xx cn58xx;
- struct cvmx_pko_mem_debug6_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug7 {
- uint64_t u64;
- struct cvmx_pko_mem_debug7_s {
- uint64_t qos:5;
- uint64_t tail:1;
- uint64_t reserved_0_57:58;
- } s;
- struct cvmx_pko_mem_debug7_cn30xx {
- uint64_t reserved_58_63:6;
- uint64_t dwb:9;
- uint64_t start:33;
- uint64_t size:16;
- } cn30xx;
- struct cvmx_pko_mem_debug7_cn30xx cn31xx;
- struct cvmx_pko_mem_debug7_cn30xx cn38xx;
- struct cvmx_pko_mem_debug7_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug7_cn50xx {
- uint64_t qos:5;
- uint64_t tail:1;
- uint64_t buf_siz:13;
- uint64_t buf_ptr:33;
- uint64_t qcb_widx:6;
- uint64_t qcb_ridx:6;
- } cn50xx;
- struct cvmx_pko_mem_debug7_cn50xx cn52xx;
- struct cvmx_pko_mem_debug7_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug7_cn50xx cn56xx;
- struct cvmx_pko_mem_debug7_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug7_cn50xx cn58xx;
- struct cvmx_pko_mem_debug7_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug8 {
- uint64_t u64;
- struct cvmx_pko_mem_debug8_s {
- uint64_t reserved_59_63:5;
- uint64_t tail:1;
- uint64_t buf_siz:13;
- uint64_t reserved_0_44:45;
- } s;
- struct cvmx_pko_mem_debug8_cn30xx {
- uint64_t qos:5;
- uint64_t tail:1;
- uint64_t buf_siz:13;
- uint64_t buf_ptr:33;
- uint64_t qcb_widx:6;
- uint64_t qcb_ridx:6;
- } cn30xx;
- struct cvmx_pko_mem_debug8_cn30xx cn31xx;
- struct cvmx_pko_mem_debug8_cn30xx cn38xx;
- struct cvmx_pko_mem_debug8_cn30xx cn38xxp2;
- struct cvmx_pko_mem_debug8_cn50xx {
- uint64_t reserved_28_63:36;
- uint64_t doorbell:20;
- uint64_t reserved_6_7:2;
- uint64_t static_p:1;
- uint64_t s_tail:1;
- uint64_t static_q:1;
- uint64_t qos:3;
- } cn50xx;
- struct cvmx_pko_mem_debug8_cn52xx {
- uint64_t reserved_29_63:35;
- uint64_t preempter:1;
- uint64_t doorbell:20;
- uint64_t reserved_7_7:1;
- uint64_t preemptee:1;
- uint64_t static_p:1;
- uint64_t s_tail:1;
- uint64_t static_q:1;
- uint64_t qos:3;
- } cn52xx;
- struct cvmx_pko_mem_debug8_cn52xx cn52xxp1;
- struct cvmx_pko_mem_debug8_cn52xx cn56xx;
- struct cvmx_pko_mem_debug8_cn52xx cn56xxp1;
- struct cvmx_pko_mem_debug8_cn50xx cn58xx;
- struct cvmx_pko_mem_debug8_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_debug9 {
- uint64_t u64;
- struct cvmx_pko_mem_debug9_s {
- uint64_t reserved_49_63:15;
- uint64_t ptrs0:17;
- uint64_t reserved_0_31:32;
- } s;
- struct cvmx_pko_mem_debug9_cn30xx {
- uint64_t reserved_28_63:36;
- uint64_t doorbell:20;
- uint64_t reserved_5_7:3;
- uint64_t s_tail:1;
- uint64_t static_q:1;
- uint64_t qos:3;
- } cn30xx;
- struct cvmx_pko_mem_debug9_cn30xx cn31xx;
- struct cvmx_pko_mem_debug9_cn38xx {
- uint64_t reserved_28_63:36;
- uint64_t doorbell:20;
- uint64_t reserved_6_7:2;
- uint64_t static_p:1;
- uint64_t s_tail:1;
- uint64_t static_q:1;
- uint64_t qos:3;
- } cn38xx;
- struct cvmx_pko_mem_debug9_cn38xx cn38xxp2;
- struct cvmx_pko_mem_debug9_cn50xx {
- uint64_t reserved_49_63:15;
- uint64_t ptrs0:17;
- uint64_t reserved_17_31:15;
- uint64_t ptrs3:17;
- } cn50xx;
- struct cvmx_pko_mem_debug9_cn50xx cn52xx;
- struct cvmx_pko_mem_debug9_cn50xx cn52xxp1;
- struct cvmx_pko_mem_debug9_cn50xx cn56xx;
- struct cvmx_pko_mem_debug9_cn50xx cn56xxp1;
- struct cvmx_pko_mem_debug9_cn50xx cn58xx;
- struct cvmx_pko_mem_debug9_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_mem_port_ptrs {
- uint64_t u64;
- struct cvmx_pko_mem_port_ptrs_s {
- uint64_t reserved_62_63:2;
- uint64_t static_p:1;
- uint64_t qos_mask:8;
- uint64_t reserved_16_52:37;
- uint64_t bp_port:6;
- uint64_t eid:4;
- uint64_t pid:6;
- } s;
- struct cvmx_pko_mem_port_ptrs_s cn52xx;
- struct cvmx_pko_mem_port_ptrs_s cn52xxp1;
- struct cvmx_pko_mem_port_ptrs_s cn56xx;
- struct cvmx_pko_mem_port_ptrs_s cn56xxp1;
-};
-
-union cvmx_pko_mem_port_qos {
- uint64_t u64;
- struct cvmx_pko_mem_port_qos_s {
- uint64_t reserved_61_63:3;
- uint64_t qos_mask:8;
- uint64_t reserved_10_52:43;
- uint64_t eid:4;
- uint64_t pid:6;
- } s;
- struct cvmx_pko_mem_port_qos_s cn52xx;
- struct cvmx_pko_mem_port_qos_s cn52xxp1;
- struct cvmx_pko_mem_port_qos_s cn56xx;
- struct cvmx_pko_mem_port_qos_s cn56xxp1;
-};
-
-union cvmx_pko_mem_port_rate0 {
- uint64_t u64;
- struct cvmx_pko_mem_port_rate0_s {
- uint64_t reserved_51_63:13;
- uint64_t rate_word:19;
- uint64_t rate_pkt:24;
- uint64_t reserved_6_7:2;
- uint64_t pid:6;
- } s;
- struct cvmx_pko_mem_port_rate0_s cn52xx;
- struct cvmx_pko_mem_port_rate0_s cn52xxp1;
- struct cvmx_pko_mem_port_rate0_s cn56xx;
- struct cvmx_pko_mem_port_rate0_s cn56xxp1;
-};
-
-union cvmx_pko_mem_port_rate1 {
- uint64_t u64;
- struct cvmx_pko_mem_port_rate1_s {
- uint64_t reserved_32_63:32;
- uint64_t rate_lim:24;
- uint64_t reserved_6_7:2;
- uint64_t pid:6;
- } s;
- struct cvmx_pko_mem_port_rate1_s cn52xx;
- struct cvmx_pko_mem_port_rate1_s cn52xxp1;
- struct cvmx_pko_mem_port_rate1_s cn56xx;
- struct cvmx_pko_mem_port_rate1_s cn56xxp1;
-};
-
-union cvmx_pko_mem_queue_ptrs {
- uint64_t u64;
- struct cvmx_pko_mem_queue_ptrs_s {
- uint64_t s_tail:1;
- uint64_t static_p:1;
- uint64_t static_q:1;
- uint64_t qos_mask:8;
- uint64_t buf_ptr:36;
- uint64_t tail:1;
- uint64_t index:3;
- uint64_t port:6;
- uint64_t queue:7;
- } s;
- struct cvmx_pko_mem_queue_ptrs_s cn30xx;
- struct cvmx_pko_mem_queue_ptrs_s cn31xx;
- struct cvmx_pko_mem_queue_ptrs_s cn38xx;
- struct cvmx_pko_mem_queue_ptrs_s cn38xxp2;
- struct cvmx_pko_mem_queue_ptrs_s cn50xx;
- struct cvmx_pko_mem_queue_ptrs_s cn52xx;
- struct cvmx_pko_mem_queue_ptrs_s cn52xxp1;
- struct cvmx_pko_mem_queue_ptrs_s cn56xx;
- struct cvmx_pko_mem_queue_ptrs_s cn56xxp1;
- struct cvmx_pko_mem_queue_ptrs_s cn58xx;
- struct cvmx_pko_mem_queue_ptrs_s cn58xxp1;
-};
-
-union cvmx_pko_mem_queue_qos {
- uint64_t u64;
- struct cvmx_pko_mem_queue_qos_s {
- uint64_t reserved_61_63:3;
- uint64_t qos_mask:8;
- uint64_t reserved_13_52:40;
- uint64_t pid:6;
- uint64_t qid:7;
- } s;
- struct cvmx_pko_mem_queue_qos_s cn30xx;
- struct cvmx_pko_mem_queue_qos_s cn31xx;
- struct cvmx_pko_mem_queue_qos_s cn38xx;
- struct cvmx_pko_mem_queue_qos_s cn38xxp2;
- struct cvmx_pko_mem_queue_qos_s cn50xx;
- struct cvmx_pko_mem_queue_qos_s cn52xx;
- struct cvmx_pko_mem_queue_qos_s cn52xxp1;
- struct cvmx_pko_mem_queue_qos_s cn56xx;
- struct cvmx_pko_mem_queue_qos_s cn56xxp1;
- struct cvmx_pko_mem_queue_qos_s cn58xx;
- struct cvmx_pko_mem_queue_qos_s cn58xxp1;
-};
-
-union cvmx_pko_reg_bist_result {
- uint64_t u64;
- struct cvmx_pko_reg_bist_result_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_pko_reg_bist_result_cn30xx {
- uint64_t reserved_27_63:37;
- uint64_t psb2:5;
- uint64_t count:1;
- uint64_t rif:1;
- uint64_t wif:1;
- uint64_t ncb:1;
- uint64_t out:1;
- uint64_t crc:1;
- uint64_t chk:1;
- uint64_t qsb:2;
- uint64_t qcb:2;
- uint64_t pdb:4;
- uint64_t psb:7;
- } cn30xx;
- struct cvmx_pko_reg_bist_result_cn30xx cn31xx;
- struct cvmx_pko_reg_bist_result_cn30xx cn38xx;
- struct cvmx_pko_reg_bist_result_cn30xx cn38xxp2;
- struct cvmx_pko_reg_bist_result_cn50xx {
- uint64_t reserved_33_63:31;
- uint64_t csr:1;
- uint64_t iob:1;
- uint64_t out_crc:1;
- uint64_t out_ctl:3;
- uint64_t out_sta:1;
- uint64_t out_wif:1;
- uint64_t prt_chk:3;
- uint64_t prt_nxt:1;
- uint64_t prt_psb:6;
- uint64_t ncb_inb:2;
- uint64_t prt_qcb:2;
- uint64_t prt_qsb:3;
- uint64_t dat_dat:4;
- uint64_t dat_ptr:4;
- } cn50xx;
- struct cvmx_pko_reg_bist_result_cn52xx {
- uint64_t reserved_35_63:29;
- uint64_t csr:1;
- uint64_t iob:1;
- uint64_t out_dat:1;
- uint64_t out_ctl:3;
- uint64_t out_sta:1;
- uint64_t out_wif:1;
- uint64_t prt_chk:3;
- uint64_t prt_nxt:1;
- uint64_t prt_psb:8;
- uint64_t ncb_inb:2;
- uint64_t prt_qcb:2;
- uint64_t prt_qsb:3;
- uint64_t prt_ctl:2;
- uint64_t dat_dat:2;
- uint64_t dat_ptr:4;
- } cn52xx;
- struct cvmx_pko_reg_bist_result_cn52xx cn52xxp1;
- struct cvmx_pko_reg_bist_result_cn52xx cn56xx;
- struct cvmx_pko_reg_bist_result_cn52xx cn56xxp1;
- struct cvmx_pko_reg_bist_result_cn50xx cn58xx;
- struct cvmx_pko_reg_bist_result_cn50xx cn58xxp1;
-};
-
-union cvmx_pko_reg_cmd_buf {
- uint64_t u64;
- struct cvmx_pko_reg_cmd_buf_s {
- uint64_t reserved_23_63:41;
- uint64_t pool:3;
- uint64_t reserved_13_19:7;
- uint64_t size:13;
- } s;
- struct cvmx_pko_reg_cmd_buf_s cn30xx;
- struct cvmx_pko_reg_cmd_buf_s cn31xx;
- struct cvmx_pko_reg_cmd_buf_s cn38xx;
- struct cvmx_pko_reg_cmd_buf_s cn38xxp2;
- struct cvmx_pko_reg_cmd_buf_s cn50xx;
- struct cvmx_pko_reg_cmd_buf_s cn52xx;
- struct cvmx_pko_reg_cmd_buf_s cn52xxp1;
- struct cvmx_pko_reg_cmd_buf_s cn56xx;
- struct cvmx_pko_reg_cmd_buf_s cn56xxp1;
- struct cvmx_pko_reg_cmd_buf_s cn58xx;
- struct cvmx_pko_reg_cmd_buf_s cn58xxp1;
-};
-
-union cvmx_pko_reg_crc_ctlx {
- uint64_t u64;
- struct cvmx_pko_reg_crc_ctlx_s {
- uint64_t reserved_2_63:62;
- uint64_t invres:1;
- uint64_t refin:1;
- } s;
- struct cvmx_pko_reg_crc_ctlx_s cn38xx;
- struct cvmx_pko_reg_crc_ctlx_s cn38xxp2;
- struct cvmx_pko_reg_crc_ctlx_s cn58xx;
- struct cvmx_pko_reg_crc_ctlx_s cn58xxp1;
-};
-
-union cvmx_pko_reg_crc_enable {
- uint64_t u64;
- struct cvmx_pko_reg_crc_enable_s {
- uint64_t reserved_32_63:32;
- uint64_t enable:32;
- } s;
- struct cvmx_pko_reg_crc_enable_s cn38xx;
- struct cvmx_pko_reg_crc_enable_s cn38xxp2;
- struct cvmx_pko_reg_crc_enable_s cn58xx;
- struct cvmx_pko_reg_crc_enable_s cn58xxp1;
-};
-
-union cvmx_pko_reg_crc_ivx {
- uint64_t u64;
- struct cvmx_pko_reg_crc_ivx_s {
- uint64_t reserved_32_63:32;
- uint64_t iv:32;
- } s;
- struct cvmx_pko_reg_crc_ivx_s cn38xx;
- struct cvmx_pko_reg_crc_ivx_s cn38xxp2;
- struct cvmx_pko_reg_crc_ivx_s cn58xx;
- struct cvmx_pko_reg_crc_ivx_s cn58xxp1;
-};
-
-union cvmx_pko_reg_debug0 {
- uint64_t u64;
- struct cvmx_pko_reg_debug0_s {
- uint64_t asserts:64;
- } s;
- struct cvmx_pko_reg_debug0_cn30xx {
- uint64_t reserved_17_63:47;
- uint64_t asserts:17;
- } cn30xx;
- struct cvmx_pko_reg_debug0_cn30xx cn31xx;
- struct cvmx_pko_reg_debug0_cn30xx cn38xx;
- struct cvmx_pko_reg_debug0_cn30xx cn38xxp2;
- struct cvmx_pko_reg_debug0_s cn50xx;
- struct cvmx_pko_reg_debug0_s cn52xx;
- struct cvmx_pko_reg_debug0_s cn52xxp1;
- struct cvmx_pko_reg_debug0_s cn56xx;
- struct cvmx_pko_reg_debug0_s cn56xxp1;
- struct cvmx_pko_reg_debug0_s cn58xx;
- struct cvmx_pko_reg_debug0_s cn58xxp1;
-};
-
-union cvmx_pko_reg_debug1 {
- uint64_t u64;
- struct cvmx_pko_reg_debug1_s {
- uint64_t asserts:64;
- } s;
- struct cvmx_pko_reg_debug1_s cn50xx;
- struct cvmx_pko_reg_debug1_s cn52xx;
- struct cvmx_pko_reg_debug1_s cn52xxp1;
- struct cvmx_pko_reg_debug1_s cn56xx;
- struct cvmx_pko_reg_debug1_s cn56xxp1;
- struct cvmx_pko_reg_debug1_s cn58xx;
- struct cvmx_pko_reg_debug1_s cn58xxp1;
-};
-
-union cvmx_pko_reg_debug2 {
- uint64_t u64;
- struct cvmx_pko_reg_debug2_s {
- uint64_t asserts:64;
- } s;
- struct cvmx_pko_reg_debug2_s cn50xx;
- struct cvmx_pko_reg_debug2_s cn52xx;
- struct cvmx_pko_reg_debug2_s cn52xxp1;
- struct cvmx_pko_reg_debug2_s cn56xx;
- struct cvmx_pko_reg_debug2_s cn56xxp1;
- struct cvmx_pko_reg_debug2_s cn58xx;
- struct cvmx_pko_reg_debug2_s cn58xxp1;
-};
-
-union cvmx_pko_reg_debug3 {
- uint64_t u64;
- struct cvmx_pko_reg_debug3_s {
- uint64_t asserts:64;
- } s;
- struct cvmx_pko_reg_debug3_s cn50xx;
- struct cvmx_pko_reg_debug3_s cn52xx;
- struct cvmx_pko_reg_debug3_s cn52xxp1;
- struct cvmx_pko_reg_debug3_s cn56xx;
- struct cvmx_pko_reg_debug3_s cn56xxp1;
- struct cvmx_pko_reg_debug3_s cn58xx;
- struct cvmx_pko_reg_debug3_s cn58xxp1;
-};
-
-union cvmx_pko_reg_engine_inflight {
- uint64_t u64;
- struct cvmx_pko_reg_engine_inflight_s {
- uint64_t reserved_40_63:24;
- uint64_t engine9:4;
- uint64_t engine8:4;
- uint64_t engine7:4;
- uint64_t engine6:4;
- uint64_t engine5:4;
- uint64_t engine4:4;
- uint64_t engine3:4;
- uint64_t engine2:4;
- uint64_t engine1:4;
- uint64_t engine0:4;
- } s;
- struct cvmx_pko_reg_engine_inflight_s cn52xx;
- struct cvmx_pko_reg_engine_inflight_s cn52xxp1;
- struct cvmx_pko_reg_engine_inflight_s cn56xx;
- struct cvmx_pko_reg_engine_inflight_s cn56xxp1;
-};
-
-union cvmx_pko_reg_engine_thresh {
- uint64_t u64;
- struct cvmx_pko_reg_engine_thresh_s {
- uint64_t reserved_10_63:54;
- uint64_t mask:10;
- } s;
- struct cvmx_pko_reg_engine_thresh_s cn52xx;
- struct cvmx_pko_reg_engine_thresh_s cn52xxp1;
- struct cvmx_pko_reg_engine_thresh_s cn56xx;
- struct cvmx_pko_reg_engine_thresh_s cn56xxp1;
-};
-
-union cvmx_pko_reg_error {
- uint64_t u64;
- struct cvmx_pko_reg_error_s {
- uint64_t reserved_3_63:61;
- uint64_t currzero:1;
- uint64_t doorbell:1;
- uint64_t parity:1;
- } s;
- struct cvmx_pko_reg_error_cn30xx {
- uint64_t reserved_2_63:62;
- uint64_t doorbell:1;
- uint64_t parity:1;
- } cn30xx;
- struct cvmx_pko_reg_error_cn30xx cn31xx;
- struct cvmx_pko_reg_error_cn30xx cn38xx;
- struct cvmx_pko_reg_error_cn30xx cn38xxp2;
- struct cvmx_pko_reg_error_s cn50xx;
- struct cvmx_pko_reg_error_s cn52xx;
- struct cvmx_pko_reg_error_s cn52xxp1;
- struct cvmx_pko_reg_error_s cn56xx;
- struct cvmx_pko_reg_error_s cn56xxp1;
- struct cvmx_pko_reg_error_s cn58xx;
- struct cvmx_pko_reg_error_s cn58xxp1;
-};
-
-union cvmx_pko_reg_flags {
- uint64_t u64;
- struct cvmx_pko_reg_flags_s {
- uint64_t reserved_4_63:60;
- uint64_t reset:1;
- uint64_t store_be:1;
- uint64_t ena_dwb:1;
- uint64_t ena_pko:1;
- } s;
- struct cvmx_pko_reg_flags_s cn30xx;
- struct cvmx_pko_reg_flags_s cn31xx;
- struct cvmx_pko_reg_flags_s cn38xx;
- struct cvmx_pko_reg_flags_s cn38xxp2;
- struct cvmx_pko_reg_flags_s cn50xx;
- struct cvmx_pko_reg_flags_s cn52xx;
- struct cvmx_pko_reg_flags_s cn52xxp1;
- struct cvmx_pko_reg_flags_s cn56xx;
- struct cvmx_pko_reg_flags_s cn56xxp1;
- struct cvmx_pko_reg_flags_s cn58xx;
- struct cvmx_pko_reg_flags_s cn58xxp1;
-};
-
-union cvmx_pko_reg_gmx_port_mode {
- uint64_t u64;
- struct cvmx_pko_reg_gmx_port_mode_s {
- uint64_t reserved_6_63:58;
- uint64_t mode1:3;
- uint64_t mode0:3;
- } s;
- struct cvmx_pko_reg_gmx_port_mode_s cn30xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn31xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn38xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn38xxp2;
- struct cvmx_pko_reg_gmx_port_mode_s cn50xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn52xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn52xxp1;
- struct cvmx_pko_reg_gmx_port_mode_s cn56xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn56xxp1;
- struct cvmx_pko_reg_gmx_port_mode_s cn58xx;
- struct cvmx_pko_reg_gmx_port_mode_s cn58xxp1;
-};
-
-union cvmx_pko_reg_int_mask {
- uint64_t u64;
- struct cvmx_pko_reg_int_mask_s {
- uint64_t reserved_3_63:61;
- uint64_t currzero:1;
- uint64_t doorbell:1;
- uint64_t parity:1;
- } s;
- struct cvmx_pko_reg_int_mask_cn30xx {
- uint64_t reserved_2_63:62;
- uint64_t doorbell:1;
- uint64_t parity:1;
- } cn30xx;
- struct cvmx_pko_reg_int_mask_cn30xx cn31xx;
- struct cvmx_pko_reg_int_mask_cn30xx cn38xx;
- struct cvmx_pko_reg_int_mask_cn30xx cn38xxp2;
- struct cvmx_pko_reg_int_mask_s cn50xx;
- struct cvmx_pko_reg_int_mask_s cn52xx;
- struct cvmx_pko_reg_int_mask_s cn52xxp1;
- struct cvmx_pko_reg_int_mask_s cn56xx;
- struct cvmx_pko_reg_int_mask_s cn56xxp1;
- struct cvmx_pko_reg_int_mask_s cn58xx;
- struct cvmx_pko_reg_int_mask_s cn58xxp1;
-};
-
-union cvmx_pko_reg_queue_mode {
- uint64_t u64;
- struct cvmx_pko_reg_queue_mode_s {
- uint64_t reserved_2_63:62;
- uint64_t mode:2;
- } s;
- struct cvmx_pko_reg_queue_mode_s cn30xx;
- struct cvmx_pko_reg_queue_mode_s cn31xx;
- struct cvmx_pko_reg_queue_mode_s cn38xx;
- struct cvmx_pko_reg_queue_mode_s cn38xxp2;
- struct cvmx_pko_reg_queue_mode_s cn50xx;
- struct cvmx_pko_reg_queue_mode_s cn52xx;
- struct cvmx_pko_reg_queue_mode_s cn52xxp1;
- struct cvmx_pko_reg_queue_mode_s cn56xx;
- struct cvmx_pko_reg_queue_mode_s cn56xxp1;
- struct cvmx_pko_reg_queue_mode_s cn58xx;
- struct cvmx_pko_reg_queue_mode_s cn58xxp1;
-};
-
-union cvmx_pko_reg_queue_ptrs1 {
- uint64_t u64;
- struct cvmx_pko_reg_queue_ptrs1_s {
- uint64_t reserved_2_63:62;
- uint64_t idx3:1;
- uint64_t qid7:1;
- } s;
- struct cvmx_pko_reg_queue_ptrs1_s cn50xx;
- struct cvmx_pko_reg_queue_ptrs1_s cn52xx;
- struct cvmx_pko_reg_queue_ptrs1_s cn52xxp1;
- struct cvmx_pko_reg_queue_ptrs1_s cn56xx;
- struct cvmx_pko_reg_queue_ptrs1_s cn56xxp1;
- struct cvmx_pko_reg_queue_ptrs1_s cn58xx;
- struct cvmx_pko_reg_queue_ptrs1_s cn58xxp1;
-};
-
-union cvmx_pko_reg_read_idx {
- uint64_t u64;
- struct cvmx_pko_reg_read_idx_s {
- uint64_t reserved_16_63:48;
- uint64_t inc:8;
- uint64_t index:8;
- } s;
- struct cvmx_pko_reg_read_idx_s cn30xx;
- struct cvmx_pko_reg_read_idx_s cn31xx;
- struct cvmx_pko_reg_read_idx_s cn38xx;
- struct cvmx_pko_reg_read_idx_s cn38xxp2;
- struct cvmx_pko_reg_read_idx_s cn50xx;
- struct cvmx_pko_reg_read_idx_s cn52xx;
- struct cvmx_pko_reg_read_idx_s cn52xxp1;
- struct cvmx_pko_reg_read_idx_s cn56xx;
- struct cvmx_pko_reg_read_idx_s cn56xxp1;
- struct cvmx_pko_reg_read_idx_s cn58xx;
- struct cvmx_pko_reg_read_idx_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-pko.c b/drivers/staging/octeon/cvmx-pko.c
deleted file mode 100644
index 50a2c9b..0000000
--- a/drivers/staging/octeon/cvmx-pko.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- * Support library for the hardware Packet Output unit.
- */
-
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-#include "cvmx-pko.h"
-#include "cvmx-helper.h"
-
-/**
- * Internal state of packet output
- */
-
-/**
- * Call before any other calls to initialize the packet
- * output system. This does chip global config, and should only be
- * done by one core.
- */
-
-void cvmx_pko_initialize_global(void)
-{
- int i;
- uint64_t priority = 8;
- union cvmx_pko_reg_cmd_buf config;
-
- /*
- * Set the size of the PKO command buffers to an odd number of
- * 64bit words. This allows the normal two word send to stay
- * aligned and never span a command word buffer.
- */
- config.u64 = 0;
- config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL;
- config.s.size = CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE / 8 - 1;
-
- cvmx_write_csr(CVMX_PKO_REG_CMD_BUF, config.u64);
-
- for (i = 0; i < CVMX_PKO_MAX_OUTPUT_QUEUES; i++)
- cvmx_pko_config_port(CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID, i, 1,
- &priority);
-
- /*
- * If we aren't using all of the queues optimize PKO's
- * internal memory.
- */
- if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)
- || OCTEON_IS_MODEL(OCTEON_CN56XX)
- || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
- int num_interfaces = cvmx_helper_get_number_of_interfaces();
- int last_port =
- cvmx_helper_get_last_ipd_port(num_interfaces - 1);
- int max_queues =
- cvmx_pko_get_base_queue(last_port) +
- cvmx_pko_get_num_queues(last_port);
- if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
- if (max_queues <= 32)
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
- else if (max_queues <= 64)
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
- } else {
- if (max_queues <= 64)
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 2);
- else if (max_queues <= 128)
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_MODE, 1);
- }
- }
-}
-
-/**
- * This function does per-core initialization required by the PKO routines.
- * This must be called on all cores that will do packet output, and must
- * be called after the FPA has been initialized and filled with pages.
- *
- * Returns 0 on success
- * !0 on failure
- */
-int cvmx_pko_initialize_local(void)
-{
- /* Nothing to do */
- return 0;
-}
-
-/**
- * Enables the packet output hardware. It must already be
- * configured.
- */
-void cvmx_pko_enable(void)
-{
- union cvmx_pko_reg_flags flags;
-
- flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
- if (flags.s.ena_pko)
- cvmx_dprintf
- ("Warning: Enabling PKO when PKO already enabled.\n");
-
- flags.s.ena_dwb = 1;
- flags.s.ena_pko = 1;
- /*
- * always enable big endian for 3-word command. Does nothing
- * for 2-word.
- */
- flags.s.store_be = 1;
- cvmx_write_csr(CVMX_PKO_REG_FLAGS, flags.u64);
-}
-
-/**
- * Disables the packet output. Does not affect any configuration.
- */
-void cvmx_pko_disable(void)
-{
- union cvmx_pko_reg_flags pko_reg_flags;
- pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
- pko_reg_flags.s.ena_pko = 0;
- cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
-}
-
-
-/**
- * Reset the packet output.
- */
-static void __cvmx_pko_reset(void)
-{
- union cvmx_pko_reg_flags pko_reg_flags;
- pko_reg_flags.u64 = cvmx_read_csr(CVMX_PKO_REG_FLAGS);
- pko_reg_flags.s.reset = 1;
- cvmx_write_csr(CVMX_PKO_REG_FLAGS, pko_reg_flags.u64);
-}
-
-/**
- * Shutdown and free resources required by packet output.
- */
-void cvmx_pko_shutdown(void)
-{
- union cvmx_pko_mem_queue_ptrs config;
- int queue;
-
- cvmx_pko_disable();
-
- for (queue = 0; queue < CVMX_PKO_MAX_OUTPUT_QUEUES; queue++) {
- config.u64 = 0;
- config.s.tail = 1;
- config.s.index = 0;
- config.s.port = CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID;
- config.s.queue = queue & 0x7f;
- config.s.qos_mask = 0;
- config.s.buf_ptr = 0;
- if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- union cvmx_pko_reg_queue_ptrs1 config1;
- config1.u64 = 0;
- config1.s.qid7 = queue >> 7;
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
- }
- cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
- cvmx_cmd_queue_shutdown(CVMX_CMD_QUEUE_PKO(queue));
- }
- __cvmx_pko_reset();
-}
-
-/**
- * Configure a output port and the associated queues for use.
- *
- * @port: Port to configure.
- * @base_queue: First queue number to associate with this port.
- * @num_queues: Number of queues to associate with this port
- * @priority: Array of priority levels for each queue. Values are
- * allowed to be 0-8. A value of 8 get 8 times the traffic
- * of a value of 1. A value of 0 indicates that no rounds
- * will be participated in. These priorities can be changed
- * on the fly while the pko is enabled. A priority of 9
- * indicates that static priority should be used. If static
- * priority is used all queues with static priority must be
- * contiguous starting at the base_queue, and lower numbered
- * queues have higher priority than higher numbered queues.
- * There must be num_queues elements in the array.
- */
-cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue,
- uint64_t num_queues,
- const uint64_t priority[])
-{
- cvmx_pko_status_t result_code;
- uint64_t queue;
- union cvmx_pko_mem_queue_ptrs config;
- union cvmx_pko_reg_queue_ptrs1 config1;
- int static_priority_base = -1;
- int static_priority_end = -1;
-
- if ((port >= CVMX_PKO_NUM_OUTPUT_PORTS)
- && (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID)) {
- cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid port %llu\n",
- (unsigned long long)port);
- return CVMX_PKO_INVALID_PORT;
- }
-
- if (base_queue + num_queues > CVMX_PKO_MAX_OUTPUT_QUEUES) {
- cvmx_dprintf
- ("ERROR: cvmx_pko_config_port: Invalid queue range %llu\n",
- (unsigned long long)(base_queue + num_queues));
- return CVMX_PKO_INVALID_QUEUE;
- }
-
- if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) {
- /*
- * Validate the static queue priority setup and set
- * static_priority_base and static_priority_end
- * accordingly.
- */
- for (queue = 0; queue < num_queues; queue++) {
- /* Find first queue of static priority */
- if (static_priority_base == -1
- && priority[queue] ==
- CVMX_PKO_QUEUE_STATIC_PRIORITY)
- static_priority_base = queue;
- /* Find last queue of static priority */
- if (static_priority_base != -1
- && static_priority_end == -1
- && priority[queue] != CVMX_PKO_QUEUE_STATIC_PRIORITY
- && queue)
- static_priority_end = queue - 1;
- else if (static_priority_base != -1
- && static_priority_end == -1
- && queue == num_queues - 1)
- /* all queues are static priority */
- static_priority_end = queue;
- /*
- * Check to make sure all static priority
- * queues are contiguous. Also catches some
- * cases of static priorites not starting at
- * queue 0.
- */
- if (static_priority_end != -1
- && (int)queue > static_priority_end
- && priority[queue] ==
- CVMX_PKO_QUEUE_STATIC_PRIORITY) {
- cvmx_dprintf("ERROR: cvmx_pko_config_port: "
- "Static priority queues aren't "
- "contiguous or don't start at "
- "base queue. q: %d, eq: %d\n",
- (int)queue, static_priority_end);
- return CVMX_PKO_INVALID_PRIORITY;
- }
- }
- if (static_priority_base > 0) {
- cvmx_dprintf("ERROR: cvmx_pko_config_port: Static "
- "priority queues don't start at base "
- "queue. sq: %d\n",
- static_priority_base);
- return CVMX_PKO_INVALID_PRIORITY;
- }
-#if 0
- cvmx_dprintf("Port %d: Static priority queue base: %d, "
- "end: %d\n", port,
- static_priority_base, static_priority_end);
-#endif
- }
- /*
- * At this point, static_priority_base and static_priority_end
- * are either both -1, or are valid start/end queue
- * numbers.
- */
-
- result_code = CVMX_PKO_SUCCESS;
-
-#ifdef PKO_DEBUG
- cvmx_dprintf("num queues: %d (%lld,%lld)\n", num_queues,
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE0,
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE1);
-#endif
-
- for (queue = 0; queue < num_queues; queue++) {
- uint64_t *buf_ptr = NULL;
-
- config1.u64 = 0;
- config1.s.idx3 = queue >> 3;
- config1.s.qid7 = (base_queue + queue) >> 7;
-
- config.u64 = 0;
- config.s.tail = queue == (num_queues - 1);
- config.s.index = queue;
- config.s.port = port;
- config.s.queue = base_queue + queue;
-
- if (!cvmx_octeon_is_pass1()) {
- config.s.static_p = static_priority_base >= 0;
- config.s.static_q = (int)queue <= static_priority_end;
- config.s.s_tail = (int)queue == static_priority_end;
- }
- /*
- * Convert the priority into an enable bit field. Try
- * to space the bits out evenly so the packet don't
- * get grouped up
- */
- switch ((int)priority[queue]) {
- case 0:
- config.s.qos_mask = 0x00;
- break;
- case 1:
- config.s.qos_mask = 0x01;
- break;
- case 2:
- config.s.qos_mask = 0x11;
- break;
- case 3:
- config.s.qos_mask = 0x49;
- break;
- case 4:
- config.s.qos_mask = 0x55;
- break;
- case 5:
- config.s.qos_mask = 0x57;
- break;
- case 6:
- config.s.qos_mask = 0x77;
- break;
- case 7:
- config.s.qos_mask = 0x7f;
- break;
- case 8:
- config.s.qos_mask = 0xff;
- break;
- case CVMX_PKO_QUEUE_STATIC_PRIORITY:
- /* Pass 1 will fall through to the error case */
- if (!cvmx_octeon_is_pass1()) {
- config.s.qos_mask = 0xff;
- break;
- }
- default:
- cvmx_dprintf("ERROR: cvmx_pko_config_port: Invalid "
- "priority %llu\n",
- (unsigned long long)priority[queue]);
- config.s.qos_mask = 0xff;
- result_code = CVMX_PKO_INVALID_PRIORITY;
- break;
- }
-
- if (port != CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID) {
- cvmx_cmd_queue_result_t cmd_res =
- cvmx_cmd_queue_initialize(CVMX_CMD_QUEUE_PKO
- (base_queue + queue),
- CVMX_PKO_MAX_QUEUE_DEPTH,
- CVMX_FPA_OUTPUT_BUFFER_POOL,
- CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
- -
- CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST
- * 8);
- if (cmd_res != CVMX_CMD_QUEUE_SUCCESS) {
- switch (cmd_res) {
- case CVMX_CMD_QUEUE_NO_MEMORY:
- cvmx_dprintf("ERROR: "
- "cvmx_pko_config_port: "
- "Unable to allocate "
- "output buffer.\n");
- return CVMX_PKO_NO_MEMORY;
- case CVMX_CMD_QUEUE_ALREADY_SETUP:
- cvmx_dprintf
- ("ERROR: cvmx_pko_config_port: Port already setup.\n");
- return CVMX_PKO_PORT_ALREADY_SETUP;
- case CVMX_CMD_QUEUE_INVALID_PARAM:
- default:
- cvmx_dprintf
- ("ERROR: cvmx_pko_config_port: Command queue initialization failed.\n");
- return CVMX_PKO_CMD_QUEUE_INIT_ERROR;
- }
- }
-
- buf_ptr =
- (uint64_t *)
- cvmx_cmd_queue_buffer(CVMX_CMD_QUEUE_PKO
- (base_queue + queue));
- config.s.buf_ptr = cvmx_ptr_to_phys(buf_ptr);
- } else
- config.s.buf_ptr = 0;
-
- CVMX_SYNCWS;
-
- if (!OCTEON_IS_MODEL(OCTEON_CN3XXX))
- cvmx_write_csr(CVMX_PKO_REG_QUEUE_PTRS1, config1.u64);
- cvmx_write_csr(CVMX_PKO_MEM_QUEUE_PTRS, config.u64);
- }
-
- return result_code;
-}
-
-#ifdef PKO_DEBUG
-/**
- * Show map of ports -> queues for different cores.
- */
-void cvmx_pko_show_queue_map()
-{
- int core, port;
- int pko_output_ports = 36;
-
- cvmx_dprintf("port");
- for (port = 0; port < pko_output_ports; port++)
- cvmx_dprintf("%3d ", port);
- cvmx_dprintf("\n");
-
- for (core = 0; core < CVMX_MAX_CORES; core++) {
- cvmx_dprintf("\n%2d: ", core);
- for (port = 0; port < pko_output_ports; port++) {
- cvmx_dprintf("%3d ",
- cvmx_pko_get_base_queue_per_core(port,
- core));
- }
- }
- cvmx_dprintf("\n");
-}
-#endif
-
-/**
- * Rate limit a PKO port to a max packets/sec. This function is only
- * supported on CN51XX and higher, excluding CN58XX.
- *
- * @port: Port to rate limit
- * @packets_s: Maximum packet/sec
- * @burst: Maximum number of packets to burst in a row before rate
- * limiting cuts in.
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst)
-{
- union cvmx_pko_mem_port_rate0 pko_mem_port_rate0;
- union cvmx_pko_mem_port_rate1 pko_mem_port_rate1;
-
- pko_mem_port_rate0.u64 = 0;
- pko_mem_port_rate0.s.pid = port;
- pko_mem_port_rate0.s.rate_pkt =
- cvmx_sysinfo_get()->cpu_clock_hz / packets_s / 16;
- /* No cost per word since we are limited by packets/sec, not bits/sec */
- pko_mem_port_rate0.s.rate_word = 0;
-
- pko_mem_port_rate1.u64 = 0;
- pko_mem_port_rate1.s.pid = port;
- pko_mem_port_rate1.s.rate_lim =
- ((uint64_t) pko_mem_port_rate0.s.rate_pkt * burst) >> 8;
-
- cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
- cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
- return 0;
-}
-
-/**
- * Rate limit a PKO port to a max bits/sec. This function is only
- * supported on CN51XX and higher, excluding CN58XX.
- *
- * @port: Port to rate limit
- * @bits_s: PKO rate limit in bits/sec
- * @burst: Maximum number of bits to burst before rate
- * limiting cuts in.
- *
- * Returns Zero on success, negative on failure
- */
-int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst)
-{
- union cvmx_pko_mem_port_rate0 pko_mem_port_rate0;
- union cvmx_pko_mem_port_rate1 pko_mem_port_rate1;
- uint64_t clock_rate = cvmx_sysinfo_get()->cpu_clock_hz;
- uint64_t tokens_per_bit = clock_rate * 16 / bits_s;
-
- pko_mem_port_rate0.u64 = 0;
- pko_mem_port_rate0.s.pid = port;
- /*
- * Each packet has a 12 bytes of interframe gap, an 8 byte
- * preamble, and a 4 byte CRC. These are not included in the
- * per word count. Multiply by 8 to covert to bits and divide
- * by 256 for limit granularity.
- */
- pko_mem_port_rate0.s.rate_pkt = (12 + 8 + 4) * 8 * tokens_per_bit / 256;
- /* Each 8 byte word has 64bits */
- pko_mem_port_rate0.s.rate_word = 64 * tokens_per_bit;
-
- pko_mem_port_rate1.u64 = 0;
- pko_mem_port_rate1.s.pid = port;
- pko_mem_port_rate1.s.rate_lim = tokens_per_bit * burst / 256;
-
- cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE0, pko_mem_port_rate0.u64);
- cvmx_write_csr(CVMX_PKO_MEM_PORT_RATE1, pko_mem_port_rate1.u64);
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-pko.h b/drivers/staging/octeon/cvmx-pko.h
deleted file mode 100644
index de3412a..0000000
--- a/drivers/staging/octeon/cvmx-pko.h
+++ /dev/null
@@ -1,610 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * Interface to the hardware Packet Output unit.
- *
- * Starting with SDK 1.7.0, the PKO output functions now support
- * two types of locking. CVMX_PKO_LOCK_ATOMIC_TAG continues to
- * function similarly to previous SDKs by using POW atomic tags
- * to preserve ordering and exclusivity. As a new option, you
- * can now pass CVMX_PKO_LOCK_CMD_QUEUE which uses a ll/sc
- * memory based locking instead. This locking has the advantage
- * of not affecting the tag state but doesn't preserve packet
- * ordering. CVMX_PKO_LOCK_CMD_QUEUE is appropriate in most
- * generic code while CVMX_PKO_LOCK_CMD_QUEUE should be used
- * with hand tuned fast path code.
- *
- * Some of other SDK differences visible to the command command
- * queuing:
- * - PKO indexes are no longer stored in the FAU. A large
- * percentage of the FAU register block used to be tied up
- * maintaining PKO queue pointers. These are now stored in a
- * global named block.
- * - The PKO <b>use_locking</b> parameter can now have a global
- * effect. Since all application use the same named block,
- * queue locking correctly applies across all operating
- * systems when using CVMX_PKO_LOCK_CMD_QUEUE.
- * - PKO 3 word commands are now supported. Use
- * cvmx_pko_send_packet_finish3().
- *
- */
-
-#ifndef __CVMX_PKO_H__
-#define __CVMX_PKO_H__
-
-#include "cvmx-fpa.h"
-#include "cvmx-pow.h"
-#include "cvmx-cmd-queue.h"
-#include "cvmx-pko-defs.h"
-
-/* Adjust the command buffer size by 1 word so that in the case of using only
- * two word PKO commands no command words stradle buffers. The useful values
- * for this are 0 and 1. */
-#define CVMX_PKO_COMMAND_BUFFER_SIZE_ADJUST (1)
-
-#define CVMX_PKO_MAX_OUTPUT_QUEUES_STATIC 256
-#define CVMX_PKO_MAX_OUTPUT_QUEUES ((OCTEON_IS_MODEL(OCTEON_CN31XX) || \
- OCTEON_IS_MODEL(OCTEON_CN3010) || OCTEON_IS_MODEL(OCTEON_CN3005) || \
- OCTEON_IS_MODEL(OCTEON_CN50XX)) ? 32 : \
- (OCTEON_IS_MODEL(OCTEON_CN58XX) || \
- OCTEON_IS_MODEL(OCTEON_CN56XX)) ? 256 : 128)
-#define CVMX_PKO_NUM_OUTPUT_PORTS 40
-/* use this for queues that are not used */
-#define CVMX_PKO_MEM_QUEUE_PTRS_ILLEGAL_PID 63
-#define CVMX_PKO_QUEUE_STATIC_PRIORITY 9
-#define CVMX_PKO_ILLEGAL_QUEUE 0xFFFF
-#define CVMX_PKO_MAX_QUEUE_DEPTH 0
-
-typedef enum {
- CVMX_PKO_SUCCESS,
- CVMX_PKO_INVALID_PORT,
- CVMX_PKO_INVALID_QUEUE,
- CVMX_PKO_INVALID_PRIORITY,
- CVMX_PKO_NO_MEMORY,
- CVMX_PKO_PORT_ALREADY_SETUP,
- CVMX_PKO_CMD_QUEUE_INIT_ERROR
-} cvmx_pko_status_t;
-
-/**
- * This enumeration represents the differnet locking modes supported by PKO.
- */
-typedef enum {
- /*
- * PKO doesn't do any locking. It is the responsibility of the
- * application to make sure that no other core is accessing
- * the same queue at the same time
- */
- CVMX_PKO_LOCK_NONE = 0,
- /*
- * PKO performs an atomic tagswitch to insure exclusive access
- * to the output queue. This will maintain packet ordering on
- * output.
- */
- CVMX_PKO_LOCK_ATOMIC_TAG = 1,
- /*
- * PKO uses the common command queue locks to insure exclusive
- * access to the output queue. This is a memory based
- * ll/sc. This is the most portable locking mechanism.
- */
- CVMX_PKO_LOCK_CMD_QUEUE = 2,
-} cvmx_pko_lock_t;
-
-typedef struct {
- uint32_t packets;
- uint64_t octets;
- uint64_t doorbell;
-} cvmx_pko_port_status_t;
-
-/**
- * This structure defines the address to use on a packet enqueue
- */
-typedef union {
- uint64_t u64;
- struct {
- /* Must CVMX_IO_SEG */
- uint64_t mem_space:2;
- /* Must be zero */
- uint64_t reserved:13;
- /* Must be one */
- uint64_t is_io:1;
- /* The ID of the device on the non-coherent bus */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved2:4;
- /* Must be zero */
- uint64_t reserved3:18;
- /*
- * The hardware likes to have the output port in
- * addition to the output queue,
- */
- uint64_t port:6;
- /*
- * The output queue to send the packet to (0-127 are
- * legal)
- */
- uint64_t queue:9;
- /* Must be zero */
- uint64_t reserved4:3;
- } s;
-} cvmx_pko_doorbell_address_t;
-
-/**
- * Structure of the first packet output command word.
- */
-typedef union {
- uint64_t u64;
- struct {
- /*
- * The size of the reg1 operation - could be 8, 16,
- * 32, or 64 bits.
- */
- uint64_t size1:2;
- /*
- * The size of the reg0 operation - could be 8, 16,
- * 32, or 64 bits.
- */
- uint64_t size0:2;
- /*
- * If set, subtract 1, if clear, subtract packet
- * size.
- */
- uint64_t subone1:1;
- /*
- * The register, subtract will be done if reg1 is
- * non-zero.
- */
- uint64_t reg1:11;
- /* If set, subtract 1, if clear, subtract packet size */
- uint64_t subone0:1;
- /* The register, subtract will be done if reg0 is non-zero */
- uint64_t reg0:11;
- /*
- * When set, interpret segment pointer and segment
- * bytes in little endian order.
- */
- uint64_t le:1;
- /*
- * When set, packet data not allocated in L2 cache by
- * PKO.
- */
- uint64_t n2:1;
- /*
- * If set and rsp is set, word3 contains a pointer to
- * a work queue entry.
- */
- uint64_t wqp:1;
- /* If set, the hardware will send a response when done */
- uint64_t rsp:1;
- /*
- * If set, the supplied pkt_ptr is really a pointer to
- * a list of pkt_ptr's.
- */
- uint64_t gather:1;
- /*
- * If ipoffp1 is non zero, (ipoffp1-1) is the number
- * of bytes to IP header, and the hardware will
- * calculate and insert the UDP/TCP checksum.
- */
- uint64_t ipoffp1:7;
- /*
- * If set, ignore the I bit (force to zero) from all
- * pointer structures.
- */
- uint64_t ignore_i:1;
- /*
- * If clear, the hardware will attempt to free the
- * buffers containing the packet.
- */
- uint64_t dontfree:1;
- /*
- * The total number of segs in the packet, if gather
- * set, also gather list length.
- */
- uint64_t segs:6;
- /* Including L2, but no trailing CRC */
- uint64_t total_bytes:16;
- } s;
-} cvmx_pko_command_word0_t;
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-
-/**
- * Definition of internal state for Packet output processing
- */
-typedef struct {
- /* ptr to start of buffer, offset kept in FAU reg */
- uint64_t *start_ptr;
-} cvmx_pko_state_elem_t;
-
-/**
- * Call before any other calls to initialize the packet
- * output system.
- */
-extern void cvmx_pko_initialize_global(void);
-extern int cvmx_pko_initialize_local(void);
-
-/**
- * Enables the packet output hardware. It must already be
- * configured.
- */
-extern void cvmx_pko_enable(void);
-
-/**
- * Disables the packet output. Does not affect any configuration.
- */
-extern void cvmx_pko_disable(void);
-
-/**
- * Shutdown and free resources required by packet output.
- */
-
-extern void cvmx_pko_shutdown(void);
-
-/**
- * Configure a output port and the associated queues for use.
- *
- * @port: Port to configure.
- * @base_queue: First queue number to associate with this port.
- * @num_queues: Number of queues t oassociate with this port
- * @priority: Array of priority levels for each queue. Values are
- * allowed to be 1-8. A value of 8 get 8 times the traffic
- * of a value of 1. There must be num_queues elements in the
- * array.
- */
-extern cvmx_pko_status_t cvmx_pko_config_port(uint64_t port,
- uint64_t base_queue,
- uint64_t num_queues,
- const uint64_t priority[]);
-
-/**
- * Ring the packet output doorbell. This tells the packet
- * output hardware that "len" command words have been added
- * to its pending list. This command includes the required
- * CVMX_SYNCWS before the doorbell ring.
- *
- * @port: Port the packet is for
- * @queue: Queue the packet is for
- * @len: Length of the command in 64 bit words
- */
-static inline void cvmx_pko_doorbell(uint64_t port, uint64_t queue,
- uint64_t len)
-{
- cvmx_pko_doorbell_address_t ptr;
-
- ptr.u64 = 0;
- ptr.s.mem_space = CVMX_IO_SEG;
- ptr.s.did = CVMX_OCT_DID_PKT_SEND;
- ptr.s.is_io = 1;
- ptr.s.port = port;
- ptr.s.queue = queue;
- /*
- * Need to make sure output queue data is in DRAM before
- * doorbell write.
- */
- CVMX_SYNCWS;
- cvmx_write_io(ptr.u64, len);
-}
-
-/**
- * Prepare to send a packet. This may initiate a tag switch to
- * get exclusive access to the output queue structure, and
- * performs other prep work for the packet send operation.
- *
- * cvmx_pko_send_packet_finish() MUST be called after this function is called,
- * and must be called with the same port/queue/use_locking arguments.
- *
- * The use_locking parameter allows the caller to use three
- * possible locking modes.
- * - CVMX_PKO_LOCK_NONE
- * - PKO doesn't do any locking. It is the responsibility
- * of the application to make sure that no other core
- * is accessing the same queue at the same time.
- * - CVMX_PKO_LOCK_ATOMIC_TAG
- * - PKO performs an atomic tagswitch to insure exclusive
- * access to the output queue. This will maintain
- * packet ordering on output.
- * - CVMX_PKO_LOCK_CMD_QUEUE
- * - PKO uses the common command queue locks to insure
- * exclusive access to the output queue. This is a
- * memory based ll/sc. This is the most portable
- * locking mechanism.
- *
- * NOTE: If atomic locking is used, the POW entry CANNOT be
- * descheduled, as it does not contain a valid WQE pointer.
- *
- * @port: Port to send it on
- * @queue: Queue to use
- * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or
- * CVMX_PKO_LOCK_CMD_QUEUE
- */
-
-static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue,
- cvmx_pko_lock_t use_locking)
-{
- if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG) {
- /*
- * Must do a full switch here to handle all cases. We
- * use a fake WQE pointer, as the POW does not access
- * this memory. The WQE pointer and group are only
- * used if this work is descheduled, which is not
- * supported by the
- * cvmx_pko_send_packet_prepare/cvmx_pko_send_packet_finish
- * combination. Note that this is a special case in
- * which these fake values can be used - this is not a
- * general technique.
- */
- uint32_t tag =
- CVMX_TAG_SW_BITS_INTERNAL << CVMX_TAG_SW_SHIFT |
- CVMX_TAG_SUBGROUP_PKO << CVMX_TAG_SUBGROUP_SHIFT |
- (CVMX_TAG_SUBGROUP_MASK & queue);
- cvmx_pow_tag_sw_full((cvmx_wqe_t *) cvmx_phys_to_ptr(0x80), tag,
- CVMX_POW_TAG_TYPE_ATOMIC, 0);
- }
-}
-
-/**
- * Complete packet output. cvmx_pko_send_packet_prepare() must be
- * called exactly once before this, and the same parameters must be
- * passed to both cvmx_pko_send_packet_prepare() and
- * cvmx_pko_send_packet_finish().
- *
- * @port: Port to send it on
- * @queue: Queue to use
- * @pko_command:
- * PKO HW command word
- * @packet: Packet to send
- * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or
- * CVMX_PKO_LOCK_CMD_QUEUE
- *
- * Returns returns CVMX_PKO_SUCCESS on success, or error code on
- * failure of output
- */
-static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(
- uint64_t port,
- uint64_t queue,
- cvmx_pko_command_word0_t pko_command,
- union cvmx_buf_ptr packet,
- cvmx_pko_lock_t use_locking)
-{
- cvmx_cmd_queue_result_t result;
- if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
- cvmx_pow_tag_sw_wait();
- result = cvmx_cmd_queue_write2(CVMX_CMD_QUEUE_PKO(queue),
- (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
- pko_command.u64, packet.u64);
- if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
- cvmx_pko_doorbell(port, queue, 2);
- return CVMX_PKO_SUCCESS;
- } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY)
- || (result == CVMX_CMD_QUEUE_FULL)) {
- return CVMX_PKO_NO_MEMORY;
- } else {
- return CVMX_PKO_INVALID_QUEUE;
- }
-}
-
-/**
- * Complete packet output. cvmx_pko_send_packet_prepare() must be
- * called exactly once before this, and the same parameters must be
- * passed to both cvmx_pko_send_packet_prepare() and
- * cvmx_pko_send_packet_finish().
- *
- * @port: Port to send it on
- * @queue: Queue to use
- * @pko_command:
- * PKO HW command word
- * @packet: Packet to send
- * @addr: Plysical address of a work queue entry or physical address
- * to zero on complete.
- * @use_locking: CVMX_PKO_LOCK_NONE, CVMX_PKO_LOCK_ATOMIC_TAG, or
- * CVMX_PKO_LOCK_CMD_QUEUE
- *
- * Returns returns CVMX_PKO_SUCCESS on success, or error code on
- * failure of output
- */
-static inline cvmx_pko_status_t cvmx_pko_send_packet_finish3(
- uint64_t port,
- uint64_t queue,
- cvmx_pko_command_word0_t pko_command,
- union cvmx_buf_ptr packet,
- uint64_t addr,
- cvmx_pko_lock_t use_locking)
-{
- cvmx_cmd_queue_result_t result;
- if (use_locking == CVMX_PKO_LOCK_ATOMIC_TAG)
- cvmx_pow_tag_sw_wait();
- result = cvmx_cmd_queue_write3(CVMX_CMD_QUEUE_PKO(queue),
- (use_locking == CVMX_PKO_LOCK_CMD_QUEUE),
- pko_command.u64, packet.u64, addr);
- if (likely(result == CVMX_CMD_QUEUE_SUCCESS)) {
- cvmx_pko_doorbell(port, queue, 3);
- return CVMX_PKO_SUCCESS;
- } else if ((result == CVMX_CMD_QUEUE_NO_MEMORY)
- || (result == CVMX_CMD_QUEUE_FULL)) {
- return CVMX_PKO_NO_MEMORY;
- } else {
- return CVMX_PKO_INVALID_QUEUE;
- }
-}
-
-/**
- * Return the pko output queue associated with a port and a specific core.
- * In normal mode (PKO lockless operation is disabled), the value returned
- * is the base queue.
- *
- * @port: Port number
- * @core: Core to get queue for
- *
- * Returns Core-specific output queue
- */
-static inline int cvmx_pko_get_base_queue_per_core(int port, int core)
-{
-#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0
-#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE0 16
-#endif
-#ifndef CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1
-#define CVMX_HELPER_PKO_MAX_PORTS_INTERFACE1 16
-#endif
-
- if (port < CVMX_PKO_MAX_PORTS_INTERFACE0)
- return port * CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + core;
- else if (port >= 16 && port < 16 + CVMX_PKO_MAX_PORTS_INTERFACE1)
- return CVMX_PKO_MAX_PORTS_INTERFACE0 *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 + (port -
- 16) *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + core;
- else if ((port >= 32) && (port < 36))
- return CVMX_PKO_MAX_PORTS_INTERFACE0 *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 +
- CVMX_PKO_MAX_PORTS_INTERFACE1 *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 + (port -
- 32) *
- CVMX_PKO_QUEUES_PER_PORT_PCI;
- else if ((port >= 36) && (port < 40))
- return CVMX_PKO_MAX_PORTS_INTERFACE0 *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 +
- CVMX_PKO_MAX_PORTS_INTERFACE1 *
- CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 +
- 4 * CVMX_PKO_QUEUES_PER_PORT_PCI + (port -
- 36) *
- CVMX_PKO_QUEUES_PER_PORT_LOOP;
- else
- /* Given the limit on the number of ports we can map to
- * CVMX_MAX_OUTPUT_QUEUES_STATIC queues (currently 256,
- * divided among all cores), the remaining unmapped ports
- * are assigned an illegal queue number */
- return CVMX_PKO_ILLEGAL_QUEUE;
-}
-
-/**
- * For a given port number, return the base pko output queue
- * for the port.
- *
- * @port: Port number
- * Returns Base output queue
- */
-static inline int cvmx_pko_get_base_queue(int port)
-{
- return cvmx_pko_get_base_queue_per_core(port, 0);
-}
-
-/**
- * For a given port number, return the number of pko output queues.
- *
- * @port: Port number
- * Returns Number of output queues
- */
-static inline int cvmx_pko_get_num_queues(int port)
-{
- if (port < 16)
- return CVMX_PKO_QUEUES_PER_PORT_INTERFACE0;
- else if (port < 32)
- return CVMX_PKO_QUEUES_PER_PORT_INTERFACE1;
- else if (port < 36)
- return CVMX_PKO_QUEUES_PER_PORT_PCI;
- else if (port < 40)
- return CVMX_PKO_QUEUES_PER_PORT_LOOP;
- else
- return 0;
-}
-
-/**
- * Get the status counters for a port.
- *
- * @port_num: Port number to get statistics for.
- * @clear: Set to 1 to clear the counters after they are read
- * @status: Where to put the results.
- */
-static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear,
- cvmx_pko_port_status_t *status)
-{
- union cvmx_pko_reg_read_idx pko_reg_read_idx;
- union cvmx_pko_mem_count0 pko_mem_count0;
- union cvmx_pko_mem_count1 pko_mem_count1;
-
- pko_reg_read_idx.u64 = 0;
- pko_reg_read_idx.s.index = port_num;
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64);
-
- pko_mem_count0.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT0);
- status->packets = pko_mem_count0.s.count;
- if (clear) {
- pko_mem_count0.s.count = port_num;
- cvmx_write_csr(CVMX_PKO_MEM_COUNT0, pko_mem_count0.u64);
- }
-
- pko_mem_count1.u64 = cvmx_read_csr(CVMX_PKO_MEM_COUNT1);
- status->octets = pko_mem_count1.s.count;
- if (clear) {
- pko_mem_count1.s.count = port_num;
- cvmx_write_csr(CVMX_PKO_MEM_COUNT1, pko_mem_count1.u64);
- }
-
- if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- union cvmx_pko_mem_debug9 debug9;
- pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num);
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64);
- debug9.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG9);
- status->doorbell = debug9.cn38xx.doorbell;
- } else {
- union cvmx_pko_mem_debug8 debug8;
- pko_reg_read_idx.s.index = cvmx_pko_get_base_queue(port_num);
- cvmx_write_csr(CVMX_PKO_REG_READ_IDX, pko_reg_read_idx.u64);
- debug8.u64 = cvmx_read_csr(CVMX_PKO_MEM_DEBUG8);
- status->doorbell = debug8.cn58xx.doorbell;
- }
-}
-
-/**
- * Rate limit a PKO port to a max packets/sec. This function is only
- * supported on CN57XX, CN56XX, CN55XX, and CN54XX.
- *
- * @port: Port to rate limit
- * @packets_s: Maximum packet/sec
- * @burst: Maximum number of packets to burst in a row before rate
- * limiting cuts in.
- *
- * Returns Zero on success, negative on failure
- */
-extern int cvmx_pko_rate_limit_packets(int port, int packets_s, int burst);
-
-/**
- * Rate limit a PKO port to a max bits/sec. This function is only
- * supported on CN57XX, CN56XX, CN55XX, and CN54XX.
- *
- * @port: Port to rate limit
- * @bits_s: PKO rate limit in bits/sec
- * @burst: Maximum number of bits to burst before rate
- * limiting cuts in.
- *
- * Returns Zero on success, negative on failure
- */
-extern int cvmx_pko_rate_limit_bits(int port, uint64_t bits_s, int burst);
-
-#endif /* __CVMX_PKO_H__ */
diff --git a/drivers/staging/octeon/cvmx-pow.h b/drivers/staging/octeon/cvmx-pow.h
deleted file mode 100644
index 999aefe..0000000
--- a/drivers/staging/octeon/cvmx-pow.h
+++ /dev/null
@@ -1,1982 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- * Interface to the hardware Packet Order / Work unit.
- *
- * New, starting with SDK 1.7.0, cvmx-pow supports a number of
- * extended consistency checks. The define
- * CVMX_ENABLE_POW_CHECKS controls the runtime insertion of POW
- * internal state checks to find common programming errors. If
- * CVMX_ENABLE_POW_CHECKS is not defined, checks are by default
- * enabled. For example, cvmx-pow will check for the following
- * program errors or POW state inconsistency.
- * - Requesting a POW operation with an active tag switch in
- * progress.
- * - Waiting for a tag switch to complete for an excessively
- * long period. This is normally a sign of an error in locking
- * causing deadlock.
- * - Illegal tag switches from NULL_NULL.
- * - Illegal tag switches from NULL.
- * - Illegal deschedule request.
- * - WQE pointer not matching the one attached to the core by
- * the POW.
- *
- */
-
-#ifndef __CVMX_POW_H__
-#define __CVMX_POW_H__
-
-#include <asm/octeon/cvmx-pow-defs.h>
-
-#include "cvmx-scratch.h"
-#include "cvmx-wqe.h"
-
-/* Default to having all POW constancy checks turned on */
-#ifndef CVMX_ENABLE_POW_CHECKS
-#define CVMX_ENABLE_POW_CHECKS 1
-#endif
-
-enum cvmx_pow_tag_type {
- /* Tag ordering is maintained */
- CVMX_POW_TAG_TYPE_ORDERED = 0L,
- /* Tag ordering is maintained, and at most one PP has the tag */
- CVMX_POW_TAG_TYPE_ATOMIC = 1L,
- /*
- * The work queue entry from the order - NEVER tag switch from
- * NULL to NULL
- */
- CVMX_POW_TAG_TYPE_NULL = 2L,
- /* A tag switch to NULL, and there is no space reserved in POW
- * - NEVER tag switch to NULL_NULL
- * - NEVER tag switch from NULL_NULL
- * - NULL_NULL is entered at the beginning of time and on a deschedule.
- * - NULL_NULL can be exited by a new work request. A NULL_SWITCH
- * load can also switch the state to NULL
- */
- CVMX_POW_TAG_TYPE_NULL_NULL = 3L
-};
-
-/**
- * Wait flag values for pow functions.
- */
-typedef enum {
- CVMX_POW_WAIT = 1,
- CVMX_POW_NO_WAIT = 0,
-} cvmx_pow_wait_t;
-
-/**
- * POW tag operations. These are used in the data stored to the POW.
- */
-typedef enum {
- /*
- * switch the tag (only) for this PP
- * - the previous tag should be non-NULL in this case
- * - tag switch response required
- * - fields used: op, type, tag
- */
- CVMX_POW_TAG_OP_SWTAG = 0L,
- /*
- * switch the tag for this PP, with full information
- * - this should be used when the previous tag is NULL
- * - tag switch response required
- * - fields used: address, op, grp, type, tag
- */
- CVMX_POW_TAG_OP_SWTAG_FULL = 1L,
- /*
- * switch the tag (and/or group) for this PP and de-schedule
- * - OK to keep the tag the same and only change the group
- * - fields used: op, no_sched, grp, type, tag
- */
- CVMX_POW_TAG_OP_SWTAG_DESCH = 2L,
- /*
- * just de-schedule
- * - fields used: op, no_sched
- */
- CVMX_POW_TAG_OP_DESCH = 3L,
- /*
- * create an entirely new work queue entry
- * - fields used: address, op, qos, grp, type, tag
- */
- CVMX_POW_TAG_OP_ADDWQ = 4L,
- /*
- * just update the work queue pointer and grp for this PP
- * - fields used: address, op, grp
- */
- CVMX_POW_TAG_OP_UPDATE_WQP_GRP = 5L,
- /*
- * set the no_sched bit on the de-schedule list
- *
- * - does nothing if the selected entry is not on the
- * de-schedule list
- *
- * - does nothing if the stored work queue pointer does not
- * match the address field
- *
- * - fields used: address, index, op
- *
- * Before issuing a *_NSCHED operation, SW must guarantee
- * that all prior deschedules and set/clr NSCHED operations
- * are complete and all prior switches are complete. The
- * hardware provides the opsdone bit and swdone bit for SW
- * polling. After issuing a *_NSCHED operation, SW must
- * guarantee that the set/clr NSCHED is complete before any
- * subsequent operations.
- */
- CVMX_POW_TAG_OP_SET_NSCHED = 6L,
- /*
- * clears the no_sched bit on the de-schedule list
- *
- * - does nothing if the selected entry is not on the
- * de-schedule list
- *
- * - does nothing if the stored work queue pointer does not
- * match the address field
- *
- * - fields used: address, index, op
- *
- * Before issuing a *_NSCHED operation, SW must guarantee that
- * all prior deschedules and set/clr NSCHED operations are
- * complete and all prior switches are complete. The hardware
- * provides the opsdone bit and swdone bit for SW
- * polling. After issuing a *_NSCHED operation, SW must
- * guarantee that the set/clr NSCHED is complete before any
- * subsequent operations.
- */
- CVMX_POW_TAG_OP_CLR_NSCHED = 7L,
- /* do nothing */
- CVMX_POW_TAG_OP_NOP = 15L
-} cvmx_pow_tag_op_t;
-
-/**
- * This structure defines the store data on a store to POW
- */
-typedef union {
- uint64_t u64;
- struct {
- /*
- * Don't reschedule this entry. no_sched is used for
- * CVMX_POW_TAG_OP_SWTAG_DESCH and
- * CVMX_POW_TAG_OP_DESCH
- */
- uint64_t no_sched:1;
- uint64_t unused:2;
- /* Tontains index of entry for a CVMX_POW_TAG_OP_*_NSCHED */
- uint64_t index:13;
- /* The operation to perform */
- cvmx_pow_tag_op_t op:4;
- uint64_t unused2:2;
- /*
- * The QOS level for the packet. qos is only used for
- * CVMX_POW_TAG_OP_ADDWQ
- */
- uint64_t qos:3;
- /*
- * The group that the work queue entry will be
- * scheduled to grp is used for CVMX_POW_TAG_OP_ADDWQ,
- * CVMX_POW_TAG_OP_SWTAG_FULL,
- * CVMX_POW_TAG_OP_SWTAG_DESCH, and
- * CVMX_POW_TAG_OP_UPDATE_WQP_GRP
- */
- uint64_t grp:4;
- /*
- * The type of the tag. type is used for everything
- * except CVMX_POW_TAG_OP_DESCH,
- * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and
- * CVMX_POW_TAG_OP_*_NSCHED
- */
- uint64_t type:3;
- /*
- * The actual tag. tag is used for everything except
- * CVMX_POW_TAG_OP_DESCH,
- * CVMX_POW_TAG_OP_UPDATE_WQP_GRP, and
- * CVMX_POW_TAG_OP_*_NSCHED
- */
- uint64_t tag:32;
- } s;
-} cvmx_pow_tag_req_t;
-
-/**
- * This structure describes the address to load stuff from POW
- */
-typedef union {
- uint64_t u64;
-
- /**
- * Address for new work request loads (did<2:0> == 0)
- */
- struct {
- /* Mips64 address region. Should be CVMX_IO_SEG */
- uint64_t mem_region:2;
- /* Must be zero */
- uint64_t reserved_49_61:13;
- /* Must be one */
- uint64_t is_io:1;
- /* the ID of POW -- did<2:0> == 0 in this case */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved_4_39:36;
- /*
- * If set, don't return load response until work is
- * available.
- */
- uint64_t wait:1;
- /* Must be zero */
- uint64_t reserved_0_2:3;
- } swork;
-
- /**
- * Address for loads to get POW internal status
- */
- struct {
- /* Mips64 address region. Should be CVMX_IO_SEG */
- uint64_t mem_region:2;
- /* Must be zero */
- uint64_t reserved_49_61:13;
- /* Must be one */
- uint64_t is_io:1;
- /* the ID of POW -- did<2:0> == 1 in this case */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved_10_39:30;
- /* The core id to get status for */
- uint64_t coreid:4;
- /*
- * If set and get_cur is set, return reverse tag-list
- * pointer rather than forward tag-list pointer.
- */
- uint64_t get_rev:1;
- /*
- * If set, return current status rather than pending
- * status.
- */
- uint64_t get_cur:1;
- /*
- * If set, get the work-queue pointer rather than
- * tag/type.
- */
- uint64_t get_wqp:1;
- /* Must be zero */
- uint64_t reserved_0_2:3;
- } sstatus;
-
- /**
- * Address for memory loads to get POW internal state
- */
- struct {
- /* Mips64 address region. Should be CVMX_IO_SEG */
- uint64_t mem_region:2;
- /* Must be zero */
- uint64_t reserved_49_61:13;
- /* Must be one */
- uint64_t is_io:1;
- /* the ID of POW -- did<2:0> == 2 in this case */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved_16_39:24;
- /* POW memory index */
- uint64_t index:11;
- /*
- * If set, return deschedule information rather than
- * the standard response for work-queue index (invalid
- * if the work-queue entry is not on the deschedule
- * list).
- */
- uint64_t get_des:1;
- /*
- * If set, get the work-queue pointer rather than
- * tag/type (no effect when get_des set).
- */
- uint64_t get_wqp:1;
- /* Must be zero */
- uint64_t reserved_0_2:3;
- } smemload;
-
- /**
- * Address for index/pointer loads
- */
- struct {
- /* Mips64 address region. Should be CVMX_IO_SEG */
- uint64_t mem_region:2;
- /* Must be zero */
- uint64_t reserved_49_61:13;
- /* Must be one */
- uint64_t is_io:1;
- /* the ID of POW -- did<2:0> == 3 in this case */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved_9_39:31;
- /*
- * when {get_rmt ==0 AND get_des_get_tail == 0}, this
- * field selects one of eight POW internal-input
- * queues (0-7), one per QOS level; values 8-15 are
- * illegal in this case; when {get_rmt ==0 AND
- * get_des_get_tail == 1}, this field selects one of
- * 16 deschedule lists (per group); when get_rmt ==1,
- * this field selects one of 16 memory-input queue
- * lists. The two memory-input queue lists associated
- * with each QOS level are:
- *
- * - qosgrp = 0, qosgrp = 8: QOS0
- * - qosgrp = 1, qosgrp = 9: QOS1
- * - qosgrp = 2, qosgrp = 10: QOS2
- * - qosgrp = 3, qosgrp = 11: QOS3
- * - qosgrp = 4, qosgrp = 12: QOS4
- * - qosgrp = 5, qosgrp = 13: QOS5
- * - qosgrp = 6, qosgrp = 14: QOS6
- * - qosgrp = 7, qosgrp = 15: QOS7
- */
- uint64_t qosgrp:4;
- /*
- * If set and get_rmt is clear, return deschedule list
- * indexes rather than indexes for the specified qos
- * level; if set and get_rmt is set, return the tail
- * pointer rather than the head pointer for the
- * specified qos level.
- */
- uint64_t get_des_get_tail:1;
- /*
- * If set, return remote pointers rather than the
- * local indexes for the specified qos level.
- */
- uint64_t get_rmt:1;
- /* Must be zero */
- uint64_t reserved_0_2:3;
- } sindexload;
-
- /**
- * address for NULL_RD request (did<2:0> == 4) when this is read,
- * HW attempts to change the state to NULL if it is NULL_NULL (the
- * hardware cannot switch from NULL_NULL to NULL if a POW entry is
- * not available - software may need to recover by finishing
- * another piece of work before a POW entry can ever become
- * available.)
- */
- struct {
- /* Mips64 address region. Should be CVMX_IO_SEG */
- uint64_t mem_region:2;
- /* Must be zero */
- uint64_t reserved_49_61:13;
- /* Must be one */
- uint64_t is_io:1;
- /* the ID of POW -- did<2:0> == 4 in this case */
- uint64_t did:8;
- /* Must be zero */
- uint64_t reserved_0_39:40;
- } snull_rd;
-} cvmx_pow_load_addr_t;
-
-/**
- * This structure defines the response to a load/SENDSINGLE to POW
- * (except CSR reads)
- */
-typedef union {
- uint64_t u64;
-
- /**
- * Response to new work request loads
- */
- struct {
- /*
- * Set when no new work queue entry was returned. *
- * If there was de-scheduled work, the HW will
- * definitely return it. When this bit is set, it
- * could mean either mean:
- *
- * - There was no work, or
- *
- * - There was no work that the HW could find. This
- * case can happen, regardless of the wait bit value
- * in the original request, when there is work in
- * the IQ's that is too deep down the list.
- */
- uint64_t no_work:1;
- /* Must be zero */
- uint64_t reserved_40_62:23;
- /* 36 in O1 -- the work queue pointer */
- uint64_t addr:40;
- } s_work;
-
- /**
- * Result for a POW Status Load (when get_cur==0 and get_wqp==0)
- */
- struct {
- uint64_t reserved_62_63:2;
- /* Set when there is a pending non-NULL SWTAG or
- * SWTAG_FULL, and the POW entry has not left the list
- * for the original tag. */
- uint64_t pend_switch:1;
- /* Set when SWTAG_FULL and pend_switch is set. */
- uint64_t pend_switch_full:1;
- /*
- * Set when there is a pending NULL SWTAG, or an
- * implicit switch to NULL.
- */
- uint64_t pend_switch_null:1;
- /* Set when there is a pending DESCHED or SWTAG_DESCHED. */
- uint64_t pend_desched:1;
- /*
- * Set when there is a pending SWTAG_DESCHED and
- * pend_desched is set.
- */
- uint64_t pend_desched_switch:1;
- /* Set when nosched is desired and pend_desched is set. */
- uint64_t pend_nosched:1;
- /* Set when there is a pending GET_WORK. */
- uint64_t pend_new_work:1;
- /*
- * When pend_new_work is set, this bit indicates that
- * the wait bit was set.
- */
- uint64_t pend_new_work_wait:1;
- /* Set when there is a pending NULL_RD. */
- uint64_t pend_null_rd:1;
- /* Set when there is a pending CLR_NSCHED. */
- uint64_t pend_nosched_clr:1;
- uint64_t reserved_51:1;
- /* This is the index when pend_nosched_clr is set. */
- uint64_t pend_index:11;
- /*
- * This is the new_grp when (pend_desched AND
- * pend_desched_switch) is set.
- */
- uint64_t pend_grp:4;
- uint64_t reserved_34_35:2;
- /*
- * This is the tag type when pend_switch or
- * (pend_desched AND pend_desched_switch) are set.
- */
- uint64_t pend_type:2;
- /*
- * - this is the tag when pend_switch or (pend_desched
- * AND pend_desched_switch) are set.
- */
- uint64_t pend_tag:32;
- } s_sstatus0;
-
- /**
- * Result for a POW Status Load (when get_cur==0 and get_wqp==1)
- */
- struct {
- uint64_t reserved_62_63:2;
- /*
- * Set when there is a pending non-NULL SWTAG or
- * SWTAG_FULL, and the POW entry has not left the list
- * for the original tag.
- */
- uint64_t pend_switch:1;
- /* Set when SWTAG_FULL and pend_switch is set. */
- uint64_t pend_switch_full:1;
- /*
- * Set when there is a pending NULL SWTAG, or an
- * implicit switch to NULL.
- */
- uint64_t pend_switch_null:1;
- /*
- * Set when there is a pending DESCHED or
- * SWTAG_DESCHED.
- */
- uint64_t pend_desched:1;
- /*
- * Set when there is a pending SWTAG_DESCHED and
- * pend_desched is set.
- */
- uint64_t pend_desched_switch:1;
- /* Set when nosched is desired and pend_desched is set. */
- uint64_t pend_nosched:1;
- /* Set when there is a pending GET_WORK. */
- uint64_t pend_new_work:1;
- /*
- * When pend_new_work is set, this bit indicates that
- * the wait bit was set.
- */
- uint64_t pend_new_work_wait:1;
- /* Set when there is a pending NULL_RD. */
- uint64_t pend_null_rd:1;
- /* Set when there is a pending CLR_NSCHED. */
- uint64_t pend_nosched_clr:1;
- uint64_t reserved_51:1;
- /* This is the index when pend_nosched_clr is set. */
- uint64_t pend_index:11;
- /*
- * This is the new_grp when (pend_desched AND
- * pend_desched_switch) is set.
- */
- uint64_t pend_grp:4;
- /* This is the wqp when pend_nosched_clr is set. */
- uint64_t pend_wqp:36;
- } s_sstatus1;
-
- /**
- * Result for a POW Status Load (when get_cur==1, get_wqp==0, and
- * get_rev==0)
- */
- struct {
- uint64_t reserved_62_63:2;
- /*
- * Points to the next POW entry in the tag list when
- * tail == 0 (and tag_type is not NULL or NULL_NULL).
- */
- uint64_t link_index:11;
- /* The POW entry attached to the core. */
- uint64_t index:11;
- /*
- * The group attached to the core (updated when new
- * tag list entered on SWTAG_FULL).
- */
- uint64_t grp:4;
- /*
- * Set when this POW entry is at the head of its tag
- * list (also set when in the NULL or NULL_NULL
- * state).
- */
- uint64_t head:1;
- /*
- * Set when this POW entry is at the tail of its tag
- * list (also set when in the NULL or NULL_NULL
- * state).
- */
- uint64_t tail:1;
- /*
- * The tag type attached to the core (updated when new
- * tag list entered on SWTAG, SWTAG_FULL, or
- * SWTAG_DESCHED).
- */
- uint64_t tag_type:2;
- /*
- * The tag attached to the core (updated when new tag
- * list entered on SWTAG, SWTAG_FULL, or
- * SWTAG_DESCHED).
- */
- uint64_t tag:32;
- } s_sstatus2;
-
- /**
- * Result for a POW Status Load (when get_cur==1, get_wqp==0, and get_rev==1)
- */
- struct {
- uint64_t reserved_62_63:2;
- /*
- * Points to the prior POW entry in the tag list when
- * head == 0 (and tag_type is not NULL or
- * NULL_NULL). This field is unpredictable when the
- * core's state is NULL or NULL_NULL.
- */
- uint64_t revlink_index:11;
- /* The POW entry attached to the core. */
- uint64_t index:11;
- /*
- * The group attached to the core (updated when new
- * tag list entered on SWTAG_FULL).
- */
- uint64_t grp:4;
- /* Set when this POW entry is at the head of its tag
- * list (also set when in the NULL or NULL_NULL
- * state).
- */
- uint64_t head:1;
- /*
- * Set when this POW entry is at the tail of its tag
- * list (also set when in the NULL or NULL_NULL
- * state).
- */
- uint64_t tail:1;
- /*
- * The tag type attached to the core (updated when new
- * tag list entered on SWTAG, SWTAG_FULL, or
- * SWTAG_DESCHED).
- */
- uint64_t tag_type:2;
- /*
- * The tag attached to the core (updated when new tag
- * list entered on SWTAG, SWTAG_FULL, or
- * SWTAG_DESCHED).
- */
- uint64_t tag:32;
- } s_sstatus3;
-
- /**
- * Result for a POW Status Load (when get_cur==1, get_wqp==1, and
- * get_rev==0)
- */
- struct {
- uint64_t reserved_62_63:2;
- /*
- * Points to the next POW entry in the tag list when
- * tail == 0 (and tag_type is not NULL or NULL_NULL).
- */
- uint64_t link_index:11;
- /* The POW entry attached to the core. */
- uint64_t index:11;
- /*
- * The group attached to the core (updated when new
- * tag list entered on SWTAG_FULL).
- */
- uint64_t grp:4;
- /*
- * The wqp attached to the core (updated when new tag
- * list entered on SWTAG_FULL).
- */
- uint64_t wqp:36;
- } s_sstatus4;
-
- /**
- * Result for a POW Status Load (when get_cur==1, get_wqp==1, and
- * get_rev==1)
- */
- struct {
- uint64_t reserved_62_63:2;
- /*
- * Points to the prior POW entry in the tag list when
- * head == 0 (and tag_type is not NULL or
- * NULL_NULL). This field is unpredictable when the
- * core's state is NULL or NULL_NULL.
- */
- uint64_t revlink_index:11;
- /* The POW entry attached to the core. */
- uint64_t index:11;
- /*
- * The group attached to the core (updated when new
- * tag list entered on SWTAG_FULL).
- */
- uint64_t grp:4;
- /*
- * The wqp attached to the core (updated when new tag
- * list entered on SWTAG_FULL).
- */
- uint64_t wqp:36;
- } s_sstatus5;
-
- /**
- * Result For POW Memory Load (get_des == 0 and get_wqp == 0)
- */
- struct {
- uint64_t reserved_51_63:13;
- /*
- * The next entry in the input, free, descheduled_head
- * list (unpredictable if entry is the tail of the
- * list).
- */
- uint64_t next_index:11;
- /* The group of the POW entry. */
- uint64_t grp:4;
- uint64_t reserved_35:1;
- /*
- * Set when this POW entry is at the tail of its tag
- * list (also set when in the NULL or NULL_NULL
- * state).
- */
- uint64_t tail:1;
- /* The tag type of the POW entry. */
- uint64_t tag_type:2;
- /* The tag of the POW entry. */
- uint64_t tag:32;
- } s_smemload0;
-
- /**
- * Result For POW Memory Load (get_des == 0 and get_wqp == 1)
- */
- struct {
- uint64_t reserved_51_63:13;
- /*
- * The next entry in the input, free, descheduled_head
- * list (unpredictable if entry is the tail of the
- * list).
- */
- uint64_t next_index:11;
- /* The group of the POW entry. */
- uint64_t grp:4;
- /* The WQP held in the POW entry. */
- uint64_t wqp:36;
- } s_smemload1;
-
- /**
- * Result For POW Memory Load (get_des == 1)
- */
- struct {
- uint64_t reserved_51_63:13;
- /*
- * The next entry in the tag list connected to the
- * descheduled head.
- */
- uint64_t fwd_index:11;
- /* The group of the POW entry. */
- uint64_t grp:4;
- /* The nosched bit for the POW entry. */
- uint64_t nosched:1;
- /* There is a pending tag switch */
- uint64_t pend_switch:1;
- /*
- * The next tag type for the new tag list when
- * pend_switch is set.
- */
- uint64_t pend_type:2;
- /*
- * The next tag for the new tag list when pend_switch
- * is set.
- */
- uint64_t pend_tag:32;
- } s_smemload2;
-
- /**
- * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 0)
- */
- struct {
- uint64_t reserved_52_63:12;
- /*
- * set when there is one or more POW entries on the
- * free list.
- */
- uint64_t free_val:1;
- /*
- * set when there is exactly one POW entry on the free
- * list.
- */
- uint64_t free_one:1;
- uint64_t reserved_49:1;
- /*
- * when free_val is set, indicates the first entry on
- * the free list.
- */
- uint64_t free_head:11;
- uint64_t reserved_37:1;
- /*
- * when free_val is set, indicates the last entry on
- * the free list.
- */
- uint64_t free_tail:11;
- /*
- * set when there is one or more POW entries on the
- * input Q list selected by qosgrp.
- */
- uint64_t loc_val:1;
- /*
- * set when there is exactly one POW entry on the
- * input Q list selected by qosgrp.
- */
- uint64_t loc_one:1;
- uint64_t reserved_23:1;
- /*
- * when loc_val is set, indicates the first entry on
- * the input Q list selected by qosgrp.
- */
- uint64_t loc_head:11;
- uint64_t reserved_11:1;
- /*
- * when loc_val is set, indicates the last entry on
- * the input Q list selected by qosgrp.
- */
- uint64_t loc_tail:11;
- } sindexload0;
-
- /**
- * Result For POW Index/Pointer Load (get_rmt == 0/get_des_get_tail == 1)
- */
- struct {
- uint64_t reserved_52_63:12;
- /*
- * set when there is one or more POW entries on the
- * nosched list.
- */
- uint64_t nosched_val:1;
- /*
- * set when there is exactly one POW entry on the
- * nosched list.
- */
- uint64_t nosched_one:1;
- uint64_t reserved_49:1;
- /*
- * when nosched_val is set, indicates the first entry
- * on the nosched list.
- */
- uint64_t nosched_head:11;
- uint64_t reserved_37:1;
- /*
- * when nosched_val is set, indicates the last entry
- * on the nosched list.
- */
- uint64_t nosched_tail:11;
- /*
- * set when there is one or more descheduled heads on
- * the descheduled list selected by qosgrp.
- */
- uint64_t des_val:1;
- /*
- * set when there is exactly one descheduled head on
- * the descheduled list selected by qosgrp.
- */
- uint64_t des_one:1;
- uint64_t reserved_23:1;
- /*
- * when des_val is set, indicates the first
- * descheduled head on the descheduled list selected
- * by qosgrp.
- */
- uint64_t des_head:11;
- uint64_t reserved_11:1;
- /*
- * when des_val is set, indicates the last descheduled
- * head on the descheduled list selected by qosgrp.
- */
- uint64_t des_tail:11;
- } sindexload1;
-
- /**
- * Result For POW Index/Pointer Load (get_rmt == 1/get_des_get_tail == 0)
- */
- struct {
- uint64_t reserved_39_63:25;
- /*
- * Set when this DRAM list is the current head
- * (i.e. is the next to be reloaded when the POW
- * hardware reloads a POW entry from DRAM). The POW
- * hardware alternates between the two DRAM lists
- * associated with a QOS level when it reloads work
- * from DRAM into the POW unit.
- */
- uint64_t rmt_is_head:1;
- /*
- * Set when the DRAM portion of the input Q list
- * selected by qosgrp contains one or more pieces of
- * work.
- */
- uint64_t rmt_val:1;
- /*
- * Set when the DRAM portion of the input Q list
- * selected by qosgrp contains exactly one piece of
- * work.
- */
- uint64_t rmt_one:1;
- /*
- * When rmt_val is set, indicates the first piece of
- * work on the DRAM input Q list selected by
- * qosgrp.
- */
- uint64_t rmt_head:36;
- } sindexload2;
-
- /**
- * Result For POW Index/Pointer Load (get_rmt ==
- * 1/get_des_get_tail == 1)
- */
- struct {
- uint64_t reserved_39_63:25;
- /*
- * set when this DRAM list is the current head
- * (i.e. is the next to be reloaded when the POW
- * hardware reloads a POW entry from DRAM). The POW
- * hardware alternates between the two DRAM lists
- * associated with a QOS level when it reloads work
- * from DRAM into the POW unit.
- */
- uint64_t rmt_is_head:1;
- /*
- * set when the DRAM portion of the input Q list
- * selected by qosgrp contains one or more pieces of
- * work.
- */
- uint64_t rmt_val:1;
- /*
- * set when the DRAM portion of the input Q list
- * selected by qosgrp contains exactly one piece of
- * work.
- */
- uint64_t rmt_one:1;
- /*
- * when rmt_val is set, indicates the last piece of
- * work on the DRAM input Q list selected by
- * qosgrp.
- */
- uint64_t rmt_tail:36;
- } sindexload3;
-
- /**
- * Response to NULL_RD request loads
- */
- struct {
- uint64_t unused:62;
- /* of type cvmx_pow_tag_type_t. state is one of the
- * following:
- *
- * - CVMX_POW_TAG_TYPE_ORDERED
- * - CVMX_POW_TAG_TYPE_ATOMIC
- * - CVMX_POW_TAG_TYPE_NULL
- * - CVMX_POW_TAG_TYPE_NULL_NULL
- */
- uint64_t state:2;
- } s_null_rd;
-
-} cvmx_pow_tag_load_resp_t;
-
-/**
- * This structure describes the address used for stores to the POW.
- * The store address is meaningful on stores to the POW. The
- * hardware assumes that an aligned 64-bit store was used for all
- * these stores. Note the assumption that the work queue entry is
- * aligned on an 8-byte boundary (since the low-order 3 address bits
- * must be zero). Note that not all fields are used by all
- * operations.
- *
- * NOTE: The following is the behavior of the pending switch bit at the PP
- * for POW stores (i.e. when did<7:3> == 0xc)
- * - did<2:0> == 0 => pending switch bit is set
- * - did<2:0> == 1 => no affect on the pending switch bit
- * - did<2:0> == 3 => pending switch bit is cleared
- * - did<2:0> == 7 => no affect on the pending switch bit
- * - did<2:0> == others => must not be used
- * - No other loads/stores have an affect on the pending switch bit
- * - The switch bus from POW can clear the pending switch bit
- *
- * NOTE: did<2:0> == 2 is used by the HW for a special single-cycle
- * ADDWQ command that only contains the pointer). SW must never use
- * did<2:0> == 2.
- */
-typedef union {
- /**
- * Unsigned 64 bit integer representation of store address
- */
- uint64_t u64;
-
- struct {
- /* Memory region. Should be CVMX_IO_SEG in most cases */
- uint64_t mem_reg:2;
- uint64_t reserved_49_61:13; /* Must be zero */
- uint64_t is_io:1; /* Must be one */
- /* Device ID of POW. Note that different sub-dids are used. */
- uint64_t did:8;
- uint64_t reserved_36_39:4; /* Must be zero */
- /* Address field. addr<2:0> must be zero */
- uint64_t addr:36;
- } stag;
-} cvmx_pow_tag_store_addr_t;
-
-/**
- * decode of the store data when an IOBDMA SENDSINGLE is sent to POW
- */
-typedef union {
- uint64_t u64;
-
- struct {
- /*
- * the (64-bit word) location in scratchpad to write
- * to (if len != 0)
- */
- uint64_t scraddr:8;
- /* the number of words in the response (0 => no response) */
- uint64_t len:8;
- /* the ID of the device on the non-coherent bus */
- uint64_t did:8;
- uint64_t unused:36;
- /* if set, don't return load response until work is available */
- uint64_t wait:1;
- uint64_t unused2:3;
- } s;
-
-} cvmx_pow_iobdma_store_t;
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-
-/**
- * Get the POW tag for this core. This returns the current
- * tag type, tag, group, and POW entry index associated with
- * this core. Index is only valid if the tag type isn't NULL_NULL.
- * If a tag switch is pending this routine returns the tag before
- * the tag switch, not after.
- *
- * Returns Current tag
- */
-static inline cvmx_pow_tag_req_t cvmx_pow_get_current_tag(void)
-{
- cvmx_pow_load_addr_t load_addr;
- cvmx_pow_tag_load_resp_t load_resp;
- cvmx_pow_tag_req_t result;
-
- load_addr.u64 = 0;
- load_addr.sstatus.mem_region = CVMX_IO_SEG;
- load_addr.sstatus.is_io = 1;
- load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
- load_addr.sstatus.coreid = cvmx_get_core_num();
- load_addr.sstatus.get_cur = 1;
- load_resp.u64 = cvmx_read_csr(load_addr.u64);
- result.u64 = 0;
- result.s.grp = load_resp.s_sstatus2.grp;
- result.s.index = load_resp.s_sstatus2.index;
- result.s.type = load_resp.s_sstatus2.tag_type;
- result.s.tag = load_resp.s_sstatus2.tag;
- return result;
-}
-
-/**
- * Get the POW WQE for this core. This returns the work queue
- * entry currently associated with this core.
- *
- * Returns WQE pointer
- */
-static inline cvmx_wqe_t *cvmx_pow_get_current_wqp(void)
-{
- cvmx_pow_load_addr_t load_addr;
- cvmx_pow_tag_load_resp_t load_resp;
-
- load_addr.u64 = 0;
- load_addr.sstatus.mem_region = CVMX_IO_SEG;
- load_addr.sstatus.is_io = 1;
- load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
- load_addr.sstatus.coreid = cvmx_get_core_num();
- load_addr.sstatus.get_cur = 1;
- load_addr.sstatus.get_wqp = 1;
- load_resp.u64 = cvmx_read_csr(load_addr.u64);
- return (cvmx_wqe_t *) cvmx_phys_to_ptr(load_resp.s_sstatus4.wqp);
-}
-
-#ifndef CVMX_MF_CHORD
-#define CVMX_MF_CHORD(dest) CVMX_RDHWR(dest, 30)
-#endif
-
-/**
- * Print a warning if a tag switch is pending for this core
- *
- * @function: Function name checking for a pending tag switch
- */
-static inline void __cvmx_pow_warn_if_pending_switch(const char *function)
-{
- uint64_t switch_complete;
- CVMX_MF_CHORD(switch_complete);
- if (!switch_complete)
- pr_warning("%s called with tag switch in progress\n", function);
-}
-
-/**
- * Waits for a tag switch to complete by polling the completion bit.
- * Note that switches to NULL complete immediately and do not need
- * to be waited for.
- */
-static inline void cvmx_pow_tag_sw_wait(void)
-{
- const uint64_t MAX_CYCLES = 1ull << 31;
- uint64_t switch_complete;
- uint64_t start_cycle = cvmx_get_cycle();
- while (1) {
- CVMX_MF_CHORD(switch_complete);
- if (unlikely(switch_complete))
- break;
- if (unlikely(cvmx_get_cycle() > start_cycle + MAX_CYCLES)) {
- pr_warning("Tag switch is taking a long time, "
- "possible deadlock\n");
- start_cycle = -MAX_CYCLES - 1;
- }
- }
-}
-
-/**
- * Synchronous work request. Requests work from the POW.
- * This function does NOT wait for previous tag switches to complete,
- * so the caller must ensure that there is not a pending tag switch.
- *
- * @wait: When set, call stalls until work becomes avaiable, or times out.
- * If not set, returns immediately.
- *
- * Returns Returns the WQE pointer from POW. Returns NULL if no work
- * was available.
- */
-static inline cvmx_wqe_t *cvmx_pow_work_request_sync_nocheck(cvmx_pow_wait_t
- wait)
-{
- cvmx_pow_load_addr_t ptr;
- cvmx_pow_tag_load_resp_t result;
-
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- ptr.u64 = 0;
- ptr.swork.mem_region = CVMX_IO_SEG;
- ptr.swork.is_io = 1;
- ptr.swork.did = CVMX_OCT_DID_TAG_SWTAG;
- ptr.swork.wait = wait;
-
- result.u64 = cvmx_read_csr(ptr.u64);
-
- if (result.s_work.no_work)
- return NULL;
- else
- return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr);
-}
-
-/**
- * Synchronous work request. Requests work from the POW.
- * This function waits for any previous tag switch to complete before
- * requesting the new work.
- *
- * @wait: When set, call stalls until work becomes avaiable, or times out.
- * If not set, returns immediately.
- *
- * Returns Returns the WQE pointer from POW. Returns NULL if no work
- * was available.
- */
-static inline cvmx_wqe_t *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /* Must not have a switch pending when requesting work */
- cvmx_pow_tag_sw_wait();
- return cvmx_pow_work_request_sync_nocheck(wait);
-
-}
-
-/**
- * Synchronous null_rd request. Requests a switch out of NULL_NULL POW state.
- * This function waits for any previous tag switch to complete before
- * requesting the null_rd.
- *
- * Returns Returns the POW state of type cvmx_pow_tag_type_t.
- */
-static inline enum cvmx_pow_tag_type cvmx_pow_work_request_null_rd(void)
-{
- cvmx_pow_load_addr_t ptr;
- cvmx_pow_tag_load_resp_t result;
-
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /* Must not have a switch pending when requesting work */
- cvmx_pow_tag_sw_wait();
-
- ptr.u64 = 0;
- ptr.snull_rd.mem_region = CVMX_IO_SEG;
- ptr.snull_rd.is_io = 1;
- ptr.snull_rd.did = CVMX_OCT_DID_TAG_NULL_RD;
-
- result.u64 = cvmx_read_csr(ptr.u64);
-
- return (enum cvmx_pow_tag_type) result.s_null_rd.state;
-}
-
-/**
- * Asynchronous work request. Work is requested from the POW unit,
- * and should later be checked with function
- * cvmx_pow_work_response_async. This function does NOT wait for
- * previous tag switches to complete, so the caller must ensure that
- * there is not a pending tag switch.
- *
- * @scr_addr: Scratch memory address that response will be returned
- * to, which is either a valid WQE, or a response with the
- * invalid bit set. Byte address, must be 8 byte aligned.
- *
- * @wait: 1 to cause response to wait for work to become available (or
- * timeout), 0 to cause response to return immediately
- */
-static inline void cvmx_pow_work_request_async_nocheck(int scr_addr,
- cvmx_pow_wait_t wait)
-{
- cvmx_pow_iobdma_store_t data;
-
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /* scr_addr must be 8 byte aligned */
- data.s.scraddr = scr_addr >> 3;
- data.s.len = 1;
- data.s.did = CVMX_OCT_DID_TAG_SWTAG;
- data.s.wait = wait;
- cvmx_send_single(data.u64);
-}
-
-/**
- * Asynchronous work request. Work is requested from the POW unit,
- * and should later be checked with function
- * cvmx_pow_work_response_async. This function waits for any previous
- * tag switch to complete before requesting the new work.
- *
- * @scr_addr: Scratch memory address that response will be returned
- * to, which is either a valid WQE, or a response with the
- * invalid bit set. Byte address, must be 8 byte aligned.
- *
- * @wait: 1 to cause response to wait for work to become available (or
- * timeout), 0 to cause response to return immediately
- */
-static inline void cvmx_pow_work_request_async(int scr_addr,
- cvmx_pow_wait_t wait)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /* Must not have a switch pending when requesting work */
- cvmx_pow_tag_sw_wait();
- cvmx_pow_work_request_async_nocheck(scr_addr, wait);
-}
-
-/**
- * Gets result of asynchronous work request. Performs a IOBDMA sync
- * to wait for the response.
- *
- * @scr_addr: Scratch memory address to get result from Byte address,
- * must be 8 byte aligned.
- *
- * Returns Returns the WQE from the scratch register, or NULL if no
- * work was available.
- */
-static inline cvmx_wqe_t *cvmx_pow_work_response_async(int scr_addr)
-{
- cvmx_pow_tag_load_resp_t result;
-
- CVMX_SYNCIOBDMA;
- result.u64 = cvmx_scratch_read64(scr_addr);
-
- if (result.s_work.no_work)
- return NULL;
- else
- return (cvmx_wqe_t *) cvmx_phys_to_ptr(result.s_work.addr);
-}
-
-/**
- * Checks if a work queue entry pointer returned by a work
- * request is valid. It may be invalid due to no work
- * being available or due to a timeout.
- *
- * @wqe_ptr: pointer to a work queue entry returned by the POW
- *
- * Returns 0 if pointer is valid
- * 1 if invalid (no work was returned)
- */
-static inline uint64_t cvmx_pow_work_invalid(cvmx_wqe_t *wqe_ptr)
-{
- return wqe_ptr == NULL;
-}
-
-/**
- * Starts a tag switch to the provided tag value and tag type.
- * Completion for the tag switch must be checked for separately. This
- * function does NOT update the work queue entry in dram to match tag
- * value and type, so the application must keep track of these if they
- * are important to the application. This tag switch command must not
- * be used for switches to NULL, as the tag switch pending bit will be
- * set by the switch request, but never cleared by the hardware.
- *
- * NOTE: This should not be used when switching from a NULL tag. Use
- * cvmx_pow_tag_sw_full() instead.
- *
- * This function does no checks, so the caller must ensure that any
- * previous tag switch has completed.
- *
- * @tag: new tag value
- * @tag_type: new tag type (ordered or atomic)
- */
-static inline void cvmx_pow_tag_sw_nocheck(uint32_t tag,
- enum cvmx_pow_tag_type tag_type)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- if (CVMX_ENABLE_POW_CHECKS) {
- cvmx_pow_tag_req_t current_tag;
- __cvmx_pow_warn_if_pending_switch(__func__);
- current_tag = cvmx_pow_get_current_tag();
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
- pr_warning("%s called with NULL_NULL tag\n",
- __func__);
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called with NULL tag\n", __func__);
- if ((current_tag.s.type == tag_type)
- && (current_tag.s.tag == tag))
- pr_warning("%s called to perform a tag switch to the "
- "same tag\n",
- __func__);
- if (tag_type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called to perform a tag switch to "
- "NULL. Use cvmx_pow_tag_sw_null() instead\n",
- __func__);
- }
-
- /*
- * Note that WQE in DRAM is not updated here, as the POW does
- * not read from DRAM once the WQE is in flight. See hardware
- * manual for complete details. It is the application's
- * responsibility to keep track of the current tag value if
- * that is important.
- */
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_SWTAG;
- tag_req.s.tag = tag;
- tag_req.s.type = tag_type;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
-
- /* once this store arrives at POW, it will attempt the switch
- software must wait for the switch to complete separately */
- cvmx_write_io(ptr.u64, tag_req.u64);
-}
-
-/**
- * Starts a tag switch to the provided tag value and tag type.
- * Completion for the tag switch must be checked for separately. This
- * function does NOT update the work queue entry in dram to match tag
- * value and type, so the application must keep track of these if they
- * are important to the application. This tag switch command must not
- * be used for switches to NULL, as the tag switch pending bit will be
- * set by the switch request, but never cleared by the hardware.
- *
- * NOTE: This should not be used when switching from a NULL tag. Use
- * cvmx_pow_tag_sw_full() instead.
- *
- * This function waits for any previous tag switch to complete, and also
- * displays an error on tag switches to NULL.
- *
- * @tag: new tag value
- * @tag_type: new tag type (ordered or atomic)
- */
-static inline void cvmx_pow_tag_sw(uint32_t tag,
- enum cvmx_pow_tag_type tag_type)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /*
- * Note that WQE in DRAM is not updated here, as the POW does
- * not read from DRAM once the WQE is in flight. See hardware
- * manual for complete details. It is the application's
- * responsibility to keep track of the current tag value if
- * that is important.
- */
-
- /*
- * Ensure that there is not a pending tag switch, as a tag
- * switch cannot be started if a previous switch is still
- * pending.
- */
- cvmx_pow_tag_sw_wait();
- cvmx_pow_tag_sw_nocheck(tag, tag_type);
-}
-
-/**
- * Starts a tag switch to the provided tag value and tag type.
- * Completion for the tag switch must be checked for separately. This
- * function does NOT update the work queue entry in dram to match tag
- * value and type, so the application must keep track of these if they
- * are important to the application. This tag switch command must not
- * be used for switches to NULL, as the tag switch pending bit will be
- * set by the switch request, but never cleared by the hardware.
- *
- * This function must be used for tag switches from NULL.
- *
- * This function does no checks, so the caller must ensure that any
- * previous tag switch has completed.
- *
- * @wqp: pointer to work queue entry to submit. This entry is
- * updated to match the other parameters
- * @tag: tag value to be assigned to work queue entry
- * @tag_type: type of tag
- * @group: group value for the work queue entry.
- */
-static inline void cvmx_pow_tag_sw_full_nocheck(cvmx_wqe_t *wqp, uint32_t tag,
- enum cvmx_pow_tag_type tag_type,
- uint64_t group)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- if (CVMX_ENABLE_POW_CHECKS) {
- cvmx_pow_tag_req_t current_tag;
- __cvmx_pow_warn_if_pending_switch(__func__);
- current_tag = cvmx_pow_get_current_tag();
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
- pr_warning("%s called with NULL_NULL tag\n",
- __func__);
- if ((current_tag.s.type == tag_type)
- && (current_tag.s.tag == tag))
- pr_warning("%s called to perform a tag switch to "
- "the same tag\n",
- __func__);
- if (tag_type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called to perform a tag switch to "
- "NULL. Use cvmx_pow_tag_sw_null() instead\n",
- __func__);
- if (wqp != cvmx_phys_to_ptr(0x80))
- if (wqp != cvmx_pow_get_current_wqp())
- pr_warning("%s passed WQE(%p) doesn't match "
- "the address in the POW(%p)\n",
- __func__, wqp,
- cvmx_pow_get_current_wqp());
- }
-
- /*
- * Note that WQE in DRAM is not updated here, as the POW does
- * not read from DRAM once the WQE is in flight. See hardware
- * manual for complete details. It is the application's
- * responsibility to keep track of the current tag value if
- * that is important.
- */
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_FULL;
- tag_req.s.tag = tag;
- tag_req.s.type = tag_type;
- tag_req.s.grp = group;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_SWTAG;
- ptr.sio.offset = CAST64(wqp);
-
- /*
- * once this store arrives at POW, it will attempt the switch
- * software must wait for the switch to complete separately.
- */
- cvmx_write_io(ptr.u64, tag_req.u64);
-}
-
-/**
- * Starts a tag switch to the provided tag value and tag type.
- * Completion for the tag switch must be checked for separately. This
- * function does NOT update the work queue entry in dram to match tag
- * value and type, so the application must keep track of these if they
- * are important to the application. This tag switch command must not
- * be used for switches to NULL, as the tag switch pending bit will be
- * set by the switch request, but never cleared by the hardware.
- *
- * This function must be used for tag switches from NULL.
- *
- * This function waits for any pending tag switches to complete
- * before requesting the tag switch.
- *
- * @wqp: pointer to work queue entry to submit. This entry is updated
- * to match the other parameters
- * @tag: tag value to be assigned to work queue entry
- * @tag_type: type of tag
- * @group: group value for the work queue entry.
- */
-static inline void cvmx_pow_tag_sw_full(cvmx_wqe_t *wqp, uint32_t tag,
- enum cvmx_pow_tag_type tag_type,
- uint64_t group)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /*
- * Ensure that there is not a pending tag switch, as a tag
- * switch cannot be started if a previous switch is still
- * pending.
- */
- cvmx_pow_tag_sw_wait();
- cvmx_pow_tag_sw_full_nocheck(wqp, tag, tag_type, group);
-}
-
-/**
- * Switch to a NULL tag, which ends any ordering or
- * synchronization provided by the POW for the current
- * work queue entry. This operation completes immediately,
- * so completion should not be waited for.
- * This function does NOT wait for previous tag switches to complete,
- * so the caller must ensure that any previous tag switches have completed.
- */
-static inline void cvmx_pow_tag_sw_null_nocheck(void)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- if (CVMX_ENABLE_POW_CHECKS) {
- cvmx_pow_tag_req_t current_tag;
- __cvmx_pow_warn_if_pending_switch(__func__);
- current_tag = cvmx_pow_get_current_tag();
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
- pr_warning("%s called with NULL_NULL tag\n",
- __func__);
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called when we already have a "
- "NULL tag\n",
- __func__);
- }
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_SWTAG;
- tag_req.s.type = CVMX_POW_TAG_TYPE_NULL;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
-
- cvmx_write_io(ptr.u64, tag_req.u64);
-
- /* switch to NULL completes immediately */
-}
-
-/**
- * Switch to a NULL tag, which ends any ordering or
- * synchronization provided by the POW for the current
- * work queue entry. This operation completes immediately,
- * so completion should not be waited for.
- * This function waits for any pending tag switches to complete
- * before requesting the switch to NULL.
- */
-static inline void cvmx_pow_tag_sw_null(void)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /*
- * Ensure that there is not a pending tag switch, as a tag
- * switch cannot be started if a previous switch is still
- * pending.
- */
- cvmx_pow_tag_sw_wait();
- cvmx_pow_tag_sw_null_nocheck();
-
- /* switch to NULL completes immediately */
-}
-
-/**
- * Submits work to an input queue. This function updates the work
- * queue entry in DRAM to match the arguments given. Note that the
- * tag provided is for the work queue entry submitted, and is
- * unrelated to the tag that the core currently holds.
- *
- * @wqp: pointer to work queue entry to submit. This entry is
- * updated to match the other parameters
- * @tag: tag value to be assigned to work queue entry
- * @tag_type: type of tag
- * @qos: Input queue to add to.
- * @grp: group value for the work queue entry.
- */
-static inline void cvmx_pow_work_submit(cvmx_wqe_t *wqp, uint32_t tag,
- enum cvmx_pow_tag_type tag_type,
- uint64_t qos, uint64_t grp)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- wqp->qos = qos;
- wqp->tag = tag;
- wqp->tag_type = tag_type;
- wqp->grp = grp;
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_ADDWQ;
- tag_req.s.type = tag_type;
- tag_req.s.tag = tag;
- tag_req.s.qos = qos;
- tag_req.s.grp = grp;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_TAG1;
- ptr.sio.offset = cvmx_ptr_to_phys(wqp);
-
- /*
- * SYNC write to memory before the work submit. This is
- * necessary as POW may read values from DRAM at this time.
- */
- CVMX_SYNCWS;
- cvmx_write_io(ptr.u64, tag_req.u64);
-}
-
-/**
- * This function sets the group mask for a core. The group mask
- * indicates which groups each core will accept work from. There are
- * 16 groups.
- *
- * @core_num: core to apply mask to
- * @mask: Group mask. There are 16 groups, so only bits 0-15 are valid,
- * representing groups 0-15.
- * Each 1 bit in the mask enables the core to accept work from
- * the corresponding group.
- */
-static inline void cvmx_pow_set_group_mask(uint64_t core_num, uint64_t mask)
-{
- union cvmx_pow_pp_grp_mskx grp_msk;
-
- grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
- grp_msk.s.grp_msk = mask;
- cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
-}
-
-/**
- * This function sets POW static priorities for a core. Each input queue has
- * an associated priority value.
- *
- * @core_num: core to apply priorities to
- * @priority: Vector of 8 priorities, one per POW Input Queue (0-7).
- * Highest priority is 0 and lowest is 7. A priority value
- * of 0xF instructs POW to skip the Input Queue when
- * scheduling to this specific core.
- * NOTE: priorities should not have gaps in values, meaning
- * {0,1,1,1,1,1,1,1} is a valid configuration while
- * {0,2,2,2,2,2,2,2} is not.
- */
-static inline void cvmx_pow_set_priority(uint64_t core_num,
- const uint8_t priority[])
-{
- /* POW priorities are supported on CN5xxx and later */
- if (!OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- union cvmx_pow_pp_grp_mskx grp_msk;
-
- grp_msk.u64 = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(core_num));
- grp_msk.s.qos0_pri = priority[0];
- grp_msk.s.qos1_pri = priority[1];
- grp_msk.s.qos2_pri = priority[2];
- grp_msk.s.qos3_pri = priority[3];
- grp_msk.s.qos4_pri = priority[4];
- grp_msk.s.qos5_pri = priority[5];
- grp_msk.s.qos6_pri = priority[6];
- grp_msk.s.qos7_pri = priority[7];
-
- /* Detect gaps between priorities and flag error */
- {
- int i;
- uint32_t prio_mask = 0;
-
- for (i = 0; i < 8; i++)
- if (priority[i] != 0xF)
- prio_mask |= 1 << priority[i];
-
- if (prio_mask ^ ((1 << cvmx_pop(prio_mask)) - 1)) {
- pr_err("POW static priorities should be "
- "contiguous (0x%llx)\n",
- (unsigned long long)prio_mask);
- return;
- }
- }
-
- cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(core_num), grp_msk.u64);
- }
-}
-
-/**
- * Performs a tag switch and then an immediate deschedule. This completes
- * immediately, so completion must not be waited for. This function does NOT
- * update the wqe in DRAM to match arguments.
- *
- * This function does NOT wait for any prior tag switches to complete, so the
- * calling code must do this.
- *
- * Note the following CAVEAT of the Octeon HW behavior when
- * re-scheduling DE-SCHEDULEd items whose (next) state is
- * ORDERED:
- * - If there are no switches pending at the time that the
- * HW executes the de-schedule, the HW will only re-schedule
- * the head of the FIFO associated with the given tag. This
- * means that in many respects, the HW treats this ORDERED
- * tag as an ATOMIC tag. Note that in the SWTAG_DESCH
- * case (to an ORDERED tag), the HW will do the switch
- * before the deschedule whenever it is possible to do
- * the switch immediately, so it may often look like
- * this case.
- * - If there is a pending switch to ORDERED at the time
- * the HW executes the de-schedule, the HW will perform
- * the switch at the time it re-schedules, and will be
- * able to reschedule any/all of the entries with the
- * same tag.
- * Due to this behavior, the RECOMMENDATION to software is
- * that they have a (next) state of ATOMIC when they
- * DE-SCHEDULE. If an ORDERED tag is what was really desired,
- * SW can choose to immediately switch to an ORDERED tag
- * after the work (that has an ATOMIC tag) is re-scheduled.
- * Note that since there are never any tag switches pending
- * when the HW re-schedules, this switch can be IMMEDIATE upon
- * the reception of the pointer during the re-schedule.
- *
- * @tag: New tag value
- * @tag_type: New tag type
- * @group: New group value
- * @no_sched: Control whether this work queue entry will be rescheduled.
- * - 1 : don't schedule this work
- * - 0 : allow this work to be scheduled.
- */
-static inline void cvmx_pow_tag_sw_desched_nocheck(
- uint32_t tag,
- enum cvmx_pow_tag_type tag_type,
- uint64_t group,
- uint64_t no_sched)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- if (CVMX_ENABLE_POW_CHECKS) {
- cvmx_pow_tag_req_t current_tag;
- __cvmx_pow_warn_if_pending_switch(__func__);
- current_tag = cvmx_pow_get_current_tag();
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
- pr_warning("%s called with NULL_NULL tag\n",
- __func__);
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called with NULL tag. Deschedule not "
- "allowed from NULL state\n",
- __func__);
- if ((current_tag.s.type != CVMX_POW_TAG_TYPE_ATOMIC)
- && (tag_type != CVMX_POW_TAG_TYPE_ATOMIC))
- pr_warning("%s called where neither the before or "
- "after tag is ATOMIC\n",
- __func__);
- }
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_SWTAG_DESCH;
- tag_req.s.tag = tag;
- tag_req.s.type = tag_type;
- tag_req.s.grp = group;
- tag_req.s.no_sched = no_sched;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
- /*
- * since TAG3 is used, this store will clear the local pending
- * switch bit.
- */
- cvmx_write_io(ptr.u64, tag_req.u64);
-}
-
-/**
- * Performs a tag switch and then an immediate deschedule. This completes
- * immediately, so completion must not be waited for. This function does NOT
- * update the wqe in DRAM to match arguments.
- *
- * This function waits for any prior tag switches to complete, so the
- * calling code may call this function with a pending tag switch.
- *
- * Note the following CAVEAT of the Octeon HW behavior when
- * re-scheduling DE-SCHEDULEd items whose (next) state is
- * ORDERED:
- * - If there are no switches pending at the time that the
- * HW executes the de-schedule, the HW will only re-schedule
- * the head of the FIFO associated with the given tag. This
- * means that in many respects, the HW treats this ORDERED
- * tag as an ATOMIC tag. Note that in the SWTAG_DESCH
- * case (to an ORDERED tag), the HW will do the switch
- * before the deschedule whenever it is possible to do
- * the switch immediately, so it may often look like
- * this case.
- * - If there is a pending switch to ORDERED at the time
- * the HW executes the de-schedule, the HW will perform
- * the switch at the time it re-schedules, and will be
- * able to reschedule any/all of the entries with the
- * same tag.
- * Due to this behavior, the RECOMMENDATION to software is
- * that they have a (next) state of ATOMIC when they
- * DE-SCHEDULE. If an ORDERED tag is what was really desired,
- * SW can choose to immediately switch to an ORDERED tag
- * after the work (that has an ATOMIC tag) is re-scheduled.
- * Note that since there are never any tag switches pending
- * when the HW re-schedules, this switch can be IMMEDIATE upon
- * the reception of the pointer during the re-schedule.
- *
- * @tag: New tag value
- * @tag_type: New tag type
- * @group: New group value
- * @no_sched: Control whether this work queue entry will be rescheduled.
- * - 1 : don't schedule this work
- * - 0 : allow this work to be scheduled.
- */
-static inline void cvmx_pow_tag_sw_desched(uint32_t tag,
- enum cvmx_pow_tag_type tag_type,
- uint64_t group, uint64_t no_sched)
-{
- if (CVMX_ENABLE_POW_CHECKS)
- __cvmx_pow_warn_if_pending_switch(__func__);
-
- /* Need to make sure any writes to the work queue entry are complete */
- CVMX_SYNCWS;
- /*
- * Ensure that there is not a pending tag switch, as a tag
- * switch cannot be started if a previous switch is still
- * pending.
- */
- cvmx_pow_tag_sw_wait();
- cvmx_pow_tag_sw_desched_nocheck(tag, tag_type, group, no_sched);
-}
-
-/**
- * Descchedules the current work queue entry.
- *
- * @no_sched: no schedule flag value to be set on the work queue
- * entry. If this is set the entry will not be
- * rescheduled.
- */
-static inline void cvmx_pow_desched(uint64_t no_sched)
-{
- cvmx_addr_t ptr;
- cvmx_pow_tag_req_t tag_req;
-
- if (CVMX_ENABLE_POW_CHECKS) {
- cvmx_pow_tag_req_t current_tag;
- __cvmx_pow_warn_if_pending_switch(__func__);
- current_tag = cvmx_pow_get_current_tag();
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL_NULL)
- pr_warning("%s called with NULL_NULL tag\n",
- __func__);
- if (current_tag.s.type == CVMX_POW_TAG_TYPE_NULL)
- pr_warning("%s called with NULL tag. Deschedule not "
- "expected from NULL state\n",
- __func__);
- }
-
- /* Need to make sure any writes to the work queue entry are complete */
- CVMX_SYNCWS;
-
- tag_req.u64 = 0;
- tag_req.s.op = CVMX_POW_TAG_OP_DESCH;
- tag_req.s.no_sched = no_sched;
-
- ptr.u64 = 0;
- ptr.sio.mem_region = CVMX_IO_SEG;
- ptr.sio.is_io = 1;
- ptr.sio.did = CVMX_OCT_DID_TAG_TAG3;
- /*
- * since TAG3 is used, this store will clear the local pending
- * switch bit.
- */
- cvmx_write_io(ptr.u64, tag_req.u64);
-}
-
-/****************************************************
-* Define usage of bits within the 32 bit tag values.
-*****************************************************/
-
-/*
- * Number of bits of the tag used by software. The SW bits are always
- * a contiguous block of the high starting at bit 31. The hardware
- * bits are always the low bits. By default, the top 8 bits of the
- * tag are reserved for software, and the low 24 are set by the IPD
- * unit.
- */
-#define CVMX_TAG_SW_BITS (8)
-#define CVMX_TAG_SW_SHIFT (32 - CVMX_TAG_SW_BITS)
-
-/* Below is the list of values for the top 8 bits of the tag. */
-/*
- * Tag values with top byte of this value are reserved for internal
- * executive uses.
- */
-#define CVMX_TAG_SW_BITS_INTERNAL 0x1
-/* The executive divides the remaining 24 bits as follows:
- * - the upper 8 bits (bits 23 - 16 of the tag) define a subgroup
- *
- * - the lower 16 bits (bits 15 - 0 of the tag) define are the value
- * with the subgroup
- *
- * Note that this section describes the format of tags generated by
- * software - refer to the hardware documentation for a description of
- * the tags values generated by the packet input hardware. Subgroups
- * are defined here.
- */
-/* Mask for the value portion of the tag */
-#define CVMX_TAG_SUBGROUP_MASK 0xFFFF
-#define CVMX_TAG_SUBGROUP_SHIFT 16
-#define CVMX_TAG_SUBGROUP_PKO 0x1
-
-/* End of executive tag subgroup definitions */
-
-/*
- * The remaining values software bit values 0x2 - 0xff are available
- * for application use.
- */
-
-/**
- * This function creates a 32 bit tag value from the two values provided.
- *
- * @sw_bits: The upper bits (number depends on configuration) are set
- * to this value. The remainder of bits are set by the
- * hw_bits parameter.
- *
- * @hw_bits: The lower bits (number depends on configuration) are set
- * to this value. The remainder of bits are set by the
- * sw_bits parameter.
- *
- * Returns 32 bit value of the combined hw and sw bits.
- */
-static inline uint32_t cvmx_pow_tag_compose(uint64_t sw_bits, uint64_t hw_bits)
-{
- return ((sw_bits & cvmx_build_mask(CVMX_TAG_SW_BITS)) <<
- CVMX_TAG_SW_SHIFT) |
- (hw_bits & cvmx_build_mask(32 - CVMX_TAG_SW_BITS));
-}
-
-/**
- * Extracts the bits allocated for software use from the tag
- *
- * @tag: 32 bit tag value
- *
- * Returns N bit software tag value, where N is configurable with the
- * CVMX_TAG_SW_BITS define
- */
-static inline uint32_t cvmx_pow_tag_get_sw_bits(uint64_t tag)
-{
- return (tag >> (32 - CVMX_TAG_SW_BITS)) &
- cvmx_build_mask(CVMX_TAG_SW_BITS);
-}
-
-/**
- *
- * Extracts the bits allocated for hardware use from the tag
- *
- * @tag: 32 bit tag value
- *
- * Returns (32 - N) bit software tag value, where N is configurable
- * with the CVMX_TAG_SW_BITS define
- */
-static inline uint32_t cvmx_pow_tag_get_hw_bits(uint64_t tag)
-{
- return tag & cvmx_build_mask(32 - CVMX_TAG_SW_BITS);
-}
-
-/**
- * Store the current POW internal state into the supplied
- * buffer. It is recommended that you pass a buffer of at least
- * 128KB. The format of the capture may change based on SDK
- * version and Octeon chip.
- *
- * @buffer: Buffer to store capture into
- * @buffer_size:
- * The size of the supplied buffer
- *
- * Returns Zero on success, negative on failure
- */
-extern int cvmx_pow_capture(void *buffer, int buffer_size);
-
-/**
- * Dump a POW capture to the console in a human readable format.
- *
- * @buffer: POW capture from cvmx_pow_capture()
- * @buffer_size:
- * Size of the buffer
- */
-extern void cvmx_pow_display(void *buffer, int buffer_size);
-
-/**
- * Return the number of POW entries supported by this chip
- *
- * Returns Number of POW entries
- */
-extern int cvmx_pow_get_num_entries(void);
-
-#endif /* __CVMX_POW_H__ */
diff --git a/drivers/staging/octeon/cvmx-scratch.h b/drivers/staging/octeon/cvmx-scratch.h
deleted file mode 100644
index 96b70cf..0000000
--- a/drivers/staging/octeon/cvmx-scratch.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * This file provides support for the processor local scratch memory.
- * Scratch memory is byte addressable - all addresses are byte addresses.
- *
- */
-
-#ifndef __CVMX_SCRATCH_H__
-#define __CVMX_SCRATCH_H__
-
-/*
- * Note: This define must be a long, not a long long in order to
- * compile without warnings for both 32bit and 64bit.
- */
-#define CVMX_SCRATCH_BASE (-32768l) /* 0xffffffffffff8000 */
-
-/**
- * Reads an 8 bit value from the processor local scratchpad memory.
- *
- * @address: byte address to read from
- *
- * Returns value read
- */
-static inline uint8_t cvmx_scratch_read8(uint64_t address)
-{
- return *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address);
-}
-
-/**
- * Reads a 16 bit value from the processor local scratchpad memory.
- *
- * @address: byte address to read from
- *
- * Returns value read
- */
-static inline uint16_t cvmx_scratch_read16(uint64_t address)
-{
- return *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address);
-}
-
-/**
- * Reads a 32 bit value from the processor local scratchpad memory.
- *
- * @address: byte address to read from
- *
- * Returns value read
- */
-static inline uint32_t cvmx_scratch_read32(uint64_t address)
-{
- return *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address);
-}
-
-/**
- * Reads a 64 bit value from the processor local scratchpad memory.
- *
- * @address: byte address to read from
- *
- * Returns value read
- */
-static inline uint64_t cvmx_scratch_read64(uint64_t address)
-{
- return *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address);
-}
-
-/**
- * Writes an 8 bit value to the processor local scratchpad memory.
- *
- * @address: byte address to write to
- * @value: value to write
- */
-static inline void cvmx_scratch_write8(uint64_t address, uint64_t value)
-{
- *CASTPTR(volatile uint8_t, CVMX_SCRATCH_BASE + address) =
- (uint8_t) value;
-}
-
-/**
- * Writes a 32 bit value to the processor local scratchpad memory.
- *
- * @address: byte address to write to
- * @value: value to write
- */
-static inline void cvmx_scratch_write16(uint64_t address, uint64_t value)
-{
- *CASTPTR(volatile uint16_t, CVMX_SCRATCH_BASE + address) =
- (uint16_t) value;
-}
-
-/**
- * Writes a 16 bit value to the processor local scratchpad memory.
- *
- * @address: byte address to write to
- * @value: value to write
- */
-static inline void cvmx_scratch_write32(uint64_t address, uint64_t value)
-{
- *CASTPTR(volatile uint32_t, CVMX_SCRATCH_BASE + address) =
- (uint32_t) value;
-}
-
-/**
- * Writes a 64 bit value to the processor local scratchpad memory.
- *
- * @address: byte address to write to
- * @value: value to write
- */
-static inline void cvmx_scratch_write64(uint64_t address, uint64_t value)
-{
- *CASTPTR(volatile uint64_t, CVMX_SCRATCH_BASE + address) = value;
-}
-
-#endif /* __CVMX_SCRATCH_H__ */
diff --git a/drivers/staging/octeon/cvmx-smix-defs.h b/drivers/staging/octeon/cvmx-smix-defs.h
deleted file mode 100644
index 9ae45fc..0000000
--- a/drivers/staging/octeon/cvmx-smix-defs.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_SMIX_DEFS_H__
-#define __CVMX_SMIX_DEFS_H__
-
-#define CVMX_SMIX_CLK(offset) \
- CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256))
-#define CVMX_SMIX_CMD(offset) \
- CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256))
-#define CVMX_SMIX_EN(offset) \
- CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256))
-#define CVMX_SMIX_RD_DAT(offset) \
- CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256))
-#define CVMX_SMIX_WR_DAT(offset) \
- CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256))
-
-union cvmx_smix_clk {
- uint64_t u64;
- struct cvmx_smix_clk_s {
- uint64_t reserved_25_63:39;
- uint64_t mode:1;
- uint64_t reserved_21_23:3;
- uint64_t sample_hi:5;
- uint64_t sample_mode:1;
- uint64_t reserved_14_14:1;
- uint64_t clk_idle:1;
- uint64_t preamble:1;
- uint64_t sample:4;
- uint64_t phase:8;
- } s;
- struct cvmx_smix_clk_cn30xx {
- uint64_t reserved_21_63:43;
- uint64_t sample_hi:5;
- uint64_t reserved_14_15:2;
- uint64_t clk_idle:1;
- uint64_t preamble:1;
- uint64_t sample:4;
- uint64_t phase:8;
- } cn30xx;
- struct cvmx_smix_clk_cn30xx cn31xx;
- struct cvmx_smix_clk_cn30xx cn38xx;
- struct cvmx_smix_clk_cn30xx cn38xxp2;
- struct cvmx_smix_clk_cn50xx {
- uint64_t reserved_25_63:39;
- uint64_t mode:1;
- uint64_t reserved_21_23:3;
- uint64_t sample_hi:5;
- uint64_t reserved_14_15:2;
- uint64_t clk_idle:1;
- uint64_t preamble:1;
- uint64_t sample:4;
- uint64_t phase:8;
- } cn50xx;
- struct cvmx_smix_clk_s cn52xx;
- struct cvmx_smix_clk_cn50xx cn52xxp1;
- struct cvmx_smix_clk_s cn56xx;
- struct cvmx_smix_clk_cn50xx cn56xxp1;
- struct cvmx_smix_clk_cn30xx cn58xx;
- struct cvmx_smix_clk_cn30xx cn58xxp1;
-};
-
-union cvmx_smix_cmd {
- uint64_t u64;
- struct cvmx_smix_cmd_s {
- uint64_t reserved_18_63:46;
- uint64_t phy_op:2;
- uint64_t reserved_13_15:3;
- uint64_t phy_adr:5;
- uint64_t reserved_5_7:3;
- uint64_t reg_adr:5;
- } s;
- struct cvmx_smix_cmd_cn30xx {
- uint64_t reserved_17_63:47;
- uint64_t phy_op:1;
- uint64_t reserved_13_15:3;
- uint64_t phy_adr:5;
- uint64_t reserved_5_7:3;
- uint64_t reg_adr:5;
- } cn30xx;
- struct cvmx_smix_cmd_cn30xx cn31xx;
- struct cvmx_smix_cmd_cn30xx cn38xx;
- struct cvmx_smix_cmd_cn30xx cn38xxp2;
- struct cvmx_smix_cmd_s cn50xx;
- struct cvmx_smix_cmd_s cn52xx;
- struct cvmx_smix_cmd_s cn52xxp1;
- struct cvmx_smix_cmd_s cn56xx;
- struct cvmx_smix_cmd_s cn56xxp1;
- struct cvmx_smix_cmd_cn30xx cn58xx;
- struct cvmx_smix_cmd_cn30xx cn58xxp1;
-};
-
-union cvmx_smix_en {
- uint64_t u64;
- struct cvmx_smix_en_s {
- uint64_t reserved_1_63:63;
- uint64_t en:1;
- } s;
- struct cvmx_smix_en_s cn30xx;
- struct cvmx_smix_en_s cn31xx;
- struct cvmx_smix_en_s cn38xx;
- struct cvmx_smix_en_s cn38xxp2;
- struct cvmx_smix_en_s cn50xx;
- struct cvmx_smix_en_s cn52xx;
- struct cvmx_smix_en_s cn52xxp1;
- struct cvmx_smix_en_s cn56xx;
- struct cvmx_smix_en_s cn56xxp1;
- struct cvmx_smix_en_s cn58xx;
- struct cvmx_smix_en_s cn58xxp1;
-};
-
-union cvmx_smix_rd_dat {
- uint64_t u64;
- struct cvmx_smix_rd_dat_s {
- uint64_t reserved_18_63:46;
- uint64_t pending:1;
- uint64_t val:1;
- uint64_t dat:16;
- } s;
- struct cvmx_smix_rd_dat_s cn30xx;
- struct cvmx_smix_rd_dat_s cn31xx;
- struct cvmx_smix_rd_dat_s cn38xx;
- struct cvmx_smix_rd_dat_s cn38xxp2;
- struct cvmx_smix_rd_dat_s cn50xx;
- struct cvmx_smix_rd_dat_s cn52xx;
- struct cvmx_smix_rd_dat_s cn52xxp1;
- struct cvmx_smix_rd_dat_s cn56xx;
- struct cvmx_smix_rd_dat_s cn56xxp1;
- struct cvmx_smix_rd_dat_s cn58xx;
- struct cvmx_smix_rd_dat_s cn58xxp1;
-};
-
-union cvmx_smix_wr_dat {
- uint64_t u64;
- struct cvmx_smix_wr_dat_s {
- uint64_t reserved_18_63:46;
- uint64_t pending:1;
- uint64_t val:1;
- uint64_t dat:16;
- } s;
- struct cvmx_smix_wr_dat_s cn30xx;
- struct cvmx_smix_wr_dat_s cn31xx;
- struct cvmx_smix_wr_dat_s cn38xx;
- struct cvmx_smix_wr_dat_s cn38xxp2;
- struct cvmx_smix_wr_dat_s cn50xx;
- struct cvmx_smix_wr_dat_s cn52xx;
- struct cvmx_smix_wr_dat_s cn52xxp1;
- struct cvmx_smix_wr_dat_s cn56xx;
- struct cvmx_smix_wr_dat_s cn56xxp1;
- struct cvmx_smix_wr_dat_s cn58xx;
- struct cvmx_smix_wr_dat_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-spi.c b/drivers/staging/octeon/cvmx-spi.c
deleted file mode 100644
index 82794d9..0000000
--- a/drivers/staging/octeon/cvmx-spi.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * Support library for the SPI
- */
-#include <asm/octeon/octeon.h>
-
-#include "cvmx-config.h"
-
-#include "cvmx-pko.h"
-#include "cvmx-spi.h"
-
-#include "cvmx-spxx-defs.h"
-#include "cvmx-stxx-defs.h"
-#include "cvmx-srxx-defs.h"
-
-#define INVOKE_CB(function_p, args...) \
- do { \
- if (function_p) { \
- res = function_p(args); \
- if (res) \
- return res; \
- } \
- } while (0)
-
-#if CVMX_ENABLE_DEBUG_PRINTS
-static const char *modes[] =
- { "UNKNOWN", "TX Halfplex", "Rx Halfplex", "Duplex" };
-#endif
-
-/* Default callbacks, can be overridden
- * using cvmx_spi_get_callbacks/cvmx_spi_set_callbacks
- */
-static cvmx_spi_callbacks_t cvmx_spi_callbacks = {
- .reset_cb = cvmx_spi_reset_cb,
- .calendar_setup_cb = cvmx_spi_calendar_setup_cb,
- .clock_detect_cb = cvmx_spi_clock_detect_cb,
- .training_cb = cvmx_spi_training_cb,
- .calendar_sync_cb = cvmx_spi_calendar_sync_cb,
- .interface_up_cb = cvmx_spi_interface_up_cb
-};
-
-/**
- * Get current SPI4 initialization callbacks
- *
- * @callbacks: Pointer to the callbacks structure.to fill
- *
- * Returns Pointer to cvmx_spi_callbacks_t structure.
- */
-void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks)
-{
- memcpy(callbacks, &cvmx_spi_callbacks, sizeof(cvmx_spi_callbacks));
-}
-
-/**
- * Set new SPI4 initialization callbacks
- *
- * @new_callbacks: Pointer to an updated callbacks structure.
- */
-void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks)
-{
- memcpy(&cvmx_spi_callbacks, new_callbacks, sizeof(cvmx_spi_callbacks));
-}
-
-/**
- * Initialize and start the SPI interface.
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- * @num_ports: Number of SPI ports to configure
- *
- * Returns Zero on success, negative of failure.
- */
-int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode, int timeout,
- int num_ports)
-{
- int res = -1;
-
- if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)))
- return res;
-
- /* Callback to perform SPI4 reset */
- INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode);
-
- /* Callback to perform calendar setup */
- INVOKE_CB(cvmx_spi_callbacks.calendar_setup_cb, interface, mode,
- num_ports);
-
- /* Callback to perform clock detection */
- INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout);
-
- /* Callback to perform SPI4 link training */
- INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout);
-
- /* Callback to perform calendar sync */
- INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode,
- timeout);
-
- /* Callback to handle interface coming up */
- INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode);
-
- return res;
-}
-
-/**
- * This routine restarts the SPI interface after it has lost synchronization
- * with its correspondent system.
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- *
- * Returns Zero on success, negative of failure.
- */
-int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode, int timeout)
-{
- int res = -1;
-
- if (!(OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)))
- return res;
-
- cvmx_dprintf("SPI%d: Restart %s\n", interface, modes[mode]);
-
- /* Callback to perform SPI4 reset */
- INVOKE_CB(cvmx_spi_callbacks.reset_cb, interface, mode);
-
- /* NOTE: Calendar setup is not performed during restart */
- /* Refer to cvmx_spi_start_interface() for the full sequence */
-
- /* Callback to perform clock detection */
- INVOKE_CB(cvmx_spi_callbacks.clock_detect_cb, interface, mode, timeout);
-
- /* Callback to perform SPI4 link training */
- INVOKE_CB(cvmx_spi_callbacks.training_cb, interface, mode, timeout);
-
- /* Callback to perform calendar sync */
- INVOKE_CB(cvmx_spi_callbacks.calendar_sync_cb, interface, mode,
- timeout);
-
- /* Callback to handle interface coming up */
- INVOKE_CB(cvmx_spi_callbacks.interface_up_cb, interface, mode);
-
- return res;
-}
-
-/**
- * Callback to perform SPI4 reset
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode)
-{
- union cvmx_spxx_dbg_deskew_ctl spxx_dbg_deskew_ctl;
- union cvmx_spxx_clk_ctl spxx_clk_ctl;
- union cvmx_spxx_bist_stat spxx_bist_stat;
- union cvmx_spxx_int_msk spxx_int_msk;
- union cvmx_stxx_int_msk stxx_int_msk;
- union cvmx_spxx_trn4_ctl spxx_trn4_ctl;
- int index;
- uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000;
-
- /* Disable SPI error events while we run BIST */
- spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
- cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
- stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
- cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
-
- /* Run BIST in the SPI interface */
- cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), 0);
- cvmx_write_csr(CVMX_STXX_COM_CTL(interface), 0);
- spxx_clk_ctl.u64 = 0;
- spxx_clk_ctl.s.runbist = 1;
- cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64);
- cvmx_wait(10 * MS);
- spxx_bist_stat.u64 = cvmx_read_csr(CVMX_SPXX_BIST_STAT(interface));
- if (spxx_bist_stat.s.stat0)
- cvmx_dprintf
- ("ERROR SPI%d: BIST failed on receive datapath FIFO\n",
- interface);
- if (spxx_bist_stat.s.stat1)
- cvmx_dprintf("ERROR SPI%d: BIST failed on RX calendar table\n",
- interface);
- if (spxx_bist_stat.s.stat2)
- cvmx_dprintf("ERROR SPI%d: BIST failed on TX calendar table\n",
- interface);
-
- /* Clear the calendar table after BIST to fix parity errors */
- for (index = 0; index < 32; index++) {
- union cvmx_srxx_spi4_calx srxx_spi4_calx;
- union cvmx_stxx_spi4_calx stxx_spi4_calx;
-
- srxx_spi4_calx.u64 = 0;
- srxx_spi4_calx.s.oddpar = 1;
- cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface),
- srxx_spi4_calx.u64);
-
- stxx_spi4_calx.u64 = 0;
- stxx_spi4_calx.s.oddpar = 1;
- cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface),
- stxx_spi4_calx.u64);
- }
-
- /* Re enable reporting of error interrupts */
- cvmx_write_csr(CVMX_SPXX_INT_REG(interface),
- cvmx_read_csr(CVMX_SPXX_INT_REG(interface)));
- cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);
- cvmx_write_csr(CVMX_STXX_INT_REG(interface),
- cvmx_read_csr(CVMX_STXX_INT_REG(interface)));
- cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
-
- /* Setup the CLKDLY right in the middle */
- spxx_clk_ctl.u64 = 0;
- spxx_clk_ctl.s.seetrn = 0;
- spxx_clk_ctl.s.clkdly = 0x10;
- spxx_clk_ctl.s.runbist = 0;
- spxx_clk_ctl.s.statdrv = 0;
- /* This should always be on the opposite edge as statdrv */
- spxx_clk_ctl.s.statrcv = 1;
- spxx_clk_ctl.s.sndtrn = 0;
- spxx_clk_ctl.s.drptrn = 0;
- spxx_clk_ctl.s.rcvtrn = 0;
- spxx_clk_ctl.s.srxdlck = 0;
- cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64);
- cvmx_wait(100 * MS);
-
- /* Reset SRX0 DLL */
- spxx_clk_ctl.s.srxdlck = 1;
- cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64);
-
- /* Waiting for Inf0 Spi4 RX DLL to lock */
- cvmx_wait(100 * MS);
-
- /* Enable dynamic alignment */
- spxx_trn4_ctl.s.trntest = 0;
- spxx_trn4_ctl.s.jitter = 1;
- spxx_trn4_ctl.s.clr_boot = 1;
- spxx_trn4_ctl.s.set_boot = 0;
- if (OCTEON_IS_MODEL(OCTEON_CN58XX))
- spxx_trn4_ctl.s.maxdist = 3;
- else
- spxx_trn4_ctl.s.maxdist = 8;
- spxx_trn4_ctl.s.macro_en = 1;
- spxx_trn4_ctl.s.mux_en = 1;
- cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64);
-
- spxx_dbg_deskew_ctl.u64 = 0;
- cvmx_write_csr(CVMX_SPXX_DBG_DESKEW_CTL(interface),
- spxx_dbg_deskew_ctl.u64);
-
- return 0;
-}
-
-/**
- * Callback to setup calendar and miscellaneous settings before clock detection
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @num_ports: Number of ports to configure on SPI
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode,
- int num_ports)
-{
- int port;
- int index;
- if (mode & CVMX_SPI_MODE_RX_HALFPLEX) {
- union cvmx_srxx_com_ctl srxx_com_ctl;
- union cvmx_srxx_spi4_stat srxx_spi4_stat;
-
- /* SRX0 number of Ports */
- srxx_com_ctl.u64 = 0;
- srxx_com_ctl.s.prts = num_ports - 1;
- srxx_com_ctl.s.st_en = 0;
- srxx_com_ctl.s.inf_en = 0;
- cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);
-
- /* SRX0 Calendar Table. This round robbins through all ports */
- port = 0;
- index = 0;
- while (port < num_ports) {
- union cvmx_srxx_spi4_calx srxx_spi4_calx;
- srxx_spi4_calx.u64 = 0;
- srxx_spi4_calx.s.prt0 = port++;
- srxx_spi4_calx.s.prt1 = port++;
- srxx_spi4_calx.s.prt2 = port++;
- srxx_spi4_calx.s.prt3 = port++;
- srxx_spi4_calx.s.oddpar =
- ~(cvmx_dpop(srxx_spi4_calx.u64) & 1);
- cvmx_write_csr(CVMX_SRXX_SPI4_CALX(index, interface),
- srxx_spi4_calx.u64);
- index++;
- }
- srxx_spi4_stat.u64 = 0;
- srxx_spi4_stat.s.len = num_ports;
- srxx_spi4_stat.s.m = 1;
- cvmx_write_csr(CVMX_SRXX_SPI4_STAT(interface),
- srxx_spi4_stat.u64);
- }
-
- if (mode & CVMX_SPI_MODE_TX_HALFPLEX) {
- union cvmx_stxx_arb_ctl stxx_arb_ctl;
- union cvmx_gmxx_tx_spi_max gmxx_tx_spi_max;
- union cvmx_gmxx_tx_spi_thresh gmxx_tx_spi_thresh;
- union cvmx_gmxx_tx_spi_ctl gmxx_tx_spi_ctl;
- union cvmx_stxx_spi4_stat stxx_spi4_stat;
- union cvmx_stxx_spi4_dat stxx_spi4_dat;
-
- /* STX0 Config */
- stxx_arb_ctl.u64 = 0;
- stxx_arb_ctl.s.igntpa = 0;
- stxx_arb_ctl.s.mintrn = 0;
- cvmx_write_csr(CVMX_STXX_ARB_CTL(interface), stxx_arb_ctl.u64);
-
- gmxx_tx_spi_max.u64 = 0;
- gmxx_tx_spi_max.s.max1 = 8;
- gmxx_tx_spi_max.s.max2 = 4;
- gmxx_tx_spi_max.s.slice = 0;
- cvmx_write_csr(CVMX_GMXX_TX_SPI_MAX(interface),
- gmxx_tx_spi_max.u64);
-
- gmxx_tx_spi_thresh.u64 = 0;
- gmxx_tx_spi_thresh.s.thresh = 4;
- cvmx_write_csr(CVMX_GMXX_TX_SPI_THRESH(interface),
- gmxx_tx_spi_thresh.u64);
-
- gmxx_tx_spi_ctl.u64 = 0;
- gmxx_tx_spi_ctl.s.tpa_clr = 0;
- gmxx_tx_spi_ctl.s.cont_pkt = 0;
- cvmx_write_csr(CVMX_GMXX_TX_SPI_CTL(interface),
- gmxx_tx_spi_ctl.u64);
-
- /* STX0 Training Control */
- stxx_spi4_dat.u64 = 0;
- /*Minimum needed by dynamic alignment */
- stxx_spi4_dat.s.alpha = 32;
- stxx_spi4_dat.s.max_t = 0xFFFF; /*Minimum interval is 0x20 */
- cvmx_write_csr(CVMX_STXX_SPI4_DAT(interface),
- stxx_spi4_dat.u64);
-
- /* STX0 Calendar Table. This round robbins through all ports */
- port = 0;
- index = 0;
- while (port < num_ports) {
- union cvmx_stxx_spi4_calx stxx_spi4_calx;
- stxx_spi4_calx.u64 = 0;
- stxx_spi4_calx.s.prt0 = port++;
- stxx_spi4_calx.s.prt1 = port++;
- stxx_spi4_calx.s.prt2 = port++;
- stxx_spi4_calx.s.prt3 = port++;
- stxx_spi4_calx.s.oddpar =
- ~(cvmx_dpop(stxx_spi4_calx.u64) & 1);
- cvmx_write_csr(CVMX_STXX_SPI4_CALX(index, interface),
- stxx_spi4_calx.u64);
- index++;
- }
- stxx_spi4_stat.u64 = 0;
- stxx_spi4_stat.s.len = num_ports;
- stxx_spi4_stat.s.m = 1;
- cvmx_write_csr(CVMX_STXX_SPI4_STAT(interface),
- stxx_spi4_stat.u64);
- }
-
- return 0;
-}
-
-/**
- * Callback to perform clock detection
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode, int timeout)
-{
- int clock_transitions;
- union cvmx_spxx_clk_stat stat;
- uint64_t timeout_time;
- uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000;
-
- /*
- * Regardless of operating mode, both Tx and Rx clocks must be
- * present for the SPI interface to operate.
- */
- cvmx_dprintf("SPI%d: Waiting to see TsClk...\n", interface);
- timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout;
- /*
- * Require 100 clock transitions in order to avoid any noise
- * in the beginning.
- */
- clock_transitions = 100;
- do {
- stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface));
- if (stat.s.s4clk0 && stat.s.s4clk1 && clock_transitions) {
- /*
- * We've seen a clock transition, so decrement
- * the number we still need.
- */
- clock_transitions--;
- cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64);
- stat.s.s4clk0 = 0;
- stat.s.s4clk1 = 0;
- }
- if (cvmx_get_cycle() > timeout_time) {
- cvmx_dprintf("SPI%d: Timeout\n", interface);
- return -1;
- }
- } while (stat.s.s4clk0 == 0 || stat.s.s4clk1 == 0);
-
- cvmx_dprintf("SPI%d: Waiting to see RsClk...\n", interface);
- timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout;
- /*
- * Require 100 clock transitions in order to avoid any noise in the
- * beginning.
- */
- clock_transitions = 100;
- do {
- stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface));
- if (stat.s.d4clk0 && stat.s.d4clk1 && clock_transitions) {
- /*
- * We've seen a clock transition, so decrement
- * the number we still need
- */
- clock_transitions--;
- cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64);
- stat.s.d4clk0 = 0;
- stat.s.d4clk1 = 0;
- }
- if (cvmx_get_cycle() > timeout_time) {
- cvmx_dprintf("SPI%d: Timeout\n", interface);
- return -1;
- }
- } while (stat.s.d4clk0 == 0 || stat.s.d4clk1 == 0);
-
- return 0;
-}
-
-/**
- * Callback to perform link training
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for link to be trained (in seconds)
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode, int timeout)
-{
- union cvmx_spxx_trn4_ctl spxx_trn4_ctl;
- union cvmx_spxx_clk_stat stat;
- uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000;
- uint64_t timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout;
- int rx_training_needed;
-
- /* SRX0 & STX0 Inf0 Links are configured - begin training */
- union cvmx_spxx_clk_ctl spxx_clk_ctl;
- spxx_clk_ctl.u64 = 0;
- spxx_clk_ctl.s.seetrn = 0;
- spxx_clk_ctl.s.clkdly = 0x10;
- spxx_clk_ctl.s.runbist = 0;
- spxx_clk_ctl.s.statdrv = 0;
- /* This should always be on the opposite edge as statdrv */
- spxx_clk_ctl.s.statrcv = 1;
- spxx_clk_ctl.s.sndtrn = 1;
- spxx_clk_ctl.s.drptrn = 1;
- spxx_clk_ctl.s.rcvtrn = 1;
- spxx_clk_ctl.s.srxdlck = 1;
- cvmx_write_csr(CVMX_SPXX_CLK_CTL(interface), spxx_clk_ctl.u64);
- cvmx_wait(1000 * MS);
-
- /* SRX0 clear the boot bit */
- spxx_trn4_ctl.u64 = cvmx_read_csr(CVMX_SPXX_TRN4_CTL(interface));
- spxx_trn4_ctl.s.clr_boot = 1;
- cvmx_write_csr(CVMX_SPXX_TRN4_CTL(interface), spxx_trn4_ctl.u64);
-
- /* Wait for the training sequence to complete */
- cvmx_dprintf("SPI%d: Waiting for training\n", interface);
- cvmx_wait(1000 * MS);
- /* Wait a really long time here */
- timeout_time = cvmx_get_cycle() + 1000ull * MS * 600;
- /*
- * The HRM says we must wait for 34 + 16 * MAXDIST training sequences.
- * We'll be pessimistic and wait for a lot more.
- */
- rx_training_needed = 500;
- do {
- stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface));
- if (stat.s.srxtrn && rx_training_needed) {
- rx_training_needed--;
- cvmx_write_csr(CVMX_SPXX_CLK_STAT(interface), stat.u64);
- stat.s.srxtrn = 0;
- }
- if (cvmx_get_cycle() > timeout_time) {
- cvmx_dprintf("SPI%d: Timeout\n", interface);
- return -1;
- }
- } while (stat.s.srxtrn == 0);
-
- return 0;
-}
-
-/**
- * Callback to perform calendar data synchronization
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for calendar data in seconds
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode, int timeout)
-{
- uint64_t MS = cvmx_sysinfo_get()->cpu_clock_hz / 1000;
- if (mode & CVMX_SPI_MODE_RX_HALFPLEX) {
- /* SRX0 interface should be good, send calendar data */
- union cvmx_srxx_com_ctl srxx_com_ctl;
- cvmx_dprintf
- ("SPI%d: Rx is synchronized, start sending calendar data\n",
- interface);
- srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface));
- srxx_com_ctl.s.inf_en = 1;
- srxx_com_ctl.s.st_en = 1;
- cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);
- }
-
- if (mode & CVMX_SPI_MODE_TX_HALFPLEX) {
- /* STX0 has achieved sync */
- /* The corespondant board should be sending calendar data */
- /* Enable the STX0 STAT receiver. */
- union cvmx_spxx_clk_stat stat;
- uint64_t timeout_time;
- union cvmx_stxx_com_ctl stxx_com_ctl;
- stxx_com_ctl.u64 = 0;
- stxx_com_ctl.s.st_en = 1;
- cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64);
-
- /* Waiting for calendar sync on STX0 STAT */
- cvmx_dprintf("SPI%d: Waiting to sync on STX[%d] STAT\n",
- interface, interface);
- timeout_time = cvmx_get_cycle() + 1000ull * MS * timeout;
- /* SPX0_CLK_STAT - SPX0_CLK_STAT[STXCAL] should be 1 (bit10) */
- do {
- stat.u64 = cvmx_read_csr(CVMX_SPXX_CLK_STAT(interface));
- if (cvmx_get_cycle() > timeout_time) {
- cvmx_dprintf("SPI%d: Timeout\n", interface);
- return -1;
- }
- } while (stat.s.stxcal == 0);
- }
-
- return 0;
-}
-
-/**
- * Callback to handle interface up
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode)
-{
- union cvmx_gmxx_rxx_frm_min gmxx_rxx_frm_min;
- union cvmx_gmxx_rxx_frm_max gmxx_rxx_frm_max;
- union cvmx_gmxx_rxx_jabber gmxx_rxx_jabber;
-
- if (mode & CVMX_SPI_MODE_RX_HALFPLEX) {
- union cvmx_srxx_com_ctl srxx_com_ctl;
- srxx_com_ctl.u64 = cvmx_read_csr(CVMX_SRXX_COM_CTL(interface));
- srxx_com_ctl.s.inf_en = 1;
- cvmx_write_csr(CVMX_SRXX_COM_CTL(interface), srxx_com_ctl.u64);
- cvmx_dprintf("SPI%d: Rx is now up\n", interface);
- }
-
- if (mode & CVMX_SPI_MODE_TX_HALFPLEX) {
- union cvmx_stxx_com_ctl stxx_com_ctl;
- stxx_com_ctl.u64 = cvmx_read_csr(CVMX_STXX_COM_CTL(interface));
- stxx_com_ctl.s.inf_en = 1;
- cvmx_write_csr(CVMX_STXX_COM_CTL(interface), stxx_com_ctl.u64);
- cvmx_dprintf("SPI%d: Tx is now up\n", interface);
- }
-
- gmxx_rxx_frm_min.u64 = 0;
- gmxx_rxx_frm_min.s.len = 64;
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_MIN(0, interface),
- gmxx_rxx_frm_min.u64);
- gmxx_rxx_frm_max.u64 = 0;
- gmxx_rxx_frm_max.s.len = 64 * 1024 - 4;
- cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(0, interface),
- gmxx_rxx_frm_max.u64);
- gmxx_rxx_jabber.u64 = 0;
- gmxx_rxx_jabber.s.cnt = 64 * 1024 - 4;
- cvmx_write_csr(CVMX_GMXX_RXX_JABBER(0, interface), gmxx_rxx_jabber.u64);
-
- return 0;
-}
diff --git a/drivers/staging/octeon/cvmx-spi.h b/drivers/staging/octeon/cvmx-spi.h
deleted file mode 100644
index e814648..0000000
--- a/drivers/staging/octeon/cvmx-spi.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/*
- *
- * This file contains defines for the SPI interface
- */
-#ifndef __CVMX_SPI_H__
-#define __CVMX_SPI_H__
-
-#include "cvmx-gmxx-defs.h"
-
-/* CSR typedefs have been moved to cvmx-csr-*.h */
-
-typedef enum {
- CVMX_SPI_MODE_UNKNOWN = 0,
- CVMX_SPI_MODE_TX_HALFPLEX = 1,
- CVMX_SPI_MODE_RX_HALFPLEX = 2,
- CVMX_SPI_MODE_DUPLEX = 3
-} cvmx_spi_mode_t;
-
-/** Callbacks structure to customize SPI4 initialization sequence */
-typedef struct {
- /** Called to reset SPI4 DLL */
- int (*reset_cb) (int interface, cvmx_spi_mode_t mode);
-
- /** Called to setup calendar */
- int (*calendar_setup_cb) (int interface, cvmx_spi_mode_t mode,
- int num_ports);
-
- /** Called for Tx and Rx clock detection */
- int (*clock_detect_cb) (int interface, cvmx_spi_mode_t mode,
- int timeout);
-
- /** Called to perform link training */
- int (*training_cb) (int interface, cvmx_spi_mode_t mode, int timeout);
-
- /** Called for calendar data synchronization */
- int (*calendar_sync_cb) (int interface, cvmx_spi_mode_t mode,
- int timeout);
-
- /** Called when interface is up */
- int (*interface_up_cb) (int interface, cvmx_spi_mode_t mode);
-
-} cvmx_spi_callbacks_t;
-
-/**
- * Return true if the supplied interface is configured for SPI
- *
- * @interface: Interface to check
- * Returns True if interface is SPI
- */
-static inline int cvmx_spi_is_spi_interface(int interface)
-{
- uint64_t gmxState = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
- return (gmxState & 0x2) && (gmxState & 0x1);
-}
-
-/**
- * Initialize and start the SPI interface.
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- * @num_ports: Number of SPI ports to configure
- *
- * Returns Zero on success, negative of failure.
- */
-extern int cvmx_spi_start_interface(int interface, cvmx_spi_mode_t mode,
- int timeout, int num_ports);
-
-/**
- * This routine restarts the SPI interface after it has lost synchronization
- * with its corespondant system.
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- * Returns Zero on success, negative of failure.
- */
-extern int cvmx_spi_restart_interface(int interface, cvmx_spi_mode_t mode,
- int timeout);
-
-/**
- * Return non-zero if the SPI interface has a SPI4000 attached
- *
- * @interface: SPI interface the SPI4000 is connected to
- *
- * Returns
- */
-static inline int cvmx_spi4000_is_present(int interface)
-{
- return 0;
-}
-
-/**
- * Initialize the SPI4000 for use
- *
- * @interface: SPI interface the SPI4000 is connected to
- */
-static inline int cvmx_spi4000_initialize(int interface)
-{
- return 0;
-}
-
-/**
- * Poll all the SPI4000 port and check its speed
- *
- * @interface: Interface the SPI4000 is on
- * @port: Port to poll (0-9)
- * Returns Status of the port. 0=down. All other values the port is up.
- */
-static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed(
- int interface,
- int port)
-{
- union cvmx_gmxx_rxx_rx_inbnd r;
- r.u64 = 0;
- return r;
-}
-
-/**
- * Get current SPI4 initialization callbacks
- *
- * @callbacks: Pointer to the callbacks structure.to fill
- *
- * Returns Pointer to cvmx_spi_callbacks_t structure.
- */
-extern void cvmx_spi_get_callbacks(cvmx_spi_callbacks_t *callbacks);
-
-/**
- * Set new SPI4 initialization callbacks
- *
- * @new_callbacks: Pointer to an updated callbacks structure.
- */
-extern void cvmx_spi_set_callbacks(cvmx_spi_callbacks_t *new_callbacks);
-
-/**
- * Callback to perform SPI4 reset
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_reset_cb(int interface, cvmx_spi_mode_t mode);
-
-/**
- * Callback to setup calendar and miscellaneous settings before clock
- * detection
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @num_ports: Number of ports to configure on SPI
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_calendar_setup_cb(int interface, cvmx_spi_mode_t mode,
- int num_ports);
-
-/**
- * Callback to perform clock detection
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for clock synchronization in seconds
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_clock_detect_cb(int interface, cvmx_spi_mode_t mode,
- int timeout);
-
-/**
- * Callback to perform link training
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for link to be trained (in seconds)
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_training_cb(int interface, cvmx_spi_mode_t mode,
- int timeout);
-
-/**
- * Callback to perform calendar data synchronization
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- * @timeout: Timeout to wait for calendar data in seconds
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_calendar_sync_cb(int interface, cvmx_spi_mode_t mode,
- int timeout);
-
-/**
- * Callback to handle interface up
- *
- * @interface: The identifier of the packet interface to configure and
- * use as a SPI interface.
- * @mode: The operating mode for the SPI interface. The interface
- * can operate as a full duplex (both Tx and Rx data paths
- * active) or as a halfplex (either the Tx data path is
- * active or the Rx data path is active, but not both).
- *
- * Returns Zero on success, non-zero error code on failure (will cause
- * SPI initialization to abort)
- */
-extern int cvmx_spi_interface_up_cb(int interface, cvmx_spi_mode_t mode);
-
-#endif /* __CVMX_SPI_H__ */
diff --git a/drivers/staging/octeon/cvmx-spxx-defs.h b/drivers/staging/octeon/cvmx-spxx-defs.h
deleted file mode 100644
index b16940e..0000000
--- a/drivers/staging/octeon/cvmx-spxx-defs.h
+++ /dev/null
@@ -1,347 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_SPXX_DEFS_H__
-#define __CVMX_SPXX_DEFS_H__
-
-#define CVMX_SPXX_BCKPRS_CNT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000340ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_BIST_STAT(block_id) \
- CVMX_ADD_IO_SEG(0x00011800900007F8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_CLK_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000348ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_CLK_STAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000350ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_DBG_DESKEW_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000368ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_DBG_DESKEW_STATE(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000370ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_DRV_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000358ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_ERR_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000320ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_INT_DAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000318ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_INT_MSK(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000308ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_INT_REG(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000300ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_INT_SYNC(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000310ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_TPA_ACC(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000338ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_TPA_MAX(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000330ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_TPA_SEL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000328ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SPXX_TRN4_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000360ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_spxx_bckprs_cnt {
- uint64_t u64;
- struct cvmx_spxx_bckprs_cnt_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_spxx_bckprs_cnt_s cn38xx;
- struct cvmx_spxx_bckprs_cnt_s cn38xxp2;
- struct cvmx_spxx_bckprs_cnt_s cn58xx;
- struct cvmx_spxx_bckprs_cnt_s cn58xxp1;
-};
-
-union cvmx_spxx_bist_stat {
- uint64_t u64;
- struct cvmx_spxx_bist_stat_s {
- uint64_t reserved_3_63:61;
- uint64_t stat2:1;
- uint64_t stat1:1;
- uint64_t stat0:1;
- } s;
- struct cvmx_spxx_bist_stat_s cn38xx;
- struct cvmx_spxx_bist_stat_s cn38xxp2;
- struct cvmx_spxx_bist_stat_s cn58xx;
- struct cvmx_spxx_bist_stat_s cn58xxp1;
-};
-
-union cvmx_spxx_clk_ctl {
- uint64_t u64;
- struct cvmx_spxx_clk_ctl_s {
- uint64_t reserved_17_63:47;
- uint64_t seetrn:1;
- uint64_t reserved_12_15:4;
- uint64_t clkdly:5;
- uint64_t runbist:1;
- uint64_t statdrv:1;
- uint64_t statrcv:1;
- uint64_t sndtrn:1;
- uint64_t drptrn:1;
- uint64_t rcvtrn:1;
- uint64_t srxdlck:1;
- } s;
- struct cvmx_spxx_clk_ctl_s cn38xx;
- struct cvmx_spxx_clk_ctl_s cn38xxp2;
- struct cvmx_spxx_clk_ctl_s cn58xx;
- struct cvmx_spxx_clk_ctl_s cn58xxp1;
-};
-
-union cvmx_spxx_clk_stat {
- uint64_t u64;
- struct cvmx_spxx_clk_stat_s {
- uint64_t reserved_11_63:53;
- uint64_t stxcal:1;
- uint64_t reserved_9_9:1;
- uint64_t srxtrn:1;
- uint64_t s4clk1:1;
- uint64_t s4clk0:1;
- uint64_t d4clk1:1;
- uint64_t d4clk0:1;
- uint64_t reserved_0_3:4;
- } s;
- struct cvmx_spxx_clk_stat_s cn38xx;
- struct cvmx_spxx_clk_stat_s cn38xxp2;
- struct cvmx_spxx_clk_stat_s cn58xx;
- struct cvmx_spxx_clk_stat_s cn58xxp1;
-};
-
-union cvmx_spxx_dbg_deskew_ctl {
- uint64_t u64;
- struct cvmx_spxx_dbg_deskew_ctl_s {
- uint64_t reserved_30_63:34;
- uint64_t fallnop:1;
- uint64_t fall8:1;
- uint64_t reserved_26_27:2;
- uint64_t sstep_go:1;
- uint64_t sstep:1;
- uint64_t reserved_22_23:2;
- uint64_t clrdly:1;
- uint64_t dec:1;
- uint64_t inc:1;
- uint64_t mux:1;
- uint64_t offset:5;
- uint64_t bitsel:5;
- uint64_t offdly:6;
- uint64_t dllfrc:1;
- uint64_t dlldis:1;
- } s;
- struct cvmx_spxx_dbg_deskew_ctl_s cn38xx;
- struct cvmx_spxx_dbg_deskew_ctl_s cn38xxp2;
- struct cvmx_spxx_dbg_deskew_ctl_s cn58xx;
- struct cvmx_spxx_dbg_deskew_ctl_s cn58xxp1;
-};
-
-union cvmx_spxx_dbg_deskew_state {
- uint64_t u64;
- struct cvmx_spxx_dbg_deskew_state_s {
- uint64_t reserved_9_63:55;
- uint64_t testres:1;
- uint64_t unxterm:1;
- uint64_t muxsel:2;
- uint64_t offset:5;
- } s;
- struct cvmx_spxx_dbg_deskew_state_s cn38xx;
- struct cvmx_spxx_dbg_deskew_state_s cn38xxp2;
- struct cvmx_spxx_dbg_deskew_state_s cn58xx;
- struct cvmx_spxx_dbg_deskew_state_s cn58xxp1;
-};
-
-union cvmx_spxx_drv_ctl {
- uint64_t u64;
- struct cvmx_spxx_drv_ctl_s {
- uint64_t reserved_0_63:64;
- } s;
- struct cvmx_spxx_drv_ctl_cn38xx {
- uint64_t reserved_16_63:48;
- uint64_t stx4ncmp:4;
- uint64_t stx4pcmp:4;
- uint64_t srx4cmp:8;
- } cn38xx;
- struct cvmx_spxx_drv_ctl_cn38xx cn38xxp2;
- struct cvmx_spxx_drv_ctl_cn58xx {
- uint64_t reserved_24_63:40;
- uint64_t stx4ncmp:4;
- uint64_t stx4pcmp:4;
- uint64_t reserved_10_15:6;
- uint64_t srx4cmp:10;
- } cn58xx;
- struct cvmx_spxx_drv_ctl_cn58xx cn58xxp1;
-};
-
-union cvmx_spxx_err_ctl {
- uint64_t u64;
- struct cvmx_spxx_err_ctl_s {
- uint64_t reserved_9_63:55;
- uint64_t prtnxa:1;
- uint64_t dipcls:1;
- uint64_t dippay:1;
- uint64_t reserved_4_5:2;
- uint64_t errcnt:4;
- } s;
- struct cvmx_spxx_err_ctl_s cn38xx;
- struct cvmx_spxx_err_ctl_s cn38xxp2;
- struct cvmx_spxx_err_ctl_s cn58xx;
- struct cvmx_spxx_err_ctl_s cn58xxp1;
-};
-
-union cvmx_spxx_int_dat {
- uint64_t u64;
- struct cvmx_spxx_int_dat_s {
- uint64_t reserved_32_63:32;
- uint64_t mul:1;
- uint64_t reserved_14_30:17;
- uint64_t calbnk:2;
- uint64_t rsvop:4;
- uint64_t prt:8;
- } s;
- struct cvmx_spxx_int_dat_s cn38xx;
- struct cvmx_spxx_int_dat_s cn38xxp2;
- struct cvmx_spxx_int_dat_s cn58xx;
- struct cvmx_spxx_int_dat_s cn58xxp1;
-};
-
-union cvmx_spxx_int_msk {
- uint64_t u64;
- struct cvmx_spxx_int_msk_s {
- uint64_t reserved_12_63:52;
- uint64_t calerr:1;
- uint64_t syncerr:1;
- uint64_t diperr:1;
- uint64_t tpaovr:1;
- uint64_t rsverr:1;
- uint64_t drwnng:1;
- uint64_t clserr:1;
- uint64_t spiovr:1;
- uint64_t reserved_2_3:2;
- uint64_t abnorm:1;
- uint64_t prtnxa:1;
- } s;
- struct cvmx_spxx_int_msk_s cn38xx;
- struct cvmx_spxx_int_msk_s cn38xxp2;
- struct cvmx_spxx_int_msk_s cn58xx;
- struct cvmx_spxx_int_msk_s cn58xxp1;
-};
-
-union cvmx_spxx_int_reg {
- uint64_t u64;
- struct cvmx_spxx_int_reg_s {
- uint64_t reserved_32_63:32;
- uint64_t spf:1;
- uint64_t reserved_12_30:19;
- uint64_t calerr:1;
- uint64_t syncerr:1;
- uint64_t diperr:1;
- uint64_t tpaovr:1;
- uint64_t rsverr:1;
- uint64_t drwnng:1;
- uint64_t clserr:1;
- uint64_t spiovr:1;
- uint64_t reserved_2_3:2;
- uint64_t abnorm:1;
- uint64_t prtnxa:1;
- } s;
- struct cvmx_spxx_int_reg_s cn38xx;
- struct cvmx_spxx_int_reg_s cn38xxp2;
- struct cvmx_spxx_int_reg_s cn58xx;
- struct cvmx_spxx_int_reg_s cn58xxp1;
-};
-
-union cvmx_spxx_int_sync {
- uint64_t u64;
- struct cvmx_spxx_int_sync_s {
- uint64_t reserved_12_63:52;
- uint64_t calerr:1;
- uint64_t syncerr:1;
- uint64_t diperr:1;
- uint64_t tpaovr:1;
- uint64_t rsverr:1;
- uint64_t drwnng:1;
- uint64_t clserr:1;
- uint64_t spiovr:1;
- uint64_t reserved_2_3:2;
- uint64_t abnorm:1;
- uint64_t prtnxa:1;
- } s;
- struct cvmx_spxx_int_sync_s cn38xx;
- struct cvmx_spxx_int_sync_s cn38xxp2;
- struct cvmx_spxx_int_sync_s cn58xx;
- struct cvmx_spxx_int_sync_s cn58xxp1;
-};
-
-union cvmx_spxx_tpa_acc {
- uint64_t u64;
- struct cvmx_spxx_tpa_acc_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_spxx_tpa_acc_s cn38xx;
- struct cvmx_spxx_tpa_acc_s cn38xxp2;
- struct cvmx_spxx_tpa_acc_s cn58xx;
- struct cvmx_spxx_tpa_acc_s cn58xxp1;
-};
-
-union cvmx_spxx_tpa_max {
- uint64_t u64;
- struct cvmx_spxx_tpa_max_s {
- uint64_t reserved_32_63:32;
- uint64_t max:32;
- } s;
- struct cvmx_spxx_tpa_max_s cn38xx;
- struct cvmx_spxx_tpa_max_s cn38xxp2;
- struct cvmx_spxx_tpa_max_s cn58xx;
- struct cvmx_spxx_tpa_max_s cn58xxp1;
-};
-
-union cvmx_spxx_tpa_sel {
- uint64_t u64;
- struct cvmx_spxx_tpa_sel_s {
- uint64_t reserved_4_63:60;
- uint64_t prtsel:4;
- } s;
- struct cvmx_spxx_tpa_sel_s cn38xx;
- struct cvmx_spxx_tpa_sel_s cn38xxp2;
- struct cvmx_spxx_tpa_sel_s cn58xx;
- struct cvmx_spxx_tpa_sel_s cn58xxp1;
-};
-
-union cvmx_spxx_trn4_ctl {
- uint64_t u64;
- struct cvmx_spxx_trn4_ctl_s {
- uint64_t reserved_13_63:51;
- uint64_t trntest:1;
- uint64_t jitter:3;
- uint64_t clr_boot:1;
- uint64_t set_boot:1;
- uint64_t maxdist:5;
- uint64_t macro_en:1;
- uint64_t mux_en:1;
- } s;
- struct cvmx_spxx_trn4_ctl_s cn38xx;
- struct cvmx_spxx_trn4_ctl_s cn38xxp2;
- struct cvmx_spxx_trn4_ctl_s cn58xx;
- struct cvmx_spxx_trn4_ctl_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-srxx-defs.h b/drivers/staging/octeon/cvmx-srxx-defs.h
deleted file mode 100644
index d82b366..0000000
--- a/drivers/staging/octeon/cvmx-srxx-defs.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_SRXX_DEFS_H__
-#define __CVMX_SRXX_DEFS_H__
-
-#define CVMX_SRXX_COM_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000200ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SRXX_IGN_RX_FULL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000218ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SRXX_SPI4_CALX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000000ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SRXX_SPI4_STAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000208ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SRXX_SW_TICK_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000220ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_SRXX_SW_TICK_DAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000228ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_srxx_com_ctl {
- uint64_t u64;
- struct cvmx_srxx_com_ctl_s {
- uint64_t reserved_8_63:56;
- uint64_t prts:4;
- uint64_t st_en:1;
- uint64_t reserved_1_2:2;
- uint64_t inf_en:1;
- } s;
- struct cvmx_srxx_com_ctl_s cn38xx;
- struct cvmx_srxx_com_ctl_s cn38xxp2;
- struct cvmx_srxx_com_ctl_s cn58xx;
- struct cvmx_srxx_com_ctl_s cn58xxp1;
-};
-
-union cvmx_srxx_ign_rx_full {
- uint64_t u64;
- struct cvmx_srxx_ign_rx_full_s {
- uint64_t reserved_16_63:48;
- uint64_t ignore:16;
- } s;
- struct cvmx_srxx_ign_rx_full_s cn38xx;
- struct cvmx_srxx_ign_rx_full_s cn38xxp2;
- struct cvmx_srxx_ign_rx_full_s cn58xx;
- struct cvmx_srxx_ign_rx_full_s cn58xxp1;
-};
-
-union cvmx_srxx_spi4_calx {
- uint64_t u64;
- struct cvmx_srxx_spi4_calx_s {
- uint64_t reserved_17_63:47;
- uint64_t oddpar:1;
- uint64_t prt3:4;
- uint64_t prt2:4;
- uint64_t prt1:4;
- uint64_t prt0:4;
- } s;
- struct cvmx_srxx_spi4_calx_s cn38xx;
- struct cvmx_srxx_spi4_calx_s cn38xxp2;
- struct cvmx_srxx_spi4_calx_s cn58xx;
- struct cvmx_srxx_spi4_calx_s cn58xxp1;
-};
-
-union cvmx_srxx_spi4_stat {
- uint64_t u64;
- struct cvmx_srxx_spi4_stat_s {
- uint64_t reserved_16_63:48;
- uint64_t m:8;
- uint64_t reserved_7_7:1;
- uint64_t len:7;
- } s;
- struct cvmx_srxx_spi4_stat_s cn38xx;
- struct cvmx_srxx_spi4_stat_s cn38xxp2;
- struct cvmx_srxx_spi4_stat_s cn58xx;
- struct cvmx_srxx_spi4_stat_s cn58xxp1;
-};
-
-union cvmx_srxx_sw_tick_ctl {
- uint64_t u64;
- struct cvmx_srxx_sw_tick_ctl_s {
- uint64_t reserved_14_63:50;
- uint64_t eop:1;
- uint64_t sop:1;
- uint64_t mod:4;
- uint64_t opc:4;
- uint64_t adr:4;
- } s;
- struct cvmx_srxx_sw_tick_ctl_s cn38xx;
- struct cvmx_srxx_sw_tick_ctl_s cn58xx;
- struct cvmx_srxx_sw_tick_ctl_s cn58xxp1;
-};
-
-union cvmx_srxx_sw_tick_dat {
- uint64_t u64;
- struct cvmx_srxx_sw_tick_dat_s {
- uint64_t dat:64;
- } s;
- struct cvmx_srxx_sw_tick_dat_s cn38xx;
- struct cvmx_srxx_sw_tick_dat_s cn58xx;
- struct cvmx_srxx_sw_tick_dat_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-stxx-defs.h b/drivers/staging/octeon/cvmx-stxx-defs.h
deleted file mode 100644
index 4f209b6..0000000
--- a/drivers/staging/octeon/cvmx-stxx-defs.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_STXX_DEFS_H__
-#define __CVMX_STXX_DEFS_H__
-
-#define CVMX_STXX_ARB_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000608ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_BCKPRS_CNT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000688ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_COM_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000600ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_DIP_CNT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000690ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_IGN_CAL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000610ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_INT_MSK(block_id) \
- CVMX_ADD_IO_SEG(0x00011800900006A0ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_INT_REG(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000698ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_INT_SYNC(block_id) \
- CVMX_ADD_IO_SEG(0x00011800900006A8ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_MIN_BST(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000618ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_SPI4_CALX(offset, block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000400ull + (((offset) & 31) * 8) + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_SPI4_DAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000628ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_SPI4_STAT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000630ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_STAT_BYTES_HI(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000648ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_STAT_BYTES_LO(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000680ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_STAT_CTL(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000638ull + (((block_id) & 1) * 0x8000000ull))
-#define CVMX_STXX_STAT_PKT_XMT(block_id) \
- CVMX_ADD_IO_SEG(0x0001180090000640ull + (((block_id) & 1) * 0x8000000ull))
-
-union cvmx_stxx_arb_ctl {
- uint64_t u64;
- struct cvmx_stxx_arb_ctl_s {
- uint64_t reserved_6_63:58;
- uint64_t mintrn:1;
- uint64_t reserved_4_4:1;
- uint64_t igntpa:1;
- uint64_t reserved_0_2:3;
- } s;
- struct cvmx_stxx_arb_ctl_s cn38xx;
- struct cvmx_stxx_arb_ctl_s cn38xxp2;
- struct cvmx_stxx_arb_ctl_s cn58xx;
- struct cvmx_stxx_arb_ctl_s cn58xxp1;
-};
-
-union cvmx_stxx_bckprs_cnt {
- uint64_t u64;
- struct cvmx_stxx_bckprs_cnt_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_stxx_bckprs_cnt_s cn38xx;
- struct cvmx_stxx_bckprs_cnt_s cn38xxp2;
- struct cvmx_stxx_bckprs_cnt_s cn58xx;
- struct cvmx_stxx_bckprs_cnt_s cn58xxp1;
-};
-
-union cvmx_stxx_com_ctl {
- uint64_t u64;
- struct cvmx_stxx_com_ctl_s {
- uint64_t reserved_4_63:60;
- uint64_t st_en:1;
- uint64_t reserved_1_2:2;
- uint64_t inf_en:1;
- } s;
- struct cvmx_stxx_com_ctl_s cn38xx;
- struct cvmx_stxx_com_ctl_s cn38xxp2;
- struct cvmx_stxx_com_ctl_s cn58xx;
- struct cvmx_stxx_com_ctl_s cn58xxp1;
-};
-
-union cvmx_stxx_dip_cnt {
- uint64_t u64;
- struct cvmx_stxx_dip_cnt_s {
- uint64_t reserved_8_63:56;
- uint64_t frmmax:4;
- uint64_t dipmax:4;
- } s;
- struct cvmx_stxx_dip_cnt_s cn38xx;
- struct cvmx_stxx_dip_cnt_s cn38xxp2;
- struct cvmx_stxx_dip_cnt_s cn58xx;
- struct cvmx_stxx_dip_cnt_s cn58xxp1;
-};
-
-union cvmx_stxx_ign_cal {
- uint64_t u64;
- struct cvmx_stxx_ign_cal_s {
- uint64_t reserved_16_63:48;
- uint64_t igntpa:16;
- } s;
- struct cvmx_stxx_ign_cal_s cn38xx;
- struct cvmx_stxx_ign_cal_s cn38xxp2;
- struct cvmx_stxx_ign_cal_s cn58xx;
- struct cvmx_stxx_ign_cal_s cn58xxp1;
-};
-
-union cvmx_stxx_int_msk {
- uint64_t u64;
- struct cvmx_stxx_int_msk_s {
- uint64_t reserved_8_63:56;
- uint64_t frmerr:1;
- uint64_t unxfrm:1;
- uint64_t nosync:1;
- uint64_t diperr:1;
- uint64_t datovr:1;
- uint64_t ovrbst:1;
- uint64_t calpar1:1;
- uint64_t calpar0:1;
- } s;
- struct cvmx_stxx_int_msk_s cn38xx;
- struct cvmx_stxx_int_msk_s cn38xxp2;
- struct cvmx_stxx_int_msk_s cn58xx;
- struct cvmx_stxx_int_msk_s cn58xxp1;
-};
-
-union cvmx_stxx_int_reg {
- uint64_t u64;
- struct cvmx_stxx_int_reg_s {
- uint64_t reserved_9_63:55;
- uint64_t syncerr:1;
- uint64_t frmerr:1;
- uint64_t unxfrm:1;
- uint64_t nosync:1;
- uint64_t diperr:1;
- uint64_t datovr:1;
- uint64_t ovrbst:1;
- uint64_t calpar1:1;
- uint64_t calpar0:1;
- } s;
- struct cvmx_stxx_int_reg_s cn38xx;
- struct cvmx_stxx_int_reg_s cn38xxp2;
- struct cvmx_stxx_int_reg_s cn58xx;
- struct cvmx_stxx_int_reg_s cn58xxp1;
-};
-
-union cvmx_stxx_int_sync {
- uint64_t u64;
- struct cvmx_stxx_int_sync_s {
- uint64_t reserved_8_63:56;
- uint64_t frmerr:1;
- uint64_t unxfrm:1;
- uint64_t nosync:1;
- uint64_t diperr:1;
- uint64_t datovr:1;
- uint64_t ovrbst:1;
- uint64_t calpar1:1;
- uint64_t calpar0:1;
- } s;
- struct cvmx_stxx_int_sync_s cn38xx;
- struct cvmx_stxx_int_sync_s cn38xxp2;
- struct cvmx_stxx_int_sync_s cn58xx;
- struct cvmx_stxx_int_sync_s cn58xxp1;
-};
-
-union cvmx_stxx_min_bst {
- uint64_t u64;
- struct cvmx_stxx_min_bst_s {
- uint64_t reserved_9_63:55;
- uint64_t minb:9;
- } s;
- struct cvmx_stxx_min_bst_s cn38xx;
- struct cvmx_stxx_min_bst_s cn38xxp2;
- struct cvmx_stxx_min_bst_s cn58xx;
- struct cvmx_stxx_min_bst_s cn58xxp1;
-};
-
-union cvmx_stxx_spi4_calx {
- uint64_t u64;
- struct cvmx_stxx_spi4_calx_s {
- uint64_t reserved_17_63:47;
- uint64_t oddpar:1;
- uint64_t prt3:4;
- uint64_t prt2:4;
- uint64_t prt1:4;
- uint64_t prt0:4;
- } s;
- struct cvmx_stxx_spi4_calx_s cn38xx;
- struct cvmx_stxx_spi4_calx_s cn38xxp2;
- struct cvmx_stxx_spi4_calx_s cn58xx;
- struct cvmx_stxx_spi4_calx_s cn58xxp1;
-};
-
-union cvmx_stxx_spi4_dat {
- uint64_t u64;
- struct cvmx_stxx_spi4_dat_s {
- uint64_t reserved_32_63:32;
- uint64_t alpha:16;
- uint64_t max_t:16;
- } s;
- struct cvmx_stxx_spi4_dat_s cn38xx;
- struct cvmx_stxx_spi4_dat_s cn38xxp2;
- struct cvmx_stxx_spi4_dat_s cn58xx;
- struct cvmx_stxx_spi4_dat_s cn58xxp1;
-};
-
-union cvmx_stxx_spi4_stat {
- uint64_t u64;
- struct cvmx_stxx_spi4_stat_s {
- uint64_t reserved_16_63:48;
- uint64_t m:8;
- uint64_t reserved_7_7:1;
- uint64_t len:7;
- } s;
- struct cvmx_stxx_spi4_stat_s cn38xx;
- struct cvmx_stxx_spi4_stat_s cn38xxp2;
- struct cvmx_stxx_spi4_stat_s cn58xx;
- struct cvmx_stxx_spi4_stat_s cn58xxp1;
-};
-
-union cvmx_stxx_stat_bytes_hi {
- uint64_t u64;
- struct cvmx_stxx_stat_bytes_hi_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_stxx_stat_bytes_hi_s cn38xx;
- struct cvmx_stxx_stat_bytes_hi_s cn38xxp2;
- struct cvmx_stxx_stat_bytes_hi_s cn58xx;
- struct cvmx_stxx_stat_bytes_hi_s cn58xxp1;
-};
-
-union cvmx_stxx_stat_bytes_lo {
- uint64_t u64;
- struct cvmx_stxx_stat_bytes_lo_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_stxx_stat_bytes_lo_s cn38xx;
- struct cvmx_stxx_stat_bytes_lo_s cn38xxp2;
- struct cvmx_stxx_stat_bytes_lo_s cn58xx;
- struct cvmx_stxx_stat_bytes_lo_s cn58xxp1;
-};
-
-union cvmx_stxx_stat_ctl {
- uint64_t u64;
- struct cvmx_stxx_stat_ctl_s {
- uint64_t reserved_5_63:59;
- uint64_t clr:1;
- uint64_t bckprs:4;
- } s;
- struct cvmx_stxx_stat_ctl_s cn38xx;
- struct cvmx_stxx_stat_ctl_s cn38xxp2;
- struct cvmx_stxx_stat_ctl_s cn58xx;
- struct cvmx_stxx_stat_ctl_s cn58xxp1;
-};
-
-union cvmx_stxx_stat_pkt_xmt {
- uint64_t u64;
- struct cvmx_stxx_stat_pkt_xmt_s {
- uint64_t reserved_32_63:32;
- uint64_t cnt:32;
- } s;
- struct cvmx_stxx_stat_pkt_xmt_s cn38xx;
- struct cvmx_stxx_stat_pkt_xmt_s cn38xxp2;
- struct cvmx_stxx_stat_pkt_xmt_s cn58xx;
- struct cvmx_stxx_stat_pkt_xmt_s cn58xxp1;
-};
-
-#endif
diff --git a/drivers/staging/octeon/cvmx-wqe.h b/drivers/staging/octeon/cvmx-wqe.h
deleted file mode 100644
index 6536109..0000000
--- a/drivers/staging/octeon/cvmx-wqe.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2008 Cavium Networks
- *
- * This file 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 file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-/**
- *
- * This header file defines the work queue entry (wqe) data structure.
- * Since this is a commonly used structure that depends on structures
- * from several hardware blocks, those definitions have been placed
- * in this file to create a single point of definition of the wqe
- * format.
- * Data structures are still named according to the block that they
- * relate to.
- *
- */
-
-#ifndef __CVMX_WQE_H__
-#define __CVMX_WQE_H__
-
-#include "cvmx-packet.h"
-
-
-#define OCT_TAG_TYPE_STRING(x) \
- (((x) == CVMX_POW_TAG_TYPE_ORDERED) ? "ORDERED" : \
- (((x) == CVMX_POW_TAG_TYPE_ATOMIC) ? "ATOMIC" : \
- (((x) == CVMX_POW_TAG_TYPE_NULL) ? "NULL" : \
- "NULL_NULL")))
-
-/**
- * HW decode / err_code in work queue entry
- */
-typedef union {
- uint64_t u64;
-
- /* Use this struct if the hardware determines that the packet is IP */
- struct {
- /* HW sets this to the number of buffers used by this packet */
- uint64_t bufs:8;
- /* HW sets to the number of L2 bytes prior to the IP */
- uint64_t ip_offset:8;
- /* set to 1 if we found DSA/VLAN in the L2 */
- uint64_t vlan_valid:1;
- /* Set to 1 if the DSA/VLAN tag is stacked */
- uint64_t vlan_stacked:1;
- uint64_t unassigned:1;
- /* HW sets to the DSA/VLAN CFI flag (valid when vlan_valid) */
- uint64_t vlan_cfi:1;
- /* HW sets to the DSA/VLAN_ID field (valid when vlan_valid) */
- uint64_t vlan_id:12;
- /* Ring Identifier (if PCIe). Requires PIP_GBL_CTL[RING_EN]=1 */
- uint64_t pr:4;
- uint64_t unassigned2:8;
- /* the packet needs to be decompressed */
- uint64_t dec_ipcomp:1;
- /* the packet is either TCP or UDP */
- uint64_t tcp_or_udp:1;
- /* the packet needs to be decrypted (ESP or AH) */
- uint64_t dec_ipsec:1;
- /* the packet is IPv6 */
- uint64_t is_v6:1;
-
- /*
- * (rcv_error, not_IP, IP_exc, is_frag, L4_error,
- * software, etc.).
- */
-
- /*
- * reserved for software use, hardware will clear on
- * packet creation.
- */
- uint64_t software:1;
- /* exceptional conditions below */
- /* the receive interface hardware detected an L4 error
- * (only applies if !is_frag) (only applies if
- * !rcv_error && !not_IP && !IP_exc && !is_frag)
- * failure indicated in err_code below, decode:
- *
- * - 1 = Malformed L4
- * - 2 = L4 Checksum Error: the L4 checksum value is
- * - 3 = UDP Length Error: The UDP length field would
- * make the UDP data longer than what remains in
- * the IP packet (as defined by the IP header
- * length field).
- * - 4 = Bad L4 Port: either the source or destination
- * TCP/UDP port is 0.
- * - 8 = TCP FIN Only: the packet is TCP and only the
- * FIN flag set.
- * - 9 = TCP No Flags: the packet is TCP and no flags
- * are set.
- * - 10 = TCP FIN RST: the packet is TCP and both FIN
- * and RST are set.
- * - 11 = TCP SYN URG: the packet is TCP and both SYN
- * and URG are set.
- * - 12 = TCP SYN RST: the packet is TCP and both SYN
- * and RST are set.
- * - 13 = TCP SYN FIN: the packet is TCP and both SYN
- * and FIN are set.
- */
- uint64_t L4_error:1;
- /* set if the packet is a fragment */
- uint64_t is_frag:1;
- /* the receive interface hardware detected an IP error
- * / exception (only applies if !rcv_error && !not_IP)
- * failure indicated in err_code below, decode:
- *
- * - 1 = Not IP: the IP version field is neither 4 nor
- * 6.
- * - 2 = IPv4 Header Checksum Error: the IPv4 header
- * has a checksum violation.
- * - 3 = IP Malformed Header: the packet is not long
- * enough to contain the IP header.
- * - 4 = IP Malformed: the packet is not long enough
- * to contain the bytes indicated by the IP
- * header. Pad is allowed.
- * - 5 = IP TTL Hop: the IPv4 TTL field or the IPv6
- * Hop Count field are zero.
- * - 6 = IP Options
- */
- uint64_t IP_exc:1;
- /*
- * Set if the hardware determined that the packet is a
- * broadcast.
- */
- uint64_t is_bcast:1;
- /*
- * St if the hardware determined that the packet is a
- * multi-cast.
- */
- uint64_t is_mcast:1;
- /*
- * Set if the packet may not be IP (must be zero in
- * this case).
- */
- uint64_t not_IP:1;
- /*
- * The receive interface hardware detected a receive
- * error (must be zero in this case).
- */
- uint64_t rcv_error:1;
- /* lower err_code = first-level descriptor of the
- * work */
- /* zero for packet submitted by hardware that isn't on
- * the slow path */
- /* type is cvmx_pip_err_t */
- uint64_t err_code:8;
- } s;
-
- /* use this to get at the 16 vlan bits */
- struct {
- uint64_t unused1:16;
- uint64_t vlan:16;
- uint64_t unused2:32;
- } svlan;
-
- /*
- * use this struct if the hardware could not determine that
- * the packet is ip.
- */
- struct {
- /*
- * HW sets this to the number of buffers used by this
- * packet.
- */
- uint64_t bufs:8;
- uint64_t unused:8;
- /* set to 1 if we found DSA/VLAN in the L2 */
- uint64_t vlan_valid:1;
- /* Set to 1 if the DSA/VLAN tag is stacked */
- uint64_t vlan_stacked:1;
- uint64_t unassigned:1;
- /*
- * HW sets to the DSA/VLAN CFI flag (valid when
- * vlan_valid)
- */
- uint64_t vlan_cfi:1;
- /*
- * HW sets to the DSA/VLAN_ID field (valid when
- * vlan_valid).
- */
- uint64_t vlan_id:12;
- /*
- * Ring Identifier (if PCIe). Requires
- * PIP_GBL_CTL[RING_EN]=1
- */
- uint64_t pr:4;
- uint64_t unassigned2:12;
- /*
- * reserved for software use, hardware will clear on
- * packet creation.
- */
- uint64_t software:1;
- uint64_t unassigned3:1;
- /*
- * set if the hardware determined that the packet is
- * rarp.
- */
- uint64_t is_rarp:1;
- /*
- * set if the hardware determined that the packet is
- * arp
- */
- uint64_t is_arp:1;
- /*
- * set if the hardware determined that the packet is a
- * broadcast.
- */
- uint64_t is_bcast:1;
- /*
- * set if the hardware determined that the packet is a
- * multi-cast
- */
- uint64_t is_mcast:1;
- /*
- * set if the packet may not be IP (must be one in
- * this case)
- */
- uint64_t not_IP:1;
- /* The receive interface hardware detected a receive
- * error. Failure indicated in err_code below,
- * decode:
- *
- * - 1 = partial error: a packet was partially
- * received, but internal buffering / bandwidth
- * was not adequate to receive the entire
- * packet.
- * - 2 = jabber error: the RGMII packet was too large
- * and is truncated.
- * - 3 = overrun error: the RGMII packet is longer
- * than allowed and had an FCS error.
- * - 4 = oversize error: the RGMII packet is longer
- * than allowed.
- * - 5 = alignment error: the RGMII packet is not an
- * integer number of bytes
- * and had an FCS error (100M and 10M only).
- * - 6 = fragment error: the RGMII packet is shorter
- * than allowed and had an FCS error.
- * - 7 = GMX FCS error: the RGMII packet had an FCS
- * error.
- * - 8 = undersize error: the RGMII packet is shorter
- * than allowed.
- * - 9 = extend error: the RGMII packet had an extend
- * error.
- * - 10 = length mismatch error: the RGMII packet had
- * a length that did not match the length field
- * in the L2 HDR.
- * - 11 = RGMII RX error/SPI4 DIP4 Error: the RGMII
- * packet had one or more data reception errors
- * (RXERR) or the SPI4 packet had one or more
- * DIP4 errors.
- * - 12 = RGMII skip error/SPI4 Abort Error: the RGMII
- * packet was not large enough to cover the
- * skipped bytes or the SPI4 packet was
- * terminated with an About EOPS.
- * - 13 = RGMII nibble error/SPI4 Port NXA Error: the
- * RGMII packet had a studder error (data not
- * repeated - 10/100M only) or the SPI4 packet
- * was sent to an NXA.
- * - 16 = FCS error: a SPI4.2 packet had an FCS error.
- * - 17 = Skip error: a packet was not large enough to
- * cover the skipped bytes.
- * - 18 = L2 header malformed: the packet is not long
- * enough to contain the L2.
- */
-
- uint64_t rcv_error:1;
- /*
- * lower err_code = first-level descriptor of the
- * work
- */
- /*
- * zero for packet submitted by hardware that isn't on
- * the slow path
- */
- /* type is cvmx_pip_err_t (union, so can't use directly */
- uint64_t err_code:8;
- } snoip;
-
-} cvmx_pip_wqe_word2;
-
-/**
- * Work queue entry format
- *
- * must be 8-byte aligned
- */
-typedef struct {
-
- /*****************************************************************
- * WORD 0
- * HW WRITE: the following 64 bits are filled by HW when a packet arrives
- */
-
- /**
- * raw chksum result generated by the HW
- */
- uint16_t hw_chksum;
- /**
- * Field unused by hardware - available for software
- */
- uint8_t unused;
- /**
- * Next pointer used by hardware for list maintenance.
- * May be written/read by HW before the work queue
- * entry is scheduled to a PP
- * (Only 36 bits used in Octeon 1)
- */
- uint64_t next_ptr:40;
-
- /*****************************************************************
- * WORD 1
- * HW WRITE: the following 64 bits are filled by HW when a packet arrives
- */
-
- /**
- * HW sets to the total number of bytes in the packet
- */
- uint64_t len:16;
- /**
- * HW sets this to input physical port
- */
- uint64_t ipprt:6;
-
- /**
- * HW sets this to what it thought the priority of the input packet was
- */
- uint64_t qos:3;
-
- /**
- * the group that the work queue entry will be scheduled to
- */
- uint64_t grp:4;
- /**
- * the type of the tag (ORDERED, ATOMIC, NULL)
- */
- uint64_t tag_type:3;
- /**
- * the synchronization/ordering tag
- */
- uint64_t tag:32;
-
- /**
- * WORD 2 HW WRITE: the following 64-bits are filled in by
- * hardware when a packet arrives This indicates a variety of
- * status and error conditions.
- */
- cvmx_pip_wqe_word2 word2;
-
- /**
- * Pointer to the first segment of the packet.
- */
- union cvmx_buf_ptr packet_ptr;
-
- /**
- * HW WRITE: octeon will fill in a programmable amount from the
- * packet, up to (at most, but perhaps less) the amount
- * needed to fill the work queue entry to 128 bytes
- *
- * If the packet is recognized to be IP, the hardware starts
- * (except that the IPv4 header is padded for appropriate
- * alignment) writing here where the IP header starts. If the
- * packet is not recognized to be IP, the hardware starts
- * writing the beginning of the packet here.
- */
- uint8_t packet_data[96];
-
- /**
- * If desired, SW can make the work Q entry any length. For the
- * purposes of discussion here, Assume 128B always, as this is all that
- * the hardware deals with.
- *
- */
-
-} CVMX_CACHE_LINE_ALIGNED cvmx_wqe_t;
-
-#endif /* __CVMX_WQE_H__ */
diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h
index 6a2cd50..bdaec8d 100644
--- a/drivers/staging/octeon/ethernet-defines.h
+++ b/drivers/staging/octeon/ethernet-defines.h
@@ -59,7 +59,7 @@
#ifndef __ETHERNET_DEFINES_H__
#define __ETHERNET_DEFINES_H__
-#include "cvmx-config.h"
+#include <asm/octeon/cvmx-config.h>
#define OCTEON_ETHERNET_VERSION "1.9"
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index f18e3e1..63800ba 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -38,9 +38,9 @@
#include "ethernet-mdio.h"
#include "ethernet-util.h"
-#include "cvmx-helper-board.h"
+#include <asm/octeon/cvmx-helper-board.h>
-#include "cvmx-smix-defs.h"
+#include <asm/octeon/cvmx-smix-defs.h>
static void cvm_oct_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c
index 635bb86..78b6cb7 100644
--- a/drivers/staging/octeon/ethernet-mem.c
+++ b/drivers/staging/octeon/ethernet-mem.c
@@ -32,7 +32,7 @@
#include "ethernet-defines.h"
-#include "cvmx-fpa.h"
+#include <asm/octeon/cvmx-fpa.h>
/**
* cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index c3d73f8..d8f5f69 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -37,11 +37,11 @@
#include "octeon-ethernet.h"
#include "ethernet-util.h"
-#include "cvmx-helper.h"
+#include <asm/octeon/cvmx-helper.h>
#include <asm/octeon/cvmx-ipd-defs.h>
#include <asm/octeon/cvmx-npi-defs.h>
-#include "cvmx-gmxx-defs.h"
+#include <asm/octeon/cvmx-gmxx-defs.h>
DEFINE_SPINLOCK(global_register_lock);
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index 8b307b4..400df8c 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -52,14 +52,14 @@
#include "octeon-ethernet.h"
#include "ethernet-util.h"
-#include "cvmx-helper.h"
-#include "cvmx-wqe.h"
-#include "cvmx-fau.h"
-#include "cvmx-pow.h"
-#include "cvmx-pip.h"
-#include "cvmx-scratch.h"
-
-#include "cvmx-gmxx-defs.h"
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-wqe.h>
+#include <asm/octeon/cvmx-fau.h>
+#include <asm/octeon/cvmx-pow.h>
+#include <asm/octeon/cvmx-pip.h>
+#include <asm/octeon/cvmx-scratch.h>
+
+#include <asm/octeon/cvmx-gmxx-defs.h>
struct cvm_napi_wrapper {
struct napi_struct napi;
diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h
index a0743b8..9240c85 100644
--- a/drivers/staging/octeon/ethernet-rx.h
+++ b/drivers/staging/octeon/ethernet-rx.h
@@ -24,7 +24,7 @@
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
*********************************************************************/
-#include "cvmx-fau.h"
+#include <asm/octeon/cvmx-fau.h>
void cvm_oct_poll_controller(struct net_device *dev);
void cvm_oct_rx_initialize(void);
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c
index 5e148b5..d3e8243 100644
--- a/drivers/staging/octeon/ethernet-sgmii.c
+++ b/drivers/staging/octeon/ethernet-sgmii.c
@@ -35,9 +35,9 @@
#include "octeon-ethernet.h"
#include "ethernet-util.h"
-#include "cvmx-helper.h"
+#include <asm/octeon/cvmx-helper.h>
-#include "cvmx-gmxx-defs.h"
+#include <asm/octeon/cvmx-gmxx-defs.h>
int cvm_oct_sgmii_open(struct net_device *dev)
{
diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c
index d0e2d51..af8d628 100644
--- a/drivers/staging/octeon/ethernet-spi.c
+++ b/drivers/staging/octeon/ethernet-spi.c
@@ -35,11 +35,11 @@
#include "octeon-ethernet.h"
#include "ethernet-util.h"
-#include "cvmx-spi.h"
+#include <asm/octeon/cvmx-spi.h>
#include <asm/octeon/cvmx-npi-defs.h>
-#include "cvmx-spxx-defs.h"
-#include "cvmx-stxx-defs.h"
+#include <asm/octeon/cvmx-spxx-defs.h>
+#include <asm/octeon/cvmx-stxx-defs.h>
static int number_spi_ports;
static int need_retrain[2] = { 0, 0 };
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 2542c37..56d74dc 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -47,13 +47,13 @@
#include "ethernet-tx.h"
#include "ethernet-util.h"
-#include "cvmx-wqe.h"
-#include "cvmx-fau.h"
-#include "cvmx-pip.h"
-#include "cvmx-pko.h"
-#include "cvmx-helper.h"
+#include <asm/octeon/cvmx-wqe.h>
+#include <asm/octeon/cvmx-fau.h>
+#include <asm/octeon/cvmx-pip.h>
+#include <asm/octeon/cvmx-pko.h>
+#include <asm/octeon/cvmx-helper.h>
-#include "cvmx-gmxx-defs.h"
+#include <asm/octeon/cvmx-gmxx-defs.h>
#define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb))
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c
index 861a4b3..419f8c3 100644
--- a/drivers/staging/octeon/ethernet-xaui.c
+++ b/drivers/staging/octeon/ethernet-xaui.c
@@ -35,9 +35,9 @@
#include "octeon-ethernet.h"
#include "ethernet-util.h"
-#include "cvmx-helper.h"
+#include <asm/octeon/cvmx-helper.h>
-#include "cvmx-gmxx-defs.h"
+#include <asm/octeon/cvmx-gmxx-defs.h>
int cvm_oct_xaui_open(struct net_device *dev)
{
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 076f866..9112cd8 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -44,14 +44,14 @@
#include "ethernet-mdio.h"
#include "ethernet-util.h"
-#include "cvmx-pip.h"
-#include "cvmx-pko.h"
-#include "cvmx-fau.h"
-#include "cvmx-ipd.h"
-#include "cvmx-helper.h"
-
-#include "cvmx-gmxx-defs.h"
-#include "cvmx-smix-defs.h"
+#include <asm/octeon/cvmx-pip.h>
+#include <asm/octeon/cvmx-pko.h>
+#include <asm/octeon/cvmx-fau.h>
+#include <asm/octeon/cvmx-ipd.h>
+#include <asm/octeon/cvmx-helper.h>
+
+#include <asm/octeon/cvmx-gmxx-defs.h>
+#include <asm/octeon/cvmx-smix-defs.h>
#if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \
&& CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index 02fafec..897a3a99 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -16,7 +16,7 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "v2.00"
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index c44e41a..1c5780f 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -16,7 +16,7 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "v2.14"
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
index 412b879..e66579e 100644
--- a/drivers/staging/speakup/speakup.h
+++ b/drivers/staging/speakup/speakup.h
@@ -116,7 +116,7 @@ extern int bleep_time, bell_pos;
extern int spell_delay, key_echo;
extern short punc_mask;
extern short pitch_shift, synth_flags;
-extern int quiet_boot;
+extern bool quiet_boot;
extern char *synth_name;
extern struct bleep unprocessed_sound;
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index c241074..2222d69 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -22,7 +22,7 @@ static struct spk_synth *synths[MAXSYNTHS];
struct spk_synth *synth;
char pitch_buff[32] = "";
static int module_status;
-int quiet_boot;
+bool quiet_boot;
struct speakup_info_t speakup_info = {
.spinlock = __SPIN_LOCK_UNLOCKED(speakup_info.spinlock),
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 08a449b..f505821 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -41,7 +41,7 @@ static void __exit tsi148_exit(void);
/* Module parameter */
-static int err_chk;
+static bool err_chk;
static int geoid;
static const char driver_name[] = "vme_tsi148";
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 6a1241c..de88aa5 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -118,7 +118,7 @@ static unsigned long board2;
static unsigned long board3;
static unsigned long board4;
static unsigned long controller;
-static int support_low_speed;
+static bool support_low_speed;
static unsigned long modem1;
static unsigned long modem2;
static unsigned long modem3;
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index f32a2ea..aca2386 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1605,4 +1605,27 @@ config SERIAL_XILINX_PS_UART_CONSOLE
help
Enable a Xilinx PS UART port to be the system console.
+config SERIAL_AR933X
+ bool "AR933X serial port support"
+ depends on SOC_AR933X
+ select SERIAL_CORE
+ help
+ If you have an Atheros AR933X SOC based board and want to use the
+ built-in UART of the SoC, say Y to this option.
+
+config SERIAL_AR933X_CONSOLE
+ bool "Console on AR933X serial port"
+ depends on SERIAL_AR933X=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Enable a built-in UART port of the AR933X to be the system console.
+
+config SERIAL_AR933X_NR_UARTS
+ int "Maximum number of AR933X serial ports"
+ depends on SERIAL_AR933X
+ default "2"
+ help
+ Set this to the number of serial ports you want the driver
+ to support.
+
endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 07e0494..f5b01f2 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -91,3 +91,4 @@ obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
+obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6958594..9ae0240 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -268,7 +268,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase + UART01x_DR,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
- .direction = DMA_TO_DEVICE,
+ .direction = DMA_MEM_TO_DEV,
.dst_maxburst = uap->fifosize >> 1,
};
struct dma_chan *chan;
@@ -301,7 +301,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase + UART01x_DR,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
- .direction = DMA_FROM_DEVICE,
+ .direction = DMA_DEV_TO_MEM,
.src_maxburst = uap->fifosize >> 1,
};
@@ -480,7 +480,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
return -EBUSY;
}
- desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE,
+ desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
@@ -676,7 +676,7 @@ static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
dma_dev = rxchan->device;
desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1,
- DMA_FROM_DEVICE,
+ DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
/*
* If the DMA engine is busy and cannot prepare a
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
new file mode 100644
index 0000000..e4f60e2
--- /dev/null
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -0,0 +1,688 @@
+/*
+ * Atheros AR933X SoC built-in UART driver
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * 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/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/mach-ath79/ar933x_uart.h>
+#include <asm/mach-ath79/ar933x_uart_platform.h>
+
+#define DRIVER_NAME "ar933x-uart"
+
+#define AR933X_DUMMY_STATUS_RD 0x01
+
+static struct uart_driver ar933x_uart_driver;
+
+struct ar933x_uart_port {
+ struct uart_port port;
+ unsigned int ier; /* shadow Interrupt Enable Register */
+};
+
+static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
+ int offset)
+{
+ return readl(up->port.membase + offset);
+}
+
+static inline void ar933x_uart_write(struct ar933x_uart_port *up,
+ int offset, unsigned int value)
+{
+ writel(value, up->port.membase + offset);
+}
+
+static inline void ar933x_uart_rmw(struct ar933x_uart_port *up,
+ unsigned int offset,
+ unsigned int mask,
+ unsigned int val)
+{
+ unsigned int t;
+
+ t = ar933x_uart_read(up, offset);
+ t &= ~mask;
+ t |= val;
+ ar933x_uart_write(up, offset, t);
+}
+
+static inline void ar933x_uart_rmw_set(struct ar933x_uart_port *up,
+ unsigned int offset,
+ unsigned int val)
+{
+ ar933x_uart_rmw(up, offset, 0, val);
+}
+
+static inline void ar933x_uart_rmw_clear(struct ar933x_uart_port *up,
+ unsigned int offset,
+ unsigned int val)
+{
+ ar933x_uart_rmw(up, offset, val, 0);
+}
+
+static inline void ar933x_uart_start_tx_interrupt(struct ar933x_uart_port *up)
+{
+ up->ier |= AR933X_UART_INT_TX_EMPTY;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+}
+
+static inline void ar933x_uart_stop_tx_interrupt(struct ar933x_uart_port *up)
+{
+ up->ier &= ~AR933X_UART_INT_TX_EMPTY;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+}
+
+static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)
+{
+ unsigned int rdata;
+
+ rdata = ch & AR933X_UART_DATA_TX_RX_MASK;
+ rdata |= AR933X_UART_DATA_TX_CSR;
+ ar933x_uart_write(up, AR933X_UART_DATA_REG, rdata);
+}
+
+static unsigned int ar933x_uart_tx_empty(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+ unsigned long flags;
+ unsigned int rdata;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return (rdata & AR933X_UART_DATA_TX_CSR) ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int ar933x_uart_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR;
+}
+
+static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static void ar933x_uart_start_tx(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
+ ar933x_uart_start_tx_interrupt(up);
+}
+
+static void ar933x_uart_stop_tx(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
+ ar933x_uart_stop_tx_interrupt(up);
+}
+
+static void ar933x_uart_stop_rx(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
+ up->ier &= ~AR933X_UART_INT_RX_VALID;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+}
+
+static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (break_state == -1)
+ ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_TX_BREAK);
+ else
+ ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_TX_BREAK);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void ar933x_uart_enable_ms(struct uart_port *port)
+{
+}
+
+static void ar933x_uart_set_termios(struct uart_port *port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+ unsigned int cs;
+ unsigned long flags;
+ unsigned int baud, scale;
+
+ /* Only CS8 is supported */
+ new->c_cflag &= ~CSIZE;
+ new->c_cflag |= CS8;
+
+ /* Only one stop bit is supported */
+ new->c_cflag &= ~CSTOPB;
+
+ cs = 0;
+ if (new->c_cflag & PARENB) {
+ if (!(new->c_cflag & PARODD))
+ cs |= AR933X_UART_CS_PARITY_EVEN;
+ else
+ cs |= AR933X_UART_CS_PARITY_ODD;
+ } else {
+ cs |= AR933X_UART_CS_PARITY_NONE;
+ }
+
+ /* Mark/space parity is not supported */
+ new->c_cflag &= ~CMSPAR;
+
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+ scale = (port->uartclk / (16 * baud)) - 1;
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /* Update the per-port timeout. */
+ uart_update_timeout(port, new->c_cflag, baud);
+
+ up->port.ignore_status_mask = 0;
+
+ /* ignore all characters if CREAD is not set */
+ if ((new->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
+
+ ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
+ scale << AR933X_UART_CLOCK_SCALE_S | 8192);
+
+ /* setup configuration register */
+ ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
+
+ /* enable host interrupt */
+ ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_HOST_INT_EN);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ if (tty_termios_baud_rate(new))
+ tty_termios_encode_baud_rate(new, baud, baud);
+}
+
+static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
+{
+ struct tty_struct *tty;
+ int max_count = 256;
+
+ tty = tty_port_tty_get(&up->port.state->port);
+ do {
+ unsigned int rdata;
+ unsigned char ch;
+
+ rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+ if ((rdata & AR933X_UART_DATA_RX_CSR) == 0)
+ break;
+
+ /* remove the character from the FIFO */
+ ar933x_uart_write(up, AR933X_UART_DATA_REG,
+ AR933X_UART_DATA_RX_CSR);
+
+ if (!tty) {
+ /* discard the data if no tty available */
+ continue;
+ }
+
+ up->port.icount.rx++;
+ ch = rdata & AR933X_UART_DATA_TX_RX_MASK;
+
+ if (uart_handle_sysrq_char(&up->port, ch))
+ continue;
+
+ if ((up->port.ignore_status_mask & AR933X_DUMMY_STATUS_RD) == 0)
+ tty_insert_flip_char(tty, ch, TTY_NORMAL);
+ } while (max_count-- > 0);
+
+ if (tty) {
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
+}
+
+static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
+{
+ struct circ_buf *xmit = &up->port.state->xmit;
+ int count;
+
+ if (uart_tx_stopped(&up->port))
+ return;
+
+ count = up->port.fifosize;
+ do {
+ unsigned int rdata;
+
+ rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+ if ((rdata & AR933X_UART_DATA_TX_CSR) == 0)
+ break;
+
+ if (up->port.x_char) {
+ ar933x_uart_putc(up, up->port.x_char);
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ continue;
+ }
+
+ if (uart_circ_empty(xmit))
+ break;
+
+ ar933x_uart_putc(up, xmit->buf[xmit->tail]);
+
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ if (!uart_circ_empty(xmit))
+ ar933x_uart_start_tx_interrupt(up);
+}
+
+static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
+{
+ struct ar933x_uart_port *up = dev_id;
+ unsigned int status;
+
+ status = ar933x_uart_read(up, AR933X_UART_CS_REG);
+ if ((status & AR933X_UART_CS_HOST_INT) == 0)
+ return IRQ_NONE;
+
+ spin_lock(&up->port.lock);
+
+ status = ar933x_uart_read(up, AR933X_UART_INT_REG);
+ status &= ar933x_uart_read(up, AR933X_UART_INT_EN_REG);
+
+ if (status & AR933X_UART_INT_RX_VALID) {
+ ar933x_uart_write(up, AR933X_UART_INT_REG,
+ AR933X_UART_INT_RX_VALID);
+ ar933x_uart_rx_chars(up);
+ }
+
+ if (status & AR933X_UART_INT_TX_EMPTY) {
+ ar933x_uart_write(up, AR933X_UART_INT_REG,
+ AR933X_UART_INT_TX_EMPTY);
+ ar933x_uart_stop_tx_interrupt(up);
+ ar933x_uart_tx_chars(up);
+ }
+
+ spin_unlock(&up->port.lock);
+
+ return IRQ_HANDLED;
+}
+
+static int ar933x_uart_startup(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+ unsigned long flags;
+ int ret;
+
+ ret = request_irq(up->port.irq, ar933x_uart_interrupt,
+ up->port.irqflags, dev_name(up->port.dev), up);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /* Enable HOST interrupts */
+ ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_HOST_INT_EN);
+
+ /* Enable RX interrupts */
+ up->ier = AR933X_UART_INT_RX_VALID;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return 0;
+}
+
+static void ar933x_uart_shutdown(struct uart_port *port)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
+ /* Disable all interrupts */
+ up->ier = 0;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+
+ /* Disable break condition */
+ ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_TX_BREAK);
+
+ free_irq(up->port.irq, up);
+}
+
+static const char *ar933x_uart_type(struct uart_port *port)
+{
+ return (port->type == PORT_AR933X) ? "AR933X UART" : NULL;
+}
+
+static void ar933x_uart_release_port(struct uart_port *port)
+{
+ /* Nothing to release ... */
+}
+
+static int ar933x_uart_request_port(struct uart_port *port)
+{
+ /* UARTs always present */
+ return 0;
+}
+
+static void ar933x_uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_AR933X;
+}
+
+static int ar933x_uart_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (ser->type != PORT_UNKNOWN &&
+ ser->type != PORT_AR933X)
+ return -EINVAL;
+
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ return -EINVAL;
+
+ if (ser->baud_base < 28800)
+ return -EINVAL;
+
+ return 0;
+}
+
+static struct uart_ops ar933x_uart_ops = {
+ .tx_empty = ar933x_uart_tx_empty,
+ .set_mctrl = ar933x_uart_set_mctrl,
+ .get_mctrl = ar933x_uart_get_mctrl,
+ .stop_tx = ar933x_uart_stop_tx,
+ .start_tx = ar933x_uart_start_tx,
+ .stop_rx = ar933x_uart_stop_rx,
+ .enable_ms = ar933x_uart_enable_ms,
+ .break_ctl = ar933x_uart_break_ctl,
+ .startup = ar933x_uart_startup,
+ .shutdown = ar933x_uart_shutdown,
+ .set_termios = ar933x_uart_set_termios,
+ .type = ar933x_uart_type,
+ .release_port = ar933x_uart_release_port,
+ .request_port = ar933x_uart_request_port,
+ .config_port = ar933x_uart_config_port,
+ .verify_port = ar933x_uart_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_AR933X_CONSOLE
+
+static struct ar933x_uart_port *
+ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
+
+static void ar933x_uart_wait_xmitr(struct ar933x_uart_port *up)
+{
+ unsigned int status;
+ unsigned int timeout = 60000;
+
+ /* Wait up to 60ms for the character(s) to be sent. */
+ do {
+ status = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ } while ((status & AR933X_UART_DATA_TX_CSR) == 0);
+}
+
+static void ar933x_uart_console_putchar(struct uart_port *port, int ch)
+{
+ struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
+ ar933x_uart_wait_xmitr(up);
+ ar933x_uart_putc(up, ch);
+}
+
+static void ar933x_uart_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct ar933x_uart_port *up = ar933x_console_ports[co->index];
+ unsigned long flags;
+ unsigned int int_en;
+ int locked = 1;
+
+ local_irq_save(flags);
+
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&up->port.lock);
+ else
+ spin_lock(&up->port.lock);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ int_en = ar933x_uart_read(up, AR933X_UART_INT_EN_REG);
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, 0);
+
+ uart_console_write(&up->port, s, count, ar933x_uart_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ ar933x_uart_wait_xmitr(up);
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, int_en);
+
+ ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+
+ local_irq_restore(flags);
+}
+
+static int ar933x_uart_console_setup(struct console *co, char *options)
+{
+ struct ar933x_uart_port *up;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index < 0 || co->index >= CONFIG_SERIAL_AR933X_NR_UARTS)
+ return -EINVAL;
+
+ up = ar933x_console_ports[co->index];
+ if (!up)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static struct console ar933x_uart_console = {
+ .name = "ttyATH",
+ .write = ar933x_uart_console_write,
+ .device = uart_console_device,
+ .setup = ar933x_uart_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &ar933x_uart_driver,
+};
+
+static void ar933x_uart_add_console_port(struct ar933x_uart_port *up)
+{
+ ar933x_console_ports[up->port.line] = up;
+}
+
+#define AR933X_SERIAL_CONSOLE (&ar933x_uart_console)
+
+#else
+
+static inline void ar933x_uart_add_console_port(struct ar933x_uart_port *up) {}
+
+#define AR933X_SERIAL_CONSOLE NULL
+
+#endif /* CONFIG_SERIAL_AR933X_CONSOLE */
+
+static struct uart_driver ar933x_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = "ttyATH",
+ .nr = CONFIG_SERIAL_AR933X_NR_UARTS,
+ .cons = AR933X_SERIAL_CONSOLE,
+};
+
+static int __devinit ar933x_uart_probe(struct platform_device *pdev)
+{
+ struct ar933x_uart_platform_data *pdata;
+ struct ar933x_uart_port *up;
+ struct uart_port *port;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ int id;
+ int ret;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ id = pdev->id;
+ if (id == -1)
+ id = 0;
+
+ if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
+ return -EINVAL;
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "no MEM resource\n");
+ return -EINVAL;
+ }
+
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq_res) {
+ dev_err(&pdev->dev, "no IRQ resource\n");
+ return -EINVAL;
+ }
+
+ up = kzalloc(sizeof(struct ar933x_uart_port), GFP_KERNEL);
+ if (!up)
+ return -ENOMEM;
+
+ port = &up->port;
+ port->mapbase = mem_res->start;
+
+ port->membase = ioremap(mem_res->start, AR933X_UART_REGS_SIZE);
+ if (!port->membase) {
+ ret = -ENOMEM;
+ goto err_free_up;
+ }
+
+ port->line = id;
+ port->irq = irq_res->start;
+ port->dev = &pdev->dev;
+ port->type = PORT_AR933X;
+ port->iotype = UPIO_MEM32;
+ port->uartclk = pdata->uartclk;
+
+ port->regshift = 2;
+ port->fifosize = AR933X_UART_FIFO_SIZE;
+ port->ops = &ar933x_uart_ops;
+
+ ar933x_uart_add_console_port(up);
+
+ ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
+ if (ret)
+ goto err_unmap;
+
+ platform_set_drvdata(pdev, up);
+ return 0;
+
+err_unmap:
+ iounmap(up->port.membase);
+err_free_up:
+ kfree(up);
+ return ret;
+}
+
+static int __devexit ar933x_uart_remove(struct platform_device *pdev)
+{
+ struct ar933x_uart_port *up;
+
+ up = platform_get_drvdata(pdev);
+ platform_set_drvdata(pdev, NULL);
+
+ if (up) {
+ uart_remove_one_port(&ar933x_uart_driver, &up->port);
+ iounmap(up->port.membase);
+ kfree(up);
+ }
+
+ return 0;
+}
+
+static struct platform_driver ar933x_uart_platform_driver = {
+ .probe = ar933x_uart_probe,
+ .remove = __devexit_p(ar933x_uart_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ar933x_uart_init(void)
+{
+ int ret;
+
+ ar933x_uart_driver.nr = CONFIG_SERIAL_AR933X_NR_UARTS;
+ ret = uart_register_driver(&ar933x_uart_driver);
+ if (ret)
+ goto err_out;
+
+ ret = platform_driver_register(&ar933x_uart_platform_driver);
+ if (ret)
+ goto err_unregister_uart_driver;
+
+ return 0;
+
+err_unregister_uart_driver:
+ uart_unregister_driver(&ar933x_uart_driver);
+err_out:
+ return ret;
+}
+
+static void __exit ar933x_uart_exit(void)
+{
+ platform_driver_unregister(&ar933x_uart_platform_driver);
+ uart_unregister_driver(&ar933x_uart_driver);
+}
+
+module_init(ar933x_uart_init);
+module_exit(ar933x_uart_exit);
+
+MODULE_DESCRIPTION("Atheros AR933X UART driver");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index de0f613..17ae657 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -764,7 +764,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
sg_dma_address(sg) = priv->rx_buf_dma;
desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
- sg, 1, DMA_FROM_DEVICE,
+ sg, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
@@ -923,7 +923,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
}
desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
- priv->sg_tx_p, nent, DMA_TO_DEVICE,
+ priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index aff9d61..7508579 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -50,6 +50,7 @@
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
@@ -73,6 +74,7 @@ struct sci_port {
struct clk *fclk;
char *irqstr[SCIx_NR_IRQS];
+ char *gpiostr[SCIx_NR_FNS];
struct dma_chan *chan_tx;
struct dma_chan *chan_rx;
@@ -474,8 +476,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
if (!reg->size)
return;
- if (!(cflag & CRTSCTS))
- sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
+ if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
+ ((!(cflag & CRTSCTS)))) {
+ unsigned short status;
+
+ status = sci_in(port, SCSPTR);
+ status &= ~SCSPTR_CTSIO;
+ status |= SCSPTR_RTSIO;
+ sci_out(port, SCSPTR, status); /* Set RTS = 1 */
+ }
}
static int sci_txfill(struct uart_port *port)
@@ -621,6 +630,7 @@ static void sci_receive_chars(struct uart_port *port)
} else {
for (i = 0; i < count; i++) {
char c = sci_in(port, SCxRDR);
+
status = sci_in(port, SCxSR);
#if defined(CONFIG_CPU_SH3)
/* Skip "chars" during break */
@@ -649,9 +659,11 @@ static void sci_receive_chars(struct uart_port *port)
/* Store data and status */
if (status & SCxSR_FER(port)) {
flag = TTY_FRAME;
+ port->icount.frame++;
dev_notice(port->dev, "frame error\n");
} else if (status & SCxSR_PER(port)) {
flag = TTY_PARITY;
+ port->icount.parity++;
dev_notice(port->dev, "parity error\n");
} else
flag = TTY_NORMAL;
@@ -723,6 +735,8 @@ static int sci_handle_errors(struct uart_port *port)
*/
if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
if (status & (1 << s->cfg->overrun_bit)) {
+ port->icount.overrun++;
+
/* overrun error */
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
copied++;
@@ -737,6 +751,8 @@ static int sci_handle_errors(struct uart_port *port)
struct sci_port *sci_port = to_sci_port(port);
if (!sci_port->break_flag) {
+ port->icount.brk++;
+
sci_port->break_flag = 1;
sci_schedule_break_timer(sci_port);
@@ -752,6 +768,8 @@ static int sci_handle_errors(struct uart_port *port)
} else {
/* frame error */
+ port->icount.frame++;
+
if (tty_insert_flip_char(tty, 0, TTY_FRAME))
copied++;
@@ -761,6 +779,8 @@ static int sci_handle_errors(struct uart_port *port)
if (status & SCxSR_PER(port)) {
/* parity error */
+ port->icount.parity++;
+
if (tty_insert_flip_char(tty, 0, TTY_PARITY))
copied++;
@@ -787,6 +807,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
sci_out(port, SCLSR, 0);
+ port->icount.overrun++;
+
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
tty_flip_buffer_push(tty);
@@ -812,6 +834,9 @@ static int sci_handle_breaks(struct uart_port *port)
/* Debounce break */
s->break_flag = 1;
#endif
+
+ port->icount.brk++;
+
/* Notify of BREAK */
if (tty_insert_flip_char(tty, 0, TTY_BREAK))
copied++;
@@ -1082,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port)
}
}
+static const char *sci_gpio_names[SCIx_NR_FNS] = {
+ "sck", "rxd", "txd", "cts", "rts",
+};
+
+static const char *sci_gpio_str(unsigned int index)
+{
+ return sci_gpio_names[index];
+}
+
+static void __devinit sci_init_gpios(struct sci_port *port)
+{
+ struct uart_port *up = &port->port;
+ int i;
+
+ if (!port->cfg)
+ return;
+
+ for (i = 0; i < SCIx_NR_FNS; i++) {
+ const char *desc;
+ int ret;
+
+ if (!port->cfg->gpios[i])
+ continue;
+
+ desc = sci_gpio_str(i);
+
+ port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s",
+ dev_name(up->dev), desc);
+
+ /*
+ * If we've failed the allocation, we can still continue
+ * on with a NULL string.
+ */
+ if (!port->gpiostr[i])
+ dev_notice(up->dev, "%s string allocation failure\n",
+ desc);
+
+ ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]);
+ if (unlikely(ret != 0)) {
+ dev_notice(up->dev, "failed %s gpio request\n", desc);
+
+ /*
+ * If we can't get the GPIO for whatever reason,
+ * no point in keeping the verbose string around.
+ */
+ kfree(port->gpiostr[i]);
+ }
+ }
+}
+
+static void sci_free_gpios(struct sci_port *port)
+{
+ int i;
+
+ for (i = 0; i < SCIx_NR_FNS; i++)
+ if (port->cfg->gpios[i]) {
+ gpio_free(port->cfg->gpios[i]);
+ kfree(port->gpiostr[i]);
+ }
+}
+
static unsigned int sci_tx_empty(struct uart_port *port)
{
unsigned short status = sci_in(port, SCxSR);
@@ -1090,19 +1176,39 @@ static unsigned int sci_tx_empty(struct uart_port *port)
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
+/*
+ * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
+ * CTS/RTS is supported in hardware by at least one port and controlled
+ * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
+ * handled via the ->init_pins() op, which is a bit of a one-way street,
+ * lacking any ability to defer pin control -- this will later be
+ * converted over to the GPIO framework).
+ *
+ * Other modes (such as loopback) are supported generically on certain
+ * port types, but not others. For these it's sufficient to test for the
+ * existence of the support register and simply ignore the port type.
+ */
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
- /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
- /* If you have signals for DTR and DCD, please implement here. */
+ if (mctrl & TIOCM_LOOP) {
+ struct plat_sci_reg *reg;
+
+ /*
+ * Standard loopback mode for SCFCR ports.
+ */
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
+ sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
+ }
}
static unsigned int sci_get_mctrl(struct uart_port *port)
{
- /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
- and CTS/RTS */
-
- return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
+ /*
+ * CTS/RTS is handled in hardware when supported, while nothing
+ * else is wired up. Keep it simple and simply assert DSR/CAR.
+ */
+ return TIOCM_DSR | TIOCM_CAR;
}
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1233,7 +1339,7 @@ static void sci_submit_rx(struct sci_port *s)
struct dma_async_tx_descriptor *desc;
desc = chan->device->device_prep_slave_sg(chan,
- sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
+ sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (desc) {
s->desc_rx[i] = desc;
@@ -1348,7 +1454,7 @@ static void work_fn_tx(struct work_struct *work)
BUG_ON(!sg_dma_len(sg));
desc = chan->device->device_prep_slave_sg(chan,
- sg, s->sg_len_tx, DMA_TO_DEVICE,
+ sg, s->sg_len_tx, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
/* switch to PIO */
@@ -1449,12 +1555,17 @@ static void sci_stop_rx(struct uart_port *port)
static void sci_enable_ms(struct uart_port *port)
{
- /* Nothing here yet .. */
+ /*
+ * Not supported by hardware, always a nop.
+ */
}
static void sci_break_ctl(struct uart_port *port, int break_state)
{
- /* Nothing here yet .. */
+ /*
+ * Not supported by hardware. Most parts couple break and rx
+ * interrupts together, with break detection always enabled.
+ */
}
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1652,6 +1763,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
static void sci_reset(struct uart_port *port)
{
+ struct plat_sci_reg *reg;
unsigned int status;
do {
@@ -1660,7 +1772,8 @@ static void sci_reset(struct uart_port *port)
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
- if (port->type != PORT_SCI)
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
}
@@ -1668,9 +1781,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct sci_port *s = to_sci_port(port);
+ struct plat_sci_reg *reg;
unsigned int baud, smr_val, max_baud;
int t = -1;
- u16 scfcr = 0;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
@@ -1720,7 +1833,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
}
sci_init_pins(port, termios->c_cflag);
- sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
+
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size) {
+ unsigned short ctrl = sci_in(port, SCFCR);
+
+ if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
+ if (termios->c_cflag & CRTSCTS)
+ ctrl |= SCFCR_MCE;
+ else
+ ctrl &= ~SCFCR_MCE;
+ }
+
+ /*
+ * As we've done a sci_reset() above, ensure we don't
+ * interfere with the FIFOs while toggling MCE. As the
+ * reset values could still be set, simply mask them out.
+ */
+ ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
+
+ sci_out(port, SCFCR, ctrl);
+ }
sci_out(port, SCSCR, s->cfg->scscr);
@@ -1892,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
struct uart_port *port = &sci_port->port;
int ret;
+ sci_port->cfg = p;
+
port->ops = &sci_uart_ops;
port->iotype = UPIO_MEM;
port->line = index;
@@ -1937,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
port->dev = &dev->dev;
+ sci_init_gpios(sci_port);
+
pm_runtime_irq_safe(&dev->dev);
pm_runtime_enable(&dev->dev);
}
@@ -1971,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
p->error_mask |= (1 << p->overrun_bit);
}
- sci_port->cfg = p;
-
port->mapbase = p->mapbase;
port->type = p->type;
port->flags = p->flags;
@@ -2113,9 +2248,16 @@ static int sci_runtime_suspend(struct device *dev)
struct uart_port *port = &sci_port->port;
if (uart_console(port)) {
+ struct plat_sci_reg *reg;
+
sci_port->saved_smr = sci_in(port, SCSMR);
sci_port->saved_brr = sci_in(port, SCBRR);
- sci_port->saved_fcr = sci_in(port, SCFCR);
+
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
+ sci_port->saved_fcr = sci_in(port, SCFCR);
+ else
+ sci_port->saved_fcr = 0;
}
return 0;
}
@@ -2129,7 +2271,10 @@ static int sci_runtime_resume(struct device *dev)
sci_reset(port);
sci_out(port, SCSMR, sci_port->saved_smr);
sci_out(port, SCBRR, sci_port->saved_brr);
- sci_out(port, SCFCR, sci_port->saved_fcr);
+
+ if (sci_port->saved_fcr)
+ sci_out(port, SCFCR, sci_port->saved_fcr);
+
sci_out(port, SCSCR, sci_port->cfg->scscr);
}
return 0;
@@ -2169,6 +2314,8 @@ static int sci_remove(struct platform_device *dev)
cpufreq_unregister_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
+ sci_free_gpios(port);
+
uart_remove_one_port(&sci_uart_driver, &port->port);
clk_put(port->iclk);
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index e9bed03..a1a2d36 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -17,7 +17,9 @@
defined(CONFIG_ARCH_SH73A0) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
+ defined(CONFIG_ARCH_SH7372) || \
+ defined(CONFIG_ARCH_R8A7740)
+
# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index e67fb20..ff8017f 100644
--- a/drivers/tty/synclink.c
+++ b/drivers/tty/synclink.c
@@ -850,7 +850,7 @@ static int mgsl_device_count;
* .text section address and breakpoint on module load.
* This is useful for use with gdb and add-symbol-file command.
*/
-static int break_on_load;
+static bool break_on_load;
/*
* Driver major number, defaults to zero to get auto
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
index 0f6b796..a7efe53 100644
--- a/drivers/tty/synclinkmp.c
+++ b/drivers/tty/synclinkmp.c
@@ -456,7 +456,7 @@ static int synclinkmp_device_count = 0;
* .text section address and breakpoint on module load.
* This is useful for use with gdb and add-symbol-file command.
*/
-static int break_on_load = 0;
+static bool break_on_load = 0;
/*
* Driver major number, defaults to zero to get auto
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 02bd47b..0bd08ef 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -45,77 +45,12 @@ to_uio_pci_generic_dev(struct uio_info *info)
static irqreturn_t irqhandler(int irq, struct uio_info *info)
{
struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
- struct pci_dev *pdev = gdev->pdev;
- irqreturn_t ret = IRQ_NONE;
- u32 cmd_status_dword;
- u16 origcmd, newcmd, status;
-
- /* We do a single dword read to retrieve both command and status.
- * Document assumptions that make this possible. */
- BUILD_BUG_ON(PCI_COMMAND % 4);
- BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
-
- pci_block_user_cfg_access(pdev);
-
- /* Read both command and status registers in a single 32-bit operation.
- * Note: we could cache the value for command and move the status read
- * out of the lock if there was a way to get notified of user changes
- * to command register through sysfs. Should be good for shared irqs. */
- pci_read_config_dword(pdev, PCI_COMMAND, &cmd_status_dword);
- origcmd = cmd_status_dword;
- status = cmd_status_dword >> 16;
-
- /* Check interrupt status register to see whether our device
- * triggered the interrupt. */
- if (!(status & PCI_STATUS_INTERRUPT))
- goto done;
-
- /* We triggered the interrupt, disable it. */
- newcmd = origcmd | PCI_COMMAND_INTX_DISABLE;
- if (newcmd != origcmd)
- pci_write_config_word(pdev, PCI_COMMAND, newcmd);
- /* UIO core will signal the user process. */
- ret = IRQ_HANDLED;
-done:
-
- pci_unblock_user_cfg_access(pdev);
- return ret;
-}
+ if (!pci_check_and_mask_intx(gdev->pdev))
+ return IRQ_NONE;
-/* Verify that the device supports Interrupt Disable bit in command register,
- * per PCI 2.3, by flipping this bit and reading it back: this bit was readonly
- * in PCI 2.2. */
-static int __devinit verify_pci_2_3(struct pci_dev *pdev)
-{
- u16 orig, new;
- int err = 0;
-
- pci_block_user_cfg_access(pdev);
- pci_read_config_word(pdev, PCI_COMMAND, &orig);
- pci_write_config_word(pdev, PCI_COMMAND,
- orig ^ PCI_COMMAND_INTX_DISABLE);
- pci_read_config_word(pdev, PCI_COMMAND, &new);
- /* There's no way to protect against
- * hardware bugs or detect them reliably, but as long as we know
- * what the value should be, let's go ahead and check it. */
- if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
- err = -EBUSY;
- dev_err(&pdev->dev, "Command changed from 0x%x to 0x%x: "
- "driver or HW bug?\n", orig, new);
- goto err;
- }
- if (!((new ^ orig) & PCI_COMMAND_INTX_DISABLE)) {
- dev_warn(&pdev->dev, "Device does not support "
- "disabling interrupts: unable to bind.\n");
- err = -ENODEV;
- goto err;
- }
- /* Now restore the original value. */
- pci_write_config_word(pdev, PCI_COMMAND, orig);
-err:
- pci_unblock_user_cfg_access(pdev);
- return err;
+ /* UIO core will signal the user process. */
+ return IRQ_HANDLED;
}
static int __devinit probe(struct pci_dev *pdev,
@@ -138,9 +73,10 @@ static int __devinit probe(struct pci_dev *pdev,
return -ENODEV;
}
- err = verify_pci_2_3(pdev);
- if (err)
+ if (!pci_intx_mask_supported(pdev)) {
+ err = -ENODEV;
goto err_verify;
+ }
gdev = kzalloc(sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
if (!gdev) {
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index b42092e..98dd9e4 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -73,9 +73,9 @@ static const char speedtch_driver_name[] = "speedtch";
#define DEFAULT_SW_BUFFERING 0
static unsigned int altsetting = 0; /* zero means: use the default */
-static int dl_512_first = DEFAULT_DL_512_FIRST;
-static int enable_isoc = DEFAULT_ENABLE_ISOC;
-static int sw_buffering = DEFAULT_SW_BUFFERING;
+static bool dl_512_first = DEFAULT_DL_512_FIRST;
+static bool enable_isoc = DEFAULT_ENABLE_ISOC;
+static bool sw_buffering = DEFAULT_SW_BUFFERING;
#define DEFAULT_B_MAX_DSL 8128
#define DEFAULT_MODEM_MODE 11
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 00f171a..01ea5d7 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -542,7 +542,7 @@ static int modem_index;
static unsigned int debug;
static unsigned int altsetting[NB_MODEM] = {
[0 ... (NB_MODEM - 1)] = FASTEST_ISO_INTF};
-static int sync_wait[NB_MODEM];
+static bool sync_wait[NB_MODEM];
static char *cmv_file[NB_MODEM];
static int annex[NB_MODEM];
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3af5e2d..8df4b76 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -93,7 +93,7 @@ struct async {
u8 bulk_status;
};
-static int usbfs_snoop;
+static bool usbfs_snoop;
module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 79d339e..a0613d8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -102,7 +102,7 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task;
/* cycle leds on hubs that aren't blinking for attention */
-static int blinkenlights = 0;
+static bool blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO);
MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");
@@ -131,12 +131,12 @@ MODULE_PARM_DESC(initial_descriptor_timeout,
* otherwise the new scheme is used. If that fails and "use_both_schemes"
* is set, then the driver will make another attempt, using the other scheme.
*/
-static int old_scheme_first = 0;
+static bool old_scheme_first = 0;
module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(old_scheme_first,
"start with the old device initialization scheme");
-static int use_both_schemes = 1;
+static bool use_both_schemes = 1;
module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(use_both_schemes,
"try the other device initialization scheme if the "
@@ -2026,7 +2026,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
#define SET_ADDRESS_TRIES 2
#define GET_DESCRIPTOR_TRIES 2
#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1))
-#define USE_NEW_SCHEME(i) ((i) / 2 == old_scheme_first)
+#define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first)
#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
#define HUB_SHORT_RESET_TIME 10
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 1382c90..8ca9f99 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -47,7 +47,7 @@
const char *usbcore_name = "usbcore";
-static int nousb; /* Disable USB when built into kernel image */
+static bool nousb; /* Disable USB when built into kernel image */
#ifdef CONFIG_USB_SUSPEND
static int usb_autosuspend_delay = 2; /* Default delay value,
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index e9a2c5c..c16ff55 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -152,15 +152,15 @@ static const char *ep_string[] = {
};
/* DMA usage flag */
-static int use_dma = 1;
+static bool use_dma = 1;
/* packet per buffer dma */
-static int use_dma_ppb = 1;
+static bool use_dma_ppb = 1;
/* with per descr. update */
-static int use_dma_ppb_du;
+static bool use_dma_ppb_du;
/* buffer fill mode */
static int use_dma_bufferfill_mode;
/* full speed only mode */
-static int use_fullspeed;
+static bool use_fullspeed;
/* tx buffer size for high speed */
static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 0cd764d..a28f6ff 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -250,9 +250,9 @@ static struct usb_configuration rndis_config_driver = {
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_ETH_EEM
-static int use_eem = 1;
+static bool use_eem = 1;
#else
-static int use_eem;
+static bool use_eem;
#endif
module_param(use_eem, bool, 0);
MODULE_PARM_DESC(use_eem, "use CDC EEM mode");
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index e0f30fc..47766f0 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -303,16 +303,16 @@ MODULE_LICENSE("Dual BSD/GPL");
static struct {
char *file[FSG_MAX_LUNS];
char *serial;
- int ro[FSG_MAX_LUNS];
- int nofua[FSG_MAX_LUNS];
+ bool ro[FSG_MAX_LUNS];
+ bool nofua[FSG_MAX_LUNS];
unsigned int num_filenames;
unsigned int num_ros;
unsigned int num_nofuas;
unsigned int nluns;
- int removable;
- int can_stall;
- int cdrom;
+ bool removable;
+ bool can_stall;
+ bool cdrom;
char *transport_parm;
char *protocol_parm;
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c
index 4c81d54..7322d29 100644
--- a/drivers/usb/gadget/net2272.c
+++ b/drivers/usb/gadget/net2272.c
@@ -69,7 +69,7 @@ static const char * const ep_name[] = {
*
* If use_dma is disabled, pio will be used instead.
*/
-static int use_dma = 0;
+static bool use_dma = 0;
module_param(use_dma, bool, 0644);
/*
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index cf1f364..cdedd13 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -90,8 +90,8 @@ static const char *const ep_name [] = {
* Some gadget drivers work better with the dma support here than others.
* These two parameters let you use PIO or more aggressive DMA.
*/
-static int use_dma = 1;
-static int use_dma_chaining = 0;
+static bool use_dma = 1;
+static bool use_dma_chaining = 0;
/* "modprobe net2280 use_dma=n" etc */
module_param (use_dma, bool, S_IRUGO);
@@ -112,7 +112,7 @@ module_param (fifo_mode, ushort, 0644);
* USB suspend requests will be ignored. This is acceptable for
* self-powered devices
*/
-static int enable_suspend = 0;
+static bool enable_suspend = 0;
/* "modprobe net2280 enable_suspend=1" etc */
module_param (enable_suspend, bool, S_IRUGO);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 7db5bbe..576cd85 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -98,7 +98,7 @@ module_param (fifo_mode, uint, 0);
MODULE_PARM_DESC (fifo_mode, "endpoint configuration");
#ifdef USE_DMA
-static unsigned use_dma = 1;
+static bool use_dma = 1;
/* "modprobe omap_udc use_dma=y", or else as a kernel
* boot parameter "omap_udc:use_dma=y"
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index dd2313c..a3fcaae 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -359,7 +359,7 @@ struct pch_udc_dev {
static const char ep0_string[] = "ep0in";
static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */
struct pch_udc_dev *pch_udc; /* pointer to device object */
-static int speed_fs;
+static bool speed_fs;
module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index ed1b816..ad9e5b2 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -123,11 +123,11 @@ MODULE_AUTHOR("Al Borchers");
MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
-static int use_acm = true;
+static bool use_acm = true;
module_param(use_acm, bool, 0);
MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
-static int use_obex = false;
+static bool use_obex = false;
module_param(use_obex, bool, 0);
MODULE_PARM_DESC(use_obex, "Use CDC OBEX, default=no");
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 20697cc..31d3483 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -81,7 +81,7 @@ module_param(buflen, uint, 0);
* work better with hosts where config changes are problematic or
* controllers (like original superh) that only support one config.
*/
-static int loopdefault = 0;
+static bool loopdefault = 0;
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 4c0c973..91413ca 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -219,7 +219,7 @@ config USB_CNS3XXX_EHCI
config USB_EHCI_ATH79
bool "EHCI support for AR7XXX/AR9XXX SoCs"
- depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X)
+ depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
select USB_EHCI_ROOT_HUB_TT
default y
---help---
diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c
index b4192c9..936af83 100644
--- a/drivers/usb/host/alchemy-common.c
+++ b/drivers/usb/host/alchemy-common.c
@@ -52,9 +52,263 @@
USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \
USBCFG_OME)
+/* Au1300 USB config registers */
+#define USB_DWC_CTRL1 0x00
+#define USB_DWC_CTRL2 0x04
+#define USB_VBUS_TIMER 0x10
+#define USB_SBUS_CTRL 0x14
+#define USB_MSR_ERR 0x18
+#define USB_DWC_CTRL3 0x1C
+#define USB_DWC_CTRL4 0x20
+#define USB_OTG_STATUS 0x28
+#define USB_DWC_CTRL5 0x2C
+#define USB_DWC_CTRL6 0x30
+#define USB_DWC_CTRL7 0x34
+#define USB_PHY_STATUS 0xC0
+#define USB_INT_STATUS 0xC4
+#define USB_INT_ENABLE 0xC8
+
+#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */
+#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */
+#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */
+
+#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */
+#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */
+#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */
+
+#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19)
+#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18)
+#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17)
+#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16)
+
+#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */
+
+#define USB_INTEN_FORCE 0x20
+#define USB_INTEN_PHY 0x10
+#define USB_INTEN_UDC 0x08
+#define USB_INTEN_EHCI 0x04
+#define USB_INTEN_OHCI1 0x02
+#define USB_INTEN_OHCI0 0x01
static DEFINE_SPINLOCK(alchemy_usb_lock);
+static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
+{
+ unsigned long r, s;
+
+ r = __raw_readl(base + USB_DWC_CTRL2);
+ s = __raw_readl(base + USB_DWC_CTRL3);
+
+ s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
+ USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
+
+ if (enable) {
+ /* simply enable all PHYs */
+ r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+ USB_DWC_CTRL2_PHYRS;
+ __raw_writel(r, base + USB_DWC_CTRL2);
+ wmb();
+ } else if (!s) {
+ /* no USB block active, do disable all PHYs */
+ r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
+ USB_DWC_CTRL2_PHYRS);
+ __raw_writel(r, base + USB_DWC_CTRL2);
+ wmb();
+ }
+}
+
+static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
+{
+ unsigned long r;
+
+ if (enable) {
+ __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */
+ r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+ : USB_DWC_CTRL3_OHCI1_CKEN;
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable); /* power up the PHYs */
+
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+
+ /* reset the OHCI start clock bit */
+ __raw_writel(0, base + USB_DWC_CTRL7);
+ wmb();
+ } else {
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL3);
+ r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
+ : USB_DWC_CTRL3_OHCI1_CKEN);
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+ }
+}
+
+static inline void __au1300_ehci_control(void __iomem *base, int enable)
+{
+ unsigned long r;
+
+ if (enable) {
+ r = __raw_readl(base + USB_DWC_CTRL3);
+ r |= USB_DWC_CTRL3_EHCI0_CKEN;
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r |= USB_DWC_CTRL1_HSTRS;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r |= USB_INTEN_EHCI;
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+ } else {
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r &= ~USB_INTEN_EHCI;
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r &= ~USB_DWC_CTRL1_HSTRS;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL3);
+ r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+ }
+}
+
+static inline void __au1300_udc_control(void __iomem *base, int enable)
+{
+ unsigned long r;
+
+ if (enable) {
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r |= USB_DWC_CTRL1_DCRS;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r |= USB_INTEN_UDC;
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+ } else {
+ r = __raw_readl(base + USB_INT_ENABLE);
+ r &= ~USB_INTEN_UDC;
+ __raw_writel(r, base + USB_INT_ENABLE);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r &= ~USB_DWC_CTRL1_DCRS;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+ }
+}
+
+static inline void __au1300_otg_control(void __iomem *base, int enable)
+{
+ unsigned long r;
+ if (enable) {
+ r = __raw_readl(base + USB_DWC_CTRL3);
+ r |= USB_DWC_CTRL3_OTG0_CKEN;
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r &= ~USB_DWC_CTRL1_OTGD;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+ } else {
+ r = __raw_readl(base + USB_DWC_CTRL1);
+ r |= USB_DWC_CTRL1_OTGD;
+ __raw_writel(r, base + USB_DWC_CTRL1);
+ wmb();
+
+ r = __raw_readl(base + USB_DWC_CTRL3);
+ r &= ~USB_DWC_CTRL3_OTG0_CKEN;
+ __raw_writel(r, base + USB_DWC_CTRL3);
+ wmb();
+
+ __au1300_usb_phyctl(base, enable);
+ }
+}
+
+static inline int au1300_usb_control(int block, int enable)
+{
+ void __iomem *base =
+ (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+ int ret = 0;
+
+ switch (block) {
+ case ALCHEMY_USB_OHCI0:
+ __au1300_ohci_control(base, enable, 0);
+ break;
+ case ALCHEMY_USB_OHCI1:
+ __au1300_ohci_control(base, enable, 1);
+ break;
+ case ALCHEMY_USB_EHCI0:
+ __au1300_ehci_control(base, enable);
+ break;
+ case ALCHEMY_USB_UDC0:
+ __au1300_udc_control(base, enable);
+ break;
+ case ALCHEMY_USB_OTG0:
+ __au1300_otg_control(base, enable);
+ break;
+ default:
+ ret = -ENODEV;
+ }
+ return ret;
+}
+
+static inline void au1300_usb_init(void)
+{
+ void __iomem *base =
+ (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+
+ /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4
+ * here at all: Port 2 routing (EHCI or UDC) must be set either
+ * by boot firmware or platform init code; I can't autodetect
+ * a sane setting.
+ */
+ __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
+ wmb();
+ __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
+ wmb();
+ __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
+ wmb();
+ __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
+ wmb();
+ /* set coherent access bit */
+ __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
+ wmb();
+}
static inline void __au1200_ohci_control(void __iomem *base, int enable)
{
@@ -233,6 +487,9 @@ int alchemy_usb_control(int block, int enable)
case ALCHEMY_CPU_AU1200:
ret = au1200_usb_control(block, enable);
break;
+ case ALCHEMY_CPU_AU1300:
+ ret = au1300_usb_control(block, enable);
+ break;
default:
ret = -ENODEV;
}
@@ -281,6 +538,20 @@ static void au1200_usb_pm(int susp)
}
}
+static void au1300_usb_pm(int susp)
+{
+ void __iomem *base =
+ (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
+ /* remember Port2 routing */
+ if (susp) {
+ alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
+ } else {
+ au1300_usb_init();
+ __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
+ wmb();
+ }
+}
+
static void alchemy_usb_pm(int susp)
{
switch (alchemy_get_cputype()) {
@@ -295,6 +566,9 @@ static void alchemy_usb_pm(int susp)
case ALCHEMY_CPU_AU1200:
au1200_usb_pm(susp);
break;
+ case ALCHEMY_CPU_AU1300:
+ au1300_usb_pm(susp);
+ break;
}
}
@@ -328,6 +602,9 @@ static int __init alchemy_usb_init(void)
case ALCHEMY_CPU_AU1200:
au1200_usb_init();
break;
+ case ALCHEMY_CPU_AU1300:
+ au1300_usb_init();
+ break;
}
register_syscore_ops(&alchemy_usb_pm_ops);
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
index afb6743..f1424f9 100644
--- a/drivers/usb/host/ehci-ath79.c
+++ b/drivers/usb/host/ehci-ath79.c
@@ -33,6 +33,10 @@ static const struct platform_device_id ehci_ath79_id_table[] = {
.driver_data = EHCI_ATH79_IP_V2,
},
{
+ .name = "ar933x-ehci",
+ .driver_data = EHCI_ATH79_IP_V2,
+ },
+ {
/* terminating entry */
},
};
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e311a51..a007a9f 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -112,7 +112,7 @@ module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
/* for flakey hardware, ignore overcurrent indicators */
-static int ignore_oc = 0;
+static bool ignore_oc = 0;
module_param (ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index 32793ce..9c2cc46 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -183,7 +183,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
}
irq = irq_of_parse_and_map(dn, 0);
- if (irq == NO_IRQ) {
+ if (!irq) {
printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
rv = -EBUSY;
goto err_irq;
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 40d886a..4ea63b2 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -89,7 +89,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
{
- int ret;
+ int ret, unit;
struct usb_hcd *hcd;
if (usb_disabled())
@@ -120,7 +120,9 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
goto err2;
}
- if (alchemy_usb_control(ALCHEMY_USB_OHCI0, 1)) {
+ unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
+ ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
+ if (alchemy_usb_control(unit, 1)) {
printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
ret = -ENODEV;
goto err3;
@@ -135,7 +137,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
return ret;
}
- alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
+ alchemy_usb_control(unit, 0);
err3:
iounmap(hcd->regs);
err2:
@@ -148,9 +150,12 @@ err1:
static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ int unit;
+ unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
+ ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
usb_remove_hcd(hcd);
- alchemy_usb_control(ALCHEMY_USB_OHCI0, 0);
+ alchemy_usb_control(unit, 0);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 5f5a632..34b9edd 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -115,13 +115,13 @@ static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
/* Some boards misreport power switching/overcurrent */
-static int distrust_firmware = 1;
+static bool distrust_firmware = 1;
module_param (distrust_firmware, bool, 0);
MODULE_PARM_DESC (distrust_firmware,
"true to distrust firmware power/overcurrent setup");
/* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */
-static int no_handshake = 0;
+static bool no_handshake = 0;
module_param (no_handshake, bool, 0);
MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 6f62de5..015c7c6 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -233,7 +233,7 @@ module_param(park, uint, S_IRUGO);
MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets");
/* For flakey hardware, ignore overcurrent indicators */
-static int ignore_oc;
+static bool ignore_oc;
module_param(ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC(ignore_oc, "ignore bogus hardware overcurrent indications");
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 533d12c..16dd6a6 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -74,7 +74,7 @@ MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
INT_MODULE_PARM(testing, 0);
/* Some boards misreport power switching/overcurrent*/
-static int distrust_firmware = 1;
+static bool distrust_firmware = 1;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup");
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index c8ae199..6b5eb10 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -59,7 +59,7 @@
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
/* for flakey hardware, ignore overcurrent indicators */
-static int ignore_oc;
+static bool ignore_oc;
module_param(ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 2dbe600..a4a3c7c 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -53,7 +53,7 @@ MODULE_AUTHOR("Tony Olech");
MODULE_DESCRIPTION("FTDI ELAN driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
-static int distrust_firmware = 1;
+static bool distrust_firmware = 1;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup");
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 2453a39..4fd0dc8 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -62,7 +62,7 @@ MODULE_LICENSE("GPL");
/* Module parameters */
static DEFINE_MUTEX(iowarrior_mutex);
-static int debug = 0;
+static bool debug = 0;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "debug=1 enables debugging messages");
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 53be7ae..66bc376 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -750,7 +750,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
* So this module parameter lets the heuristic be disabled. When using
* gadgetfs, the heuristic will probably need to be disabled.
*/
-static int cppi_rx_rndis = 1;
+static bool cppi_rx_rndis = 1;
module_param(cppi_rx_rndis, bool, 0);
MODULE_PARM_DESC(cppi_rx_rndis, "enable/disable RX RNDIS heuristic");
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index f6ff792..56cf024 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1586,7 +1586,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
EXPORT_SYMBOL_GPL(musb_interrupt);
#ifndef CONFIG_MUSB_PIO_ONLY
-static int __initdata use_dma = 1;
+static bool __initdata use_dma = 1;
/* "modprobe ... use_dma=0" etc */
module_param(use_dma, bool, 0);
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index a163632..97cb459 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -84,7 +84,7 @@ static bool ux500_configure_channel(struct dma_channel *channel,
struct musb_hw_ep *hw_ep = ux500_channel->hw_ep;
struct dma_chan *dma_chan = ux500_channel->dma_chan;
struct dma_async_tx_descriptor *dma_desc;
- enum dma_data_direction direction;
+ enum dma_transfer_direction direction;
struct scatterlist sg;
struct dma_slave_config slave_conf;
enum dma_slave_buswidth addr_width;
@@ -104,7 +104,7 @@ static bool ux500_configure_channel(struct dma_channel *channel,
sg_dma_address(&sg) = dma_addr;
sg_dma_len(&sg) = len;
- direction = ux500_channel->is_tx ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ direction = ux500_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
addr_width = (len & 0x3) ? DMA_SLAVE_BUSWIDTH_1_BYTE :
DMA_SLAVE_BUSWIDTH_4_BYTES;
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index 07ccea9..74fe6e6 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -30,7 +30,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/mfd/abx500.h>
-#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500/ab8500.h>
#define AB8500_MAIN_WD_CTRL_REG 0x01
#define AB8500_USB_LINE_STAT_REG 0x80
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index b51fcd8..72339bd 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -772,10 +772,10 @@ static void usbhsf_dma_prepare_tasklet(unsigned long data)
struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
struct device *dev = usbhs_priv_to_dev(priv);
- enum dma_data_direction dir;
+ enum dma_transfer_direction dir;
dma_cookie_t cookie;
- dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
sg_init_table(&sg, 1);
sg_set_page(&sg, virt_to_page(pkt->dma),
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index b43d07d..123bf91 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -52,7 +52,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
+static bool debug;
/* Vendor and Product ID */
#define AIRCABLE_VID 0x16CA
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 18e875b..69328dc 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -37,7 +37,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
-static int debug;
+static bool debug;
/*
* Version information
*/
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index f9f29b2..29ffeb6 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -37,7 +37,7 @@
#include <linux/usb/serial.h>
#include "belkin_sa.h"
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 0e77511..5e53cc5 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -70,7 +70,7 @@
#define CH341_NBREAK_BITS_REG2 0x40
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) },
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index adfe660..fba1147 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -49,7 +49,7 @@ static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 98bf833..6bc3802 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -43,7 +43,7 @@
#define CYBERJACK_LOCAL_BUF_SIZE 32
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 07680d6..3bdeafa 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -46,10 +46,10 @@
#include "cypress_m8.h"
-static int debug;
-static int stats;
+static bool debug;
+static bool stats;
static int interval;
-static int unstable_bauds;
+static bool unstable_bauds;
/*
* Version Information
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 6d26a77..b23bebd 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -251,7 +251,7 @@ static int digi_read_oob_callback(struct urb *urb);
/* Statics */
-static int debug;
+static bool debug;
static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 504b558..aced681 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -28,7 +28,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c290df9..01b6404 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -55,7 +55,7 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
-static int debug;
+static bool debug;
static __u16 vendor = FTDI_VID;
static __u16 product;
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index e21ce9d..5d4b099 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -16,7 +16,7 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1404, 0xcddc) },
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index bf12565..2134337 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -42,7 +42,7 @@
static int initial_mode = 1;
/* debug flag */
-static int debug;
+static bool debug;
#define GARMIN_VENDOR_ID 0x091E
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index abd2ee2..0497575 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -191,7 +191,7 @@ static const struct divisor_table_entry divisor_table[] = {
};
/* local variables */
-static int debug;
+static bool debug;
static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index e44d375..65bf06a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -210,10 +210,10 @@ static unsigned char OperationalMajorVersion;
static unsigned char OperationalMinorVersion;
static unsigned short OperationalBuildNumber;
-static int debug;
+static bool debug;
static int closing_wait = EDGE_CLOSING_WAIT;
-static int ignore_cpu_rev;
+static bool ignore_cpu_rev;
static int default_uart_mode; /* RS232 */
static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 36f5cbe..06053a9 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -34,7 +34,7 @@
#define DRIVER_DESC "USB PocketPC PDA driver"
static __u16 product, vendor;
-static int debug;
+static bool debug;
static int connect_retries = KP_RETRIES;
static int initial_wait;
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 5170799..6f9356f 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -147,7 +147,7 @@ static struct usb_driver usb_ipw_driver = {
.no_dynamic_id = 1,
};
-static int debug;
+static bool debug;
static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
{
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 0c537da..84a396e 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -45,7 +45,7 @@
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>"
#define DRIVER_DESC "USB IR Dongle driver"
-static int debug;
+static bool debug;
/* if overridden by the user, then use their value for the size of the read and
* write urbs */
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 64d0ffd..3077a44 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -34,9 +34,9 @@
#ifdef CONFIG_USB_SERIAL_DEBUG
-static int debug = 1;
+static bool debug = 1;
#else
-static int debug;
+static bool debug;
#endif
/*
@@ -65,7 +65,7 @@ static int clockmode = 1;
static int cdmode = 1;
static int iuu_cardin;
static int iuu_cardout;
-static int xmas;
+static bool xmas;
static int vcc_default = 5;
static void read_rxcmd_callback(struct urb *urb);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index bc8dc20..4cc36c7 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -45,7 +45,7 @@
#include <linux/usb/serial.h>
#include "keyspan.h"
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index a406156..7c62a70 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -31,7 +31,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
+static bool debug;
/* make a simple define to handle if we are compiling keyspan_pda or xircom support */
#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE)
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 19373cb..fc064e1 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -49,7 +49,7 @@
#include <linux/usb/serial.h>
#include "kl5kusb105.h"
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a975bb8..27fa9c8 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -45,7 +45,7 @@
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
-static int debug;
+static bool debug;
/*
* Function prototypes
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 19d112f..4554ee4 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -71,7 +71,7 @@ struct moschip_port {
struct urb *write_urb_pool[NUM_URBS];
};
-static int debug;
+static bool debug;
static struct usb_serial_driver moschip7720_2port_driver;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 55cfd62..03b5e249 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -263,7 +263,7 @@ struct moschip_port {
};
-static int debug;
+static bool debug;
/*
* mos7840_set_reg_sync
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 1f00f24..b28f1db 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -21,7 +21,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 45a8c55..8b8d58a 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -23,7 +23,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-static int debug;
+static bool debug;
/*
* Version Information
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 691f57a..262ded9 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -32,7 +32,7 @@
* an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */
#define DRIVER_DESC "Opticon USB barcode to serial driver (1D)"
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x065a, 0x0009) },
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c96b6b6..420d985 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1234,7 +1234,7 @@ static struct usb_serial_driver option_1port_device = {
#endif
};
-static int debug;
+static bool debug;
/* per port private data */
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 2161d1c..e287fd3 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -74,7 +74,7 @@ static struct usb_driver oti6858_driver = {
.no_dynamic_id = 1,
};
-static int debug;
+static bool debug;
/* requests */
#define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00)
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3292956..3d8cda5 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -36,7 +36,7 @@
*/
#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
-static int debug;
+static bool debug;
#define PL2303_CLOSING_WAIT (30*HZ)
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index aa9367f..1d5deee 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -22,7 +22,7 @@
#define DRIVER_AUTHOR "Qualcomm Inc"
#define DRIVER_DESC "Qualcomm USB Serial driver"
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index a36e231..d074b37 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -81,9 +81,9 @@
#define CONFIG_USB_SERIAL_SAFE_PADDED 0
#endif
-static int debug;
-static int safe = 1;
-static int padded = CONFIG_USB_SERIAL_SAFE_PADDED;
+static bool debug;
+static bool safe = 1;
+static bool padded = CONFIG_USB_SERIAL_SAFE_PADDED;
#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold <jhovold@gmail.com>"
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index f248542..fdae0a4 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -46,8 +46,8 @@
allocations > PAGE_SIZE and the number of packets in a page
is an integer 512 is the largest possible packet on EHCI */
-static int debug;
-static int nmea;
+static bool debug;
+static bool nmea;
/* Used in interface blacklisting */
struct sierra_iface_info {
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 180ea6c..d7f5eee 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -33,7 +33,7 @@
#define DRIVER_VERSION "v0.10"
#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
-static int debug;
+static bool debug;
#define SPCP8x5_007_VID 0x04FC
#define SPCP8x5_007_PID 0x0201
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 87362e4..7697858 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -46,7 +46,7 @@
#define FULLPWRBIT 0x00000080
#define NEXT_BOARD_POWER_BIT 0x00000004
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "v0.1"
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index c70cc01..50651cf 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -20,7 +20,7 @@
#include <linux/usb/serial.h>
#include <linux/uaccess.h>
-static int debug;
+static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x05e0, 0x0600) },
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 4af21f4..8468eb7 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -150,7 +150,7 @@ static int ti_download_firmware(struct ti_device *tdev);
/* Data */
/* module parameters */
-static int debug;
+static bool debug;
static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
static unsigned int vendor_3410_count;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index ce6c1a6..611b206 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -61,7 +61,7 @@ static struct usb_driver usb_serial_driver = {
drivers depend on it.
*/
-static int debug;
+static bool debug;
/* initially all NULL */
static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
static DEFINE_MUTEX(table_lock);
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index d555ca9..c88657d 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -37,7 +37,7 @@
#include <linux/serial.h>
#include "usb-wwan.h"
-static int debug;
+static bool debug;
void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
{
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 1c11959..210e4b10 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -52,7 +52,7 @@ static int palm_os_4_probe(struct usb_serial *serial,
const struct usb_device_id *id);
/* Parameters that may be passed into the module. */
-static int debug;
+static bool debug;
static __u16 vendor;
static __u16 product;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 11af903..7e0acf5 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -36,7 +36,7 @@
#include <linux/ihex.h>
#include "whiteheat.h" /* WhiteHEAT specific commands */
-static int debug;
+static bool debug;
#ifndef CMSPAR
#define CMSPAR 0
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 882a51f..9dab1f5 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -856,9 +856,9 @@ static const struct file_operations vhost_net_fops = {
};
static struct miscdevice vhost_net_misc = {
- MISC_DYNAMIC_MINOR,
- "vhost-net",
- &vhost_net_fops,
+ .minor = VHOST_NET_MINOR,
+ .name = "vhost-net",
+ .fops = &vhost_net_fops,
};
static int vhost_net_init(void)
@@ -879,3 +879,5 @@ MODULE_VERSION("0.0.1");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Michael S. Tsirkin");
MODULE_DESCRIPTION("Host kernel accelerator for virtio net");
+MODULE_ALIAS_MISCDEV(VHOST_NET_MINOR);
+MODULE_ALIAS("devname:vhost-net");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d83e967..6ca0c40 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1763,16 +1763,16 @@ config FB_AU1100
au1100fb:panel=<name>.
config FB_AU1200
- bool "Au1200 LCD Driver"
+ bool "Au1200/Au1300 LCD Driver"
depends on (FB = y) && MIPS_ALCHEMY
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
help
- This is the framebuffer driver for the AMD Au1200 SOC. It can drive
- various panels and CRTs by passing in kernel cmd line option
- au1200fb:panel=<name>.
+ This is the framebuffer driver for the Au1200/Au1300 SOCs.
+ It can drive various panels and CRTs by passing in kernel cmd line
+ option au1200fb:panel=<name>.
config FB_VT8500
bool "VT8500 LCD Driver"
@@ -2413,7 +2413,6 @@ source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
source "drivers/video/backlight/Kconfig"
-source "drivers/video/display/Kconfig"
if VT
source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9b9d8ff..1426068 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -13,7 +13,7 @@ fb-objs := $(fb-y)
obj-$(CONFIG_VT) += console/
obj-$(CONFIG_LOGO) += logo/
-obj-y += backlight/ display/
+obj-y += backlight/
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 5ea6596..f23cae09 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -152,10 +152,10 @@
- hsstrt: Start of horizontal synchronization pulse
- hsstop: End of horizontal synchronization pulse
- - htotal: Last value on the line (i.e. line length = htotal+1)
+ - htotal: Last value on the line (i.e. line length = htotal + 1)
- vsstrt: Start of vertical synchronization pulse
- vsstop: End of vertical synchronization pulse
- - vtotal: Last line value (i.e. number of lines = vtotal+1)
+ - vtotal: Last line value (i.e. number of lines = vtotal + 1)
- hcenter: Start of vertical retrace for interlace
You can specify the blanking timings independently. Currently I just set
@@ -184,7 +184,7 @@
clock):
- diwstrt_h: Horizontal start of the visible window
- - diwstop_h: Horizontal stop+1(*) of the visible window
+ - diwstop_h: Horizontal stop + 1(*) of the visible window
- diwstrt_v: Vertical start of the visible window
- diwstop_v: Vertical stop of the visible window
- ddfstrt: Horizontal start of display DMA
@@ -193,7 +193,7 @@
Sprite positioning:
- - sprstrt_h: Horizontal start-4 of sprite
+ - sprstrt_h: Horizontal start - 4 of sprite
- sprstrt_v: Vertical start of sprite
(*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
@@ -212,21 +212,21 @@
display parameters. Here's what I found out:
- ddfstrt and ddfstop are best aligned to 64 pixels.
- - the chipset needs 64+4 horizontal pixels after the DMA start before the
- first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to
- display the first pixel on the line too. Increase diwstrt_h for virtual
- screen panning.
+ - the chipset needs 64 + 4 horizontal pixels after the DMA start before
+ the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
+ to display the first pixel on the line too. Increase diwstrt_h for
+ virtual screen panning.
- the display DMA always fetches 64 pixels at a time (fmode = 3).
- - ddfstop is ddfstrt+#pixels-64.
- - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1
- more than htotal.
+ - ddfstop is ddfstrt+#pixels - 64.
+ - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
+ be 1 more than htotal.
- hscroll simply adds a delay to the display output. Smooth horizontal
- panning needs an extra 64 pixels on the left to prefetch the pixels that
- `fall off' on the left.
+ panning needs an extra 64 pixels on the left to prefetch the pixels that
+ `fall off' on the left.
- if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
- DMA, so it's best to make the DMA start as late as possible.
+ DMA, so it's best to make the DMA start as late as possible.
- you really don't want to make ddfstrt < 128, since this will steal DMA
- cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
+ cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
- I make diwstop_h and diwstop_v as large as possible.
General dependencies
@@ -234,8 +234,8 @@
- all values are SHRES pixel (35ns)
- table 1:fetchstart table 2:prefetch table 3:fetchsize
- ------------------ ---------------- -----------------
+ table 1:fetchstart table 2:prefetch table 3:fetchsize
+ ------------------ ---------------- -----------------
Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
-------------#------+-----+------#------+-----+------#------+-----+------
Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
@@ -245,21 +245,21 @@
- chipset needs 4 pixels before the first pixel is output
- ddfstrt must be aligned to fetchstart (table 1)
- chipset needs also prefetch (table 2) to get first pixel data, so
- ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch
+ ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
- for horizontal panning decrease diwstrt_h
- the length of a fetchline must be aligned to fetchsize (table 3)
- if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
- moved to optimize use of dma (useful for OCS/ECS overscan displays)
- - ddfstop is ddfstrt+ddfsize-fetchsize
+ moved to optimize use of dma (useful for OCS/ECS overscan displays)
+ - ddfstop is ddfstrt + ddfsize - fetchsize
- If C= didn't change anything for AGA, then at following positions the
- dma bus is already used:
- ddfstrt < 48 -> memory refresh
- < 96 -> disk dma
- < 160 -> audio dma
- < 192 -> sprite 0 dma
- < 416 -> sprite dma (32 per sprite)
+ dma bus is already used:
+ ddfstrt < 48 -> memory refresh
+ < 96 -> disk dma
+ < 160 -> audio dma
+ < 192 -> sprite 0 dma
+ < 416 -> sprite dma (32 per sprite)
- in accordance with the hardware reference manual a hardware stop is at
- 192, but AGA (ECS?) can go below this.
+ 192, but AGA (ECS?) can go below this.
DMA priorities
--------------
@@ -269,7 +269,7 @@
the hardware cursor:
- if you want to start display DMA too early, you lose the ability to
- do smooth horizontal panning (xpanstep 1 -> 64).
+ do smooth horizontal panning (xpanstep 1 -> 64).
- if you want to go even further, you lose the hardware cursor too.
IMHO a hardware cursor is more important for X than horizontal scrolling,
@@ -286,8 +286,8 @@
Standard VGA timings
--------------------
- xres yres left right upper lower hsync vsync
- ---- ---- ---- ----- ----- ----- ----- -----
+ xres yres left right upper lower hsync vsync
+ ---- ---- ---- ----- ----- ----- ----- -----
80x25 720 400 27 45 35 12 108 2
80x30 720 480 27 45 30 9 108 2
@@ -297,8 +297,8 @@
As a comparison, graphics/monitor.h suggests the following:
- xres yres left right upper lower hsync vsync
- ---- ---- ---- ----- ----- ----- ----- -----
+ xres yres left right upper lower hsync vsync
+ ---- ---- ---- ----- ----- ----- ----- -----
VGA 640 480 52 112 24 19 112 - 2 +
VGA70 640 400 52 112 27 21 112 - 2 -
@@ -309,10 +309,10 @@
VSYNC HSYNC Vertical size Vertical total
----- ----- ------------- --------------
- + + Reserved Reserved
- + - 400 414
- - + 350 362
- - - 480 496
+ + + Reserved Reserved
+ + - 400 414
+ - + 350 362
+ - - 480 496
Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
@@ -326,33 +326,34 @@
-----------
- a scanline is 64 µs long, of which 52.48 µs are visible. This is about
- 736 visible 70 ns pixels per line.
+ 736 visible 70 ns pixels per line.
- we have 625 scanlines, of which 575 are visible (interlaced); after
- rounding this becomes 576.
+ rounding this becomes 576.
RETMA -> NTSC
-------------
- a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
- 736 visible 70 ns pixels per line.
+ 736 visible 70 ns pixels per line.
- we have 525 scanlines, of which 485 are visible (interlaced); after
- rounding this becomes 484.
+ rounding this becomes 484.
Thus if you want a PAL compatible display, you have to do the following:
- set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
- timings are to be used.
- - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an
- interlaced, 312 for a non-interlaced and 156 for a doublescanned
- display.
- - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES,
- 908 for a HIRES and 454 for a LORES display.
+ timings are to be used.
+ - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
+ interlaced, 312 for a non-interlaced and 156 for a doublescanned
+ display.
+ - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
+ SHRES, 908 for a HIRES and 454 for a LORES display.
- the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
- left_margin+2*hsync_len must be greater or equal.
+ left_margin + 2 * hsync_len must be greater or equal.
- the upper visible part begins at 48 (interlaced; non-interlaced:24,
- doublescanned:12), upper_margin+2*vsync_len must be greater or equal.
+ doublescanned:12), upper_margin + 2 * vsync_len must be greater or
+ equal.
- ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
- of 4 scanlines
+ of 4 scanlines
The settings for a NTSC compatible display are straightforward.
@@ -361,7 +362,7 @@
anything about horizontal/vertical synchronization nor refresh rates.
- -- Geert --
+ -- Geert --
*******************************************************************************/
@@ -540,45 +541,45 @@ static u_short maxfmode, chipset;
* Various macros
*/
-#define up2(v) (((v)+1) & -2)
+#define up2(v) (((v) + 1) & -2)
#define down2(v) ((v) & -2)
#define div2(v) ((v)>>1)
#define mod2(v) ((v) & 1)
-#define up4(v) (((v)+3) & -4)
+#define up4(v) (((v) + 3) & -4)
#define down4(v) ((v) & -4)
-#define mul4(v) ((v)<<2)
+#define mul4(v) ((v) << 2)
#define div4(v) ((v)>>2)
#define mod4(v) ((v) & 3)
-#define up8(v) (((v)+7) & -8)
+#define up8(v) (((v) + 7) & -8)
#define down8(v) ((v) & -8)
#define div8(v) ((v)>>3)
#define mod8(v) ((v) & 7)
-#define up16(v) (((v)+15) & -16)
+#define up16(v) (((v) + 15) & -16)
#define down16(v) ((v) & -16)
#define div16(v) ((v)>>4)
#define mod16(v) ((v) & 15)
-#define up32(v) (((v)+31) & -32)
+#define up32(v) (((v) + 31) & -32)
#define down32(v) ((v) & -32)
#define div32(v) ((v)>>5)
#define mod32(v) ((v) & 31)
-#define up64(v) (((v)+63) & -64)
+#define up64(v) (((v) + 63) & -64)
#define down64(v) ((v) & -64)
#define div64(v) ((v)>>6)
#define mod64(v) ((v) & 63)
-#define upx(x,v) (((v)+(x)-1) & -(x))
-#define downx(x,v) ((v) & -(x))
-#define modx(x,v) ((v) & ((x)-1))
+#define upx(x, v) (((v) + (x) - 1) & -(x))
+#define downx(x, v) ((v) & -(x))
+#define modx(x, v) ((v) & ((x) - 1))
/* if x1 is not a constant, this macro won't make real sense :-) */
#ifdef __mc68000__
#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
- "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;})
+ "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
#else
/* We know a bit about the numbers, so we can do it this way */
#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
@@ -607,7 +608,7 @@ static u_short maxfmode, chipset;
#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
-#define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */
+#define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */
#define DUMMYSPRITEMEMSIZE (8)
static u_long spritememory;
@@ -634,9 +635,9 @@ static u_long min_fstrt = 192;
* Copper Instructions
*/
-#define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val))
-#define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val))
-#define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe)
+#define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
+#define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
+#define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
#define CEND (0xfffffffe)
@@ -709,7 +710,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite;
* Current Video Mode
*/
-static struct amifb_par {
+struct amifb_par {
/* General Values */
@@ -772,15 +773,6 @@ static struct amifb_par {
/* Additional AGA Hardware Registers */
u_short fmode; /* vmode */
-} currentpar;
-
-
-static struct fb_info fb_info = {
- .fix = {
- .id = "Amiga ",
- .visual = FB_VISUAL_PSEUDOCOLOR,
- .accel = FB_ACCEL_AMIGABLITT
- }
};
@@ -820,116 +812,123 @@ static u_short is_lace = 0; /* Screen is laced */
static struct fb_videomode ami_modedb[] __initdata = {
- /*
- * AmigaOS Video Modes
- *
- * If you change these, make sure to update DEFMODE_* as well!
- */
-
- {
- /* 640x200, 15 kHz, 60 Hz (NTSC) */
- "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
- FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
- "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
- FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x256, 15 kHz, 50 Hz (PAL) */
- "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
- FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
- "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
- FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x480, 29 kHz, 57 Hz */
- "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x960, 29 kHz, 57 Hz interlaced */
- "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x200, 15 kHz, 72 Hz */
- "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 15 kHz, 72 Hz interlaced */
- "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 29 kHz, 68 Hz */
- "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x800, 29 kHz, 68 Hz interlaced */
- "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 800x300, 23 kHz, 70 Hz */
- "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 800x600, 23 kHz, 70 Hz interlaced */
- "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x200, 27 kHz, 57 Hz doublescan */
- "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
- 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
- }, {
- /* 640x400, 27 kHz, 57 Hz */
- "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x800, 27 kHz, 57 Hz interlaced */
- "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x256, 27 kHz, 47 Hz doublescan */
- "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
- 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
- }, {
- /* 640x512, 27 kHz, 47 Hz */
- "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x1024, 27 kHz, 47 Hz interlaced */
- "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14,
- 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
- },
-
- /*
- * VGA Video Modes
- */
-
- {
- /* 640x480, 31 kHz, 60 Hz (VGA) */
- "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 640x400, 31 kHz, 70 Hz (VGA) */
- "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
- FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- },
+ /*
+ * AmigaOS Video Modes
+ *
+ * If you change these, make sure to update DEFMODE_* as well!
+ */
+
+ {
+ /* 640x200, 15 kHz, 60 Hz (NTSC) */
+ "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
+ FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
+ "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
+ FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x256, 15 kHz, 50 Hz (PAL) */
+ "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
+ FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
+ "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
+ FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x480, 29 kHz, 57 Hz */
+ "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x960, 29 kHz, 57 Hz interlaced */
+ "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
+ 16,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x200, 15 kHz, 72 Hz */
+ "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x400, 15 kHz, 72 Hz interlaced */
+ "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
+ 10,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x400, 29 kHz, 68 Hz */
+ "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x800, 29 kHz, 68 Hz interlaced */
+ "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
+ 16,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 800x300, 23 kHz, 70 Hz */
+ "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 800x600, 23 kHz, 70 Hz interlaced */
+ "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
+ 14,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x200, 27 kHz, 57 Hz doublescan */
+ "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
+ 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
+ }, {
+ /* 640x400, 27 kHz, 57 Hz */
+ "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x800, 27 kHz, 57 Hz interlaced */
+ "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
+ 14,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x256, 27 kHz, 47 Hz doublescan */
+ "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
+ 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
+ }, {
+ /* 640x512, 27 kHz, 47 Hz */
+ "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x1024, 27 kHz, 47 Hz interlaced */
+ "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
+ 14,
+ 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
+ },
+
+ /*
+ * VGA Video Modes
+ */
+
+ {
+ /* 640x480, 31 kHz, 60 Hz (VGA) */
+ "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 640x400, 31 kHz, 70 Hz (VGA) */
+ "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
+ FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
+ FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ },
#if 0
- /*
- * A2024 video modes
- * These modes don't work yet because there's no A2024 driver.
- */
-
- {
- /* 1024x800, 10 Hz */
- "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }, {
- /* 1024x800, 15 Hz */
- "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
- 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
- }
+ /*
+ * A2024 video modes
+ * These modes don't work yet because there's no A2024 driver.
+ */
+
+ {
+ /* 1024x800, 10 Hz */
+ "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }, {
+ /* 1024x800, 15 Hz */
+ "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
+ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+ }
#endif
};
@@ -953,6 +952,11 @@ static int round_down_bpp = 1; /* for mode probing */
static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
static int amifb_inverse = 0;
+static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
+static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
+static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */
+static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */
+
/*
* Macros for the conversion from real world values to hardware register
@@ -992,19 +996,20 @@ static int amifb_inverse = 0;
/* bplcon1 (smooth scrolling) */
#define hscroll2hw(hscroll) \
- (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
- ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
+ (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
+ ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
+ ((hscroll)>>2 & 0x000f))
/* diwstrt/diwstop/diwhigh (visible display window) */
#define diwstrt2hw(diwstrt_h, diwstrt_v) \
- (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
+ (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
#define diwstop2hw(diwstop_h, diwstop_v) \
- (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
+ (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
- (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
+ (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
- ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
+ ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
/* ddfstrt/ddfstop (display DMA) */
@@ -1015,38 +1020,39 @@ static int amifb_inverse = 0;
#define hsstrt2hw(hsstrt) (div8(hsstrt))
#define hsstop2hw(hsstop) (div8(hsstop))
-#define htotal2hw(htotal) (div8(htotal)-1)
+#define htotal2hw(htotal) (div8(htotal) - 1)
#define vsstrt2hw(vsstrt) (div2(vsstrt))
#define vsstop2hw(vsstop) (div2(vsstop))
-#define vtotal2hw(vtotal) (div2(vtotal)-1)
+#define vtotal2hw(vtotal) (div2(vtotal) - 1)
#define hcenter2hw(htotal) (div8(htotal))
/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
-#define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
-#define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
+#define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
+#define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
#define vbstrt2hw(vbstrt) (div2(vbstrt))
#define vbstop2hw(vbstop) (div2(vbstop))
/* colour */
#define rgb2hw8_high(red, green, blue) \
- (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
+ (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
#define rgb2hw8_low(red, green, blue) \
- (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
+ (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
#define rgb2hw4(red, green, blue) \
- (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
+ (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
#define rgb2hw2(red, green, blue) \
- (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
+ (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
/* sprpos/sprctl (sprite positioning) */
#define spr2hw_pos(start_v, start_h) \
- (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff))
+ (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
#define spr2hw_ctl(start_v, start_h, stop_v) \
- (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \
- ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \
- ((start_h)>>2&0x0001))
+ (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
+ ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
+ ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
+ ((start_h)>>2 & 0x0001))
/* get current vertical position of beam */
#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
@@ -1055,7 +1061,7 @@ static int amifb_inverse = 0;
* Copper Initialisation List
*/
-#define COPINITSIZE (sizeof(copins)*40)
+#define COPINITSIZE (sizeof(copins) * 40)
enum {
cip_bplcon0
@@ -1066,7 +1072,7 @@ enum {
* Don't change the order, build_copper()/rebuild_copper() rely on this
*/
-#define COPLISTSIZE (sizeof(copins)*64)
+#define COPLISTSIZE (sizeof(copins) * 64)
enum {
cop_wait, cop_bplcon0,
@@ -1108,82 +1114,1199 @@ static u_short sprfetchmode[3] = {
};
+/* --------------------------- Hardware routines --------------------------- */
+
/*
- * Interface used by the world
+ * Get the video params out of `var'. If a value doesn't fit, round
+ * it up, if it's too big, return -EINVAL.
*/
-int amifb_setup(char*);
+static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
+ const struct fb_info *info)
+{
+ u_short clk_shift, line_shift;
+ u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
+ u_int htotal, vtotal;
-static int amifb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info);
-static int amifb_set_par(struct fb_info *info);
-static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info);
-static int amifb_blank(int blank, struct fb_info *info);
-static int amifb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info);
-static void amifb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect);
-static void amifb_copyarea(struct fb_info *info,
- const struct fb_copyarea *region);
-static void amifb_imageblit(struct fb_info *info,
- const struct fb_image *image);
-static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
+ /*
+ * Find a matching Pixel Clock
+ */
+ for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
+ if (var->pixclock <= pixclock[clk_shift])
+ break;
+ if (clk_shift > TAG_LORES) {
+ DPRINTK("pixclock too high\n");
+ return -EINVAL;
+ }
+ par->clk_shift = clk_shift;
/*
- * Interface to the low level console driver
+ * Check the Geometry Values
*/
-static void amifb_deinit(struct platform_device *pdev);
+ if ((par->xres = var->xres) < 64)
+ par->xres = 64;
+ if ((par->yres = var->yres) < 64)
+ par->yres = 64;
+ if ((par->vxres = var->xres_virtual) < par->xres)
+ par->vxres = par->xres;
+ if ((par->vyres = var->yres_virtual) < par->yres)
+ par->vyres = par->yres;
+
+ par->bpp = var->bits_per_pixel;
+ if (!var->nonstd) {
+ if (par->bpp < 1)
+ par->bpp = 1;
+ if (par->bpp > maxdepth[clk_shift]) {
+ if (round_down_bpp && maxdepth[clk_shift])
+ par->bpp = maxdepth[clk_shift];
+ else {
+ DPRINTK("invalid bpp\n");
+ return -EINVAL;
+ }
+ }
+ } else if (var->nonstd == FB_NONSTD_HAM) {
+ if (par->bpp < 6)
+ par->bpp = 6;
+ if (par->bpp != 6) {
+ if (par->bpp < 8)
+ par->bpp = 8;
+ if (par->bpp != 8 || !IS_AGA) {
+ DPRINTK("invalid bpp for ham mode\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ DPRINTK("unknown nonstd mode\n");
+ return -EINVAL;
+ }
/*
- * Internal routines
+ * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
+ * checks failed and smooth scrolling is not possible
*/
-static int flash_cursor(void);
-static irqreturn_t amifb_interrupt(int irq, void *dev_id);
-static u_long chipalloc(u_long size);
-static void chipfree(void);
+ par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
+ switch (par->vmode & FB_VMODE_MASK) {
+ case FB_VMODE_INTERLACED:
+ line_shift = 0;
+ break;
+ case FB_VMODE_NONINTERLACED:
+ line_shift = 1;
+ break;
+ case FB_VMODE_DOUBLE:
+ if (!IS_AGA) {
+ DPRINTK("double mode only possible with aga\n");
+ return -EINVAL;
+ }
+ line_shift = 2;
+ break;
+ default:
+ DPRINTK("unknown video mode\n");
+ return -EINVAL;
+ break;
+ }
+ par->line_shift = line_shift;
/*
- * Hardware routines
+ * Vertical and Horizontal Timings
*/
-static int ami_decode_var(struct fb_var_screeninfo *var,
- struct amifb_par *par);
-static int ami_encode_var(struct fb_var_screeninfo *var,
- struct amifb_par *par);
-static void ami_pan_var(struct fb_var_screeninfo *var);
-static int ami_update_par(void);
-static void ami_update_display(void);
-static void ami_init_display(void);
-static void ami_do_blank(void);
-static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
-static int ami_get_cursorstate(struct fb_cursorstate *state);
-static int ami_set_cursorstate(struct fb_cursorstate *state);
-static void ami_set_sprite(void);
-static void ami_init_copper(void);
-static void ami_reinit_copper(void);
-static void ami_build_copper(void);
-static void ami_rebuild_copper(void);
+ xres_n = par->xres << clk_shift;
+ yres_n = par->yres << line_shift;
+ par->htotal = down8((var->left_margin + par->xres + var->right_margin +
+ var->hsync_len) << clk_shift);
+ par->vtotal =
+ down2(((var->upper_margin + par->yres + var->lower_margin +
+ var->vsync_len) << line_shift) + 1);
+ if (IS_AGA)
+ par->bplcon3 = sprpixmode[clk_shift];
+ else
+ par->bplcon3 = 0;
+ if (var->sync & FB_SYNC_BROADCAST) {
+ par->diwstop_h = par->htotal -
+ ((var->right_margin - var->hsync_len) << clk_shift);
+ if (IS_AGA)
+ par->diwstop_h += mod4(var->hsync_len);
+ else
+ par->diwstop_h = down4(par->diwstop_h);
+
+ par->diwstrt_h = par->diwstop_h - xres_n;
+ par->diwstop_v = par->vtotal -
+ ((var->lower_margin - var->vsync_len) << line_shift);
+ par->diwstrt_v = par->diwstop_v - yres_n;
+ if (par->diwstop_h >= par->htotal + 8) {
+ DPRINTK("invalid diwstop_h\n");
+ return -EINVAL;
+ }
+ if (par->diwstop_v > par->vtotal) {
+ DPRINTK("invalid diwstop_v\n");
+ return -EINVAL;
+ }
+
+ if (!IS_OCS) {
+ /* Initialize sync with some reasonable values for pwrsave */
+ par->hsstrt = 160;
+ par->hsstop = 320;
+ par->vsstrt = 30;
+ par->vsstop = 34;
+ } else {
+ par->hsstrt = 0;
+ par->hsstop = 0;
+ par->vsstrt = 0;
+ par->vsstop = 0;
+ }
+ if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
+ /* PAL video mode */
+ if (par->htotal != PAL_HTOTAL) {
+ DPRINTK("htotal invalid for pal\n");
+ return -EINVAL;
+ }
+ if (par->diwstrt_h < PAL_DIWSTRT_H) {
+ DPRINTK("diwstrt_h too low for pal\n");
+ return -EINVAL;
+ }
+ if (par->diwstrt_v < PAL_DIWSTRT_V) {
+ DPRINTK("diwstrt_v too low for pal\n");
+ return -EINVAL;
+ }
+ htotal = PAL_HTOTAL>>clk_shift;
+ vtotal = PAL_VTOTAL>>1;
+ if (!IS_OCS) {
+ par->beamcon0 = BMC0_PAL;
+ par->bplcon3 |= BPC3_BRDRBLNK;
+ } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+ AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+ par->beamcon0 = BMC0_PAL;
+ par->hsstop = 1;
+ } else if (amiga_vblank != 50) {
+ DPRINTK("pal not supported by this chipset\n");
+ return -EINVAL;
+ }
+ } else {
+ /* NTSC video mode
+ * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
+ * and NTSC activated, so than better let diwstop_h <= 1812
+ */
+ if (par->htotal != NTSC_HTOTAL) {
+ DPRINTK("htotal invalid for ntsc\n");
+ return -EINVAL;
+ }
+ if (par->diwstrt_h < NTSC_DIWSTRT_H) {
+ DPRINTK("diwstrt_h too low for ntsc\n");
+ return -EINVAL;
+ }
+ if (par->diwstrt_v < NTSC_DIWSTRT_V) {
+ DPRINTK("diwstrt_v too low for ntsc\n");
+ return -EINVAL;
+ }
+ htotal = NTSC_HTOTAL>>clk_shift;
+ vtotal = NTSC_VTOTAL>>1;
+ if (!IS_OCS) {
+ par->beamcon0 = 0;
+ par->bplcon3 |= BPC3_BRDRBLNK;
+ } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
+ AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
+ par->beamcon0 = 0;
+ par->hsstop = 1;
+ } else if (amiga_vblank != 60) {
+ DPRINTK("ntsc not supported by this chipset\n");
+ return -EINVAL;
+ }
+ }
+ if (IS_OCS) {
+ if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
+ par->diwstrt_v >= 512 || par->diwstop_v < 256) {
+ DPRINTK("invalid position for display on ocs\n");
+ return -EINVAL;
+ }
+ }
+ } else if (!IS_OCS) {
+ /* Programmable video mode */
+ par->hsstrt = var->right_margin << clk_shift;
+ par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
+ par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
+ if (!IS_AGA)
+ par->diwstop_h = down4(par->diwstop_h) - 16;
+ par->diwstrt_h = par->diwstop_h - xres_n;
+ par->hbstop = par->diwstrt_h + 4;
+ par->hbstrt = par->diwstop_h + 4;
+ if (par->hbstrt >= par->htotal + 8)
+ par->hbstrt -= par->htotal;
+ par->hcenter = par->hsstrt + (par->htotal >> 1);
+ par->vsstrt = var->lower_margin << line_shift;
+ par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
+ par->diwstop_v = par->vtotal;
+ if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ par->diwstop_v -= 2;
+ par->diwstrt_v = par->diwstop_v - yres_n;
+ par->vbstop = par->diwstrt_v - 2;
+ par->vbstrt = par->diwstop_v - 2;
+ if (par->vtotal > 2048) {
+ DPRINTK("vtotal too high\n");
+ return -EINVAL;
+ }
+ if (par->htotal > 2048) {
+ DPRINTK("htotal too high\n");
+ return -EINVAL;
+ }
+ par->bplcon3 |= BPC3_EXTBLKEN;
+ par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
+ BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
+ BMC0_PAL | BMC0_VARCSYEN;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->beamcon0 |= BMC0_HSYTRUE;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->beamcon0 |= BMC0_VSYTRUE;
+ if (var->sync & FB_SYNC_COMP_HIGH_ACT)
+ par->beamcon0 |= BMC0_CSYTRUE;
+ htotal = par->htotal>>clk_shift;
+ vtotal = par->vtotal>>1;
+ } else {
+ DPRINTK("only broadcast modes possible for ocs\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Checking the DMA timing
+ */
+
+ fconst = 16 << maxfmode << clk_shift;
+
+ /*
+ * smallest window start value without turn off other dma cycles
+ * than sprite1-7, unless you change min_fstrt
+ */
+
+
+ fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
+ fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
+ if (fstrt < min_fstrt) {
+ DPRINTK("fetch start too low\n");
+ return -EINVAL;
+ }
+
+ /*
+ * smallest window start value where smooth scrolling is possible
+ */
+
+ fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
+ fsize;
+ if (fstrt < min_fstrt)
+ par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+ maxfetchstop = down16(par->htotal - 80);
+
+ fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
+ fsize = upx(fconst, xres_n +
+ modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
+ if (fstrt + fsize > maxfetchstop)
+ par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+ fsize = upx(fconst, xres_n);
+ if (fstrt + fsize > maxfetchstop) {
+ DPRINTK("fetch stop too high\n");
+ return -EINVAL;
+ }
+
+ if (maxfmode + clk_shift <= 1) {
+ fsize = up64(xres_n + fconst - 1);
+ if (min_fstrt + fsize - 64 > maxfetchstop)
+ par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+ fsize = up64(xres_n);
+ if (min_fstrt + fsize - 64 > maxfetchstop) {
+ DPRINTK("fetch size too high\n");
+ return -EINVAL;
+ }
+
+ fsize -= 64;
+ } else
+ fsize -= fconst;
+
+ /*
+ * Check if there is enough time to update the bitplane pointers for ywrap
+ */
+
+ if (par->htotal - fsize - 64 < par->bpp * 64)
+ par->vmode &= ~FB_VMODE_YWRAP;
+
+ /*
+ * Bitplane calculations and check the Memory Requirements
+ */
+
+ if (amifb_ilbm) {
+ par->next_plane = div8(upx(16 << maxfmode, par->vxres));
+ par->next_line = par->bpp * par->next_plane;
+ if (par->next_line * par->vyres > info->fix.smem_len) {
+ DPRINTK("too few video mem\n");
+ return -EINVAL;
+ }
+ } else {
+ par->next_line = div8(upx(16 << maxfmode, par->vxres));
+ par->next_plane = par->vyres * par->next_line;
+ if (par->next_plane * par->bpp > info->fix.smem_len) {
+ DPRINTK("too few video mem\n");
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Hardware Register Values
+ */
+
+ par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
+ if (!IS_OCS)
+ par->bplcon0 |= BPC0_ECSENA;
+ if (par->bpp == 8)
+ par->bplcon0 |= BPC0_BPU3;
+ else
+ par->bplcon0 |= par->bpp << 12;
+ if (var->nonstd == FB_NONSTD_HAM)
+ par->bplcon0 |= BPC0_HAM;
+ if (var->sync & FB_SYNC_EXT)
+ par->bplcon0 |= BPC0_ERSY;
+
+ if (IS_AGA)
+ par->fmode = bplfetchmode[maxfmode];
+
+ switch (par->vmode & FB_VMODE_MASK) {
+ case FB_VMODE_INTERLACED:
+ par->bplcon0 |= BPC0_LACE;
+ break;
+ case FB_VMODE_DOUBLE:
+ if (IS_AGA)
+ par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
+ break;
+ }
+
+ if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
+ par->xoffset = var->xoffset;
+ par->yoffset = var->yoffset;
+ if (par->vmode & FB_VMODE_YWRAP) {
+ if (par->xoffset || par->yoffset < 0 ||
+ par->yoffset >= par->vyres)
+ par->xoffset = par->yoffset = 0;
+ } else {
+ if (par->xoffset < 0 ||
+ par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
+ par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
+ par->xoffset = par->yoffset = 0;
+ }
+ } else
+ par->xoffset = par->yoffset = 0;
+
+ par->crsr.crsr_x = par->crsr.crsr_y = 0;
+ par->crsr.spot_x = par->crsr.spot_y = 0;
+ par->crsr.height = par->crsr.width = 0;
+
+ return 0;
+}
+
+ /*
+ * Fill the `var' structure based on the values in `par' and maybe
+ * other values read out of the hardware.
+ */
+
+static void ami_encode_var(struct fb_var_screeninfo *var,
+ struct amifb_par *par)
+{
+ u_short clk_shift, line_shift;
+
+ memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+ clk_shift = par->clk_shift;
+ line_shift = par->line_shift;
+
+ var->xres = par->xres;
+ var->yres = par->yres;
+ var->xres_virtual = par->vxres;
+ var->yres_virtual = par->vyres;
+ var->xoffset = par->xoffset;
+ var->yoffset = par->yoffset;
+
+ var->bits_per_pixel = par->bpp;
+ var->grayscale = 0;
+
+ var->red.offset = 0;
+ var->red.msb_right = 0;
+ var->red.length = par->bpp;
+ if (par->bplcon0 & BPC0_HAM)
+ var->red.length -= 2;
+ var->blue = var->green = var->red;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->transp.msb_right = 0;
+
+ if (par->bplcon0 & BPC0_HAM)
+ var->nonstd = FB_NONSTD_HAM;
+ else
+ var->nonstd = 0;
+ var->activate = 0;
+
+ var->height = -1;
+ var->width = -1;
+
+ var->pixclock = pixclock[clk_shift];
+
+ if (IS_AGA && par->fmode & FMODE_BSCAN2)
+ var->vmode = FB_VMODE_DOUBLE;
+ else if (par->bplcon0 & BPC0_LACE)
+ var->vmode = FB_VMODE_INTERLACED;
+ else
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
+ var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
+ var->right_margin = par->hsstrt>>clk_shift;
+ var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
+ var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
+ var->lower_margin = par->vsstrt>>line_shift;
+ var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
+ var->sync = 0;
+ if (par->beamcon0 & BMC0_HSYTRUE)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (par->beamcon0 & BMC0_VSYTRUE)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (par->beamcon0 & BMC0_CSYTRUE)
+ var->sync |= FB_SYNC_COMP_HIGH_ACT;
+ } else {
+ var->sync = FB_SYNC_BROADCAST;
+ var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
+ var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
+ var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
+ var->vsync_len = 4>>line_shift;
+ var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
+ var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
+ var->lower_margin - var->vsync_len;
+ }
+
+ if (par->bplcon0 & BPC0_ERSY)
+ var->sync |= FB_SYNC_EXT;
+ if (par->vmode & FB_VMODE_YWRAP)
+ var->vmode |= FB_VMODE_YWRAP;
+}
+
+
+ /*
+ * Update hardware
+ */
+
+static void ami_update_par(struct fb_info *info)
+{
+ struct amifb_par *par = info->par;
+ short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
+
+ clk_shift = par->clk_shift;
+
+ if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
+ par->xoffset = upx(16 << maxfmode, par->xoffset);
+
+ fconst = 16 << maxfmode << clk_shift;
+ vshift = modx(16 << maxfmode, par->xoffset);
+ fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
+ fsize = (par->xres + vshift) << clk_shift;
+ shift = modx(fconst, fstrt);
+ move = downx(2 << maxfmode, div8(par->xoffset));
+ if (maxfmode + clk_shift > 1) {
+ fstrt = downx(fconst, fstrt) - 64;
+ fsize = upx(fconst, fsize);
+ fstop = fstrt + fsize - fconst;
+ } else {
+ mod = fstrt = downx(fconst, fstrt) - fconst;
+ fstop = fstrt + upx(fconst, fsize) - 64;
+ fsize = up64(fsize);
+ fstrt = fstop - fsize + 64;
+ if (fstrt < min_fstrt) {
+ fstop += min_fstrt - fstrt;
+ fstrt = min_fstrt;
+ }
+ move = move - div8((mod - fstrt)>>clk_shift);
+ }
+ mod = par->next_line - div8(fsize>>clk_shift);
+ par->ddfstrt = fstrt;
+ par->ddfstop = fstop;
+ par->bplcon1 = hscroll2hw(shift);
+ par->bpl2mod = mod;
+ if (par->bplcon0 & BPC0_LACE)
+ par->bpl2mod += par->next_line;
+ if (IS_AGA && (par->fmode & FMODE_BSCAN2))
+ par->bpl1mod = -div8(fsize>>clk_shift);
+ else
+ par->bpl1mod = par->bpl2mod;
+
+ if (par->yoffset) {
+ par->bplpt0 = info->fix.smem_start +
+ par->next_line * par->yoffset + move;
+ if (par->vmode & FB_VMODE_YWRAP) {
+ if (par->yoffset > par->vyres - par->yres) {
+ par->bplpt0wrap = info->fix.smem_start + move;
+ if (par->bplcon0 & BPC0_LACE &&
+ mod2(par->diwstrt_v + par->vyres -
+ par->yoffset))
+ par->bplpt0wrap += par->next_line;
+ }
+ }
+ } else
+ par->bplpt0 = info->fix.smem_start + move;
+
+ if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
+ par->bplpt0 += par->next_line;
+}
+
+
+ /*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ * in `var'.
+ */
+
+static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct amifb_par *par = info->par;
+
+ par->xoffset = var->xoffset;
+ par->yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ par->vmode |= FB_VMODE_YWRAP;
+ else
+ par->vmode &= ~FB_VMODE_YWRAP;
+
+ do_vmode_pan = 0;
+ ami_update_par(info);
+ do_vmode_pan = 1;
+}
+
+
+static void ami_update_display(const struct amifb_par *par)
+{
+ custom.bplcon1 = par->bplcon1;
+ custom.bpl1mod = par->bpl1mod;
+ custom.bpl2mod = par->bpl2mod;
+ custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
+ custom.ddfstop = ddfstop2hw(par->ddfstop);
+}
+
+ /*
+ * Change the video mode (called by VBlank interrupt)
+ */
+
+static void ami_init_display(const struct amifb_par *par)
+{
+ int i;
+
+ custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
+ custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
+ if (!IS_OCS) {
+ custom.bplcon3 = par->bplcon3;
+ if (IS_AGA)
+ custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
+ if (par->beamcon0 & BMC0_VARBEAMEN) {
+ custom.htotal = htotal2hw(par->htotal);
+ custom.hbstrt = hbstrt2hw(par->hbstrt);
+ custom.hbstop = hbstop2hw(par->hbstop);
+ custom.hsstrt = hsstrt2hw(par->hsstrt);
+ custom.hsstop = hsstop2hw(par->hsstop);
+ custom.hcenter = hcenter2hw(par->hcenter);
+ custom.vtotal = vtotal2hw(par->vtotal);
+ custom.vbstrt = vbstrt2hw(par->vbstrt);
+ custom.vbstop = vbstop2hw(par->vbstop);
+ custom.vsstrt = vsstrt2hw(par->vsstrt);
+ custom.vsstop = vsstop2hw(par->vsstop);
+ }
+ }
+ if (!IS_OCS || par->hsstop)
+ custom.beamcon0 = par->beamcon0;
+ if (IS_AGA)
+ custom.fmode = par->fmode;
+
+ /*
+ * The minimum period for audio depends on htotal
+ */
+
+ amiga_audio_min_period = div16(par->htotal);
+
+ is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
+#if 1
+ if (is_lace) {
+ i = custom.vposr >> 15;
+ } else {
+ custom.vposw = custom.vposr | 0x8000;
+ i = 1;
+ }
+#else
+ i = 1;
+ custom.vposw = custom.vposr | 0x8000;
+#endif
+ custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
+}
+
+ /*
+ * (Un)Blank the screen (called by VBlank interrupt)
+ */
+
+static void ami_do_blank(const struct amifb_par *par)
+{
+#if defined(CONFIG_FB_AMIGA_AGA)
+ u_short bplcon3 = par->bplcon3;
+#endif
+ u_char red, green, blue;
+
+ if (do_blank > 0) {
+ custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
+ red = green = blue = 0;
+ if (!IS_OCS && do_blank > 1) {
+ switch (do_blank) {
+ case FB_BLANK_VSYNC_SUSPEND:
+ custom.hsstrt = hsstrt2hw(par->hsstrt);
+ custom.hsstop = hsstop2hw(par->hsstop);
+ custom.vsstrt = vsstrt2hw(par->vtotal + 4);
+ custom.vsstop = vsstop2hw(par->vtotal + 4);
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ custom.hsstrt = hsstrt2hw(par->htotal + 16);
+ custom.hsstop = hsstop2hw(par->htotal + 16);
+ custom.vsstrt = vsstrt2hw(par->vsstrt);
+ custom.vsstop = vsstrt2hw(par->vsstop);
+ break;
+ case FB_BLANK_POWERDOWN:
+ custom.hsstrt = hsstrt2hw(par->htotal + 16);
+ custom.hsstop = hsstop2hw(par->htotal + 16);
+ custom.vsstrt = vsstrt2hw(par->vtotal + 4);
+ custom.vsstop = vsstop2hw(par->vtotal + 4);
+ break;
+ }
+ if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
+ custom.htotal = htotal2hw(par->htotal);
+ custom.vtotal = vtotal2hw(par->vtotal);
+ custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
+ BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
+ }
+ }
+ } else {
+ custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
+ red = red0;
+ green = green0;
+ blue = blue0;
+ if (!IS_OCS) {
+ custom.hsstrt = hsstrt2hw(par->hsstrt);
+ custom.hsstop = hsstop2hw(par->hsstop);
+ custom.vsstrt = vsstrt2hw(par->vsstrt);
+ custom.vsstop = vsstop2hw(par->vsstop);
+ custom.beamcon0 = par->beamcon0;
+ }
+ }
+#if defined(CONFIG_FB_AMIGA_AGA)
+ if (IS_AGA) {
+ custom.bplcon3 = bplcon3;
+ custom.color[0] = rgb2hw8_high(red, green, blue);
+ custom.bplcon3 = bplcon3 | BPC3_LOCT;
+ custom.color[0] = rgb2hw8_low(red, green, blue);
+ custom.bplcon3 = bplcon3;
+ } else
+#endif
+#if defined(CONFIG_FB_AMIGA_ECS)
+ if (par->bplcon0 & BPC0_SHRES) {
+ u_short color, mask;
+ int i;
+
+ mask = 0x3333;
+ color = rgb2hw2(red, green, blue);
+ for (i = 12; i >= 0; i -= 4)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ mask <<= 2; color >>= 2;
+ for (i = 3; i >= 0; i--)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ } else
+#endif
+ custom.color[0] = rgb2hw4(red, green, blue);
+ is_blanked = do_blank > 0 ? do_blank : 0;
+}
+
+static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
+ const struct amifb_par *par)
+{
+ fix->crsr_width = fix->crsr_xsize = par->crsr.width;
+ fix->crsr_height = fix->crsr_ysize = par->crsr.height;
+ fix->crsr_color1 = 17;
+ fix->crsr_color2 = 18;
+ return 0;
+}
+
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
+ u_char __user *data,
+ const struct amifb_par *par)
+{
+ register u_short *lspr, *sspr;
+#ifdef __mc68000__
+ register u_long datawords asm ("d2");
+#else
+ register u_long datawords;
+#endif
+ register short delta;
+ register u_char color;
+ short height, width, bits, words;
+ int size, alloc;
+
+ size = par->crsr.height * par->crsr.width;
+ alloc = var->height * var->width;
+ var->height = par->crsr.height;
+ var->width = par->crsr.width;
+ var->xspot = par->crsr.spot_x;
+ var->yspot = par->crsr.spot_y;
+ if (size > var->height * var->width)
+ return -ENAMETOOLONG;
+ if (!access_ok(VERIFY_WRITE, data, size))
+ return -EFAULT;
+ delta = 1 << par->crsr.fmode;
+ lspr = lofsprite + (delta << 1);
+ if (par->bplcon0 & BPC0_LACE)
+ sspr = shfsprite + (delta << 1);
+ else
+ sspr = NULL;
+ for (height = (short)var->height - 1; height >= 0; height--) {
+ bits = 0; words = delta; datawords = 0;
+ for (width = (short)var->width - 1; width >= 0; width--) {
+ if (bits == 0) {
+ bits = 16; --words;
+#ifdef __mc68000__
+ asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
+ : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
+#else
+ datawords = (*(lspr + delta) << 16) | (*lspr++);
+#endif
+ }
+ --bits;
+#ifdef __mc68000__
+ asm volatile (
+ "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
+ "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
+ : "=d" (color), "=d" (datawords) : "1" (datawords));
+#else
+ color = (((datawords >> 30) & 2)
+ | ((datawords >> 15) & 1));
+ datawords <<= 1;
+#endif
+ put_user(color, data++);
+ }
+ if (bits > 0) {
+ --words; ++lspr;
+ }
+ while (--words >= 0)
+ ++lspr;
+#ifdef __mc68000__
+ asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
+ : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
+#else
+ lspr += delta;
+ if (sspr) {
+ u_short *tmp = lspr;
+ lspr = sspr;
+ sspr = tmp;
+ }
+#endif
+ }
+ return 0;
+}
+
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
+ u_char __user *data, struct amifb_par *par)
+{
+ register u_short *lspr, *sspr;
+#ifdef __mc68000__
+ register u_long datawords asm ("d2");
+#else
+ register u_long datawords;
+#endif
+ register short delta;
+ u_short fmode;
+ short height, width, bits, words;
+
+ if (!var->width)
+ return -EINVAL;
+ else if (var->width <= 16)
+ fmode = TAG_FMODE_1;
+ else if (var->width <= 32)
+ fmode = TAG_FMODE_2;
+ else if (var->width <= 64)
+ fmode = TAG_FMODE_4;
+ else
+ return -EINVAL;
+ if (fmode > maxfmode)
+ return -EINVAL;
+ if (!var->height)
+ return -EINVAL;
+ if (!access_ok(VERIFY_READ, data, var->width * var->height))
+ return -EFAULT;
+ delta = 1 << fmode;
+ lofsprite = shfsprite = (u_short *)spritememory;
+ lspr = lofsprite + (delta << 1);
+ if (par->bplcon0 & BPC0_LACE) {
+ if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
+ return -EINVAL;
+ memset(lspr, 0, (var->height + 4) << fmode << 2);
+ shfsprite += ((var->height + 5)&-2) << fmode;
+ sspr = shfsprite + (delta << 1);
+ } else {
+ if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
+ return -EINVAL;
+ memset(lspr, 0, (var->height + 2) << fmode << 2);
+ sspr = NULL;
+ }
+ for (height = (short)var->height - 1; height >= 0; height--) {
+ bits = 16; words = delta; datawords = 0;
+ for (width = (short)var->width - 1; width >= 0; width--) {
+ unsigned long tdata = 0;
+ get_user(tdata, data);
+ data++;
+#ifdef __mc68000__
+ asm volatile (
+ "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
+ "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
+ : "=d" (datawords)
+ : "0" (datawords), "d" (tdata));
+#else
+ datawords = ((datawords << 1) & 0xfffefffe);
+ datawords |= tdata & 1;
+ datawords |= (tdata & 2) << (16 - 1);
+#endif
+ if (--bits == 0) {
+ bits = 16; --words;
+#ifdef __mc68000__
+ asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
+ : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
+#else
+ *(lspr + delta) = (u_short) (datawords >> 16);
+ *lspr++ = (u_short) (datawords & 0xffff);
+#endif
+ }
+ }
+ if (bits < 16) {
+ --words;
+#ifdef __mc68000__
+ asm volatile (
+ "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
+ "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
+ : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
+#else
+ *(lspr + delta) = (u_short) (datawords >> (16 + bits));
+ *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
+#endif
+ }
+ while (--words >= 0) {
+#ifdef __mc68000__
+ asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
+ : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
+#else
+ *(lspr + delta) = 0;
+ *lspr++ = 0;
+#endif
+ }
+#ifdef __mc68000__
+ asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
+ : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
+#else
+ lspr += delta;
+ if (sspr) {
+ u_short *tmp = lspr;
+ lspr = sspr;
+ sspr = tmp;
+ }
+#endif
+ }
+ par->crsr.height = var->height;
+ par->crsr.width = var->width;
+ par->crsr.spot_x = var->xspot;
+ par->crsr.spot_y = var->yspot;
+ par->crsr.fmode = fmode;
+ if (IS_AGA) {
+ par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
+ par->fmode |= sprfetchmode[fmode];
+ custom.fmode = par->fmode;
+ }
+ return 0;
+}
+
+static int ami_get_cursorstate(struct fb_cursorstate *state,
+ const struct amifb_par *par)
+{
+ state->xoffset = par->crsr.crsr_x;
+ state->yoffset = par->crsr.crsr_y;
+ state->mode = cursormode;
+ return 0;
+}
+
+static int ami_set_cursorstate(struct fb_cursorstate *state,
+ struct amifb_par *par)
+{
+ par->crsr.crsr_x = state->xoffset;
+ par->crsr.crsr_y = state->yoffset;
+ if ((cursormode = state->mode) == FB_CURSOR_OFF)
+ cursorstate = -1;
+ do_cursor = 1;
+ return 0;
+}
+
+static void ami_set_sprite(const struct amifb_par *par)
+{
+ copins *copl, *cops;
+ u_short hs, vs, ve;
+ u_long pl, ps, pt;
+ short mx, my;
+
+ cops = copdisplay.list[currentcop][0];
+ copl = copdisplay.list[currentcop][1];
+ ps = pl = ZTWO_PADDR(dummysprite);
+ mx = par->crsr.crsr_x - par->crsr.spot_x;
+ my = par->crsr.crsr_y - par->crsr.spot_y;
+ if (!(par->vmode & FB_VMODE_YWRAP)) {
+ mx -= par->xoffset;
+ my -= par->yoffset;
+ }
+ if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
+ mx > -(short)par->crsr.width && mx < par->xres &&
+ my > -(short)par->crsr.height && my < par->yres) {
+ pl = ZTWO_PADDR(lofsprite);
+ hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
+ vs = par->diwstrt_v + (my << par->line_shift);
+ ve = vs + (par->crsr.height << par->line_shift);
+ if (par->bplcon0 & BPC0_LACE) {
+ ps = ZTWO_PADDR(shfsprite);
+ lofsprite[0] = spr2hw_pos(vs, hs);
+ shfsprite[0] = spr2hw_pos(vs + 1, hs);
+ if (mod2(vs)) {
+ lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
+ shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
+ pt = pl; pl = ps; ps = pt;
+ } else {
+ lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
+ shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
+ }
+ } else {
+ lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
+ lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
+ }
+ }
+ copl[cop_spr0ptrh].w[1] = highw(pl);
+ copl[cop_spr0ptrl].w[1] = loww(pl);
+ if (par->bplcon0 & BPC0_LACE) {
+ cops[cop_spr0ptrh].w[1] = highw(ps);
+ cops[cop_spr0ptrl].w[1] = loww(ps);
+ }
+}
+
+
+ /*
+ * Initialise the Copper Initialisation List
+ */
+
+static void __init ami_init_copper(void)
+{
+ copins *cop = copdisplay.init;
+ u_long p;
+ int i;
+
+ if (!IS_OCS) {
+ (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
+ (cop++)->l = CMOVE(0x0181, diwstrt);
+ (cop++)->l = CMOVE(0x0281, diwstop);
+ (cop++)->l = CMOVE(0x0000, diwhigh);
+ } else
+ (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
+ p = ZTWO_PADDR(dummysprite);
+ for (i = 0; i < 8; i++) {
+ (cop++)->l = CMOVE(0, spr[i].pos);
+ (cop++)->l = CMOVE(highw(p), sprpt[i]);
+ (cop++)->l = CMOVE2(loww(p), sprpt[i]);
+ }
+
+ (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
+ copdisplay.wait = cop;
+ (cop++)->l = CEND;
+ (cop++)->l = CMOVE(0, copjmp2);
+ cop->l = CEND;
+
+ custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
+ custom.copjmp1 = 0;
+}
+
+static void ami_reinit_copper(const struct amifb_par *par)
+{
+ copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
+ copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
+}
+
+
+ /*
+ * Rebuild the Copper List
+ *
+ * We only change the things that are not static
+ */
+
+static void ami_rebuild_copper(const struct amifb_par *par)
+{
+ copins *copl, *cops;
+ u_short line, h_end1, h_end2;
+ short i;
+ u_long p;
+
+ if (IS_AGA && maxfmode + par->clk_shift == 0)
+ h_end1 = par->diwstrt_h - 64;
+ else
+ h_end1 = par->htotal - 32;
+ h_end2 = par->ddfstop + 64;
+
+ ami_set_sprite(par);
+
+ copl = copdisplay.rebuild[1];
+ p = par->bplpt0;
+ if (par->vmode & FB_VMODE_YWRAP) {
+ if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
+ if (par->yoffset > par->vyres - par->yres) {
+ for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+ (copl++)->l = CMOVE(highw(p), bplpt[i]);
+ (copl++)->l = CMOVE2(loww(p), bplpt[i]);
+ }
+ line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
+ while (line >= 512) {
+ (copl++)->l = CWAIT(h_end1, 510);
+ line -= 512;
+ }
+ if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
+ (copl++)->l = CWAIT(h_end1, line);
+ else
+ (copl++)->l = CWAIT(h_end2, line);
+ p = par->bplpt0wrap;
+ }
+ } else
+ p = par->bplpt0wrap;
+ }
+ for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+ (copl++)->l = CMOVE(highw(p), bplpt[i]);
+ (copl++)->l = CMOVE2(loww(p), bplpt[i]);
+ }
+ copl->l = CEND;
+
+ if (par->bplcon0 & BPC0_LACE) {
+ cops = copdisplay.rebuild[0];
+ p = par->bplpt0;
+ if (mod2(par->diwstrt_v))
+ p -= par->next_line;
+ else
+ p += par->next_line;
+ if (par->vmode & FB_VMODE_YWRAP) {
+ if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
+ if (par->yoffset > par->vyres - par->yres + 1) {
+ for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+ (cops++)->l = CMOVE(highw(p), bplpt[i]);
+ (cops++)->l = CMOVE2(loww(p), bplpt[i]);
+ }
+ line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
+ while (line >= 512) {
+ (cops++)->l = CWAIT(h_end1, 510);
+ line -= 512;
+ }
+ if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
+ (cops++)->l = CWAIT(h_end1, line);
+ else
+ (cops++)->l = CWAIT(h_end2, line);
+ p = par->bplpt0wrap;
+ if (mod2(par->diwstrt_v + par->vyres -
+ par->yoffset))
+ p -= par->next_line;
+ else
+ p += par->next_line;
+ }
+ } else
+ p = par->bplpt0wrap - par->next_line;
+ }
+ for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
+ (cops++)->l = CMOVE(highw(p), bplpt[i]);
+ (cops++)->l = CMOVE2(loww(p), bplpt[i]);
+ }
+ cops->l = CEND;
+ }
+}
+
+
+ /*
+ * Build the Copper List
+ */
+
+static void ami_build_copper(struct fb_info *info)
+{
+ struct amifb_par *par = info->par;
+ copins *copl, *cops;
+ u_long p;
+
+ currentcop = 1 - currentcop;
+
+ copl = copdisplay.list[currentcop][1];
+
+ (copl++)->l = CWAIT(0, 10);
+ (copl++)->l = CMOVE(par->bplcon0, bplcon0);
+ (copl++)->l = CMOVE(0, sprpt[0]);
+ (copl++)->l = CMOVE2(0, sprpt[0]);
+
+ if (par->bplcon0 & BPC0_LACE) {
+ cops = copdisplay.list[currentcop][0];
+
+ (cops++)->l = CWAIT(0, 10);
+ (cops++)->l = CMOVE(par->bplcon0, bplcon0);
+ (cops++)->l = CMOVE(0, sprpt[0]);
+ (cops++)->l = CMOVE2(0, sprpt[0]);
+
+ (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
+ (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
+ (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
+ (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
+ if (!IS_OCS) {
+ (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
+ par->diwstop_h, par->diwstop_v + 1), diwhigh);
+ (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
+ par->diwstop_h, par->diwstop_v), diwhigh);
+#if 0
+ if (par->beamcon0 & BMC0_VARBEAMEN) {
+ (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+ (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
+ (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
+ (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+ (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
+ (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
+ }
+#endif
+ }
+ p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
+ (copl++)->l = CMOVE(highw(p), cop2lc);
+ (copl++)->l = CMOVE2(loww(p), cop2lc);
+ p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
+ (cops++)->l = CMOVE(highw(p), cop2lc);
+ (cops++)->l = CMOVE2(loww(p), cop2lc);
+ copdisplay.rebuild[0] = cops;
+ } else {
+ (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
+ (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
+ if (!IS_OCS) {
+ (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
+ par->diwstop_h, par->diwstop_v), diwhigh);
+#if 0
+ if (par->beamcon0 & BMC0_VARBEAMEN) {
+ (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
+ (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
+ (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
+ }
+#endif
+ }
+ }
+ copdisplay.rebuild[1] = copl;
+
+ ami_update_par(info);
+ ami_rebuild_copper(info->par);
+}
-static struct fb_ops amifb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = amifb_check_var,
- .fb_set_par = amifb_set_par,
- .fb_setcolreg = amifb_setcolreg,
- .fb_blank = amifb_blank,
- .fb_pan_display = amifb_pan_display,
- .fb_fillrect = amifb_fillrect,
- .fb_copyarea = amifb_copyarea,
- .fb_imageblit = amifb_imageblit,
- .fb_ioctl = amifb_ioctl,
-};
static void __init amifb_setup_mcap(char *spec)
{
@@ -1216,13 +2339,13 @@ static void __init amifb_setup_mcap(char *spec)
if (hmax <= 0 || hmax <= hmin)
return;
- fb_info.monspecs.vfmin = vmin;
- fb_info.monspecs.vfmax = vmax;
- fb_info.monspecs.hfmin = hmin;
- fb_info.monspecs.hfmax = hmax;
+ amifb_hfmin = hmin;
+ amifb_hfmax = hmax;
+ amifb_vfmin = vmin;
+ amifb_vfmax = vmax;
}
-int __init amifb_setup(char *options)
+static int __init amifb_setup(char *options)
{
char *this_opt;
@@ -1238,9 +2361,9 @@ int __init amifb_setup(char *options)
} else if (!strcmp(this_opt, "ilbm"))
amifb_ilbm = 1;
else if (!strncmp(this_opt, "monitorcap:", 11))
- amifb_setup_mcap(this_opt+11);
+ amifb_setup_mcap(this_opt + 11);
else if (!strncmp(this_opt, "fstart:", 7))
- min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
+ min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
else
mode_option = this_opt;
}
@@ -1259,7 +2382,8 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
struct amifb_par par;
/* Validate wanted screen parameters */
- if ((err = ami_decode_var(var, &par)))
+ err = ami_decode_var(var, &par, info);
+ if (err)
return err;
/* Encode (possibly rounded) screen parameters */
@@ -1270,16 +2394,19 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
static int amifb_set_par(struct fb_info *info)
{
- struct amifb_par *par = (struct amifb_par *)info->par;
+ struct amifb_par *par = info->par;
+ int error;
do_vmode_pan = 0;
do_vmode_full = 0;
/* Decode wanted screen parameters */
- ami_decode_var(&info->var, par);
+ error = ami_decode_var(&info->var, par, info);
+ if (error)
+ return error;
/* Set new videomode */
- ami_build_copper();
+ ami_build_copper(info);
/* Set VBlank trigger */
do_vmode_full = 1;
@@ -1295,20 +2422,20 @@ static int amifb_set_par(struct fb_info *info)
info->fix.type = FB_TYPE_PLANES;
info->fix.type_aux = 0;
}
- info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));
+ info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
if (par->vmode & FB_VMODE_YWRAP) {
info->fix.ywrapstep = 1;
info->fix.xpanstep = 0;
info->fix.ypanstep = 0;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
- FBINFO_READS_FAST; /* override SCROLL_REDRAW */
+ FBINFO_READS_FAST; /* override SCROLL_REDRAW */
} else {
info->fix.ywrapstep = 0;
if (par->vmode & FB_VMODE_SMOOTH_XPAN)
info->fix.xpanstep = 1;
else
- info->fix.xpanstep = 16<<maxfmode;
+ info->fix.xpanstep = 16 << maxfmode;
info->fix.ypanstep = 1;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
}
@@ -1317,6 +2444,95 @@ static int amifb_set_par(struct fb_info *info)
/*
+ * Set a single color register. The values supplied are already
+ * rounded down to the hardware's capabilities (according to the
+ * entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ const struct amifb_par *par = info->par;
+
+ if (IS_AGA) {
+ if (regno > 255)
+ return 1;
+ } else if (par->bplcon0 & BPC0_SHRES) {
+ if (regno > 3)
+ return 1;
+ } else {
+ if (regno > 31)
+ return 1;
+ }
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ if (!regno) {
+ red0 = red;
+ green0 = green;
+ blue0 = blue;
+ }
+
+ /*
+ * Update the corresponding Hardware Color Register, unless it's Color
+ * Register 0 and the screen is blanked.
+ *
+ * VBlank is switched off to protect bplcon3 or ecs_palette[] from
+ * being changed by ami_do_blank() during the VBlank.
+ */
+
+ if (regno || !is_blanked) {
+#if defined(CONFIG_FB_AMIGA_AGA)
+ if (IS_AGA) {
+ u_short bplcon3 = par->bplcon3;
+ VBlankOff();
+ custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
+ custom.color[regno & 31] = rgb2hw8_high(red, green,
+ blue);
+ custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
+ BPC3_LOCT;
+ custom.color[regno & 31] = rgb2hw8_low(red, green,
+ blue);
+ custom.bplcon3 = bplcon3;
+ VBlankOn();
+ } else
+#endif
+#if defined(CONFIG_FB_AMIGA_ECS)
+ if (par->bplcon0 & BPC0_SHRES) {
+ u_short color, mask;
+ int i;
+
+ mask = 0x3333;
+ color = rgb2hw2(red, green, blue);
+ VBlankOff();
+ for (i = regno + 12; i >= (int)regno; i -= 4)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ mask <<= 2; color >>= 2;
+ regno = down16(regno) + mul4(mod4(regno));
+ for (i = regno + 3; i >= (int)regno; i--)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ VBlankOn();
+ } else
+#endif
+ custom.color[regno] = rgb2hw4(red, green, blue);
+ }
+ return 0;
+}
+
+
+ /*
+ * Blank the display.
+ */
+
+static int amifb_blank(int blank, struct fb_info *info)
+{
+ do_blank = blank ? blank : -1;
+
+ return 0;
+}
+
+
+ /*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
@@ -1327,18 +2543,19 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
{
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 ||
- var->yoffset >= info->var.yres_virtual || var->xoffset)
- return -EINVAL;
+ var->yoffset >= info->var.yres_virtual || var->xoffset)
+ return -EINVAL;
} else {
/*
* TODO: There will be problems when xpan!=1, so some columns
* on the right side will never be seen
*/
- if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||
- var->yoffset+info->var.yres > info->var.yres_virtual)
+ if (var->xoffset + info->var.xres >
+ upx(16 << maxfmode, info->var.xres_virtual) ||
+ var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
- ami_pan_var(var);
+ ami_pan_var(var, info);
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
@@ -1360,10 +2577,10 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
#endif
- /*
- * Compose two values, using a bitmask as decision value
- * This is equivalent to (a & mask) | (b & ~mask)
- */
+ /*
+ * Compose two values, using a bitmask as decision value
+ * This is equivalent to (a & mask) | (b & ~mask)
+ */
static inline unsigned long comp(unsigned long a, unsigned long b,
unsigned long mask)
@@ -1379,29 +2596,29 @@ static inline unsigned long xor(unsigned long a, unsigned long b,
}
- /*
- * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
- */
+ /*
+ * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
+ */
static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
int src_idx, u32 n)
{
unsigned long first, last;
- int shift = dst_idx-src_idx, left, right;
+ int shift = dst_idx - src_idx, left, right;
unsigned long d0, d1;
int m;
if (!n)
return;
- shift = dst_idx-src_idx;
+ shift = dst_idx - src_idx;
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
+ last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
if (!shift) {
// Same alignment for source and dest
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single word
if (last)
first &= last;
@@ -1413,7 +2630,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
*dst = comp(*src, *dst, first);
dst++;
src++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1439,17 +2656,17 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
} else {
// Different alignment for source and dest
- right = shift & (BITS_PER_LONG-1);
- left = -shift & (BITS_PER_LONG-1);
+ right = shift & (BITS_PER_LONG - 1);
+ left = -shift & (BITS_PER_LONG - 1);
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single destination word
if (last)
first &= last;
if (shift > 0) {
// Single source word
*dst = comp(*src >> right, *dst, first);
- } else if (src_idx+n <= BITS_PER_LONG) {
+ } else if (src_idx + n <= BITS_PER_LONG) {
// Single source word
*dst = comp(*src << left, *dst, first);
} else {
@@ -1467,7 +2684,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
// Single source word
*dst = comp(d0 >> right, *dst, first);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
} else {
// 2 source words
d1 = *src++;
@@ -1475,7 +2692,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
first);
d0 = d1;
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1519,40 +2736,40 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
}
- /*
- * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
- */
+ /*
+ * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
+ */
static void bitcpy_rev(unsigned long *dst, int dst_idx,
const unsigned long *src, int src_idx, u32 n)
{
unsigned long first, last;
- int shift = dst_idx-src_idx, left, right;
+ int shift = dst_idx - src_idx, left, right;
unsigned long d0, d1;
int m;
if (!n)
return;
- dst += (n-1)/BITS_PER_LONG;
- src += (n-1)/BITS_PER_LONG;
- if ((n-1) % BITS_PER_LONG) {
- dst_idx += (n-1) % BITS_PER_LONG;
+ dst += (n - 1) / BITS_PER_LONG;
+ src += (n - 1) / BITS_PER_LONG;
+ if ((n - 1) % BITS_PER_LONG) {
+ dst_idx += (n - 1) % BITS_PER_LONG;
dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= BITS_PER_LONG-1;
- src_idx += (n-1) % BITS_PER_LONG;
+ dst_idx &= BITS_PER_LONG - 1;
+ src_idx += (n - 1) % BITS_PER_LONG;
src += src_idx >> SHIFT_PER_LONG;
- src_idx &= BITS_PER_LONG-1;
+ src_idx &= BITS_PER_LONG - 1;
}
- shift = dst_idx-src_idx;
- first = ~0UL << (BITS_PER_LONG-1-dst_idx);
- last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
+ shift = dst_idx - src_idx;
+ first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
+ last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
if (!shift) {
// Same alignment for source and dest
- if ((unsigned long)dst_idx+1 >= n) {
+ if ((unsigned long)dst_idx + 1 >= n) {
// Single word
if (last)
first &= last;
@@ -1564,7 +2781,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
*dst = comp(*src, *dst, first);
dst--;
src--;
- n -= dst_idx+1;
+ n -= dst_idx + 1;
}
// Main chunk
@@ -1590,17 +2807,17 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
} else {
// Different alignment for source and dest
- right = shift & (BITS_PER_LONG-1);
- left = -shift & (BITS_PER_LONG-1);
+ right = shift & (BITS_PER_LONG - 1);
+ left = -shift & (BITS_PER_LONG - 1);
- if ((unsigned long)dst_idx+1 >= n) {
+ if ((unsigned long)dst_idx + 1 >= n) {
// Single destination word
if (last)
first &= last;
if (shift < 0) {
// Single source word
*dst = comp(*src << left, *dst, first);
- } else if (1+(unsigned long)src_idx >= n) {
+ } else if (1 + (unsigned long)src_idx >= n) {
// Single source word
*dst = comp(*src >> right, *dst, first);
} else {
@@ -1618,7 +2835,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
// Single source word
*dst = comp(d0 << left, *dst, first);
dst--;
- n -= dst_idx+1;
+ n -= dst_idx + 1;
} else {
// 2 source words
d1 = *src--;
@@ -1626,7 +2843,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
first);
d0 = d1;
dst--;
- n -= dst_idx+1;
+ n -= dst_idx + 1;
}
// Main chunk
@@ -1670,30 +2887,30 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
}
- /*
- * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
- * accesses
- */
+ /*
+ * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
+ * accesses
+ */
static void bitcpy_not(unsigned long *dst, int dst_idx,
const unsigned long *src, int src_idx, u32 n)
{
unsigned long first, last;
- int shift = dst_idx-src_idx, left, right;
+ int shift = dst_idx - src_idx, left, right;
unsigned long d0, d1;
int m;
if (!n)
return;
- shift = dst_idx-src_idx;
+ shift = dst_idx - src_idx;
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
+ last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
if (!shift) {
// Same alignment for source and dest
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single word
if (last)
first &= last;
@@ -1705,7 +2922,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
*dst = comp(~*src, *dst, first);
dst++;
src++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1731,17 +2948,17 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
} else {
// Different alignment for source and dest
- right = shift & (BITS_PER_LONG-1);
- left = -shift & (BITS_PER_LONG-1);
+ right = shift & (BITS_PER_LONG - 1);
+ left = -shift & (BITS_PER_LONG - 1);
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single destination word
if (last)
first &= last;
if (shift > 0) {
// Single source word
*dst = comp(~*src >> right, *dst, first);
- } else if (src_idx+n <= BITS_PER_LONG) {
+ } else if (src_idx + n <= BITS_PER_LONG) {
// Single source word
*dst = comp(~*src << left, *dst, first);
} else {
@@ -1759,7 +2976,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
// Single source word
*dst = comp(d0 >> right, *dst, first);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
} else {
// 2 source words
d1 = ~*src++;
@@ -1767,7 +2984,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
first);
d0 = d1;
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1811,9 +3028,9 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
}
- /*
- * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
- */
+ /*
+ * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
+ */
static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
{
@@ -1828,9 +3045,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
#endif
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
+ last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single word
if (last)
first &= last;
@@ -1841,7 +3058,7 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
if (first) {
*dst = comp(val, *dst, first);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1867,9 +3084,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
}
- /*
- * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
- */
+ /*
+ * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
+ */
static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
{
@@ -1884,9 +3101,9 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
#endif
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
+ last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
- if (dst_idx+n <= BITS_PER_LONG) {
+ if (dst_idx + n <= BITS_PER_LONG) {
// Single word
if (last)
first &= last;
@@ -1897,7 +3114,7 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
if (first) {
*dst = xor(val, *dst, first);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= BITS_PER_LONG - dst_idx;
}
// Main chunk
@@ -1924,12 +3141,12 @@ static inline void fill_one_line(int bpp, unsigned long next_plane,
{
while (1) {
dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
+ dst_idx &= (BITS_PER_LONG - 1);
bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
if (!--bpp)
break;
color >>= 1;
- dst_idx += next_plane*8;
+ dst_idx += next_plane * 8;
}
}
@@ -1939,12 +3156,12 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
{
while (color) {
dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
+ dst_idx &= (BITS_PER_LONG - 1);
bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
if (!--bpp)
break;
color >>= 1;
- dst_idx += next_plane*8;
+ dst_idx += next_plane * 8;
}
}
@@ -1952,7 +3169,7 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
static void amifb_fillrect(struct fb_info *info,
const struct fb_fillrect *rect)
{
- struct amifb_par *par = (struct amifb_par *)info->par;
+ struct amifb_par *par = info->par;
int dst_idx, x2, y2;
unsigned long *dst;
u32 width, height;
@@ -1972,23 +3189,23 @@ static void amifb_fillrect(struct fb_info *info,
height = y2 - rect->dy;
dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
- dst_idx += rect->dy*par->next_line*8+rect->dx;
+ ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+ dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+ dst_idx += rect->dy * par->next_line * 8 + rect->dx;
while (height--) {
switch (rect->rop) {
- case ROP_COPY:
+ case ROP_COPY:
fill_one_line(info->var.bits_per_pixel,
par->next_plane, dst, dst_idx, width,
rect->color);
break;
- case ROP_XOR:
+ case ROP_XOR:
xor_one_line(info->var.bits_per_pixel, par->next_plane,
dst, dst_idx, width, rect->color);
break;
}
- dst_idx += par->next_line*8;
+ dst_idx += par->next_line * 8;
}
}
@@ -1998,14 +3215,14 @@ static inline void copy_one_line(int bpp, unsigned long next_plane,
{
while (1) {
dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
+ dst_idx &= (BITS_PER_LONG - 1);
src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BITS_PER_LONG-1);
+ src_idx &= (BITS_PER_LONG - 1);
bitcpy(dst, dst_idx, src, src_idx, n);
if (!--bpp)
break;
- dst_idx += next_plane*8;
- src_idx += next_plane*8;
+ dst_idx += next_plane * 8;
+ src_idx += next_plane * 8;
}
}
@@ -2015,14 +3232,14 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
{
while (1) {
dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
+ dst_idx &= (BITS_PER_LONG - 1);
src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BITS_PER_LONG-1);
+ src_idx &= (BITS_PER_LONG - 1);
bitcpy_rev(dst, dst_idx, src, src_idx, n);
if (!--bpp)
break;
- dst_idx += next_plane*8;
- src_idx += next_plane*8;
+ dst_idx += next_plane * 8;
+ src_idx += next_plane * 8;
}
}
@@ -2030,7 +3247,7 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
static void amifb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
- struct amifb_par *par = (struct amifb_par *)info->par;
+ struct amifb_par *par = info->par;
int x2, y2;
u32 dx, dy, sx, sy, width, height;
unsigned long *dst, *src;
@@ -2065,16 +3282,16 @@ static void amifb_copyarea(struct fb_info *info,
rev_copy = 1;
}
dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
+ ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
src = dst;
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
+ dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
src_idx = dst_idx;
- dst_idx += dy*par->next_line*8+dx;
- src_idx += sy*par->next_line*8+sx;
+ dst_idx += dy * par->next_line * 8 + dx;
+ src_idx += sy * par->next_line * 8 + sx;
if (rev_copy) {
while (height--) {
- dst_idx -= par->next_line*8;
- src_idx -= par->next_line*8;
+ dst_idx -= par->next_line * 8;
+ src_idx -= par->next_line * 8;
copy_one_line_rev(info->var.bits_per_pixel,
par->next_plane, dst, dst_idx, src,
src_idx, width);
@@ -2084,8 +3301,8 @@ static void amifb_copyarea(struct fb_info *info,
copy_one_line(info->var.bits_per_pixel,
par->next_plane, dst, dst_idx, src,
src_idx, width);
- dst_idx += par->next_line*8;
- src_idx += par->next_line*8;
+ dst_idx += par->next_line * 8;
+ src_idx += par->next_line * 8;
}
}
}
@@ -2095,34 +3312,35 @@ static inline void expand_one_line(int bpp, unsigned long next_plane,
unsigned long *dst, int dst_idx, u32 n,
const u8 *data, u32 bgcolor, u32 fgcolor)
{
- const unsigned long *src;
- int src_idx;
-
- while (1) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
- if ((bgcolor ^ fgcolor) & 1) {
- src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));
- src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;
- if (fgcolor & 1)
- bitcpy(dst, dst_idx, src, src_idx, n);
- else
- bitcpy_not(dst, dst_idx, src, src_idx, n);
- /* set or clear */
- } else
- bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
- if (!--bpp)
- break;
- bgcolor >>= 1;
- fgcolor >>= 1;
- dst_idx += next_plane*8;
- }
+ const unsigned long *src;
+ int src_idx;
+
+ while (1) {
+ dst += dst_idx >> SHIFT_PER_LONG;
+ dst_idx &= (BITS_PER_LONG - 1);
+ if ((bgcolor ^ fgcolor) & 1) {
+ src = (unsigned long *)
+ ((unsigned long)data & ~(BYTES_PER_LONG - 1));
+ src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
+ if (fgcolor & 1)
+ bitcpy(dst, dst_idx, src, src_idx, n);
+ else
+ bitcpy_not(dst, dst_idx, src, src_idx, n);
+ /* set or clear */
+ } else
+ bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
+ if (!--bpp)
+ break;
+ bgcolor >>= 1;
+ fgcolor >>= 1;
+ dst_idx += next_plane * 8;
+ }
}
static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct amifb_par *par = (struct amifb_par *)info->par;
+ struct amifb_par *par = info->par;
int x2, y2;
unsigned long *dst;
int dst_idx;
@@ -2145,17 +3363,17 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
if (image->depth == 1) {
dst = (unsigned long *)
- ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
- dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
- dst_idx += dy*par->next_line*8+dx;
+ ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+ dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+ dst_idx += dy * par->next_line * 8 + dx;
src = image->data;
- pitch = (image->width+7)/8;
+ pitch = (image->width + 7) / 8;
while (height--) {
expand_one_line(info->var.bits_per_pixel,
par->next_plane, dst, dst_idx, width,
src, image->bg_color,
image->fg_color);
- dst_idx += par->next_line*8;
+ dst_idx += par->next_line * 8;
src += pitch;
}
} else {
@@ -2182,45 +3400,119 @@ static int amifb_ioctl(struct fb_info *info,
int i;
switch (cmd) {
- case FBIOGET_FCURSORINFO:
- i = ami_get_fix_cursorinfo(&crsr.fix);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.fix,
- sizeof(crsr.fix)) ? -EFAULT : 0;
-
- case FBIOGET_VCURSORINFO:
- i = ami_get_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo __user *)arg)->data);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.var,
- sizeof(crsr.var)) ? -EFAULT : 0;
-
- case FBIOPUT_VCURSORINFO:
- if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
- return -EFAULT;
- return ami_set_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo __user *)arg)->data);
-
- case FBIOGET_CURSORSTATE:
- i = ami_get_cursorstate(&crsr.state);
- if (i)
- return i;
- return copy_to_user(argp, &crsr.state,
- sizeof(crsr.state)) ? -EFAULT : 0;
-
- case FBIOPUT_CURSORSTATE:
- if (copy_from_user(&crsr.state, argp,
- sizeof(crsr.state)))
- return -EFAULT;
- return ami_set_cursorstate(&crsr.state);
+ case FBIOGET_FCURSORINFO:
+ i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
+ if (i)
+ return i;
+ return copy_to_user(argp, &crsr.fix,
+ sizeof(crsr.fix)) ? -EFAULT : 0;
+
+ case FBIOGET_VCURSORINFO:
+ i = ami_get_var_cursorinfo(&crsr.var,
+ ((struct fb_var_cursorinfo __user *)arg)->data,
+ info->par);
+ if (i)
+ return i;
+ return copy_to_user(argp, &crsr.var,
+ sizeof(crsr.var)) ? -EFAULT : 0;
+
+ case FBIOPUT_VCURSORINFO:
+ if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
+ return -EFAULT;
+ return ami_set_var_cursorinfo(&crsr.var,
+ ((struct fb_var_cursorinfo __user *)arg)->data,
+ info->par);
+
+ case FBIOGET_CURSORSTATE:
+ i = ami_get_cursorstate(&crsr.state, info->par);
+ if (i)
+ return i;
+ return copy_to_user(argp, &crsr.state,
+ sizeof(crsr.state)) ? -EFAULT : 0;
+
+ case FBIOPUT_CURSORSTATE:
+ if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
+ return -EFAULT;
+ return ami_set_cursorstate(&crsr.state, info->par);
}
return -EINVAL;
}
/*
+ * Flash the cursor (called by VBlank interrupt)
+ */
+
+static int flash_cursor(void)
+{
+ static int cursorcount = 1;
+
+ if (cursormode == FB_CURSOR_FLASH) {
+ if (!--cursorcount) {
+ cursorstate = -cursorstate;
+ cursorcount = cursorrate;
+ if (!is_blanked)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+ /*
+ * VBlank Display Interrupt
+ */
+
+static irqreturn_t amifb_interrupt(int irq, void *dev_id)
+{
+ struct amifb_par *par = dev_id;
+
+ if (do_vmode_pan || do_vmode_full)
+ ami_update_display(par);
+
+ if (do_vmode_full)
+ ami_init_display(par);
+
+ if (do_vmode_pan) {
+ flash_cursor();
+ ami_rebuild_copper(par);
+ do_cursor = do_vmode_pan = 0;
+ } else if (do_cursor) {
+ flash_cursor();
+ ami_set_sprite(par);
+ do_cursor = 0;
+ } else {
+ if (flash_cursor())
+ ami_set_sprite(par);
+ }
+
+ if (do_blank) {
+ ami_do_blank(par);
+ do_blank = 0;
+ }
+
+ if (do_vmode_full) {
+ ami_reinit_copper(par);
+ do_vmode_full = 0;
+ }
+ return IRQ_HANDLED;
+}
+
+
+static struct fb_ops amifb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = amifb_check_var,
+ .fb_set_par = amifb_set_par,
+ .fb_setcolreg = amifb_setcolreg,
+ .fb_blank = amifb_blank,
+ .fb_pan_display = amifb_pan_display,
+ .fb_fillrect = amifb_fillrect,
+ .fb_copyarea = amifb_copyarea,
+ .fb_imageblit = amifb_imageblit,
+ .fb_ioctl = amifb_ioctl,
+};
+
+
+ /*
* Allocate, Clear and Align a Block of Chip Memory
*/
@@ -2250,6 +3542,7 @@ static inline void chipfree(void)
static int __init amifb_probe(struct platform_device *pdev)
{
+ struct fb_info *info;
int tag, i, err = 0;
u_long chipptr;
u_int defmode;
@@ -2265,71 +3558,80 @@ static int __init amifb_probe(struct platform_device *pdev)
#endif
custom.dmacon = DMAF_ALL | DMAF_MASTER;
+ info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
+ if (!info) {
+ dev_err(&pdev->dev, "framebuffer_alloc failed\n");
+ return -ENOMEM;
+ }
+
+ strcpy(info->fix.id, "Amiga ");
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ info->fix.accel = FB_ACCEL_AMIGABLITT;
+
switch (amiga_chipset) {
#ifdef CONFIG_FB_AMIGA_OCS
- case CS_OCS:
- strcat(fb_info.fix.id, "OCS");
+ case CS_OCS:
+ strcat(info->fix.id, "OCS");
default_chipset:
- chipset = TAG_OCS;
- maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
- maxdepth[TAG_HIRES] = 4;
- maxdepth[TAG_LORES] = 6;
- maxfmode = TAG_FMODE_1;
- defmode = amiga_vblank == 50 ? DEFMODE_PAL
- : DEFMODE_NTSC;
- fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
- break;
+ chipset = TAG_OCS;
+ maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
+ maxdepth[TAG_HIRES] = 4;
+ maxdepth[TAG_LORES] = 6;
+ maxfmode = TAG_FMODE_1;
+ defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
+ info->fix.smem_len = VIDEOMEMSIZE_OCS;
+ break;
#endif /* CONFIG_FB_AMIGA_OCS */
#ifdef CONFIG_FB_AMIGA_ECS
- case CS_ECS:
- strcat(fb_info.fix.id, "ECS");
- chipset = TAG_ECS;
- maxdepth[TAG_SHRES] = 2;
- maxdepth[TAG_HIRES] = 4;
- maxdepth[TAG_LORES] = 6;
- maxfmode = TAG_FMODE_1;
- if (AMIGAHW_PRESENT(AMBER_FF))
- defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
- : DEFMODE_AMBER_NTSC;
- else
- defmode = amiga_vblank == 50 ? DEFMODE_PAL
- : DEFMODE_NTSC;
- if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
- VIDEOMEMSIZE_ECS_2M)
- fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
- else
- fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
- break;
+ case CS_ECS:
+ strcat(info->fix.id, "ECS");
+ chipset = TAG_ECS;
+ maxdepth[TAG_SHRES] = 2;
+ maxdepth[TAG_HIRES] = 4;
+ maxdepth[TAG_LORES] = 6;
+ maxfmode = TAG_FMODE_1;
+ if (AMIGAHW_PRESENT(AMBER_FF))
+ defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
+ : DEFMODE_AMBER_NTSC;
+ else
+ defmode = amiga_vblank == 50 ? DEFMODE_PAL
+ : DEFMODE_NTSC;
+ if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
+ VIDEOMEMSIZE_ECS_2M)
+ info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
+ else
+ info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
+ break;
#endif /* CONFIG_FB_AMIGA_ECS */
#ifdef CONFIG_FB_AMIGA_AGA
- case CS_AGA:
- strcat(fb_info.fix.id, "AGA");
- chipset = TAG_AGA;
- maxdepth[TAG_SHRES] = 8;
- maxdepth[TAG_HIRES] = 8;
- maxdepth[TAG_LORES] = 8;
- maxfmode = TAG_FMODE_4;
- defmode = DEFMODE_AGA;
- if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
- VIDEOMEMSIZE_AGA_2M)
- fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
- else
- fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
- break;
+ case CS_AGA:
+ strcat(info->fix.id, "AGA");
+ chipset = TAG_AGA;
+ maxdepth[TAG_SHRES] = 8;
+ maxdepth[TAG_HIRES] = 8;
+ maxdepth[TAG_LORES] = 8;
+ maxfmode = TAG_FMODE_4;
+ defmode = DEFMODE_AGA;
+ if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
+ VIDEOMEMSIZE_AGA_2M)
+ info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
+ else
+ info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
+ break;
#endif /* CONFIG_FB_AMIGA_AGA */
- default:
+ default:
#ifdef CONFIG_FB_AMIGA_OCS
- printk("Unknown graphics chipset, defaulting to OCS\n");
- strcat(fb_info.fix.id, "Unknown");
- goto default_chipset;
+ printk("Unknown graphics chipset, defaulting to OCS\n");
+ strcat(info->fix.id, "Unknown");
+ goto default_chipset;
#else /* CONFIG_FB_AMIGA_OCS */
- err = -ENODEV;
- goto amifb_error;
+ err = -ENODEV;
+ goto release;
#endif /* CONFIG_FB_AMIGA_OCS */
- break;
+ break;
}
/*
@@ -2356,42 +3658,44 @@ default_chipset:
}
}
- /*
- * These monitor specs are for a typical Amiga monitor (e.g. A1960)
- */
- if (fb_info.monspecs.hfmin == 0) {
- fb_info.monspecs.hfmin = 15000;
- fb_info.monspecs.hfmax = 38000;
- fb_info.monspecs.vfmin = 49;
- fb_info.monspecs.vfmax = 90;
+ if (amifb_hfmin) {
+ info->monspecs.hfmin = amifb_hfmin;
+ info->monspecs.hfmax = amifb_hfmax;
+ info->monspecs.vfmin = amifb_vfmin;
+ info->monspecs.vfmax = amifb_vfmax;
+ } else {
+ /*
+ * These are for a typical Amiga monitor (e.g. A1960)
+ */
+ info->monspecs.hfmin = 15000;
+ info->monspecs.hfmax = 38000;
+ info->monspecs.vfmin = 49;
+ info->monspecs.vfmax = 90;
}
- fb_info.fbops = &amifb_ops;
- fb_info.par = &currentpar;
- fb_info.flags = FBINFO_DEFAULT;
- fb_info.device = &pdev->dev;
+ info->fbops = &amifb_ops;
+ info->flags = FBINFO_DEFAULT;
+ info->device = &pdev->dev;
- if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
+ if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
err = -EINVAL;
- goto amifb_error;
+ goto release;
}
fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
- &fb_info.modelist);
+ &info->modelist);
round_down_bpp = 0;
- chipptr = chipalloc(fb_info.fix.smem_len+
- SPRITEMEMSIZE+
- DUMMYSPRITEMEMSIZE+
- COPINITSIZE+
- 4*COPLISTSIZE);
+ chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
+ DUMMYSPRITEMEMSIZE + COPINITSIZE +
+ 4 * COPLISTSIZE);
if (!chipptr) {
err = -ENOMEM;
- goto amifb_error;
+ goto release;
}
- assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
+ assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
@@ -2403,1398 +3707,78 @@ default_chipset:
/*
* access the videomem with writethrough cache
*/
- fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
- videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
- fb_info.fix.smem_len);
+ info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
+ videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
+ info->fix.smem_len);
if (!videomemory) {
- printk("amifb: WARNING! unable to map videomem cached writethrough\n");
- fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
+ dev_warn(&pdev->dev,
+ "Unable to map videomem cached writethrough\n");
+ info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
} else
- fb_info.screen_base = (char *)videomemory;
+ info->screen_base = (char *)videomemory;
memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
/*
- * Enable Display DMA
- */
-
- custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
- DMAF_BLITTER | DMAF_SPRITE;
-
- /*
* Make sure the Copper has something to do
*/
-
ami_init_copper();
- if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
- "fb vertb handler", &currentpar)) {
- err = -EBUSY;
- goto amifb_error;
- }
-
- err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
- if (err)
- goto amifb_error;
-
- if (register_framebuffer(&fb_info) < 0) {
- err = -EINVAL;
- goto amifb_error;
- }
-
- printk("fb%d: %s frame buffer device, using %dK of video memory\n",
- fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
-
- return 0;
-
-amifb_error:
- amifb_deinit(pdev);
- return err;
-}
-
-static void amifb_deinit(struct platform_device *pdev)
-{
- if (fb_info.cmap.len)
- fb_dealloc_cmap(&fb_info.cmap);
- fb_dealloc_cmap(&fb_info.cmap);
- chipfree();
- if (videomemory)
- iounmap((void*)videomemory);
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
-}
-
-
- /*
- * Blank the display.
- */
-
-static int amifb_blank(int blank, struct fb_info *info)
-{
- do_blank = blank ? blank : -1;
-
- return 0;
-}
-
- /*
- * Flash the cursor (called by VBlank interrupt)
- */
-
-static int flash_cursor(void)
-{
- static int cursorcount = 1;
-
- if (cursormode == FB_CURSOR_FLASH) {
- if (!--cursorcount) {
- cursorstate = -cursorstate;
- cursorcount = cursorrate;
- if (!is_blanked)
- return 1;
- }
- }
- return 0;
-}
-
- /*
- * VBlank Display Interrupt
- */
-
-static irqreturn_t amifb_interrupt(int irq, void *dev_id)
-{
- if (do_vmode_pan || do_vmode_full)
- ami_update_display();
-
- if (do_vmode_full)
- ami_init_display();
-
- if (do_vmode_pan) {
- flash_cursor();
- ami_rebuild_copper();
- do_cursor = do_vmode_pan = 0;
- } else if (do_cursor) {
- flash_cursor();
- ami_set_sprite();
- do_cursor = 0;
- } else {
- if (flash_cursor())
- ami_set_sprite();
- }
-
- if (do_blank) {
- ami_do_blank();
- do_blank = 0;
- }
-
- if (do_vmode_full) {
- ami_reinit_copper();
- do_vmode_full = 0;
- }
- return IRQ_HANDLED;
-}
-
-/* --------------------------- Hardware routines --------------------------- */
-
- /*
- * Get the video params out of `var'. If a value doesn't fit, round
- * it up, if it's too big, return -EINVAL.
- */
-
-static int ami_decode_var(struct fb_var_screeninfo *var,
- struct amifb_par *par)
-{
- u_short clk_shift, line_shift;
- u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
- u_int htotal, vtotal;
-
- /*
- * Find a matching Pixel Clock
- */
-
- for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
- if (var->pixclock <= pixclock[clk_shift])
- break;
- if (clk_shift > TAG_LORES) {
- DPRINTK("pixclock too high\n");
- return -EINVAL;
- }
- par->clk_shift = clk_shift;
-
- /*
- * Check the Geometry Values
- */
-
- if ((par->xres = var->xres) < 64)
- par->xres = 64;
- if ((par->yres = var->yres) < 64)
- par->yres = 64;
- if ((par->vxres = var->xres_virtual) < par->xres)
- par->vxres = par->xres;
- if ((par->vyres = var->yres_virtual) < par->yres)
- par->vyres = par->yres;
-
- par->bpp = var->bits_per_pixel;
- if (!var->nonstd) {
- if (par->bpp < 1)
- par->bpp = 1;
- if (par->bpp > maxdepth[clk_shift]) {
- if (round_down_bpp && maxdepth[clk_shift])
- par->bpp = maxdepth[clk_shift];
- else {
- DPRINTK("invalid bpp\n");
- return -EINVAL;
- }
- }
- } else if (var->nonstd == FB_NONSTD_HAM) {
- if (par->bpp < 6)
- par->bpp = 6;
- if (par->bpp != 6) {
- if (par->bpp < 8)
- par->bpp = 8;
- if (par->bpp != 8 || !IS_AGA) {
- DPRINTK("invalid bpp for ham mode\n");
- return -EINVAL;
- }
- }
- } else {
- DPRINTK("unknown nonstd mode\n");
- return -EINVAL;
- }
-
- /*
- * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
- * checks failed and smooth scrolling is not possible
- */
-
- par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
- switch (par->vmode & FB_VMODE_MASK) {
- case FB_VMODE_INTERLACED:
- line_shift = 0;
- break;
- case FB_VMODE_NONINTERLACED:
- line_shift = 1;
- break;
- case FB_VMODE_DOUBLE:
- if (!IS_AGA) {
- DPRINTK("double mode only possible with aga\n");
- return -EINVAL;
- }
- line_shift = 2;
- break;
- default:
- DPRINTK("unknown video mode\n");
- return -EINVAL;
- break;
- }
- par->line_shift = line_shift;
-
- /*
- * Vertical and Horizontal Timings
- */
-
- xres_n = par->xres<<clk_shift;
- yres_n = par->yres<<line_shift;
- par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
- par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
-
- if (IS_AGA)
- par->bplcon3 = sprpixmode[clk_shift];
- else
- par->bplcon3 = 0;
- if (var->sync & FB_SYNC_BROADCAST) {
- par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
- if (IS_AGA)
- par->diwstop_h += mod4(var->hsync_len);
- else
- par->diwstop_h = down4(par->diwstop_h);
-
- par->diwstrt_h = par->diwstop_h - xres_n;
- par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
- par->diwstrt_v = par->diwstop_v - yres_n;
- if (par->diwstop_h >= par->htotal+8) {
- DPRINTK("invalid diwstop_h\n");
- return -EINVAL;
- }
- if (par->diwstop_v > par->vtotal) {
- DPRINTK("invalid diwstop_v\n");
- return -EINVAL;
- }
-
- if (!IS_OCS) {
- /* Initialize sync with some reasonable values for pwrsave */
- par->hsstrt = 160;
- par->hsstop = 320;
- par->vsstrt = 30;
- par->vsstop = 34;
- } else {
- par->hsstrt = 0;
- par->hsstop = 0;
- par->vsstrt = 0;
- par->vsstop = 0;
- }
- if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
- /* PAL video mode */
- if (par->htotal != PAL_HTOTAL) {
- DPRINTK("htotal invalid for pal\n");
- return -EINVAL;
- }
- if (par->diwstrt_h < PAL_DIWSTRT_H) {
- DPRINTK("diwstrt_h too low for pal\n");
- return -EINVAL;
- }
- if (par->diwstrt_v < PAL_DIWSTRT_V) {
- DPRINTK("diwstrt_v too low for pal\n");
- return -EINVAL;
- }
- htotal = PAL_HTOTAL>>clk_shift;
- vtotal = PAL_VTOTAL>>1;
- if (!IS_OCS) {
- par->beamcon0 = BMC0_PAL;
- par->bplcon3 |= BPC3_BRDRBLNK;
- } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
- AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
- par->beamcon0 = BMC0_PAL;
- par->hsstop = 1;
- } else if (amiga_vblank != 50) {
- DPRINTK("pal not supported by this chipset\n");
- return -EINVAL;
- }
- } else {
- /* NTSC video mode
- * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
- * and NTSC activated, so than better let diwstop_h <= 1812
- */
- if (par->htotal != NTSC_HTOTAL) {
- DPRINTK("htotal invalid for ntsc\n");
- return -EINVAL;
- }
- if (par->diwstrt_h < NTSC_DIWSTRT_H) {
- DPRINTK("diwstrt_h too low for ntsc\n");
- return -EINVAL;
- }
- if (par->diwstrt_v < NTSC_DIWSTRT_V) {
- DPRINTK("diwstrt_v too low for ntsc\n");
- return -EINVAL;
- }
- htotal = NTSC_HTOTAL>>clk_shift;
- vtotal = NTSC_VTOTAL>>1;
- if (!IS_OCS) {
- par->beamcon0 = 0;
- par->bplcon3 |= BPC3_BRDRBLNK;
- } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
- AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
- par->beamcon0 = 0;
- par->hsstop = 1;
- } else if (amiga_vblank != 60) {
- DPRINTK("ntsc not supported by this chipset\n");
- return -EINVAL;
- }
- }
- if (IS_OCS) {
- if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
- par->diwstrt_v >= 512 || par->diwstop_v < 256) {
- DPRINTK("invalid position for display on ocs\n");
- return -EINVAL;
- }
- }
- } else if (!IS_OCS) {
- /* Programmable video mode */
- par->hsstrt = var->right_margin<<clk_shift;
- par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
- par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
- if (!IS_AGA)
- par->diwstop_h = down4(par->diwstop_h) - 16;
- par->diwstrt_h = par->diwstop_h - xres_n;
- par->hbstop = par->diwstrt_h + 4;
- par->hbstrt = par->diwstop_h + 4;
- if (par->hbstrt >= par->htotal + 8)
- par->hbstrt -= par->htotal;
- par->hcenter = par->hsstrt + (par->htotal >> 1);
- par->vsstrt = var->lower_margin<<line_shift;
- par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
- par->diwstop_v = par->vtotal;
- if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
- par->diwstop_v -= 2;
- par->diwstrt_v = par->diwstop_v - yres_n;
- par->vbstop = par->diwstrt_v - 2;
- par->vbstrt = par->diwstop_v - 2;
- if (par->vtotal > 2048) {
- DPRINTK("vtotal too high\n");
- return -EINVAL;
- }
- if (par->htotal > 2048) {
- DPRINTK("htotal too high\n");
- return -EINVAL;
- }
- par->bplcon3 |= BPC3_EXTBLKEN;
- par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
- BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
- BMC0_PAL | BMC0_VARCSYEN;
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- par->beamcon0 |= BMC0_HSYTRUE;
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- par->beamcon0 |= BMC0_VSYTRUE;
- if (var->sync & FB_SYNC_COMP_HIGH_ACT)
- par->beamcon0 |= BMC0_CSYTRUE;
- htotal = par->htotal>>clk_shift;
- vtotal = par->vtotal>>1;
- } else {
- DPRINTK("only broadcast modes possible for ocs\n");
- return -EINVAL;
- }
-
- /*
- * Checking the DMA timing
- */
-
- fconst = 16<<maxfmode<<clk_shift;
-
- /*
- * smallest window start value without turn off other dma cycles
- * than sprite1-7, unless you change min_fstrt
- */
-
-
- fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
- fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
- if (fstrt < min_fstrt) {
- DPRINTK("fetch start too low\n");
- return -EINVAL;
- }
-
- /*
- * smallest window start value where smooth scrolling is possible
- */
-
- fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
- if (fstrt < min_fstrt)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- maxfetchstop = down16(par->htotal - 80);
-
- fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
- fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
- if (fstrt + fsize > maxfetchstop)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- fsize = upx(fconst, xres_n);
- if (fstrt + fsize > maxfetchstop) {
- DPRINTK("fetch stop too high\n");
- return -EINVAL;
- }
-
- if (maxfmode + clk_shift <= 1) {
- fsize = up64(xres_n + fconst - 1);
- if (min_fstrt + fsize - 64 > maxfetchstop)
- par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
-
- fsize = up64(xres_n);
- if (min_fstrt + fsize - 64 > maxfetchstop) {
- DPRINTK("fetch size too high\n");
- return -EINVAL;
- }
-
- fsize -= 64;
- } else
- fsize -= fconst;
-
- /*
- * Check if there is enough time to update the bitplane pointers for ywrap
- */
-
- if (par->htotal-fsize-64 < par->bpp*64)
- par->vmode &= ~FB_VMODE_YWRAP;
-
- /*
- * Bitplane calculations and check the Memory Requirements
- */
-
- if (amifb_ilbm) {
- par->next_plane = div8(upx(16<<maxfmode, par->vxres));
- par->next_line = par->bpp*par->next_plane;
- if (par->next_line * par->vyres > fb_info.fix.smem_len) {
- DPRINTK("too few video mem\n");
- return -EINVAL;
- }
- } else {
- par->next_line = div8(upx(16<<maxfmode, par->vxres));
- par->next_plane = par->vyres*par->next_line;
- if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
- DPRINTK("too few video mem\n");
- return -EINVAL;
- }
- }
-
- /*
- * Hardware Register Values
- */
-
- par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
- if (!IS_OCS)
- par->bplcon0 |= BPC0_ECSENA;
- if (par->bpp == 8)
- par->bplcon0 |= BPC0_BPU3;
- else
- par->bplcon0 |= par->bpp<<12;
- if (var->nonstd == FB_NONSTD_HAM)
- par->bplcon0 |= BPC0_HAM;
- if (var->sync & FB_SYNC_EXT)
- par->bplcon0 |= BPC0_ERSY;
-
- if (IS_AGA)
- par->fmode = bplfetchmode[maxfmode];
-
- switch (par->vmode & FB_VMODE_MASK) {
- case FB_VMODE_INTERLACED:
- par->bplcon0 |= BPC0_LACE;
- break;
- case FB_VMODE_DOUBLE:
- if (IS_AGA)
- par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
- break;
- }
-
- if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
- par->xoffset = var->xoffset;
- par->yoffset = var->yoffset;
- if (par->vmode & FB_VMODE_YWRAP) {
- if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
- par->xoffset = par->yoffset = 0;
- } else {
- if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
- par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
- par->xoffset = par->yoffset = 0;
- }
- } else
- par->xoffset = par->yoffset = 0;
-
- par->crsr.crsr_x = par->crsr.crsr_y = 0;
- par->crsr.spot_x = par->crsr.spot_y = 0;
- par->crsr.height = par->crsr.width = 0;
-
- return 0;
-}
-
- /*
- * Fill the `var' structure based on the values in `par' and maybe
- * other values read out of the hardware.
- */
-
-static int ami_encode_var(struct fb_var_screeninfo *var,
- struct amifb_par *par)
-{
- u_short clk_shift, line_shift;
-
- memset(var, 0, sizeof(struct fb_var_screeninfo));
-
- clk_shift = par->clk_shift;
- line_shift = par->line_shift;
-
- var->xres = par->xres;
- var->yres = par->yres;
- var->xres_virtual = par->vxres;
- var->yres_virtual = par->vyres;
- var->xoffset = par->xoffset;
- var->yoffset = par->yoffset;
-
- var->bits_per_pixel = par->bpp;
- var->grayscale = 0;
-
- var->red.offset = 0;
- var->red.msb_right = 0;
- var->red.length = par->bpp;
- if (par->bplcon0 & BPC0_HAM)
- var->red.length -= 2;
- var->blue = var->green = var->red;
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
-
- if (par->bplcon0 & BPC0_HAM)
- var->nonstd = FB_NONSTD_HAM;
- else
- var->nonstd = 0;
- var->activate = 0;
-
- var->height = -1;
- var->width = -1;
-
- var->pixclock = pixclock[clk_shift];
-
- if (IS_AGA && par->fmode & FMODE_BSCAN2)
- var->vmode = FB_VMODE_DOUBLE;
- else if (par->bplcon0 & BPC0_LACE)
- var->vmode = FB_VMODE_INTERLACED;
- else
- var->vmode = FB_VMODE_NONINTERLACED;
-
- if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
- var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
- var->right_margin = par->hsstrt>>clk_shift;
- var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
- var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
- var->lower_margin = par->vsstrt>>line_shift;
- var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
- var->sync = 0;
- if (par->beamcon0 & BMC0_HSYTRUE)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (par->beamcon0 & BMC0_VSYTRUE)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (par->beamcon0 & BMC0_CSYTRUE)
- var->sync |= FB_SYNC_COMP_HIGH_ACT;
- } else {
- var->sync = FB_SYNC_BROADCAST;
- var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
- var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
- var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
- var->vsync_len = 4>>line_shift;
- var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
- var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
- var->lower_margin - var->vsync_len;
- }
-
- if (par->bplcon0 & BPC0_ERSY)
- var->sync |= FB_SYNC_EXT;
- if (par->vmode & FB_VMODE_YWRAP)
- var->vmode |= FB_VMODE_YWRAP;
-
- return 0;
-}
-
-
/*
- * Pan or Wrap the Display
- *
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
- * in `var'.
- */
-
-static void ami_pan_var(struct fb_var_screeninfo *var)
-{
- struct amifb_par *par = &currentpar;
-
- par->xoffset = var->xoffset;
- par->yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP)
- par->vmode |= FB_VMODE_YWRAP;
- else
- par->vmode &= ~FB_VMODE_YWRAP;
-
- do_vmode_pan = 0;
- ami_update_par();
- do_vmode_pan = 1;
-}
-
- /*
- * Update hardware
- */
-
-static int ami_update_par(void)
-{
- struct amifb_par *par = &currentpar;
- short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
-
- clk_shift = par->clk_shift;
-
- if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
- par->xoffset = upx(16<<maxfmode, par->xoffset);
-
- fconst = 16<<maxfmode<<clk_shift;
- vshift = modx(16<<maxfmode, par->xoffset);
- fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
- fsize = (par->xres+vshift)<<clk_shift;
- shift = modx(fconst, fstrt);
- move = downx(2<<maxfmode, div8(par->xoffset));
- if (maxfmode + clk_shift > 1) {
- fstrt = downx(fconst, fstrt) - 64;
- fsize = upx(fconst, fsize);
- fstop = fstrt + fsize - fconst;
- } else {
- mod = fstrt = downx(fconst, fstrt) - fconst;
- fstop = fstrt + upx(fconst, fsize) - 64;
- fsize = up64(fsize);
- fstrt = fstop - fsize + 64;
- if (fstrt < min_fstrt) {
- fstop += min_fstrt - fstrt;
- fstrt = min_fstrt;
- }
- move = move - div8((mod-fstrt)>>clk_shift);
- }
- mod = par->next_line - div8(fsize>>clk_shift);
- par->ddfstrt = fstrt;
- par->ddfstop = fstop;
- par->bplcon1 = hscroll2hw(shift);
- par->bpl2mod = mod;
- if (par->bplcon0 & BPC0_LACE)
- par->bpl2mod += par->next_line;
- if (IS_AGA && (par->fmode & FMODE_BSCAN2))
- par->bpl1mod = -div8(fsize>>clk_shift);
- else
- par->bpl1mod = par->bpl2mod;
-
- if (par->yoffset) {
- par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
- if (par->vmode & FB_VMODE_YWRAP) {
- if (par->yoffset > par->vyres-par->yres) {
- par->bplpt0wrap = fb_info.fix.smem_start + move;
- if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
- par->bplpt0wrap += par->next_line;
- }
- }
- } else
- par->bplpt0 = fb_info.fix.smem_start + move;
-
- if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
- par->bplpt0 += par->next_line;
-
- return 0;
-}
-
-
- /*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
-{
- if (IS_AGA) {
- if (regno > 255)
- return 1;
- } else if (currentpar.bplcon0 & BPC0_SHRES) {
- if (regno > 3)
- return 1;
- } else {
- if (regno > 31)
- return 1;
- }
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- if (!regno) {
- red0 = red;
- green0 = green;
- blue0 = blue;
- }
-
- /*
- * Update the corresponding Hardware Color Register, unless it's Color
- * Register 0 and the screen is blanked.
- *
- * VBlank is switched off to protect bplcon3 or ecs_palette[] from
- * being changed by ami_do_blank() during the VBlank.
- */
-
- if (regno || !is_blanked) {
-#if defined(CONFIG_FB_AMIGA_AGA)
- if (IS_AGA) {
- u_short bplcon3 = currentpar.bplcon3;
- VBlankOff();
- custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
- custom.color[regno&31] = rgb2hw8_high(red, green, blue);
- custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
- custom.color[regno&31] = rgb2hw8_low(red, green, blue);
- custom.bplcon3 = bplcon3;
- VBlankOn();
- } else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
- if (currentpar.bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- VBlankOff();
- for (i = regno+12; i >= (int)regno; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<=2; color >>= 2;
- regno = down16(regno)+mul4(mod4(regno));
- for (i = regno+3; i >= (int)regno; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- VBlankOn();
- } else
-#endif
- custom.color[regno] = rgb2hw4(red, green, blue);
- }
- return 0;
-}
-
-static void ami_update_display(void)
-{
- struct amifb_par *par = &currentpar;
-
- custom.bplcon1 = par->bplcon1;
- custom.bpl1mod = par->bpl1mod;
- custom.bpl2mod = par->bpl2mod;
- custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
- custom.ddfstop = ddfstop2hw(par->ddfstop);
-}
-
- /*
- * Change the video mode (called by VBlank interrupt)
- */
-
-static void ami_init_display(void)
-{
- struct amifb_par *par = &currentpar;
- int i;
-
- custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
- custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
- if (!IS_OCS) {
- custom.bplcon3 = par->bplcon3;
- if (IS_AGA)
- custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- custom.htotal = htotal2hw(par->htotal);
- custom.hbstrt = hbstrt2hw(par->hbstrt);
- custom.hbstop = hbstop2hw(par->hbstop);
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.hcenter = hcenter2hw(par->hcenter);
- custom.vtotal = vtotal2hw(par->vtotal);
- custom.vbstrt = vbstrt2hw(par->vbstrt);
- custom.vbstop = vbstop2hw(par->vbstop);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstop2hw(par->vsstop);
- }
- }
- if (!IS_OCS || par->hsstop)
- custom.beamcon0 = par->beamcon0;
- if (IS_AGA)
- custom.fmode = par->fmode;
-
- /*
- * The minimum period for audio depends on htotal
- */
-
- amiga_audio_min_period = div16(par->htotal);
-
- is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
-#if 1
- if (is_lace) {
- i = custom.vposr >> 15;
- } else {
- custom.vposw = custom.vposr | 0x8000;
- i = 1;
- }
-#else
- i = 1;
- custom.vposw = custom.vposr | 0x8000;
-#endif
- custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
-}
-
- /*
- * (Un)Blank the screen (called by VBlank interrupt)
+ * Enable Display DMA
*/
+ custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
+ DMAF_BLITTER | DMAF_SPRITE;
-static void ami_do_blank(void)
-{
- struct amifb_par *par = &currentpar;
-#if defined(CONFIG_FB_AMIGA_AGA)
- u_short bplcon3 = par->bplcon3;
-#endif
- u_char red, green, blue;
-
- if (do_blank > 0) {
- custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
- red = green = blue = 0;
- if (!IS_OCS && do_blank > 1) {
- switch (do_blank) {
- case FB_BLANK_VSYNC_SUSPEND:
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.vsstrt = vsstrt2hw(par->vtotal+4);
- custom.vsstop = vsstop2hw(par->vtotal+4);
- break;
- case FB_BLANK_HSYNC_SUSPEND:
- custom.hsstrt = hsstrt2hw(par->htotal+16);
- custom.hsstop = hsstop2hw(par->htotal+16);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstrt2hw(par->vsstop);
- break;
- case FB_BLANK_POWERDOWN:
- custom.hsstrt = hsstrt2hw(par->htotal+16);
- custom.hsstop = hsstop2hw(par->htotal+16);
- custom.vsstrt = vsstrt2hw(par->vtotal+4);
- custom.vsstop = vsstop2hw(par->vtotal+4);
- break;
- }
- if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
- custom.htotal = htotal2hw(par->htotal);
- custom.vtotal = vtotal2hw(par->vtotal);
- custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
- BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
- }
- }
- } else {
- custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
- red = red0;
- green = green0;
- blue = blue0;
- if (!IS_OCS) {
- custom.hsstrt = hsstrt2hw(par->hsstrt);
- custom.hsstop = hsstop2hw(par->hsstop);
- custom.vsstrt = vsstrt2hw(par->vsstrt);
- custom.vsstop = vsstop2hw(par->vsstop);
- custom.beamcon0 = par->beamcon0;
- }
- }
-#if defined(CONFIG_FB_AMIGA_AGA)
- if (IS_AGA) {
- custom.bplcon3 = bplcon3;
- custom.color[0] = rgb2hw8_high(red, green, blue);
- custom.bplcon3 = bplcon3 | BPC3_LOCT;
- custom.color[0] = rgb2hw8_low(red, green, blue);
- custom.bplcon3 = bplcon3;
- } else
-#endif
-#if defined(CONFIG_FB_AMIGA_ECS)
- if (par->bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- for (i = 12; i >= 0; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<=2; color >>= 2;
- for (i = 3; i >= 0; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- } else
-#endif
- custom.color[0] = rgb2hw4(red, green, blue);
- is_blanked = do_blank > 0 ? do_blank : 0;
-}
-
-static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
-{
- struct amifb_par *par = &currentpar;
-
- fix->crsr_width = fix->crsr_xsize = par->crsr.width;
- fix->crsr_height = fix->crsr_ysize = par->crsr.height;
- fix->crsr_color1 = 17;
- fix->crsr_color2 = 18;
- return 0;
-}
-
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
-{
- struct amifb_par *par = &currentpar;
- register u_short *lspr, *sspr;
-#ifdef __mc68000__
- register u_long datawords asm ("d2");
-#else
- register u_long datawords;
-#endif
- register short delta;
- register u_char color;
- short height, width, bits, words;
- int size, alloc;
-
- size = par->crsr.height*par->crsr.width;
- alloc = var->height*var->width;
- var->height = par->crsr.height;
- var->width = par->crsr.width;
- var->xspot = par->crsr.spot_x;
- var->yspot = par->crsr.spot_y;
- if (size > var->height*var->width)
- return -ENAMETOOLONG;
- if (!access_ok(VERIFY_WRITE, data, size))
- return -EFAULT;
- delta = 1<<par->crsr.fmode;
- lspr = lofsprite + (delta<<1);
- if (par->bplcon0 & BPC0_LACE)
- sspr = shfsprite + (delta<<1);
- else
- sspr = NULL;
- for (height = (short)var->height-1; height >= 0; height--) {
- bits = 0; words = delta; datawords = 0;
- for (width = (short)var->width-1; width >= 0; width--) {
- if (bits == 0) {
- bits = 16; --words;
-#ifdef __mc68000__
- asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
- : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
-#else
- datawords = (*(lspr+delta) << 16) | (*lspr++);
-#endif
- }
- --bits;
-#ifdef __mc68000__
- asm volatile (
- "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
- "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
- : "=d" (color), "=d" (datawords) : "1" (datawords));
-#else
- color = (((datawords >> 30) & 2)
- | ((datawords >> 15) & 1));
- datawords <<= 1;
-#endif
- put_user(color, data++);
- }
- if (bits > 0) {
- --words; ++lspr;
- }
- while (--words >= 0)
- ++lspr;
-#ifdef __mc68000__
- asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
- : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
- lspr += delta;
- if (sspr) {
- u_short *tmp = lspr;
- lspr = sspr;
- sspr = tmp;
- }
-#endif
- }
- return 0;
-}
-
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
-{
- struct amifb_par *par = &currentpar;
- register u_short *lspr, *sspr;
-#ifdef __mc68000__
- register u_long datawords asm ("d2");
-#else
- register u_long datawords;
-#endif
- register short delta;
- u_short fmode;
- short height, width, bits, words;
+ err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
+ "fb vertb handler", info->par);
+ if (err)
+ goto disable_dma;
- if (!var->width)
- return -EINVAL;
- else if (var->width <= 16)
- fmode = TAG_FMODE_1;
- else if (var->width <= 32)
- fmode = TAG_FMODE_2;
- else if (var->width <= 64)
- fmode = TAG_FMODE_4;
- else
- return -EINVAL;
- if (fmode > maxfmode)
- return -EINVAL;
- if (!var->height)
- return -EINVAL;
- if (!access_ok(VERIFY_READ, data, var->width*var->height))
- return -EFAULT;
- delta = 1<<fmode;
- lofsprite = shfsprite = (u_short *)spritememory;
- lspr = lofsprite + (delta<<1);
- if (par->bplcon0 & BPC0_LACE) {
- if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
- return -EINVAL;
- memset(lspr, 0, (var->height+4)<<fmode<<2);
- shfsprite += ((var->height+5)&-2)<<fmode;
- sspr = shfsprite + (delta<<1);
- } else {
- if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
- return -EINVAL;
- memset(lspr, 0, (var->height+2)<<fmode<<2);
- sspr = NULL;
- }
- for (height = (short)var->height-1; height >= 0; height--) {
- bits = 16; words = delta; datawords = 0;
- for (width = (short)var->width-1; width >= 0; width--) {
- unsigned long tdata = 0;
- get_user(tdata, data);
- data++;
-#ifdef __mc68000__
- asm volatile (
- "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
- "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
- : "=d" (datawords)
- : "0" (datawords), "d" (tdata));
-#else
- datawords = ((datawords << 1) & 0xfffefffe);
- datawords |= tdata & 1;
- datawords |= (tdata & 2) << (16-1);
-#endif
- if (--bits == 0) {
- bits = 16; --words;
-#ifdef __mc68000__
- asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
-#else
- *(lspr+delta) = (u_short) (datawords >> 16);
- *lspr++ = (u_short) (datawords & 0xffff);
-#endif
- }
- }
- if (bits < 16) {
- --words;
-#ifdef __mc68000__
- asm volatile (
- "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
- "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
-#else
- *(lspr+delta) = (u_short) (datawords >> (16+bits));
- *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
-#endif
- }
- while (--words >= 0) {
-#ifdef __mc68000__
- asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
- : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
-#else
- *(lspr+delta) = 0;
- *lspr++ = 0;
-#endif
- }
-#ifdef __mc68000__
- asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
- : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
-#else
- lspr += delta;
- if (sspr) {
- u_short *tmp = lspr;
- lspr = sspr;
- sspr = tmp;
- }
-#endif
- }
- par->crsr.height = var->height;
- par->crsr.width = var->width;
- par->crsr.spot_x = var->xspot;
- par->crsr.spot_y = var->yspot;
- par->crsr.fmode = fmode;
- if (IS_AGA) {
- par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
- par->fmode |= sprfetchmode[fmode];
- custom.fmode = par->fmode;
- }
- return 0;
-}
+ err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
+ if (err)
+ goto free_irq;
-static int ami_get_cursorstate(struct fb_cursorstate *state)
-{
- struct amifb_par *par = &currentpar;
+ dev_set_drvdata(&pdev->dev, info);
- state->xoffset = par->crsr.crsr_x;
- state->yoffset = par->crsr.crsr_y;
- state->mode = cursormode;
- return 0;
-}
+ err = register_framebuffer(info);
+ if (err)
+ goto unset_drvdata;
-static int ami_set_cursorstate(struct fb_cursorstate *state)
-{
- struct amifb_par *par = &currentpar;
+ printk("fb%d: %s frame buffer device, using %dK of video memory\n",
+ info->node, info->fix.id, info->fix.smem_len>>10);
- par->crsr.crsr_x = state->xoffset;
- par->crsr.crsr_y = state->yoffset;
- if ((cursormode = state->mode) == FB_CURSOR_OFF)
- cursorstate = -1;
- do_cursor = 1;
return 0;
-}
-
-static void ami_set_sprite(void)
-{
- struct amifb_par *par = &currentpar;
- copins *copl, *cops;
- u_short hs, vs, ve;
- u_long pl, ps, pt;
- short mx, my;
-
- cops = copdisplay.list[currentcop][0];
- copl = copdisplay.list[currentcop][1];
- ps = pl = ZTWO_PADDR(dummysprite);
- mx = par->crsr.crsr_x-par->crsr.spot_x;
- my = par->crsr.crsr_y-par->crsr.spot_y;
- if (!(par->vmode & FB_VMODE_YWRAP)) {
- mx -= par->xoffset;
- my -= par->yoffset;
- }
- if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
- mx > -(short)par->crsr.width && mx < par->xres &&
- my > -(short)par->crsr.height && my < par->yres) {
- pl = ZTWO_PADDR(lofsprite);
- hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
- vs = par->diwstrt_v + (my<<par->line_shift);
- ve = vs + (par->crsr.height<<par->line_shift);
- if (par->bplcon0 & BPC0_LACE) {
- ps = ZTWO_PADDR(shfsprite);
- lofsprite[0] = spr2hw_pos(vs, hs);
- shfsprite[0] = spr2hw_pos(vs+1, hs);
- if (mod2(vs)) {
- lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
- shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
- pt = pl; pl = ps; ps = pt;
- } else {
- lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
- shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
- }
- } else {
- lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
- lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
- }
- }
- copl[cop_spr0ptrh].w[1] = highw(pl);
- copl[cop_spr0ptrl].w[1] = loww(pl);
- if (par->bplcon0 & BPC0_LACE) {
- cops[cop_spr0ptrh].w[1] = highw(ps);
- cops[cop_spr0ptrl].w[1] = loww(ps);
- }
-}
-
-
- /*
- * Initialise the Copper Initialisation List
- */
-
-static void __init ami_init_copper(void)
-{
- copins *cop = copdisplay.init;
- u_long p;
- int i;
-
- if (!IS_OCS) {
- (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
- (cop++)->l = CMOVE(0x0181, diwstrt);
- (cop++)->l = CMOVE(0x0281, diwstop);
- (cop++)->l = CMOVE(0x0000, diwhigh);
- } else
- (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
- p = ZTWO_PADDR(dummysprite);
- for (i = 0; i < 8; i++) {
- (cop++)->l = CMOVE(0, spr[i].pos);
- (cop++)->l = CMOVE(highw(p), sprpt[i]);
- (cop++)->l = CMOVE2(loww(p), sprpt[i]);
- }
-
- (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
- copdisplay.wait = cop;
- (cop++)->l = CEND;
- (cop++)->l = CMOVE(0, copjmp2);
- cop->l = CEND;
-
- custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
- custom.copjmp1 = 0;
-}
-static void ami_reinit_copper(void)
-{
- struct amifb_par *par = &currentpar;
-
- copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
- copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
+unset_drvdata:
+ dev_set_drvdata(&pdev->dev, NULL);
+ fb_dealloc_cmap(&info->cmap);
+free_irq:
+ free_irq(IRQ_AMIGA_COPPER, info->par);
+disable_dma:
+ custom.dmacon = DMAF_ALL | DMAF_MASTER;
+ if (videomemory)
+ iounmap((void *)videomemory);
+ chipfree();
+release:
+ framebuffer_release(info);
+ return err;
}
- /*
- * Build the Copper List
- */
-
-static void ami_build_copper(void)
-{
- struct amifb_par *par = &currentpar;
- copins *copl, *cops;
- u_long p;
-
- currentcop = 1 - currentcop;
-
- copl = copdisplay.list[currentcop][1];
-
- (copl++)->l = CWAIT(0, 10);
- (copl++)->l = CMOVE(par->bplcon0, bplcon0);
- (copl++)->l = CMOVE(0, sprpt[0]);
- (copl++)->l = CMOVE2(0, sprpt[0]);
-
- if (par->bplcon0 & BPC0_LACE) {
- cops = copdisplay.list[currentcop][0];
-
- (cops++)->l = CWAIT(0, 10);
- (cops++)->l = CMOVE(par->bplcon0, bplcon0);
- (cops++)->l = CMOVE(0, sprpt[0]);
- (cops++)->l = CMOVE2(0, sprpt[0]);
-
- (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
- (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
- (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
- (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
- if (!IS_OCS) {
- (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
- par->diwstop_h, par->diwstop_v+1), diwhigh);
- (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
- par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
- (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
- (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
- (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
- }
-#endif
- }
- p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
- (copl++)->l = CMOVE(highw(p), cop2lc);
- (copl++)->l = CMOVE2(loww(p), cop2lc);
- p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
- (cops++)->l = CMOVE(highw(p), cop2lc);
- (cops++)->l = CMOVE2(loww(p), cop2lc);
- copdisplay.rebuild[0] = cops;
- } else {
- (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
- (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
- if (!IS_OCS) {
- (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
- par->diwstop_h, par->diwstop_v), diwhigh);
-#if 0
- if (par->beamcon0 & BMC0_VARBEAMEN) {
- (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
- (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
- (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
- }
-#endif
- }
- }
- copdisplay.rebuild[1] = copl;
-
- ami_update_par();
- ami_rebuild_copper();
-}
-
- /*
- * Rebuild the Copper List
- *
- * We only change the things that are not static
- */
-
-static void ami_rebuild_copper(void)
-{
- struct amifb_par *par = &currentpar;
- copins *copl, *cops;
- u_short line, h_end1, h_end2;
- short i;
- u_long p;
-
- if (IS_AGA && maxfmode + par->clk_shift == 0)
- h_end1 = par->diwstrt_h-64;
- else
- h_end1 = par->htotal-32;
- h_end2 = par->ddfstop+64;
-
- ami_set_sprite();
-
- copl = copdisplay.rebuild[1];
- p = par->bplpt0;
- if (par->vmode & FB_VMODE_YWRAP) {
- if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
- if (par->yoffset > par->vyres-par->yres) {
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (copl++)->l = CMOVE(highw(p), bplpt[i]);
- (copl++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
- while (line >= 512) {
- (copl++)->l = CWAIT(h_end1, 510);
- line -= 512;
- }
- if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
- (copl++)->l = CWAIT(h_end1, line);
- else
- (copl++)->l = CWAIT(h_end2, line);
- p = par->bplpt0wrap;
- }
- } else p = par->bplpt0wrap;
- }
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (copl++)->l = CMOVE(highw(p), bplpt[i]);
- (copl++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- copl->l = CEND;
-
- if (par->bplcon0 & BPC0_LACE) {
- cops = copdisplay.rebuild[0];
- p = par->bplpt0;
- if (mod2(par->diwstrt_v))
- p -= par->next_line;
- else
- p += par->next_line;
- if (par->vmode & FB_VMODE_YWRAP) {
- if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
- if (par->yoffset > par->vyres-par->yres+1) {
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (cops++)->l = CMOVE(highw(p), bplpt[i]);
- (cops++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
- while (line >= 512) {
- (cops++)->l = CWAIT(h_end1, 510);
- line -= 512;
- }
- if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
- (cops++)->l = CWAIT(h_end1, line);
- else
- (cops++)->l = CWAIT(h_end2, line);
- p = par->bplpt0wrap;
- if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
- p -= par->next_line;
- else
- p += par->next_line;
- }
- } else p = par->bplpt0wrap - par->next_line;
- }
- for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
- (cops++)->l = CMOVE(highw(p), bplpt[i]);
- (cops++)->l = CMOVE2(loww(p), bplpt[i]);
- }
- cops->l = CEND;
- }
-}
static int __exit amifb_remove(struct platform_device *pdev)
{
- unregister_framebuffer(&fb_info);
- amifb_deinit(pdev);
+ struct fb_info *info = dev_get_drvdata(&pdev->dev);
+
+ unregister_framebuffer(info);
+ dev_set_drvdata(&pdev->dev, NULL);
+ fb_dealloc_cmap(&info->cmap);
+ free_irq(IRQ_AMIGA_COPPER, info->par);
+ custom.dmacon = DMAF_ALL | DMAF_MASTER;
+ if (videomemory)
+ iounmap((void *)videomemory);
+ chipfree();
+ framebuffer_release(info);
amifb_video_off();
return 0;
}
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 63409c1..0d7b20d 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -100,8 +100,11 @@ static int atmel_bl_update_status(struct backlight_device *bl)
brightness = 0;
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
- lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
+ if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
brightness ? contrast_ctr : 0);
+ else
+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
@@ -682,14 +685,30 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
case FB_VISUAL_PSEUDOCOLOR:
if (regno < 256) {
- val = ((red >> 11) & 0x001f);
- val |= ((green >> 6) & 0x03e0);
- val |= ((blue >> 1) & 0x7c00);
-
- /*
- * TODO: intensity bit. Maybe something like
- * ~(red[10] ^ green[10] ^ blue[10]) & 1
- */
+ if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
+ || cpu_is_at91sam9rl()) {
+ /* old style I+BGR:555 */
+ val = ((red >> 11) & 0x001f);
+ val |= ((green >> 6) & 0x03e0);
+ val |= ((blue >> 1) & 0x7c00);
+
+ /*
+ * TODO: intensity bit. Maybe something like
+ * ~(red[10] ^ green[10] ^ blue[10]) & 1
+ */
+ } else {
+ /* new style BGR:565 / RGB:565 */
+ if (sinfo->lcd_wiring_mode ==
+ ATMEL_LCDC_WIRING_RGB) {
+ val = ((blue >> 11) & 0x001f);
+ val |= ((red >> 0) & 0xf800);
+ } else {
+ val = ((red >> 11) & 0x001f);
+ val |= ((blue >> 0) & 0xf800);
+ }
+
+ val |= ((green >> 5) & 0x07e0);
+ }
lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
ret = 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 44bdce4..622f12b 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -301,9 +301,9 @@ static struct fb_ops atyfb_ops = {
.fb_sync = atyfb_sync,
};
-static int noaccel;
+static bool noaccel;
#ifdef CONFIG_MTRR
-static int nomtrr;
+static bool nomtrr;
#endif
static int vram;
static int pll;
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 1506848..ce1506b 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -263,19 +263,19 @@ static reg_val common_regs[] = {
static char *mode_option;
static char *monitor_layout;
-static int noaccel = 0;
+static bool noaccel = 0;
static int default_dynclk = -2;
-static int nomodeset = 0;
-static int ignore_edid = 0;
-static int mirror = 0;
+static bool nomodeset = 0;
+static bool ignore_edid = 0;
+static bool mirror = 0;
static int panel_yres = 0;
-static int force_dfp = 0;
-static int force_measure_pll = 0;
+static bool force_dfp = 0;
+static bool force_measure_pll = 0;
#ifdef CONFIG_MTRR
-static int nomtrr = 0;
+static bool nomtrr = 0;
#endif
-static int force_sleep;
-static int ignore_devlist;
+static bool force_sleep;
+static bool ignore_devlist;
#ifdef CONFIG_PMAC_BACKLIGHT
static int backlight = 1;
#else
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 649cb35..de9da67 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -60,18 +60,6 @@
#include "au1100fb.h"
-/*
- * Sanity check. If this is a new Au1100 based board, search for
- * the PB1100 ifdefs to make sure you modify the code accordingly.
- */
-#if defined(CONFIG_MIPS_PB1100)
- #include <asm/mach-pb1x00/pb1100.h>
-#elif defined(CONFIG_MIPS_DB1100)
- #include <asm/mach-db1x00/db1x00.h>
-#else
- #error "Unknown Au1100 board, Au1100 FB driver not supported"
-#endif
-
#define DRIVER_NAME "au1100fb"
#define DRIVER_DESC "LCD controller driver for AU1100 processors"
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 7200559..04e4479 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -44,6 +44,7 @@
#include <linux/slab.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1200fb.h> /* platform_data */
#include "au1200fb.h"
#define DRIVER_NAME "au1200fb"
@@ -143,6 +144,7 @@ struct au1200_lcd_iodata_t {
/* Private, per-framebuffer management information (independent of the panel itself) */
struct au1200fb_device {
struct fb_info *fb_info; /* FB driver info record */
+ struct au1200fb_platdata *pd;
int plane;
unsigned char* fb_mem; /* FrameBuffer memory map */
@@ -201,9 +203,6 @@ struct window_settings {
#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
#endif
-extern int board_au1200fb_panel_init (void);
-extern int board_au1200fb_panel_shutdown (void);
-
/*
* Default window configurations
*/
@@ -334,8 +333,6 @@ struct panel_settings
uint32 mode_toyclksrc;
uint32 mode_backlight;
uint32 mode_auxpll;
- int (*device_init)(void);
- int (*device_shutdown)(void);
#define Xres min_xres
#define Yres min_yres
u32 min_xres; /* Minimum horizontal resolution */
@@ -385,8 +382,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
320, 320,
240, 240,
},
@@ -415,8 +410,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
640, 480,
640, 480,
},
@@ -445,8 +438,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
800, 800,
600, 600,
},
@@ -475,8 +466,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 6, /* 72MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
1024, 1024,
768, 768,
},
@@ -505,8 +494,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 10, /* 120MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
1280, 1280,
1024, 1024,
},
@@ -535,8 +522,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
1024, 1024,
768, 768,
},
@@ -568,8 +553,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
640, 480,
640, 480,
},
@@ -601,8 +584,6 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
320, 320,
240, 240,
},
@@ -634,11 +615,43 @@ static struct panel_settings known_lcd_panels[] =
.mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
856, 856,
480, 480,
},
+ [9] = {
+ .name = "DB1300_800x480",
+ .monspecs = {
+ .modedb = NULL,
+ .modedb_len = 0,
+ .hfmin = 30000,
+ .hfmax = 70000,
+ .vfmin = 60,
+ .vfmax = 60,
+ .dclkmin = 6000000,
+ .dclkmax = 28000000,
+ .input = FB_DISP_RGB,
+ },
+ .mode_screen = LCD_SCREEN_SX_N(800) |
+ LCD_SCREEN_SY_N(480),
+ .mode_horztiming = LCD_HORZTIMING_HPW_N(5) |
+ LCD_HORZTIMING_HND1_N(16) |
+ LCD_HORZTIMING_HND2_N(8),
+ .mode_verttiming = LCD_VERTTIMING_VPW_N(4) |
+ LCD_VERTTIMING_VND1_N(8) |
+ LCD_VERTTIMING_VND2_N(5),
+ .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(1) |
+ LCD_CLKCONTROL_IV |
+ LCD_CLKCONTROL_IH,
+ .mode_pwmdiv = 0x00000000,
+ .mode_pwmhi = 0x00000000,
+ .mode_outmask = 0x00FFFFFF,
+ .mode_fifoctrl = 0x2f2f2f2f,
+ .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
+ .mode_backlight = 0x00000000,
+ .mode_auxpll = (48/12) * 2,
+ 800, 800,
+ 480, 480,
+ },
};
#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
@@ -764,7 +777,8 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
return 0;
}
-static void au1200_setpanel (struct panel_settings *newpanel)
+static void au1200_setpanel(struct panel_settings *newpanel,
+ struct au1200fb_platdata *pd)
{
/*
* Perform global setup/init of LCD controller
@@ -798,8 +812,8 @@ static void au1200_setpanel (struct panel_settings *newpanel)
the controller, the clock cannot be turned off before first
shutting down the controller.
*/
- if (panel->device_shutdown != NULL)
- panel->device_shutdown();
+ if (pd->panel_shutdown)
+ pd->panel_shutdown();
}
/* Newpanel == NULL indicates a shutdown operation only */
@@ -852,7 +866,8 @@ static void au1200_setpanel (struct panel_settings *newpanel)
au_sync();
/* Call init of panel */
- if (panel->device_init != NULL) panel->device_init();
+ if (pd->panel_init)
+ pd->panel_init();
/* FIX!!!! not appropriate on panel change!!! Global setup/init */
lcd->intenable = 0;
@@ -1185,6 +1200,8 @@ static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
*/
static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
{
+ struct au1200fb_device *fbdev = fbi->par;
+
/* Short-circuit screen blanking */
if (noblanking)
return 0;
@@ -1194,13 +1211,13 @@ static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
case FB_BLANK_UNBLANK:
case FB_BLANK_NORMAL:
/* printk("turn on panel\n"); */
- au1200_setpanel(panel);
+ au1200_setpanel(panel, fbdev->pd);
break;
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
/* printk("turn off panel\n"); */
- au1200_setpanel(NULL);
+ au1200_setpanel(NULL, fbdev->pd);
break;
default:
break;
@@ -1428,6 +1445,7 @@ static void get_window(unsigned int plane,
static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
+ struct au1200fb_device *fbdev = info->par;
int plane;
int val;
@@ -1472,7 +1490,7 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
struct panel_settings *newpanel;
panel_index = iodata.global.panel_choice;
newpanel = &known_lcd_panels[panel_index];
- au1200_setpanel(newpanel);
+ au1200_setpanel(newpanel, fbdev->pd);
}
break;
@@ -1588,22 +1606,102 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
/*-------------------------------------------------------------------------*/
-/* AU1200 LCD controller device driver */
+static int au1200fb_setup(struct au1200fb_platdata *pd)
+{
+ char *options = NULL;
+ char *this_opt, *endptr;
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ int panel_idx = -1;
+
+ fb_get_options(DRIVER_NAME, &options);
+
+ if (!options)
+ goto out;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ /* Panel option - can be panel name,
+ * "bs" for board-switch, or number/index */
+ if (!strncmp(this_opt, "panel:", 6)) {
+ int i;
+ long int li;
+ char *endptr;
+ this_opt += 6;
+ /* First check for index, which allows
+ * to short circuit this mess */
+ li = simple_strtol(this_opt, &endptr, 0);
+ if (*endptr == '\0')
+ panel_idx = (int)li;
+ else if (strcmp(this_opt, "bs") == 0)
+ panel_idx = pd->panel_index();
+ else {
+ for (i = 0; i < num_panels; i++) {
+ if (!strcmp(this_opt,
+ known_lcd_panels[i].name)) {
+ panel_idx = i;
+ break;
+ }
+ }
+ }
+ if ((panel_idx < 0) || (panel_idx >= num_panels))
+ print_warn("Panel %s not supported!", this_opt);
+ else
+ panel_index = panel_idx;
+
+ } else if (strncmp(this_opt, "nohwcursor", 10) == 0)
+ nohwcursor = 1;
+ else if (strncmp(this_opt, "devices:", 8) == 0) {
+ this_opt += 8;
+ device_count = simple_strtol(this_opt, &endptr, 0);
+ if ((device_count < 0) ||
+ (device_count > MAX_DEVICE_COUNT))
+ device_count = MAX_DEVICE_COUNT;
+ } else if (strncmp(this_opt, "wincfg:", 7) == 0) {
+ this_opt += 7;
+ window_index = simple_strtol(this_opt, &endptr, 0);
+ if ((window_index < 0) ||
+ (window_index >= ARRAY_SIZE(windows)))
+ window_index = DEFAULT_WINDOW_INDEX;
+ } else if (strncmp(this_opt, "off", 3) == 0)
+ return 1;
+ else
+ print_warn("Unsupported option \"%s\"", this_opt);
+ }
+
+out:
+ return 0;
+}
+
+/* AU1200 LCD controller device driver */
static int __devinit au1200fb_drv_probe(struct platform_device *dev)
{
struct au1200fb_device *fbdev;
+ struct au1200fb_platdata *pd;
struct fb_info *fbi = NULL;
unsigned long page;
int bpp, plane, ret, irq;
+ print_info("" DRIVER_DESC "");
+
+ pd = dev->dev.platform_data;
+ if (!pd)
+ return -ENODEV;
+
+ /* Setup driver with options */
+ if (au1200fb_setup(pd))
+ return -ENODEV;
+
+ /* Point to the panel selected */
+ panel = &known_lcd_panels[panel_index];
+ win = &windows[window_index];
+
+ printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+ printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
/* shut gcc up */
ret = 0;
fbdev = NULL;
- /* Kickstart the panel */
- au1200_setpanel(panel);
-
for (plane = 0; plane < device_count; ++plane) {
bpp = winbpp(win->w[plane].mode_winctrl1);
if (win->w[plane].xres == 0)
@@ -1619,6 +1717,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
_au1200fb_infos[plane] = fbi;
fbdev = fbi->par;
fbdev->fb_info = fbi;
+ fbdev->pd = pd;
fbdev->plane = plane;
@@ -1680,6 +1779,11 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
goto failed;
}
+ platform_set_drvdata(dev, pd);
+
+ /* Kickstart the panel */
+ au1200_setpanel(panel, pd);
+
return 0;
failed:
@@ -1699,12 +1803,13 @@ failed:
static int __devexit au1200fb_drv_remove(struct platform_device *dev)
{
+ struct au1200fb_platdata *pd = platform_get_drvdata(dev);
struct au1200fb_device *fbdev;
struct fb_info *fbi;
int plane;
/* Turn off the panel */
- au1200_setpanel(NULL);
+ au1200_setpanel(NULL, pd);
for (plane = 0; plane < device_count; ++plane) {
fbi = _au1200fb_infos[plane];
@@ -1732,7 +1837,8 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int au1200fb_drv_suspend(struct device *dev)
{
- au1200_setpanel(NULL);
+ struct au1200fb_platdata *pd = dev_get_drvdata(dev);
+ au1200_setpanel(NULL, pd);
lcd->outmask = 0;
au_sync();
@@ -1742,11 +1848,12 @@ static int au1200fb_drv_suspend(struct device *dev)
static int au1200fb_drv_resume(struct device *dev)
{
+ struct au1200fb_platdata *pd = dev_get_drvdata(dev);
struct fb_info *fbi;
int i;
/* Kickstart the panel */
- au1200_setpanel(panel);
+ au1200_setpanel(panel, pd);
for (i = 0; i < device_count; i++) {
fbi = _au1200fb_infos[i];
@@ -1781,100 +1888,8 @@ static struct platform_driver au1200fb_driver = {
/*-------------------------------------------------------------------------*/
-/* Kernel driver */
-
-static int au1200fb_setup(void)
-{
- char *options = NULL;
- char *this_opt, *endptr;
- int num_panels = ARRAY_SIZE(known_lcd_panels);
- int panel_idx = -1;
-
- fb_get_options(DRIVER_NAME, &options);
-
- if (options) {
- while ((this_opt = strsep(&options,",")) != NULL) {
- /* Panel option - can be panel name,
- * "bs" for board-switch, or number/index */
- if (!strncmp(this_opt, "panel:", 6)) {
- int i;
- long int li;
- char *endptr;
- this_opt += 6;
- /* First check for index, which allows
- * to short circuit this mess */
- li = simple_strtol(this_opt, &endptr, 0);
- if (*endptr == '\0') {
- panel_idx = (int)li;
- }
- else if (strcmp(this_opt, "bs") == 0) {
- extern int board_au1200fb_panel(void);
- panel_idx = board_au1200fb_panel();
- }
-
- else
- for (i = 0; i < num_panels; i++) {
- if (!strcmp(this_opt, known_lcd_panels[i].name)) {
- panel_idx = i;
- break;
- }
- }
-
- if ((panel_idx < 0) || (panel_idx >= num_panels)) {
- print_warn("Panel %s not supported!", this_opt);
- }
- else
- panel_index = panel_idx;
- }
-
- else if (strncmp(this_opt, "nohwcursor", 10) == 0) {
- nohwcursor = 1;
- }
-
- else if (strncmp(this_opt, "devices:", 8) == 0) {
- this_opt += 8;
- device_count = simple_strtol(this_opt,
- &endptr, 0);
- if ((device_count < 0) ||
- (device_count > MAX_DEVICE_COUNT))
- device_count = MAX_DEVICE_COUNT;
- }
-
- else if (strncmp(this_opt, "wincfg:", 7) == 0) {
- this_opt += 7;
- window_index = simple_strtol(this_opt,
- &endptr, 0);
- if ((window_index < 0) ||
- (window_index >= ARRAY_SIZE(windows)))
- window_index = DEFAULT_WINDOW_INDEX;
- }
-
- else if (strncmp(this_opt, "off", 3) == 0)
- return 1;
- /* Unsupported option */
- else {
- print_warn("Unsupported option \"%s\"", this_opt);
- }
- }
- }
- return 0;
-}
-
static int __init au1200fb_init(void)
{
- print_info("" DRIVER_DESC "");
-
- /* Setup driver with options */
- if (au1200fb_setup())
- return -ENODEV;
-
- /* Point to the panel selected */
- panel = &known_lcd_panels[panel_index];
- win = &windows[window_index];
-
- printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
- printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
-
return platform_driver_register(&au1200fb_driver);
}
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index 1105fa1..a1376dc 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -270,17 +270,7 @@ static struct platform_driver pm860x_backlight_driver = {
.remove = pm860x_backlight_remove,
};
-static int __init pm860x_backlight_init(void)
-{
- return platform_driver_register(&pm860x_backlight_driver);
-}
-module_init(pm860x_backlight_init);
-
-static void __exit pm860x_backlight_exit(void)
-{
- platform_driver_unregister(&pm860x_backlight_driver);
-}
-module_exit(pm860x_backlight_exit);
+module_platform_driver(pm860x_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 278aeaa..681b369 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -280,14 +280,6 @@ config BACKLIGHT_WM831X
If you have a backlight driven by the ISINK and DCDC of a
WM831x PMIC say y to enable the backlight driver for it.
-config BACKLIGHT_ADX
- tristate "Avionic Design Xanthos Backlight Driver"
- depends on ARCH_PXA_ADX
- default y
- help
- Say Y to enable the backlight driver on Avionic Design Xanthos-based
- boards.
-
config BACKLIGHT_ADP5520
tristate "Backlight Driver for ADP5520/ADP5501 using WLED"
depends on PMIC_ADP5520
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index fdd1fc4..af5cf65 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
-obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index dfb763e..2e630bf 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -384,17 +384,7 @@ static struct platform_driver adp5520_bl_driver = {
.resume = adp5520_bl_resume,
};
-static int __init adp5520_bl_init(void)
-{
- return platform_driver_register(&adp5520_bl_driver);
-}
-module_init(adp5520_bl_init);
-
-static void __exit adp5520_bl_exit(void)
-{
- platform_driver_unregister(&adp5520_bl_driver);
-}
-module_exit(adp5520_bl_exit);
+module_platform_driver(adp5520_bl_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADP5520(01) Backlight Driver");
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
deleted file mode 100644
index c861c41..0000000
--- a/drivers/video/backlight/adx_bl.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * linux/drivers/video/backlight/adx.c
- *
- * Copyright (C) 2009 Avionic Design GmbH
- *
- * 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.
- *
- * Written by Thierry Reding <thierry.reding@avionic-design.de>
- */
-
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-/* register definitions */
-#define ADX_BACKLIGHT_CONTROL 0x00
-#define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0)
-#define ADX_BACKLIGHT_BRIGHTNESS 0x08
-#define ADX_BACKLIGHT_STATUS 0x10
-#define ADX_BACKLIGHT_ERROR 0x18
-
-struct adxbl {
- void __iomem *base;
-};
-
-static int adx_backlight_update_status(struct backlight_device *bldev)
-{
- struct adxbl *bl = bl_get_data(bldev);
- u32 value;
-
- value = bldev->props.brightness;
- writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS);
-
- value = readl(bl->base + ADX_BACKLIGHT_CONTROL);
-
- if (bldev->props.state & BL_CORE_FBBLANK)
- value &= ~ADX_BACKLIGHT_CONTROL_ENABLE;
- else
- value |= ADX_BACKLIGHT_CONTROL_ENABLE;
-
- writel(value, bl->base + ADX_BACKLIGHT_CONTROL);
-
- return 0;
-}
-
-static int adx_backlight_get_brightness(struct backlight_device *bldev)
-{
- struct adxbl *bl = bl_get_data(bldev);
- u32 brightness;
-
- brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS);
- return brightness & 0xff;
-}
-
-static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb)
-{
- return 1;
-}
-
-static const struct backlight_ops adx_backlight_ops = {
- .options = 0,
- .update_status = adx_backlight_update_status,
- .get_brightness = adx_backlight_get_brightness,
- .check_fb = adx_backlight_check_fb,
-};
-
-static int __devinit adx_backlight_probe(struct platform_device *pdev)
-{
- struct backlight_properties props;
- struct backlight_device *bldev;
- struct resource *res;
- struct adxbl *bl;
- int ret = 0;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- goto out;
- }
-
- res = devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), res->name);
- if (!res) {
- ret = -ENXIO;
- goto out;
- }
-
- bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
- if (!bl) {
- ret = -ENOMEM;
- goto out;
- }
-
- bl->base = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
- if (!bl->base) {
- ret = -ENXIO;
- goto out;
- }
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.type = BACKLIGHT_RAW;
- props.max_brightness = 0xff;
- bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
- bl, &adx_backlight_ops, &props);
- if (IS_ERR(bldev)) {
- ret = PTR_ERR(bldev);
- goto out;
- }
-
- bldev->props.brightness = 0xff;
- bldev->props.power = FB_BLANK_UNBLANK;
-
- platform_set_drvdata(pdev, bldev);
-
-out:
- return ret;
-}
-
-static int __devexit adx_backlight_remove(struct platform_device *pdev)
-{
- struct backlight_device *bldev;
- int ret = 0;
-
- bldev = platform_get_drvdata(pdev);
- bldev->props.power = FB_BLANK_UNBLANK;
- bldev->props.brightness = 0xff;
- backlight_update_status(bldev);
- backlight_device_unregister(bldev);
- platform_set_drvdata(pdev, NULL);
-
- return ret;
-}
-
-#ifdef CONFIG_PM
-static int adx_backlight_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- return 0;
-}
-
-static int adx_backlight_resume(struct platform_device *pdev)
-{
- return 0;
-}
-#else
-#define adx_backlight_suspend NULL
-#define adx_backlight_resume NULL
-#endif
-
-static struct platform_driver adx_backlight_driver = {
- .probe = adx_backlight_probe,
- .remove = __devexit_p(adx_backlight_remove),
- .suspend = adx_backlight_suspend,
- .resume = adx_backlight_resume,
- .driver = {
- .name = "adx-backlight",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init adx_backlight_init(void)
-{
- return platform_driver_register(&adx_backlight_driver);
-}
-
-static void __exit adx_backlight_exit(void)
-{
- platform_driver_unregister(&adx_backlight_driver);
-}
-
-module_init(adx_backlight_init);
-module_exit(adx_backlight_exit);
-
-MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 7363c1b..bf5b1ec 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -102,7 +102,7 @@ static void backlight_generate_event(struct backlight_device *bd,
}
static ssize_t backlight_show_power(struct device *dev,
- struct device_attribute *attr,char *buf)
+ struct device_attribute *attr, char *buf)
{
struct backlight_device *bd = to_backlight_device(dev);
@@ -116,7 +116,7 @@ static ssize_t backlight_store_power(struct device *dev,
struct backlight_device *bd = to_backlight_device(dev);
unsigned long power;
- rc = strict_strtoul(buf, 0, &power);
+ rc = kstrtoul(buf, 0, &power);
if (rc)
return rc;
@@ -150,7 +150,7 @@ static ssize_t backlight_store_brightness(struct device *dev,
struct backlight_device *bd = to_backlight_device(dev);
unsigned long brightness;
- rc = strict_strtoul(buf, 0, &brightness);
+ rc = kstrtoul(buf, 0, &brightness);
if (rc)
return rc;
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index d68f14b..abb4a06 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -199,17 +199,7 @@ static struct platform_driver da903x_backlight_driver = {
.remove = da903x_backlight_remove,
};
-static int __init da903x_backlight_init(void)
-{
- return platform_driver_register(&da903x_backlight_driver);
-}
-module_init(da903x_backlight_init);
-
-static void __exit da903x_backlight_exit(void)
-{
- platform_driver_unregister(&da903x_backlight_driver);
-}
-module_exit(da903x_backlight_exit);
+module_platform_driver(da903x_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index c74a6f4..b62b8b9 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/module.h>
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/backlight.h>
@@ -144,17 +143,7 @@ static struct platform_driver ep93xxbl_driver = {
.resume = ep93xxbl_resume,
};
-static int __init ep93xxbl_init(void)
-{
- return platform_driver_register(&ep93xxbl_driver);
-}
-module_init(ep93xxbl_init);
-
-static void __exit ep93xxbl_exit(void)
-{
- platform_driver_unregister(&ep93xxbl_driver);
-}
-module_exit(ep93xxbl_exit);
+module_platform_driver(ep93xxbl_driver);
MODULE_DESCRIPTION("EP93xx Backlight Driver");
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index adb1914..9ce6170 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -132,18 +132,7 @@ static struct platform_driver genericbl_driver = {
},
};
-static int __init genericbl_init(void)
-{
- return platform_driver_register(&genericbl_driver);
-}
-
-static void __exit genericbl_exit(void)
-{
- platform_driver_unregister(&genericbl_driver);
-}
-
-module_init(genericbl_init);
-module_exit(genericbl_exit);
+module_platform_driver(genericbl_driver);
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
MODULE_DESCRIPTION("Generic Backlight Driver");
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index de65d80..2f8af5d 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -147,19 +147,8 @@ static struct platform_driver jornada_bl_driver = {
},
};
-static int __init jornada_bl_init(void)
-{
- return platform_driver_register(&jornada_bl_driver);
-}
-
-static void __exit jornada_bl_exit(void)
-{
- platform_driver_unregister(&jornada_bl_driver);
-}
+module_platform_driver(jornada_bl_driver);
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>");
MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver");
MODULE_LICENSE("GPL");
-
-module_init(jornada_bl_init);
-module_exit(jornada_bl_exit);
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index d2ff658..22d231a 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -135,19 +135,8 @@ static struct platform_driver jornada_lcd_driver = {
},
};
-static int __init jornada_lcd_init(void)
-{
- return platform_driver_register(&jornada_lcd_driver);
-}
-
-static void __exit jornada_lcd_exit(void)
-{
- platform_driver_unregister(&jornada_lcd_driver);
-}
+module_platform_driver(jornada_lcd_driver);
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver");
MODULE_LICENSE("GPL");
-
-module_init(jornada_lcd_init);
-module_exit(jornada_lcd_exit);
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 71a11ca..79c1b0d 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -97,19 +97,16 @@ static ssize_t lcd_store_power(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int rc = -ENXIO;
- char *endp;
struct lcd_device *ld = to_lcd_device(dev);
- int power = simple_strtoul(buf, &endp, 0);
- size_t size = endp - buf;
+ unsigned long power;
- if (isspace(*endp))
- size++;
- if (size != count)
- return -EINVAL;
+ rc = kstrtoul(buf, 0, &power);
+ if (rc)
+ return rc;
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_power) {
- pr_debug("lcd: set power to %d\n", power);
+ pr_debug("lcd: set power to %lu\n", power);
ld->ops->set_power(ld, power);
rc = count;
}
@@ -136,19 +133,16 @@ static ssize_t lcd_store_contrast(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int rc = -ENXIO;
- char *endp;
struct lcd_device *ld = to_lcd_device(dev);
- int contrast = simple_strtoul(buf, &endp, 0);
- size_t size = endp - buf;
+ unsigned long contrast;
- if (isspace(*endp))
- size++;
- if (size != count)
- return -EINVAL;
+ rc = kstrtoul(buf, 0, &contrast);
+ if (rc)
+ return rc;
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_contrast) {
- pr_debug("lcd: set contrast to %d\n", contrast);
+ pr_debug("lcd: set contrast to %lu\n", contrast);
ld->ops->set_contrast(ld, contrast);
rc = count;
}
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index da9a5ce..78dafc0 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -31,6 +31,7 @@
#include <linux/lcd.h>
#include <linux/backlight.h>
#include <linux/module.h>
+#include <linux/regulator/consumer.h>
#include "ld9040_gamma.h"
@@ -53,8 +54,51 @@ struct ld9040 {
struct lcd_device *ld;
struct backlight_device *bd;
struct lcd_platform_data *lcd_pd;
+
+ struct mutex lock;
+ bool enabled;
+};
+
+static struct regulator_bulk_data supplies[] = {
+ { .supply = "vdd3", },
+ { .supply = "vci", },
};
+static void ld9040_regulator_enable(struct ld9040 *lcd)
+{
+ int ret = 0;
+ struct lcd_platform_data *pd = NULL;
+
+ pd = lcd->lcd_pd;
+ mutex_lock(&lcd->lock);
+ if (!lcd->enabled) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+ if (ret)
+ goto out;
+
+ lcd->enabled = true;
+ }
+ mdelay(pd->power_on_delay);
+out:
+ mutex_unlock(&lcd->lock);
+}
+
+static void ld9040_regulator_disable(struct ld9040 *lcd)
+{
+ int ret = 0;
+
+ mutex_lock(&lcd->lock);
+ if (lcd->enabled) {
+ ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+ if (ret)
+ goto out;
+
+ lcd->enabled = false;
+ }
+out:
+ mutex_unlock(&lcd->lock);
+}
+
static const unsigned short seq_swreset[] = {
0x01, COMMAND_ONLY,
ENDDEF, 0x00
@@ -532,13 +576,8 @@ static int ld9040_power_on(struct ld9040 *lcd)
return -EFAULT;
}
- if (!pd->power_on) {
- dev_err(lcd->dev, "power_on is NULL.\n");
- return -EFAULT;
- } else {
- pd->power_on(lcd->ld, 1);
- mdelay(pd->power_on_delay);
- }
+ /* lcd power on */
+ ld9040_regulator_enable(lcd);
if (!pd->reset) {
dev_err(lcd->dev, "reset is NULL.\n");
@@ -582,11 +621,8 @@ static int ld9040_power_off(struct ld9040 *lcd)
mdelay(pd->power_off_delay);
- if (!pd->power_on) {
- dev_err(lcd->dev, "power_on is NULL.\n");
- return -EFAULT;
- } else
- pd->power_on(lcd->ld, 0);
+ /* lcd power off */
+ ld9040_regulator_disable(lcd);
return 0;
}
@@ -693,6 +729,14 @@ static int ld9040_probe(struct spi_device *spi)
goto out_free_lcd;
}
+ mutex_init(&lcd->lock);
+
+ ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
+ if (ret) {
+ dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
+ goto out_free_lcd;
+ }
+
ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
if (IS_ERR(ld)) {
ret = PTR_ERR(ld);
@@ -739,6 +783,8 @@ static int ld9040_probe(struct spi_device *spi)
out_unregister_lcd:
lcd_device_unregister(lcd->ld);
out_free_lcd:
+ regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+
kfree(lcd);
return ret;
}
@@ -750,6 +796,7 @@ static int __devexit ld9040_remove(struct spi_device *spi)
ld9040_power(lcd, FB_BLANK_POWERDOWN);
backlight_device_unregister(lcd->bd);
lcd_device_unregister(lcd->ld);
+ regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
kfree(lcd);
return 0;
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index 7bbc80256..c915e3b 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -188,17 +188,7 @@ static struct platform_driver max8925_backlight_driver = {
.remove = __devexit_p(max8925_backlight_remove),
};
-static int __init max8925_backlight_init(void)
-{
- return platform_driver_register(&max8925_backlight_driver);
-}
-module_init(max8925_backlight_init);
-
-static void __exit max8925_backlight_exit(void)
-{
- platform_driver_unregister(&max8925_backlight_driver);
-};
-module_exit(max8925_backlight_exit);
+module_platform_driver(max8925_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 08d26a7..d8cde27 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -195,18 +195,7 @@ static struct platform_driver omapbl_driver = {
},
};
-static int __init omapbl_init(void)
-{
- return platform_driver_register(&omapbl_driver);
-}
-
-static void __exit omapbl_exit(void)
-{
- platform_driver_unregister(&omapbl_driver);
-}
-
-module_init(omapbl_init);
-module_exit(omapbl_exit);
+module_platform_driver(omapbl_driver);
MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>");
MODULE_DESCRIPTION("OMAP LCD Backlight driver");
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index ef5628d..13e88b7 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -173,17 +173,7 @@ static struct platform_driver pcf50633_bl_driver = {
},
};
-static int __init pcf50633_bl_init(void)
-{
- return platform_driver_register(&pcf50633_bl_driver);
-}
-module_init(pcf50633_bl_init);
-
-static void __exit pcf50633_bl_exit(void)
-{
- platform_driver_unregister(&pcf50633_bl_driver);
-}
-module_exit(pcf50633_bl_exit);
+module_platform_driver(pcf50633_bl_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("PCF50633 backlight driver");
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 302330a..f0bf491 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -85,7 +85,8 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
return -EINVAL;
}
- plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+ plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd),
+ GFP_KERNEL);
if (!plcd) {
dev_err(dev, "no memory for state\n");
return -ENOMEM;
@@ -98,7 +99,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
if (IS_ERR(plcd->lcd)) {
dev_err(dev, "cannot register lcd device\n");
err = PTR_ERR(plcd->lcd);
- goto err_mem;
+ goto err;
}
platform_set_drvdata(pdev, plcd);
@@ -106,8 +107,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
return 0;
- err_mem:
- kfree(plcd);
+ err:
return err;
}
@@ -116,7 +116,6 @@ static int __devexit platform_lcd_remove(struct platform_device *pdev)
struct platform_lcd *plcd = platform_get_drvdata(pdev);
lcd_device_unregister(plcd->lcd);
- kfree(plcd);
return 0;
}
@@ -157,18 +156,7 @@ static struct platform_driver platform_lcd_driver = {
.resume = platform_lcd_resume,
};
-static int __init platform_lcd_init(void)
-{
- return platform_driver_register(&platform_lcd_driver);
-}
-
-static void __exit platform_lcd_cleanup(void)
-{
- platform_driver_unregister(&platform_lcd_driver);
-}
-
-module_init(platform_lcd_init);
-module_exit(platform_lcd_cleanup);
+module_platform_driver(platform_lcd_driver);
MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 8b5b2a4..7496d04 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -169,10 +169,9 @@ static int pwm_backlight_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int pwm_backlight_suspend(struct platform_device *pdev,
- pm_message_t state)
+static int pwm_backlight_suspend(struct device *dev)
{
- struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct backlight_device *bl = dev_get_drvdata(dev);
struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
if (pb->notify)
@@ -184,40 +183,32 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
return 0;
}
-static int pwm_backlight_resume(struct platform_device *pdev)
+static int pwm_backlight_resume(struct device *dev)
{
- struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct backlight_device *bl = dev_get_drvdata(dev);
backlight_update_status(bl);
return 0;
}
-#else
-#define pwm_backlight_suspend NULL
-#define pwm_backlight_resume NULL
+
+static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend,
+ pwm_backlight_resume);
+
#endif
static struct platform_driver pwm_backlight_driver = {
.driver = {
.name = "pwm-backlight",
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &pwm_backlight_pm_ops,
+#endif
},
.probe = pwm_backlight_probe,
.remove = pwm_backlight_remove,
- .suspend = pwm_backlight_suspend,
- .resume = pwm_backlight_resume,
};
-static int __init pwm_backlight_init(void)
-{
- return platform_driver_register(&pwm_backlight_driver);
-}
-module_init(pwm_backlight_init);
-
-static void __exit pwm_backlight_exit(void)
-{
- platform_driver_unregister(&pwm_backlight_driver);
-}
-module_exit(pwm_backlight_exit);
+module_platform_driver(pwm_backlight_driver);
MODULE_DESCRIPTION("PWM based Backlight Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index fbe9e93..4e915f5 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -236,17 +236,7 @@ static struct platform_driver wm831x_backlight_driver = {
.remove = wm831x_backlight_remove,
};
-static int __init wm831x_backlight_init(void)
-{
- return platform_driver_register(&wm831x_backlight_driver);
-}
-module_init(wm831x_backlight_init);
-
-static void __exit wm831x_backlight_exit(void)
-{
- platform_driver_unregister(&wm831x_backlight_driver);
-}
-module_exit(wm831x_backlight_exit);
+module_platform_driver(wm831x_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com");
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6df7c54..738c8ce 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -280,52 +280,74 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
#endif /* CONFIG_PCI */
#ifdef CONFIG_ZORRO
-static const struct zorro_device_id cirrusfb_zorro_table[] = {
+struct zorrocl {
+ enum cirrus_board type; /* Board type */
+ u32 regoffset; /* Offset of registers in first Zorro device */
+ u32 ramsize; /* Size of video RAM in first Zorro device */
+ /* If zero, use autoprobe on RAM device */
+ u32 ramoffset; /* Offset of video RAM in first Zorro device */
+ zorro_id ramid; /* Zorro ID of RAM device */
+ zorro_id ramid2; /* Zorro ID of optional second RAM device */
+};
+
+static const struct zorrocl zcl_sd64 __devinitconst = {
+ .type = BT_SD64,
+ .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
+};
+
+static const struct zorrocl zcl_piccolo __devinitconst = {
+ .type = BT_PICCOLO,
+ .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+};
+
+static const struct zorrocl zcl_picasso __devinitconst = {
+ .type = BT_PICASSO,
+ .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+};
+
+static const struct zorrocl zcl_spectrum __devinitconst = {
+ .type = BT_SPECTRUM,
+ .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+};
+
+static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
+ .type = BT_PICASSO4,
+ .regoffset = 0x00600000,
+ .ramsize = 4 * MB_,
+ .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
+};
+
+static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
+ .type = BT_PICASSO4,
+ .regoffset = 0x10000,
+ .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
+ .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
+};
+
+
+static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
{
- .id = ZORRO_PROD_HELFRICH_SD64_RAM,
- .driver_data = BT_SD64,
+ .id = ZORRO_PROD_HELFRICH_SD64_REG,
+ .driver_data = (unsigned long)&zcl_sd64,
}, {
- .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
- .driver_data = BT_PICCOLO,
+ .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
+ .driver_data = (unsigned long)&zcl_piccolo,
}, {
- .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
- .driver_data = BT_PICASSO,
+ .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+ .driver_data = (unsigned long)&zcl_picasso,
}, {
- .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
- .driver_data = BT_SPECTRUM,
+ .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+ .driver_data = (unsigned long)&zcl_spectrum,
}, {
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
- .driver_data = BT_PICASSO4,
+ .driver_data = (unsigned long)&zcl_picasso4_z3,
+ }, {
+ .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
+ .driver_data = (unsigned long)&zcl_picasso4_z2,
},
{ 0 }
};
MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
-
-static const struct {
- zorro_id id2;
- unsigned long size;
-} cirrusfb_zorro_table2[] = {
- [BT_SD64] = {
- .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
- .size = 0x400000
- },
- [BT_PICCOLO] = {
- .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
- .size = 0x200000
- },
- [BT_PICASSO] = {
- .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
- .size = 0x200000
- },
- [BT_SPECTRUM] = {
- .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
- .size = 0x200000
- },
- [BT_PICASSO4] = {
- .id2 = 0,
- .size = 0x400000
- }
-};
#endif /* CONFIG_ZORRO */
#ifdef CIRRUSFB_DEBUG
@@ -350,7 +372,7 @@ struct cirrusfb_info {
void (*unmap)(struct fb_info *info);
};
-static int noaccel __devinitdata;
+static bool noaccel __devinitdata;
static char *mode_option __devinitdata = "640x480@60";
/****************************************************************************/
@@ -1956,16 +1978,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
struct cirrusfb_info *cinfo = info->par;
struct zorro_dev *zdev = to_zorro_dev(info->device);
- zorro_release_device(zdev);
-
- if (cinfo->btype == BT_PICASSO4) {
- cinfo->regbase -= 0x600000;
- iounmap((void *)cinfo->regbase);
+ if (info->fix.smem_start > 16 * MB_)
iounmap(info->screen_base);
- } else {
- if (zorro_resource_start(zdev) > 0x01000000)
- iounmap(info->screen_base);
- }
+ if (info->fix.mmio_start > 16 * MB_)
+ iounmap(cinfo->regbase);
+
+ zorro_release_device(zdev);
}
#endif /* CONFIG_ZORRO */
@@ -2222,115 +2240,116 @@ static struct pci_driver cirrusfb_pci_driver = {
static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
const struct zorro_device_id *ent)
{
- struct cirrusfb_info *cinfo;
struct fb_info *info;
+ int error;
+ const struct zorrocl *zcl;
enum cirrus_board btype;
- struct zorro_dev *z2 = NULL;
- unsigned long board_addr, board_size, size;
- int ret;
-
- btype = ent->driver_data;
- if (cirrusfb_zorro_table2[btype].id2)
- z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
- size = cirrusfb_zorro_table2[btype].size;
+ unsigned long regbase, ramsize, rambase;
+ struct cirrusfb_info *cinfo;
info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
if (!info) {
printk(KERN_ERR "cirrusfb: could not allocate memory\n");
- ret = -ENOMEM;
- goto err_out;
+ return -ENOMEM;
+ }
+
+ zcl = (const struct zorrocl *)ent->driver_data;
+ btype = zcl->type;
+ regbase = zorro_resource_start(z) + zcl->regoffset;
+ ramsize = zcl->ramsize;
+ if (ramsize) {
+ rambase = zorro_resource_start(z) + zcl->ramoffset;
+ if (zorro_resource_len(z) == 64 * MB_) {
+ /* Quirk for 64 MiB Picasso IV */
+ rambase += zcl->ramoffset;
+ }
+ } else {
+ struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
+ if (!ram || !zorro_resource_len(ram)) {
+ dev_err(info->device, "No video RAM found\n");
+ error = -ENODEV;
+ goto err_release_fb;
+ }
+ rambase = zorro_resource_start(ram);
+ ramsize = zorro_resource_len(ram);
+ if (zcl->ramid2 &&
+ (ram = zorro_find_device(zcl->ramid2, NULL))) {
+ if (zorro_resource_start(ram) != rambase + ramsize) {
+ dev_warn(info->device,
+ "Skipping non-contiguous RAM at %pR\n",
+ &ram->resource);
+ } else {
+ ramsize += zorro_resource_len(ram);
+ }
+ }
}
- dev_info(info->device, "%s board detected\n",
- cirrusfb_board_info[btype].name);
-
- cinfo = info->par;
- cinfo->btype = btype;
-
- assert(z);
- assert(btype != BT_NONE);
-
- board_addr = zorro_resource_start(z);
- board_size = zorro_resource_len(z);
- info->screen_size = size;
+ dev_info(info->device,
+ "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
+ cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
+ rambase);
if (!zorro_request_device(z, "cirrusfb")) {
- dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
- board_addr);
- ret = -EBUSY;
+ dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
+ error = -EBUSY;
goto err_release_fb;
}
- ret = -EIO;
-
- if (btype == BT_PICASSO4) {
- dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
-
- /* To be precise, for the P4 this is not the */
- /* begin of the board, but the begin of RAM. */
- /* for P4, map in its address space in 2 chunks (### TEST! ) */
- /* (note the ugly hardcoded 16M number) */
- cinfo->regbase = ioremap(board_addr, 16777216);
- if (!cinfo->regbase)
- goto err_release_region;
-
- dev_dbg(info->device, "Virtual address for board set to: $%p\n",
- cinfo->regbase);
- cinfo->regbase += 0x600000;
- info->fix.mmio_start = board_addr + 0x600000;
-
- info->fix.smem_start = board_addr + 16777216;
- info->screen_base = ioremap(info->fix.smem_start, 16777216);
- if (!info->screen_base)
- goto err_unmap_regbase;
- } else {
- dev_info(info->device, " REG at $%lx\n",
- (unsigned long) z2->resource.start);
-
- info->fix.smem_start = board_addr;
- if (board_addr > 0x01000000)
- info->screen_base = ioremap(board_addr, board_size);
- else
- info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
- if (!info->screen_base)
- goto err_release_region;
+ cinfo = info->par;
+ cinfo->btype = btype;
- /* set address for REG area of board */
- cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
- info->fix.mmio_start = z2->resource.start;
+ info->fix.mmio_start = regbase;
+ cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
+ : (caddr_t)ZTWO_VADDR(regbase);
+ if (!cinfo->regbase) {
+ dev_err(info->device, "Cannot map registers\n");
+ error = -EIO;
+ goto err_release_dev;
+ }
- dev_dbg(info->device, "Virtual address for board set to: $%p\n",
- cinfo->regbase);
+ info->fix.smem_start = rambase;
+ info->screen_size = ramsize;
+ info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
+ : (caddr_t)ZTWO_VADDR(rambase);
+ if (!info->screen_base) {
+ dev_err(info->device, "Cannot map video RAM\n");
+ error = -EIO;
+ goto err_unmap_reg;
}
+
cinfo->unmap = cirrusfb_zorro_unmap;
dev_info(info->device,
- "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
- board_size / MB_, board_addr);
-
- zorro_set_drvdata(z, info);
+ "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
+ ramsize / MB_, rambase);
/* MCLK select etc. */
if (cirrusfb_board_info[btype].init_sr1f)
vga_wseq(cinfo->regbase, CL_SEQR1F,
cirrusfb_board_info[btype].sr1f);
- ret = cirrusfb_register(info);
- if (!ret)
- return 0;
+ error = cirrusfb_register(info);
+ if (error) {
+ dev_err(info->device, "Failed to register device, error %d\n",
+ error);
+ goto err_unmap_ram;
+ }
- if (btype == BT_PICASSO4 || board_addr > 0x01000000)
+ zorro_set_drvdata(z, info);
+ return 0;
+
+err_unmap_ram:
+ if (rambase > 16 * MB_)
iounmap(info->screen_base);
-err_unmap_regbase:
- if (btype == BT_PICASSO4)
- iounmap(cinfo->regbase - 0x600000);
-err_release_region:
- release_region(board_addr, board_size);
+err_unmap_reg:
+ if (regbase > 16 * MB_)
+ iounmap(cinfo->regbase);
+err_release_dev:
+ zorro_release_device(z);
err_release_fb:
framebuffer_release(info);
-err_out:
- return ret;
+ return error;
}
void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
@@ -2338,6 +2357,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
struct fb_info *info = zorro_get_drvdata(z);
cirrusfb_cleanup(info);
+ zorro_set_drvdata(z, NULL);
}
static struct zorro_driver cirrusfb_zorro_driver = {
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 93317b5..a122d92 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -25,14 +25,13 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/gio_device.h>
+
#include <video/newport.h>
#include <linux/linux_logo.h>
#include <linux/font.h>
-
-extern unsigned long sgi_gfxaddr;
-
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
/* borrowed from fbcon.c */
@@ -304,12 +303,6 @@ static const char *newport_startup(void)
{
int i;
- if (!sgi_gfxaddr)
- return NULL;
-
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
npregs->cset.config = NPORT_CFG_GD0;
if (newport_wait(npregs))
@@ -743,26 +736,58 @@ const struct consw newport_con = {
.con_save_screen = DUMMY
};
-#ifdef MODULE
-static int __init newport_console_init(void)
+static int newport_probe(struct gio_device *dev,
+ const struct gio_device_id *id)
{
- if (!sgi_gfxaddr)
- return 0;
+ unsigned long newport_addr;
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+ if (!dev->resource.start)
+ return -EINVAL;
+
+ if (npregs)
+ return -EBUSY; /* we only support one Newport as console */
+
+ newport_addr = dev->resource.start + 0xF0000;
+ if (!request_mem_region(newport_addr, 0x10000, "Newport"))
+ return -ENODEV;
+
+ npregs = (struct newport_regs *)/* ioremap cannot fail */
+ ioremap(newport_addr, sizeof(struct newport_regs));
return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
}
-module_init(newport_console_init);
-static void __exit newport_console_exit(void)
+static void newport_remove(struct gio_device *dev)
{
give_up_console(&newport_con);
iounmap((void *)npregs);
}
+
+static struct gio_device_id newport_ids[] = {
+ { .id = 0x7e },
+ { .id = 0xff }
+};
+
+MODULE_ALIAS("gio:7e");
+
+static struct gio_driver newport_driver = {
+ .name = "newport",
+ .id_table = newport_ids,
+ .probe = newport_probe,
+ .remove = newport_remove,
+};
+
+int __init newport_console_init(void)
+{
+ return gio_register_driver(&newport_driver);
+}
+
+void __exit newport_console_exit(void)
+{
+ gio_unregister_driver(&newport_driver);
+}
+
+module_init(newport_console_init);
module_exit(newport_console_exit);
-#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 7b2c40a..0c189b3 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -420,7 +420,7 @@ static int __init init_control(struct fb_info_control *p)
/* Try to pick a video mode out of NVRAM if we have one. */
#ifdef CONFIG_NVRAM
- if (default_cmode == CMODE_NVRAM){
+ if (default_cmode == CMODE_NVRAM) {
cmode = nvram_read_byte(NV_CMODE);
if(cmode < CMODE_8 || cmode > CMODE_32)
cmode = CMODE_8;
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
deleted file mode 100644
index f99af93..0000000
--- a/drivers/video/display/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Display drivers configuration
-#
-
-menu "Display device support"
-
-config DISPLAY_SUPPORT
- tristate "Display panel/monitor support"
- ---help---
- This framework adds support for low-level control of a display.
- This includes support for power.
-
- Enable this to be able to choose the drivers for controlling the
- physical display panel/monitor on some platforms. This not only
- covers LCD displays for PDAs but also other types of displays
- such as CRT, TVout etc.
-
- To have support for your specific display panel you will have to
- select the proper drivers which depend on this option.
-
-comment "Display hardware drivers"
- depends on DISPLAY_SUPPORT
-
-endmenu
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
deleted file mode 100644
index c0ea832..0000000
--- a/drivers/video/display/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# Display drivers
-
-display-objs := display-sysfs.o
-
-obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
-
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
deleted file mode 100644
index 0c647d7..0000000
--- a/drivers/video/display/display-sysfs.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * display-sysfs.c - Display output driver sysfs interface
- *
- * Copyright (C) 2007 James Simmons <jsimmons@infradead.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/display.h>
-#include <linux/ctype.h>
-#include <linux/idr.h>
-#include <linux/err.h>
-#include <linux/kdev_t.h>
-#include <linux/slab.h>
-
-static ssize_t display_show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
-}
-
-static ssize_t display_show_type(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
-}
-
-static ssize_t display_show_contrast(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
- ssize_t rc = -ENXIO;
-
- mutex_lock(&dsp->lock);
- if (likely(dsp->driver) && dsp->driver->get_contrast)
- rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
- mutex_unlock(&dsp->lock);
- return rc;
-}
-
-static ssize_t display_store_contrast(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
- ssize_t ret = -EINVAL, size;
- int contrast;
- char *endp;
-
- contrast = simple_strtoul(buf, &endp, 0);
- size = endp - buf;
-
- if (isspace(*endp))
- size++;
-
- if (size != count)
- return ret;
-
- mutex_lock(&dsp->lock);
- if (likely(dsp->driver && dsp->driver->set_contrast)) {
- pr_debug("display: set contrast to %d\n", contrast);
- dsp->driver->set_contrast(dsp, contrast);
- ret = count;
- }
- mutex_unlock(&dsp->lock);
- return ret;
-}
-
-static ssize_t display_show_max_contrast(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
- ssize_t rc = -ENXIO;
-
- mutex_lock(&dsp->lock);
- if (likely(dsp->driver))
- rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
- mutex_unlock(&dsp->lock);
- return rc;
-}
-
-static struct device_attribute display_attrs[] = {
- __ATTR(name, S_IRUGO, display_show_name, NULL),
- __ATTR(type, S_IRUGO, display_show_type, NULL),
- __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
- __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
-};
-
-static int display_suspend(struct device *dev, pm_message_t state)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
-
- mutex_lock(&dsp->lock);
- if (likely(dsp->driver->suspend))
- dsp->driver->suspend(dsp, state);
- mutex_unlock(&dsp->lock);
- return 0;
-};
-
-static int display_resume(struct device *dev)
-{
- struct display_device *dsp = dev_get_drvdata(dev);
-
- mutex_lock(&dsp->lock);
- if (likely(dsp->driver->resume))
- dsp->driver->resume(dsp);
- mutex_unlock(&dsp->lock);
- return 0;
-};
-
-static struct mutex allocated_dsp_lock;
-static DEFINE_IDR(allocated_dsp);
-static struct class *display_class;
-
-struct display_device *display_device_register(struct display_driver *driver,
- struct device *parent, void *devdata)
-{
- struct display_device *new_dev = NULL;
- int ret = -EINVAL;
-
- if (unlikely(!driver))
- return ERR_PTR(ret);
-
- mutex_lock(&allocated_dsp_lock);
- ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
- mutex_unlock(&allocated_dsp_lock);
- if (!ret)
- return ERR_PTR(ret);
-
- new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
- if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
- // Reserve the index for this display
- mutex_lock(&allocated_dsp_lock);
- ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
- mutex_unlock(&allocated_dsp_lock);
-
- if (!ret) {
- new_dev->dev = device_create(display_class, parent,
- MKDEV(0, 0), new_dev,
- "display%d", new_dev->idx);
- if (!IS_ERR(new_dev->dev)) {
- new_dev->parent = parent;
- new_dev->driver = driver;
- mutex_init(&new_dev->lock);
- return new_dev;
- }
- mutex_lock(&allocated_dsp_lock);
- idr_remove(&allocated_dsp, new_dev->idx);
- mutex_unlock(&allocated_dsp_lock);
- ret = -EINVAL;
- }
- }
- kfree(new_dev);
- return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(display_device_register);
-
-void display_device_unregister(struct display_device *ddev)
-{
- if (!ddev)
- return;
- // Free device
- mutex_lock(&ddev->lock);
- device_unregister(ddev->dev);
- mutex_unlock(&ddev->lock);
- // Mark device index as available
- mutex_lock(&allocated_dsp_lock);
- idr_remove(&allocated_dsp, ddev->idx);
- mutex_unlock(&allocated_dsp_lock);
- kfree(ddev);
-}
-EXPORT_SYMBOL(display_device_unregister);
-
-static int __init display_class_init(void)
-{
- display_class = class_create(THIS_MODULE, "display");
- if (IS_ERR(display_class)) {
- printk(KERN_ERR "Failed to create display class\n");
- display_class = NULL;
- return -EINVAL;
- }
- display_class->dev_attrs = display_attrs;
- display_class->suspend = display_suspend;
- display_class->resume = display_resume;
- mutex_init(&allocated_dsp_lock);
- return 0;
-}
-
-static void __exit display_class_exit(void)
-{
- class_destroy(display_class);
-}
-
-module_init(display_class_init);
-module_exit(display_class_exit);
-
-MODULE_DESCRIPTION("Display Hardware handling");
-MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ad93629..ac9141b 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -967,6 +967,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
u32 activate = var->activate;
+ /* When using FOURCC mode, make sure the red, green, blue and
+ * transp fields are set to 0.
+ */
+ if ((info->fix.capabilities & FB_CAP_FOURCC) &&
+ var->grayscale > 1) {
+ if (var->red.offset || var->green.offset ||
+ var->blue.offset || var->transp.offset ||
+ var->red.length || var->green.length ||
+ var->blue.length || var->transp.length ||
+ var->red.msb_right || var->green.msb_right ||
+ var->blue.msb_right || var->transp.msb_right)
+ return -EINVAL;
+ }
+
if (!info->fbops->fb_check_var) {
*var = info->var;
goto done;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index a16beeb..acf292b 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -36,8 +36,7 @@
#include <linux/fsl-diu-fb.h>
#include "edid.h"
-#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
- /* 1 for plane 0, 2 for plane 1&2 each */
+#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
/* HW cursor parameters */
#define MAX_CURS 32
@@ -49,12 +48,6 @@
#define INT_PARERR 0x08 /* Display parameters error interrupt */
#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
-struct diu_addr {
- void *vaddr; /* Virtual address */
- dma_addr_t paddr; /* Physical address */
- __u32 offset;
-};
-
/*
* List of supported video modes
*
@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
static DEFINE_SPINLOCK(diu_lock);
-struct fsl_diu_data {
- struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
- /*FSL_AOI_NUM has one dummy AOI */
- struct device_attribute dev_attr;
- struct diu_ad *dummy_ad;
- void *dummy_aoi_virt;
- unsigned int irq;
- int fb_enabled;
- enum fsl_diu_monitor_port monitor_port;
- struct diu __iomem *diu_reg;
- spinlock_t reg_lock;
- struct diu_addr ad;
- struct diu_addr gamma;
- struct diu_addr pallete;
- struct diu_addr cursor;
-};
-
enum mfb_index {
PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
PLANE1_AOI0, /* Plane 1, first AOI */
@@ -370,6 +346,42 @@ struct mfb_info {
u8 *edid_data;
};
+/**
+ * struct fsl_diu_data - per-DIU data structure
+ * @dma_addr: DMA address of this structure
+ * @fsl_diu_info: fb_info objects, one per AOI
+ * @dev_attr: sysfs structure
+ * @irq: IRQ
+ * @monitor_port: the monitor port this DIU is connected to
+ * @diu_reg: pointer to the DIU hardware registers
+ * @reg_lock: spinlock for register access
+ * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
+ * dummy_ad: DIU Area Descriptor for the dummy AOI
+ * @ad[]: Area Descriptors for each real AOI
+ * @gamma: gamma color table
+ * @cursor: hardware cursor data
+ *
+ * This data structure must be allocated with 32-byte alignment, so that the
+ * internal fields can be aligned properly.
+ */
+struct fsl_diu_data {
+ dma_addr_t dma_addr;
+ struct fb_info fsl_diu_info[NUM_AOIS];
+ struct mfb_info mfb[NUM_AOIS];
+ struct device_attribute dev_attr;
+ unsigned int irq;
+ enum fsl_diu_monitor_port monitor_port;
+ struct diu __iomem *diu_reg;
+ spinlock_t reg_lock;
+ u8 dummy_aoi[4 * 4 * 4];
+ struct diu_ad dummy_ad __aligned(8);
+ struct diu_ad ad[NUM_AOIS] __aligned(8);
+ u8 gamma[256 * 3] __aligned(32);
+ u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+} __aligned(32);
+
+/* Determine the DMA address of a member of the fsl_diu_data structure */
+#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
static struct mfb_info mfb_template[] = {
{
@@ -449,37 +461,6 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
return diu_ops.valid_monitor_port(port);
}
-/**
- * fsl_diu_alloc - allocate memory for the DIU
- * @size: number of bytes to allocate
- * @param: returned physical address of memory
- *
- * This function allocates a physically-contiguous block of memory.
- */
-static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
-{
- void *virt;
-
- virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
- if (virt)
- *phys = virt_to_phys(virt);
-
- return virt;
-}
-
-/**
- * fsl_diu_free - release DIU memory
- * @virt: pointer returned by fsl_diu_alloc()
- * @size: number of bytes allocated by fsl_diu_alloc()
- *
- * This function releases memory allocated by fsl_diu_alloc().
- */
-static void fsl_diu_free(void *virt, size_t size)
-{
- if (virt && size)
- free_pages_exact(virt, size);
-}
-
/*
* Workaround for failed writing desc register of planes.
* Needed with MPC5121 DIU rev 2.0 silicon.
@@ -495,8 +476,8 @@ static void fsl_diu_enable_panel(struct fb_info *info)
{
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
struct diu_ad *ad = mfbi->ad;
- struct fsl_diu_data *machine_data = mfbi->parent;
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct fsl_diu_data *data = mfbi->parent;
+ struct diu __iomem *hw = data->diu_reg;
switch (mfbi->index) {
case PLANE0:
@@ -504,7 +485,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
wr_reg_wa(&hw->desc[0], ad->paddr);
break;
case PLANE1_AOI0:
- cmfbi = machine_data->fsl_diu_info[2]->par;
+ cmfbi = &data->mfb[2];
if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
if (cmfbi->count > 0) /* AOI1 open */
ad->next_ad =
@@ -515,7 +496,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
}
break;
case PLANE2_AOI0:
- cmfbi = machine_data->fsl_diu_info[4]->par;
+ cmfbi = &data->mfb[4];
if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
if (cmfbi->count > 0) /* AOI1 open */
ad->next_ad =
@@ -526,17 +507,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
}
break;
case PLANE1_AOI1:
- pmfbi = machine_data->fsl_diu_info[1]->par;
+ pmfbi = &data->mfb[1];
ad->next_ad = 0;
- if (hw->desc[1] == machine_data->dummy_ad->paddr)
+ if (hw->desc[1] == data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[1], ad->paddr);
else /* AOI0 open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
break;
case PLANE2_AOI1:
- pmfbi = machine_data->fsl_diu_info[3]->par;
+ pmfbi = &data->mfb[3];
ad->next_ad = 0;
- if (hw->desc[2] == machine_data->dummy_ad->paddr)
+ if (hw->desc[2] == data->dummy_ad.paddr)
wr_reg_wa(&hw->desc[2], ad->paddr);
else /* AOI0 was open */
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
@@ -548,52 +529,52 @@ static void fsl_diu_disable_panel(struct fb_info *info)
{
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
struct diu_ad *ad = mfbi->ad;
- struct fsl_diu_data *machine_data = mfbi->parent;
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct fsl_diu_data *data = mfbi->parent;
+ struct diu __iomem *hw = data->diu_reg;
switch (mfbi->index) {
case PLANE0:
- if (hw->desc[0] != machine_data->dummy_ad->paddr)
- wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
+ if (hw->desc[0] != data->dummy_ad.paddr)
+ wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
break;
case PLANE1_AOI0:
- cmfbi = machine_data->fsl_diu_info[2]->par;
+ cmfbi = &data->mfb[2];
if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
/* move AOI1 to the first */
else /* AOI1 was closed */
- wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
+ wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
/* close AOI 0 */
break;
case PLANE2_AOI0:
- cmfbi = machine_data->fsl_diu_info[4]->par;
+ cmfbi = &data->mfb[4];
if (cmfbi->count > 0) /* AOI1 is open */
wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
/* move AOI1 to the first */
else /* AOI1 was closed */
- wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
+ wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
/* close AOI 0 */
break;
case PLANE1_AOI1:
- pmfbi = machine_data->fsl_diu_info[1]->par;
+ pmfbi = &data->mfb[1];
if (hw->desc[1] != ad->paddr) {
/* AOI1 is not the first in the chain */
if (pmfbi->count > 0)
/* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */
- wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
+ wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
/* close AOI 1 */
break;
case PLANE2_AOI1:
- pmfbi = machine_data->fsl_diu_info[3]->par;
+ pmfbi = &data->mfb[3];
if (hw->desc[2] != ad->paddr) {
/* AOI1 is not the first in the chain */
if (pmfbi->count > 0)
/* AOI0 is open, must be the first */
pmfbi->ad->next_ad = 0;
} else /* AOI1 is the first in the chain */
- wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
+ wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
/* close AOI 1 */
break;
}
@@ -602,39 +583,33 @@ static void fsl_diu_disable_panel(struct fb_info *info)
static void enable_lcdc(struct fb_info *info)
{
struct mfb_info *mfbi = info->par;
- struct fsl_diu_data *machine_data = mfbi->parent;
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct fsl_diu_data *data = mfbi->parent;
+ struct diu __iomem *hw = data->diu_reg;
- if (!machine_data->fb_enabled) {
- out_be32(&hw->diu_mode, MFB_MODE1);
- machine_data->fb_enabled++;
- }
+ out_be32(&hw->diu_mode, MFB_MODE1);
}
static void disable_lcdc(struct fb_info *info)
{
struct mfb_info *mfbi = info->par;
- struct fsl_diu_data *machine_data = mfbi->parent;
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct fsl_diu_data *data = mfbi->parent;
+ struct diu __iomem *hw = data->diu_reg;
- if (machine_data->fb_enabled) {
- out_be32(&hw->diu_mode, 0);
- machine_data->fb_enabled = 0;
- }
+ out_be32(&hw->diu_mode, 0);
}
static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
- struct fsl_diu_data *machine_data = mfbi->parent;
+ struct fsl_diu_data *data = mfbi->parent;
int available_height, upper_aoi_bottom;
enum mfb_index index = mfbi->index;
int lower_aoi_is_open, upper_aoi_is_open;
__u32 base_plane_width, base_plane_height, upper_aoi_height;
- base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
- base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
+ base_plane_width = data->fsl_diu_info[0].var.xres;
+ base_plane_height = data->fsl_diu_info[0].var.yres;
if (mfbi->x_aoi_d < 0)
mfbi->x_aoi_d = 0;
@@ -649,7 +624,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
break;
case PLANE1_AOI0:
case PLANE2_AOI0:
- lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par;
+ lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
if (var->xres > base_plane_width)
var->xres = base_plane_width;
@@ -667,9 +642,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
break;
case PLANE1_AOI1:
case PLANE2_AOI1:
- upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par;
- upper_aoi_height =
- machine_data->fsl_diu_info[index-1]->var.yres;
+ upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
+ upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
if (var->xres > base_plane_width)
@@ -809,33 +783,33 @@ static void update_lcdc(struct fb_info *info)
{
struct fb_var_screeninfo *var = &info->var;
struct mfb_info *mfbi = info->par;
- struct fsl_diu_data *machine_data = mfbi->parent;
+ struct fsl_diu_data *data = mfbi->parent;
struct diu __iomem *hw;
int i, j;
- char __iomem *cursor_base, *gamma_table_base;
+ u8 *gamma_table_base;
u32 temp;
- hw = machine_data->diu_reg;
+ hw = data->diu_reg;
+
+ diu_ops.set_monitor_port(data->monitor_port);
+ gamma_table_base = data->gamma;
- diu_ops.set_monitor_port(machine_data->monitor_port);
- gamma_table_base = machine_data->gamma.vaddr;
- cursor_base = machine_data->cursor.vaddr;
/* Prep for DIU init - gamma table, cursor table */
for (i = 0; i <= 2; i++)
for (j = 0; j <= 255; j++)
*gamma_table_base++ = j;
- diu_ops.set_gamma_table(machine_data->monitor_port,
- machine_data->gamma.vaddr);
+ if (diu_ops.set_gamma_table)
+ diu_ops.set_gamma_table(data->monitor_port, data->gamma);
disable_lcdc(info);
/* Program DIU registers */
- out_be32(&hw->gamma, machine_data->gamma.paddr);
- out_be32(&hw->cursor, machine_data->cursor.paddr);
+ out_be32(&hw->gamma, DMA_ADDR(data, gamma));
+ out_be32(&hw->cursor, DMA_ADDR(data, cursor));
out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
@@ -870,16 +844,17 @@ static void update_lcdc(struct fb_info *info)
static int map_video_memory(struct fb_info *info)
{
- phys_addr_t phys;
u32 smem_len = info->fix.line_length * info->var.yres_virtual;
+ void *p;
- info->screen_base = fsl_diu_alloc(smem_len, &phys);
- if (info->screen_base == NULL) {
+ p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO);
+ if (!p) {
dev_err(info->dev, "unable to allocate fb memory\n");
return -ENOMEM;
}
mutex_lock(&info->mm_lock);
- info->fix.smem_start = (unsigned long) phys;
+ info->screen_base = p;
+ info->fix.smem_start = virt_to_phys(info->screen_base);
info->fix.smem_len = smem_len;
mutex_unlock(&info->mm_lock);
info->screen_size = info->fix.smem_len;
@@ -889,12 +864,17 @@ static int map_video_memory(struct fb_info *info)
static void unmap_video_memory(struct fb_info *info)
{
- fsl_diu_free(info->screen_base, info->fix.smem_len);
+ void *p = info->screen_base;
+ size_t l = info->fix.smem_len;
+
mutex_lock(&info->mm_lock);
info->screen_base = NULL;
info->fix.smem_start = 0;
info->fix.smem_len = 0;
mutex_unlock(&info->mm_lock);
+
+ if (p)
+ free_pages_exact(p, l);
}
/*
@@ -913,6 +893,59 @@ static int fsl_diu_set_aoi(struct fb_info *info)
return 0;
}
+/**
+ * fsl_diu_get_pixel_format: return the pixel format for a given color depth
+ *
+ * The pixel format is a 32-bit value that determine which bits in each
+ * pixel are to be used for each color. This is the default function used
+ * if the platform does not define its own version.
+ */
+static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
+{
+#define PF_BYTE_F 0x10000000
+#define PF_ALPHA_C_MASK 0x0E000000
+#define PF_ALPHA_C_SHIFT 25
+#define PF_BLUE_C_MASK 0x01800000
+#define PF_BLUE_C_SHIFT 23
+#define PF_GREEN_C_MASK 0x00600000
+#define PF_GREEN_C_SHIFT 21
+#define PF_RED_C_MASK 0x00180000
+#define PF_RED_C_SHIFT 19
+#define PF_PALETTE 0x00040000
+#define PF_PIXEL_S_MASK 0x00030000
+#define PF_PIXEL_S_SHIFT 16
+#define PF_COMP_3_MASK 0x0000F000
+#define PF_COMP_3_SHIFT 12
+#define PF_COMP_2_MASK 0x00000F00
+#define PF_COMP_2_SHIFT 8
+#define PF_COMP_1_MASK 0x000000F0
+#define PF_COMP_1_SHIFT 4
+#define PF_COMP_0_MASK 0x0000000F
+#define PF_COMP_0_SHIFT 0
+
+#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \
+ cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
+ (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
+ (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
+ (c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \
+ (c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT))
+
+ switch (bits_per_pixel) {
+ case 32:
+ /* 0x88883316 */
+ return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8);
+ case 24:
+ /* 0x88082219 */
+ return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8);
+ case 16:
+ /* 0x65053118 */
+ return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
+ default:
+ pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
+ return 0;
+ }
+}
+
/*
* Using the fb_var_screeninfo in fb_info we set the resolution of this
* particular framebuffer. This function alters the fb_fix_screeninfo stored
@@ -926,11 +959,11 @@ static int fsl_diu_set_par(struct fb_info *info)
unsigned long len;
struct fb_var_screeninfo *var = &info->var;
struct mfb_info *mfbi = info->par;
- struct fsl_diu_data *machine_data = mfbi->parent;
+ struct fsl_diu_data *data = mfbi->parent;
struct diu_ad *ad = mfbi->ad;
struct diu __iomem *hw;
- hw = machine_data->diu_reg;
+ hw = data->diu_reg;
set_fix(info);
mfbi->cursor_reset = 1;
@@ -948,8 +981,12 @@ static int fsl_diu_set_par(struct fb_info *info)
}
}
- ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port,
- var->bits_per_pixel);
+ if (diu_ops.get_pixel_format)
+ ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
+ var->bits_per_pixel);
+ else
+ ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
+
ad->addr = cpu_to_le32(info->fix.smem_start);
ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
var->xres_virtual) | mfbi->g_alpha;
@@ -1208,21 +1245,6 @@ static struct fb_ops fsl_diu_ops = {
.fb_release = fsl_diu_release,
};
-static int init_fbinfo(struct fb_info *info)
-{
- struct mfb_info *mfbi = info->par;
-
- info->device = NULL;
- info->var.activate = FB_ACTIVATE_NOW;
- info->fbops = &fsl_diu_ops;
- info->flags = FBINFO_FLAG_DEFAULT;
- info->pseudo_palette = &mfbi->pseudo_palette;
-
- /* Allocate colormap */
- fb_alloc_cmap(&info->cmap, 16, 0);
- return 0;
-}
-
static int __devinit install_fb(struct fb_info *info)
{
int rc;
@@ -1232,8 +1254,15 @@ static int __devinit install_fb(struct fb_info *info)
unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
int has_default_mode = 1;
- if (init_fbinfo(info))
- return -EINVAL;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->fbops = &fsl_diu_ops;
+ info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
+ FBINFO_READS_FAST;
+ info->pseudo_palette = mfbi->pseudo_palette;
+
+ rc = fb_alloc_cmap(&info->cmap, 16, 0);
+ if (rc)
+ return rc;
if (mfbi->index == PLANE0) {
if (mfbi->edid_data) {
@@ -1359,16 +1388,16 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
return IRQ_NONE;
}
-static int request_irq_local(struct fsl_diu_data *machine_data)
+static int request_irq_local(struct fsl_diu_data *data)
{
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct diu __iomem *hw = data->diu_reg;
u32 ints;
int ret;
/* Read to clear the status */
in_be32(&hw->int_status);
- ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
+ ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
if (!ret) {
ints = INT_PARERR | INT_LS_BF_VS;
#if !defined(CONFIG_NOT_COHERENT_CACHE)
@@ -1383,14 +1412,14 @@ static int request_irq_local(struct fsl_diu_data *machine_data)
return ret;
}
-static void free_irq_local(struct fsl_diu_data *machine_data)
+static void free_irq_local(struct fsl_diu_data *data)
{
- struct diu __iomem *hw = machine_data->diu_reg;
+ struct diu __iomem *hw = data->diu_reg;
/* Disable all LCDC interrupt */
out_be32(&hw->int_mask, 0x1f);
- free_irq(machine_data->irq, NULL);
+ free_irq(data->irq, NULL);
}
#ifdef CONFIG_PM
@@ -1400,20 +1429,20 @@ static void free_irq_local(struct fsl_diu_data *machine_data)
*/
static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
{
- struct fsl_diu_data *machine_data;
+ struct fsl_diu_data *data;
- machine_data = dev_get_drvdata(&ofdev->dev);
- disable_lcdc(machine_data->fsl_diu_info[0]);
+ data = dev_get_drvdata(&ofdev->dev);
+ disable_lcdc(data->fsl_diu_info[0]);
return 0;
}
static int fsl_diu_resume(struct platform_device *ofdev)
{
- struct fsl_diu_data *machine_data;
+ struct fsl_diu_data *data;
- machine_data = dev_get_drvdata(&ofdev->dev);
- enable_lcdc(machine_data->fsl_diu_info[0]);
+ data = dev_get_drvdata(&ofdev->dev);
+ enable_lcdc(data->fsl_diu_info[0]);
return 0;
}
@@ -1423,56 +1452,24 @@ static int fsl_diu_resume(struct platform_device *ofdev)
#define fsl_diu_resume NULL
#endif /* CONFIG_PM */
-/* Align to 64-bit(8-byte), 32-byte, etc. */
-static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
- u32 bytes_align)
-{
- u32 offset;
- dma_addr_t mask;
-
- buf->vaddr =
- dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
- GFP_DMA | __GFP_ZERO);
- if (!buf->vaddr)
- return -ENOMEM;
-
- mask = bytes_align - 1;
- offset = buf->paddr & mask;
- if (offset) {
- buf->offset = bytes_align - offset;
- buf->paddr = buf->paddr + offset;
- } else
- buf->offset = 0;
-
- return 0;
-}
-
-static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
- u32 bytes_align)
-{
- dma_free_coherent(dev, size + bytes_align, buf->vaddr,
- buf->paddr - buf->offset);
-}
-
static ssize_t store_monitor(struct device *device,
struct device_attribute *attr, const char *buf, size_t count)
{
enum fsl_diu_monitor_port old_monitor_port;
- struct fsl_diu_data *machine_data =
+ struct fsl_diu_data *data =
container_of(attr, struct fsl_diu_data, dev_attr);
- old_monitor_port = machine_data->monitor_port;
- machine_data->monitor_port = fsl_diu_name_to_port(buf);
+ old_monitor_port = data->monitor_port;
+ data->monitor_port = fsl_diu_name_to_port(buf);
- if (old_monitor_port != machine_data->monitor_port) {
+ if (old_monitor_port != data->monitor_port) {
/* All AOIs need adjust pixel format
* fsl_diu_set_par only change the pixsel format here
* unlikely to fail. */
- fsl_diu_set_par(machine_data->fsl_diu_info[0]);
- fsl_diu_set_par(machine_data->fsl_diu_info[1]);
- fsl_diu_set_par(machine_data->fsl_diu_info[2]);
- fsl_diu_set_par(machine_data->fsl_diu_info[3]);
- fsl_diu_set_par(machine_data->fsl_diu_info[4]);
+ unsigned int i;
+
+ for (i=0; i < NUM_AOIS; i++)
+ fsl_diu_set_par(&data->fsl_diu_info[i]);
}
return count;
}
@@ -1480,10 +1477,10 @@ static ssize_t store_monitor(struct device *device,
static ssize_t show_monitor(struct device *device,
struct device_attribute *attr, char *buf)
{
- struct fsl_diu_data *machine_data =
+ struct fsl_diu_data *data =
container_of(attr, struct fsl_diu_data, dev_attr);
- switch (machine_data->monitor_port) {
+ switch (data->monitor_port) {
case FSL_DIU_PORT_DVI:
return sprintf(buf, "DVI\n");
case FSL_DIU_PORT_LVDS:
@@ -1499,28 +1496,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mfb_info *mfbi;
- phys_addr_t dummy_ad_addr = 0;
- int ret, i, error = 0;
- struct fsl_diu_data *machine_data;
+ struct fsl_diu_data *data;
int diu_mode;
+ dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
+ unsigned int i;
+ int ret;
- machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
- if (!machine_data)
+ data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
+ &dma_addr, GFP_DMA | __GFP_ZERO);
+ if (!data)
return -ENOMEM;
+ data->dma_addr = dma_addr;
+
+ /*
+ * dma_alloc_coherent() uses a page allocator, so the address is
+ * always page-aligned. We need the memory to be 32-byte aligned,
+ * so that's good. However, if one day the allocator changes, we
+ * need to catch that. It's not worth the effort to handle unaligned
+ * alloctions now because it's highly unlikely to ever be a problem.
+ */
+ if ((unsigned long)data & 31) {
+ dev_err(&pdev->dev, "misaligned allocation");
+ ret = -ENOMEM;
+ goto error;
+ }
- spin_lock_init(&machine_data->reg_lock);
+ spin_lock_init(&data->reg_lock);
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
- machine_data->fsl_diu_info[i] =
- framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
- if (!machine_data->fsl_diu_info[i]) {
- dev_err(&pdev->dev, "cannot allocate memory\n");
- ret = -ENOMEM;
- goto error2;
- }
- mfbi = machine_data->fsl_diu_info[i]->par;
+ for (i = 0; i < NUM_AOIS; i++) {
+ struct fb_info *info = &data->fsl_diu_info[i];
+
+ info->device = &pdev->dev;
+ info->par = &data->mfb[i];
+
+ /*
+ * We store the physical address of the AD in the reserved
+ * 'paddr' field of the AD itself.
+ */
+ data->ad[i].paddr = DMA_ADDR(data, ad[i]);
+
+ info->fix.smem_start = 0;
+
+ /* Initialize the AOI data structure */
+ mfbi = info->par;
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
- mfbi->parent = machine_data;
+ mfbi->parent = data;
+ mfbi->ad = &data->ad[i];
if (mfbi->index == PLANE0) {
const u8 *prop;
@@ -1534,158 +1555,102 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
}
}
- machine_data->diu_reg = of_iomap(np, 0);
- if (!machine_data->diu_reg) {
+ data->diu_reg = of_iomap(np, 0);
+ if (!data->diu_reg) {
dev_err(&pdev->dev, "cannot map DIU registers\n");
ret = -EFAULT;
- goto error2;
+ goto error;
}
- diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
+ diu_mode = in_be32(&data->diu_reg->diu_mode);
if (diu_mode == MFB_MODE0)
- out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */
+ out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
/* Get the IRQ of the DIU */
- machine_data->irq = irq_of_parse_and_map(np, 0);
+ data->irq = irq_of_parse_and_map(np, 0);
- if (!machine_data->irq) {
+ if (!data->irq) {
dev_err(&pdev->dev, "could not get DIU IRQ\n");
ret = -EINVAL;
goto error;
}
- machine_data->monitor_port = monitor_port;
-
- /* Area descriptor memory pool aligns to 64-bit boundary */
- if (allocate_buf(&pdev->dev, &machine_data->ad,
- sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
- return -ENOMEM;
-
- /* Get memory for Gamma Table - 32-byte aligned memory */
- if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
- ret = -ENOMEM;
- goto error;
- }
-
- /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
- if (allocate_buf(&pdev->dev, &machine_data->cursor,
- MAX_CURS * MAX_CURS * 2, 32)) {
- ret = -ENOMEM;
- goto error;
- }
-
- i = ARRAY_SIZE(machine_data->fsl_diu_info);
- machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
- machine_data->ad.offset) + i;
- machine_data->dummy_ad->paddr = machine_data->ad.paddr +
- i * sizeof(struct diu_ad);
- machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
- if (!machine_data->dummy_aoi_virt) {
- ret = -ENOMEM;
- goto error;
- }
- machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
- machine_data->dummy_ad->pix_fmt = 0x88882317;
- machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
- machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
- machine_data->dummy_ad->offset_xyi = 0;
- machine_data->dummy_ad->offset_xyd = 0;
- machine_data->dummy_ad->next_ad = 0;
+ data->monitor_port = monitor_port;
+
+ /* Initialize the dummy Area Descriptor */
+ data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
+ data->dummy_ad.pix_fmt = 0x88882317;
+ data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
+ data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
+ data->dummy_ad.offset_xyi = 0;
+ data->dummy_ad.offset_xyd = 0;
+ data->dummy_ad.next_ad = 0;
+ data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
/*
* Let DIU display splash screen if it was pre-initialized
* by the bootloader, set dummy area descriptor otherwise.
*/
if (diu_mode == MFB_MODE0)
- out_be32(&machine_data->diu_reg->desc[0],
- machine_data->dummy_ad->paddr);
-
- out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr);
- out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr);
-
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
- machine_data->fsl_diu_info[i]->fix.smem_start = 0;
- mfbi = machine_data->fsl_diu_info[i]->par;
- mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
- + machine_data->ad.offset) + i;
- mfbi->ad->paddr =
- machine_data->ad.paddr + i * sizeof(struct diu_ad);
- ret = install_fb(machine_data->fsl_diu_info[i]);
+ out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
+
+ out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
+ out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
+
+ for (i = 0; i < NUM_AOIS; i++) {
+ ret = install_fb(&data->fsl_diu_info[i]);
if (ret) {
dev_err(&pdev->dev, "could not register fb %d\n", i);
goto error;
}
}
- if (request_irq_local(machine_data)) {
+ if (request_irq_local(data)) {
dev_err(&pdev->dev, "could not claim irq\n");
goto error;
}
- sysfs_attr_init(&machine_data->dev_attr.attr);
- machine_data->dev_attr.attr.name = "monitor";
- machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
- machine_data->dev_attr.show = show_monitor;
- machine_data->dev_attr.store = store_monitor;
- error = device_create_file(machine_data->fsl_diu_info[0]->dev,
- &machine_data->dev_attr);
- if (error) {
+ sysfs_attr_init(&data->dev_attr.attr);
+ data->dev_attr.attr.name = "monitor";
+ data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
+ data->dev_attr.show = show_monitor;
+ data->dev_attr.store = store_monitor;
+ ret = device_create_file(&pdev->dev, &data->dev_attr);
+ if (ret) {
dev_err(&pdev->dev, "could not create sysfs file %s\n",
- machine_data->dev_attr.attr.name);
+ data->dev_attr.attr.name);
}
- dev_set_drvdata(&pdev->dev, machine_data);
+ dev_set_drvdata(&pdev->dev, data);
return 0;
error:
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- uninstall_fb(machine_data->fsl_diu_info[i]);
-
- if (machine_data->ad.vaddr)
- free_buf(&pdev->dev, &machine_data->ad,
- sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
- if (machine_data->gamma.vaddr)
- free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
- if (machine_data->cursor.vaddr)
- free_buf(&pdev->dev, &machine_data->cursor,
- MAX_CURS * MAX_CURS * 2, 32);
- if (machine_data->dummy_aoi_virt)
- fsl_diu_free(machine_data->dummy_aoi_virt, 64);
- iounmap(machine_data->diu_reg);
-
-error2:
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- if (machine_data->fsl_diu_info[i])
- framebuffer_release(machine_data->fsl_diu_info[i]);
- kfree(machine_data);
+ for (i = 0; i < NUM_AOIS; i++)
+ uninstall_fb(&data->fsl_diu_info[i]);
+
+ iounmap(data->diu_reg);
+
+ dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
+ data->dma_addr);
return ret;
}
static int fsl_diu_remove(struct platform_device *pdev)
{
- struct fsl_diu_data *machine_data;
+ struct fsl_diu_data *data;
int i;
- machine_data = dev_get_drvdata(&pdev->dev);
- disable_lcdc(machine_data->fsl_diu_info[0]);
- free_irq_local(machine_data);
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- uninstall_fb(machine_data->fsl_diu_info[i]);
- if (machine_data->ad.vaddr)
- free_buf(&pdev->dev, &machine_data->ad,
- sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
- if (machine_data->gamma.vaddr)
- free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
- if (machine_data->cursor.vaddr)
- free_buf(&pdev->dev, &machine_data->cursor,
- MAX_CURS * MAX_CURS * 2, 32);
- if (machine_data->dummy_aoi_virt)
- fsl_diu_free(machine_data->dummy_aoi_virt, 64);
- iounmap(machine_data->diu_reg);
- for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
- if (machine_data->fsl_diu_info[i])
- framebuffer_release(machine_data->fsl_diu_info[i]);
- kfree(machine_data);
+ data = dev_get_drvdata(&pdev->dev);
+ disable_lcdc(&data->fsl_diu_info[0]);
+ free_irq_local(data);
+
+ for (i = 0; i < NUM_AOIS; i++)
+ uninstall_fb(&data->fsl_diu_info[i]);
+
+ iounmap(data->diu_reg);
+
+ dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
+ data->dma_addr);
return 0;
}
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
index f37e025..da066c2 100644
--- a/drivers/video/grvga.c
+++ b/drivers/video/grvga.c
@@ -70,7 +70,7 @@ static const struct fb_videomode grvga_modedb[] = {
}
};
-static struct fb_fix_screeninfo grvga_fix __initdata = {
+static struct fb_fix_screeninfo grvga_fix __devinitdata = {
.id = "AG SVGACTRL",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -267,7 +267,7 @@ static struct fb_ops grvga_ops = {
.fb_imageblit = cfb_imageblit
};
-static int __init grvga_parse_custom(char *options,
+static int __devinit grvga_parse_custom(char *options,
struct fb_var_screeninfo *screendata)
{
char *this_opt;
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 4394389..c645f92 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -133,7 +133,7 @@ static struct fb_fix_screeninfo hga_fix __devinitdata = {
/* Don't assume that tty1 will be the initial current console. */
static int release_io_port = 0;
static int release_io_ports = 0;
-static int nologo = 0;
+static bool nologo = 0;
/* -------------------------------------------------------------------------
*
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 318f6fb..b83f361 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -135,8 +135,8 @@ static struct pci_driver i810fb_driver = {
static char *mode_option __devinitdata = NULL;
static int vram __devinitdata = 4;
static int bpp __devinitdata = 8;
-static int mtrr __devinitdata;
-static int accel __devinitdata;
+static bool mtrr __devinitdata;
+static bool accel __devinitdata;
static int hsync1 __devinitdata;
static int hsync2 __devinitdata;
static int vsync1 __devinitdata;
@@ -144,10 +144,10 @@ static int vsync2 __devinitdata;
static int xres __devinitdata;
static int yres;
static int vyres __devinitdata;
-static int sync __devinitdata;
-static int extvga __devinitdata;
-static int dcolor __devinitdata;
-static int ddc3 __devinitdata = 2;
+static bool sync __devinitdata;
+static bool extvga __devinitdata;
+static bool dcolor __devinitdata;
+static bool ddc3 __devinitdata;
/*------------------------------------------------------------*/
@@ -1776,7 +1776,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
if (sync)
par->dev_flags |= ALWAYS_SYNC;
- par->ddc_num = ddc3;
+ par->ddc_num = (ddc3 ? 3 : 2);
if (bpp < 8)
bpp = 8;
@@ -1999,7 +1999,7 @@ static int __devinit i810fb_setup(char *options)
else if (!strncmp(this_opt, "dcolor", 6))
dcolor = 1;
else if (!strncmp(this_opt, "ddc3", 4))
- ddc3 = 3;
+ ddc3 = true;
else
mode_option = this_opt;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 5ba3999..c6afa33 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -230,15 +230,15 @@ MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
-static int accel = 1;
+static bool accel = 1;
static int vram = 4;
-static int hwcursor = 0;
-static int mtrr = 1;
-static int fixed = 0;
-static int noinit = 0;
-static int noregister = 0;
-static int probeonly = 0;
-static int idonly = 0;
+static bool hwcursor = 0;
+static bool mtrr = 1;
+static bool fixed = 0;
+static bool noinit = 0;
+static bool noregister = 0;
+static bool probeonly = 0;
+static bool idonly = 0;
static int bailearly = 0;
static int voffset = 48;
static char *mode = NULL;
@@ -263,7 +263,7 @@ module_param(probeonly, bool, 0);
MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
module_param(idonly, bool, 0);
MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
-module_param(bailearly, bool, 0);
+module_param(bailearly, int, 0);
MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
module_param(mode, charp, S_IRUGO);
MODULE_PARM_DESC(mode,
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index ea7a8cc..080c35b 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -21,7 +21,7 @@
#include <asm/bootinfo.h>
#endif
-static int nologo;
+static bool nologo;
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo");
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 44bf8d4..401a56e 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -147,7 +147,6 @@ static struct fb_var_screeninfo vesafb_defined = {
39721L,48L,16L,33L,10L,
96L,2L,~0, /* No sync info */
FB_VMODE_NONINTERLACED,
- 0, {0,0,0,0,0}
};
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index d7112c3..02796a4 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -593,7 +593,6 @@ static struct fb_var_screeninfo matroxfb_dh_defined = {
39721L,48L,16L,33L,10L,
96L,2,0, /* no sync info */
FB_VMODE_NONINTERLACED,
- 0, {0,0,0,0,0}
};
static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 6ce3416..55bf619 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -1053,18 +1053,7 @@ static struct platform_driver mbxfb_driver = {
},
};
-int __devinit mbxfb_init(void)
-{
- return platform_driver_register(&mbxfb_driver);
-}
-
-static void __devexit mbxfb_exit(void)
-{
- platform_driver_unregister(&mbxfb_driver);
-}
-
-module_init(mbxfb_init);
-module_exit(mbxfb_exit);
+module_platform_driver(mbxfb_driver);
MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
MODULE_AUTHOR("Mike Rapoport, Compulab");
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index e3406ab..727a514 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -245,6 +245,7 @@ struct mx3fb_data {
uint32_t h_start_width;
uint32_t v_start_width;
+ enum disp_data_mapping disp_data_fmt;
};
struct dma_chan_request {
@@ -287,11 +288,14 @@ static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long r
__raw_writel(value, mx3fb->reg_base + reg);
}
-static const uint32_t di_mappings[] = {
- 0x1600AAAA, 0x00E05555, 0x00070000, 3, /* RGB888 */
- 0x0005000F, 0x000B000F, 0x0011000F, 1, /* RGB666 */
- 0x0011000F, 0x000B000F, 0x0005000F, 1, /* BGR666 */
- 0x0004003F, 0x000A000F, 0x000F003F, 1 /* RGB565 */
+struct di_mapping {
+ uint32_t b0, b1, b2;
+};
+
+static const struct di_mapping di_mappings[] = {
+ [IPU_DISP_DATA_MAPPING_RGB666] = { 0x0005000f, 0x000b000f, 0x0011000f },
+ [IPU_DISP_DATA_MAPPING_RGB565] = { 0x0004003f, 0x000a000f, 0x000f003f },
+ [IPU_DISP_DATA_MAPPING_RGB888] = { 0x00070000, 0x000f0000, 0x00170000 },
};
static void sdc_fb_init(struct mx3fb_info *fbi)
@@ -334,7 +338,7 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
/* This enables the channel */
if (mx3_fbi->cookie < 0) {
mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
- &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
+ &mx3_fbi->sg[0], 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!mx3_fbi->txd) {
dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
dma_chan->chan_id);
@@ -425,7 +429,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
* @pixel_clk: desired pixel clock frequency in Hz.
* @width: width of panel in pixels.
* @height: height of panel in pixels.
- * @pixel_fmt: pixel format of buffer as FOURCC ASCII code.
* @h_start_width: number of pixel clocks between the HSYNC signal pulse
* and the start of valid data.
* @h_sync_width: width of the HSYNC signal in units of pixel clocks.
@@ -442,7 +445,6 @@ static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel
static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
uint32_t pixel_clk,
uint16_t width, uint16_t height,
- enum pixel_fmt pixel_fmt,
uint16_t h_start_width, uint16_t h_sync_width,
uint16_t h_end_width, uint16_t v_start_width,
uint16_t v_sync_width, uint16_t v_end_width,
@@ -453,6 +455,7 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
uint32_t old_conf;
uint32_t div;
struct clk *ipu_clk;
+ const struct di_mapping *map;
dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
@@ -540,36 +543,10 @@ static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel,
sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT;
mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL);
- switch (pixel_fmt) {
- case IPU_PIX_FMT_RGB24:
- mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
- mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
- ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
- break;
- case IPU_PIX_FMT_RGB666:
- mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
- mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
- ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
- break;
- case IPU_PIX_FMT_BGR666:
- mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
- mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
- ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
- break;
- default:
- mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
- mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
- mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
- ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
- break;
- }
+ map = &di_mappings[mx3fb->disp_data_fmt];
+ mx3fb_write_reg(mx3fb, map->b0, DI_DISP3_B0_MAP);
+ mx3fb_write_reg(mx3fb, map->b1, DI_DISP3_B1_MAP);
+ mx3fb_write_reg(mx3fb, map->b2, DI_DISP3_B2_MAP);
spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
@@ -780,8 +757,6 @@ static int __set_par(struct fb_info *fbi, bool lock)
if (sdc_init_panel(mx3fb, mode,
(PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
fbi->var.xres, fbi->var.yres,
- (fbi->var.sync & FB_SYNC_SWAP_RGB) ?
- IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
fbi->var.left_margin,
fbi->var.hsync_len,
fbi->var.right_margin +
@@ -1117,7 +1092,7 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
async_tx_ack(mx3_fbi->txd);
txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
- mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
+ mx3_fbi->cur_ipu_buf, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!txd) {
dev_err(fbi->device,
"Error preparing a DMA transaction descriptor.\n");
@@ -1349,6 +1324,12 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
const struct fb_videomode *mode;
int ret, num_modes;
+ if (mx3fb_pdata->disp_data_fmt >= ARRAY_SIZE(di_mappings)) {
+ dev_err(dev, "Illegal display data format %d\n",
+ mx3fb_pdata->disp_data_fmt);
+ return -EINVAL;
+ }
+
ichan->client = mx3fb;
irq = ichan->eof_irq;
@@ -1402,6 +1383,8 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
mx3fbi->mx3fb = mx3fb;
mx3fbi->blank = FB_BLANK_NORMAL;
+ mx3fb->disp_data_fmt = mx3fb_pdata->disp_data_fmt;
+
init_completion(&mx3fbi->flip_cmpl);
disable_irq(ichan->eof_irq);
dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index eb3c5ee..4a89f88 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -902,18 +902,7 @@ static struct platform_driver mxsfb_driver = {
},
};
-static int __init mxsfb_init(void)
-{
- return platform_driver_register(&mxsfb_driver);
-}
-
-static void __exit mxsfb_exit(void)
-{
- platform_driver_unregister(&mxsfb_driver);
-}
-
-module_init(mxsfb_init);
-module_exit(mxsfb_exit);
+module_platform_driver(mxsfb_driver);
MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index feea7b1..fb3f673 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -84,11 +84,11 @@
/* --------------------------------------------------------------------- */
-static int internal;
-static int external;
-static int libretto;
-static int nostretch;
-static int nopciburst;
+static bool internal;
+static bool external;
+static bool libretto;
+static bool nostretch;
+static bool nopciburst;
static char *mode_option __devinitdata = NULL;
#ifdef MODULE
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d1fbbd8..e10f551 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -762,18 +762,7 @@ static struct platform_driver nuc900fb_driver = {
},
};
-int __devinit nuc900fb_init(void)
-{
- return platform_driver_register(&nuc900fb_driver);
-}
-
-static void __exit nuc900fb_cleanup(void)
-{
- platform_driver_unregister(&nuc900fb_driver);
-}
-
-module_init(nuc900fb_init);
-module_exit(nuc900fb_cleanup);
+module_platform_driver(nuc900fb_driver);
MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 081dc47..fe13ac5 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -81,7 +81,7 @@ static int vram __devinitdata = 0;
static int bpp __devinitdata = 8;
static int reverse_i2c __devinitdata;
#ifdef CONFIG_MTRR
-static int nomtrr __devinitdata = 0;
+static bool nomtrr __devinitdata = false;
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
static int backlight __devinitdata = 1;
@@ -1509,7 +1509,7 @@ static int __devinit nvidiafb_setup(char *options)
backlight = simple_strtoul(this_opt+10, NULL, 0);
#ifdef CONFIG_MTRR
} else if (!strncmp(this_opt, "nomtrr", 6)) {
- nomtrr = 1;
+ nomtrr = true;
#endif
} else if (!strncmp(this_opt, "fpdither:", 9)) {
fpdither = simple_strtol(this_opt+9, NULL, 0);
@@ -1599,7 +1599,7 @@ MODULE_PARM_DESC(bpp, "pixel width in bits"
module_param(reverse_i2c, int, 0);
MODULE_PARM_DESC(reverse_i2c, "reverse port assignment of the i2c bus");
#ifdef CONFIG_MTRR
-module_param(nomtrr, bool, 0);
+module_param(nomtrr, bool, false);
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
"(default=0)");
#endif
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index 6978ae4..0fdd6f6 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -198,7 +198,7 @@ static int ams_delta_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver ams_delta_panel_driver = {
+static struct platform_driver ams_delta_panel_driver = {
.probe = ams_delta_panel_probe,
.remove = ams_delta_panel_remove,
.suspend = ams_delta_panel_suspend,
@@ -209,15 +209,4 @@ struct platform_driver ams_delta_panel_driver = {
},
};
-static int __init ams_delta_panel_drv_init(void)
-{
- return platform_driver_register(&ams_delta_panel_driver);
-}
-
-static void __exit ams_delta_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&ams_delta_panel_driver);
-}
-
-module_init(ams_delta_panel_drv_init);
-module_exit(ams_delta_panel_drv_cleanup);
+module_platform_driver(ams_delta_panel_driver);
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 622ad83..49bdeca 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -113,7 +113,7 @@ static int h3_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver h3_panel_driver = {
+static struct platform_driver h3_panel_driver = {
.probe = h3_panel_probe,
.remove = h3_panel_remove,
.suspend = h3_panel_suspend,
@@ -124,16 +124,4 @@ struct platform_driver h3_panel_driver = {
},
};
-static int __init h3_panel_drv_init(void)
-{
- return platform_driver_register(&h3_panel_driver);
-}
-
-static void __exit h3_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&h3_panel_driver);
-}
-
-module_init(h3_panel_drv_init);
-module_exit(h3_panel_drv_cleanup);
-
+module_platform_driver(h3_panel_driver);
diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c
index 4802419..20f4778 100644
--- a/drivers/video/omap/lcd_htcherald.c
+++ b/drivers/video/omap/lcd_htcherald.c
@@ -104,7 +104,7 @@ static int htcherald_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver htcherald_panel_driver = {
+static struct platform_driver htcherald_panel_driver = {
.probe = htcherald_panel_probe,
.remove = htcherald_panel_remove,
.suspend = htcherald_panel_suspend,
@@ -115,16 +115,4 @@ struct platform_driver htcherald_panel_driver = {
},
};
-static int __init htcherald_panel_drv_init(void)
-{
- return platform_driver_register(&htcherald_panel_driver);
-}
-
-static void __exit htcherald_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&htcherald_panel_driver);
-}
-
-module_init(htcherald_panel_drv_init);
-module_exit(htcherald_panel_drv_cleanup);
-
+module_platform_driver(htcherald_panel_driver);
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index 3271f16..b38b1dd 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -98,7 +98,7 @@ static int innovator1510_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver innovator1510_panel_driver = {
+static struct platform_driver innovator1510_panel_driver = {
.probe = innovator1510_panel_probe,
.remove = innovator1510_panel_remove,
.suspend = innovator1510_panel_suspend,
@@ -109,16 +109,4 @@ struct platform_driver innovator1510_panel_driver = {
},
};
-static int __init innovator1510_panel_drv_init(void)
-{
- return platform_driver_register(&innovator1510_panel_driver);
-}
-
-static void __exit innovator1510_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&innovator1510_panel_driver);
-}
-
-module_init(innovator1510_panel_drv_init);
-module_exit(innovator1510_panel_drv_cleanup);
-
+module_platform_driver(innovator1510_panel_driver);
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 12cc52a..7e8bd8e 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -122,7 +122,7 @@ static int innovator1610_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver innovator1610_panel_driver = {
+static struct platform_driver innovator1610_panel_driver = {
.probe = innovator1610_panel_probe,
.remove = innovator1610_panel_remove,
.suspend = innovator1610_panel_suspend,
@@ -133,16 +133,4 @@ struct platform_driver innovator1610_panel_driver = {
},
};
-static int __init innovator1610_panel_drv_init(void)
-{
- return platform_driver_register(&innovator1610_panel_driver);
-}
-
-static void __exit innovator1610_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&innovator1610_panel_driver);
-}
-
-module_init(innovator1610_panel_drv_init);
-module_exit(innovator1610_panel_drv_cleanup);
-
+module_platform_driver(innovator1610_panel_driver);
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index eb381db..8d546dd 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
static struct spi_driver mipid_spi_driver = {
.driver = {
.name = MIPID_MODULE_NAME,
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = mipid_spi_probe,
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index 6f8d13c..5914220 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -116,7 +116,7 @@ static int osk_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver osk_panel_driver = {
+static struct platform_driver osk_panel_driver = {
.probe = osk_panel_probe,
.remove = osk_panel_remove,
.suspend = osk_panel_suspend,
@@ -127,16 +127,4 @@ struct platform_driver osk_panel_driver = {
},
};
-static int __init osk_panel_drv_init(void)
-{
- return platform_driver_register(&osk_panel_driver);
-}
-
-static void __exit osk_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&osk_panel_driver);
-}
-
-module_init(osk_panel_drv_init);
-module_exit(osk_panel_drv_cleanup);
-
+module_platform_driver(osk_panel_driver);
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 4cb3017..88c31eb 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -97,7 +97,7 @@ static int palmte_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver palmte_panel_driver = {
+static struct platform_driver palmte_panel_driver = {
.probe = palmte_panel_probe,
.remove = palmte_panel_remove,
.suspend = palmte_panel_suspend,
@@ -108,16 +108,4 @@ struct platform_driver palmte_panel_driver = {
},
};
-static int __init palmte_panel_drv_init(void)
-{
- return platform_driver_register(&palmte_panel_driver);
-}
-
-static void __exit palmte_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&palmte_panel_driver);
-}
-
-module_init(palmte_panel_drv_init);
-module_exit(palmte_panel_drv_cleanup);
-
+module_platform_driver(palmte_panel_driver);
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index b51b332..aaf3c8b 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -102,7 +102,7 @@ static int palmtt_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver palmtt_panel_driver = {
+static struct platform_driver palmtt_panel_driver = {
.probe = palmtt_panel_probe,
.remove = palmtt_panel_remove,
.suspend = palmtt_panel_suspend,
@@ -113,15 +113,4 @@ struct platform_driver palmtt_panel_driver = {
},
};
-static int __init palmtt_panel_drv_init(void)
-{
- return platform_driver_register(&palmtt_panel_driver);
-}
-
-static void __exit palmtt_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&palmtt_panel_driver);
-}
-
-module_init(palmtt_panel_drv_init);
-module_exit(palmtt_panel_drv_cleanup);
+module_platform_driver(palmtt_panel_driver);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index 2334e56..3b7d8aa 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -98,7 +98,7 @@ static int palmz71_panel_resume(struct platform_device *pdev)
return 0;
}
-struct platform_driver palmz71_panel_driver = {
+static struct platform_driver palmz71_panel_driver = {
.probe = palmz71_panel_probe,
.remove = palmz71_panel_remove,
.suspend = palmz71_panel_suspend,
@@ -109,15 +109,4 @@ struct platform_driver palmz71_panel_driver = {
},
};
-static int __init palmz71_panel_drv_init(void)
-{
- return platform_driver_register(&palmz71_panel_driver);
-}
-
-static void __exit palmz71_panel_drv_cleanup(void)
-{
- platform_driver_unregister(&palmz71_panel_driver);
-}
-
-module_init(palmz71_panel_drv_init);
-module_exit(palmz71_panel_drv_cleanup);
+module_platform_driver(palmz71_panel_driver);
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 25d8e51..b291bfa 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -47,9 +47,9 @@ static unsigned int def_rotate;
static unsigned int def_mirror;
#ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
-static int manual_update = 1;
+static bool manual_update = 1;
#else
-static int manual_update;
+static bool manual_update;
#endif
static struct platform_device *fbdev_pdev;
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 8d8e1fe..74d29b5 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -41,7 +41,7 @@ config PANEL_NEC_NL8048HL11_01B
config PANEL_PICODLP
tristate "TI PICO DLP mini-projector"
- depends on OMAP2_DSS && I2C
+ depends on OMAP2_DSS_DPI && I2C
help
A mini-projector used in TI's SDP4430 and EVM boards
For more info please visit http://www.dlp.com/projector/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index dbd59b8..51a87e1 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -803,7 +803,6 @@ static int acx565akm_spi_remove(struct spi_device *spi)
static struct spi_driver acx565akm_spi_driver = {
.driver = {
.name = "acx565akm",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = acx565akm_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 519c47d..28b9a6d 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -297,6 +297,72 @@ static struct panel_config generic_dpi_panels[] = {
.name = "apollon",
},
+ /* FocalTech ETM070003DH6 */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 28000,
+
+ .hsw = 48,
+ .hfp = 40,
+ .hbp = 40,
+
+ .vsw = 3,
+ .vfp = 13,
+ .vbp = 29,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .name = "focaltech_etm070003dh6",
+ },
+
+ /* Microtips Technologies - UMSH-8173MD */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 34560,
+
+ .hsw = 13,
+ .hfp = 101,
+ .hbp = 101,
+
+ .vsw = 23,
+ .vfp = 1,
+ .vbp = 1,
+ },
+ .acbi = 0x0,
+ .acb = 0x0,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "microtips_umsh_8173md",
+ },
+
+ /* OrtusTech COM43H4M10XTC */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 8000,
+
+ .hsw = 41,
+ .hfp = 8,
+ .hbp = 4,
+
+ .vsw = 10,
+ .vfp = 4,
+ .vbp = 2,
+ },
+ .config = OMAP_DSS_LCD_TFT,
+
+ .name = "ortustech_com43h4m10xtc",
+ },
};
struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 150e8ba..dc9408d 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -708,7 +708,6 @@ static int mipid_spi_remove(struct spi_device *spi)
static struct spi_driver mipid_spi_driver = {
.driver = {
.name = "lcd_mipid",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 2ba9d0c..0eb31ca 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -163,50 +163,93 @@ static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
kfree(necd);
}
-static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
+static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
{
- int r = 0;
+ int r;
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
struct backlight_device *bl = necd->bl;
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ r = omapdss_dpi_display_enable(dssdev);
+ if (r)
+ goto err0;
+
if (dssdev->platform_enable) {
r = dssdev->platform_enable(dssdev);
if (r)
- return r;
+ goto err1;
}
r = nec_8048_bl_update_status(bl);
if (r < 0)
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
- r = omapdss_dpi_display_enable(dssdev);
-
+ return 0;
+err1:
+ omapdss_dpi_display_disable(dssdev);
+err0:
return r;
}
-static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
+static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
{
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
struct backlight_device *bl = necd->bl;
- omapdss_dpi_display_disable(dssdev);
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
bl->props.brightness = 0;
nec_8048_bl_update_status(bl);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
+
+ omapdss_dpi_display_disable(dssdev);
+}
+
+static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = nec_8048_panel_power_on(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
+{
+ nec_8048_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
{
- nec_8048_panel_disable(dssdev);
+ nec_8048_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+
return 0;
}
static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
{
- return nec_8048_panel_enable(dssdev);
+ int r;
+
+ r = nec_8048_panel_power_on(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
}
static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
@@ -303,7 +346,6 @@ static struct spi_driver nec_8048_spi_driver = {
.resume = nec_8048_spi_resume,
.driver = {
.name = "nec_8048_spi",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
};
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 80c3f6a..00c5c61 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -198,12 +198,6 @@ struct taal_data {
bool te_enabled;
atomic_t do_update;
- struct {
- u16 x;
- u16 y;
- u16 w;
- u16 h;
- } update_region;
int channel;
struct delayed_work te_timeout_work;
@@ -1188,6 +1182,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if (r)
goto err;
+ r = dsi_enable_video_output(dssdev, td->channel);
+ if (r)
+ goto err;
+
td->enabled = 1;
if (!td->intro_printed) {
@@ -1217,6 +1215,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
+ dsi_disable_video_output(dssdev, td->channel);
+
r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
if (!r)
r = taal_sleep_in(td);
@@ -1394,12 +1394,8 @@ static irqreturn_t taal_te_isr(int irq, void *data)
if (old) {
cancel_delayed_work(&td->te_timeout_work);
- r = omap_dsi_update(dssdev, td->channel,
- td->update_region.x,
- td->update_region.y,
- td->update_region.w,
- td->update_region.h,
- taal_framedone_cb, dssdev);
+ r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
+ dssdev);
if (r)
goto err;
}
@@ -1444,26 +1440,20 @@ static int taal_update(struct omap_dss_device *dssdev,
goto err;
}
- r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
- if (r)
- goto err;
-
- r = taal_set_update_window(td, x, y, w, h);
+ /* XXX no need to send this every frame, but dsi break if not done */
+ r = taal_set_update_window(td, 0, 0,
+ td->panel_config->timings.x_res,
+ td->panel_config->timings.y_res);
if (r)
goto err;
if (td->te_enabled && panel_data->use_ext_te) {
- td->update_region.x = x;
- td->update_region.y = y;
- td->update_region.w = w;
- td->update_region.h = h;
- barrier();
schedule_delayed_work(&td->te_timeout_work,
msecs_to_jiffies(250));
atomic_set(&td->do_update, 1);
} else {
- r = omap_dsi_update(dssdev, td->channel, x, y, w, h,
- taal_framedone_cb, dssdev);
+ r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
+ dssdev);
if (r)
goto err;
}
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 2462b9e..e6649aa 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -512,7 +512,6 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
static struct spi_driver tpo_td043_spi_driver = {
.driver = {
.name = "tpo_td043mtea1_panel_spi",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = tpo_td043_spi_probe,
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index bd34ac5..5c450b0 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
-omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
+omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
+ manager.o overlay.o apply.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
new file mode 100644
index 0000000..052dc87
--- /dev/null
+++ b/drivers/video/omap2/dss/apply.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@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.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+/*
+ * We have 4 levels of cache for the dispc settings. First two are in SW and
+ * the latter two in HW.
+ *
+ * set_info()
+ * v
+ * +--------------------+
+ * | user_info |
+ * +--------------------+
+ * v
+ * apply()
+ * v
+ * +--------------------+
+ * | info |
+ * +--------------------+
+ * v
+ * write_regs()
+ * v
+ * +--------------------+
+ * | shadow registers |
+ * +--------------------+
+ * v
+ * VFP or lcd/digit_enable
+ * v
+ * +--------------------+
+ * | registers |
+ * +--------------------+
+ */
+
+struct ovl_priv_data {
+
+ bool user_info_dirty;
+ struct omap_overlay_info user_info;
+
+ bool info_dirty;
+ struct omap_overlay_info info;
+
+ bool shadow_info_dirty;
+
+ bool extra_info_dirty;
+ bool shadow_extra_info_dirty;
+
+ bool enabled;
+ enum omap_channel channel;
+ u32 fifo_low, fifo_high;
+
+ /*
+ * True if overlay is to be enabled. Used to check and calculate configs
+ * for the overlay before it is enabled in the HW.
+ */
+ bool enabling;
+};
+
+struct mgr_priv_data {
+
+ bool user_info_dirty;
+ struct omap_overlay_manager_info user_info;
+
+ bool info_dirty;
+ struct omap_overlay_manager_info info;
+
+ bool shadow_info_dirty;
+
+ /* If true, GO bit is up and shadow registers cannot be written.
+ * Never true for manual update displays */
+ bool busy;
+
+ /* If true, dispc output is enabled */
+ bool updating;
+
+ /* If true, a display is enabled using this manager */
+ bool enabled;
+};
+
+static struct {
+ struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
+ struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
+
+ bool irq_enabled;
+} dss_data;
+
+/* protects dss_data */
+static spinlock_t data_lock;
+/* lock for blocking functions */
+static DEFINE_MUTEX(apply_lock);
+static DECLARE_COMPLETION(extra_updated_completion);
+
+static void dss_register_vsync_isr(void);
+
+static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
+{
+ return &dss_data.ovl_priv_data_array[ovl->id];
+}
+
+static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
+{
+ return &dss_data.mgr_priv_data_array[mgr->id];
+}
+
+void dss_apply_init(void)
+{
+ const int num_ovls = dss_feat_get_num_ovls();
+ int i;
+
+ spin_lock_init(&data_lock);
+
+ for (i = 0; i < num_ovls; ++i) {
+ struct ovl_priv_data *op;
+
+ op = &dss_data.ovl_priv_data_array[i];
+
+ op->info.global_alpha = 255;
+
+ switch (i) {
+ case 0:
+ op->info.zorder = 0;
+ break;
+ case 1:
+ op->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
+ break;
+ case 2:
+ op->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+ break;
+ case 3:
+ op->info.zorder =
+ dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
+ break;
+ }
+
+ op->user_info = op->info;
+ }
+}
+
+static bool ovl_manual_update(struct omap_overlay *ovl)
+{
+ return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+}
+
+static bool mgr_manual_update(struct omap_overlay_manager *mgr)
+{
+ return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+}
+
+static int dss_check_settings_low(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev, bool applying)
+{
+ struct omap_overlay_info *oi;
+ struct omap_overlay_manager_info *mi;
+ struct omap_overlay *ovl;
+ struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
+ struct ovl_priv_data *op;
+ struct mgr_priv_data *mp;
+
+ mp = get_mgr_priv(mgr);
+
+ if (applying && mp->user_info_dirty)
+ mi = &mp->user_info;
+ else
+ mi = &mp->info;
+
+ /* collect the infos to be tested into the array */
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ op = get_ovl_priv(ovl);
+
+ if (!op->enabled && !op->enabling)
+ oi = NULL;
+ else if (applying && op->user_info_dirty)
+ oi = &op->user_info;
+ else
+ oi = &op->info;
+
+ ois[ovl->id] = oi;
+ }
+
+ return dss_mgr_check(mgr, dssdev, mi, ois);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from data->info
+ */
+static int dss_check_settings(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+{
+ return dss_check_settings_low(mgr, dssdev, false);
+}
+
+/*
+ * check manager and overlay settings using overlay_info from ovl->info if
+ * dirty and from data->info otherwise
+ */
+static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+{
+ return dss_check_settings_low(mgr, dssdev, true);
+}
+
+static bool need_isr(void)
+{
+ const int num_mgrs = dss_feat_get_num_mgrs();
+ int i;
+
+ for (i = 0; i < num_mgrs; ++i) {
+ struct omap_overlay_manager *mgr;
+ struct mgr_priv_data *mp;
+ struct omap_overlay *ovl;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->enabled)
+ continue;
+
+ if (mgr_manual_update(mgr)) {
+ /* to catch FRAMEDONE */
+ if (mp->updating)
+ return true;
+ } else {
+ /* to catch GO bit going down */
+ if (mp->busy)
+ return true;
+
+ /* to write new values to registers */
+ if (mp->info_dirty)
+ return true;
+
+ /* to set GO bit */
+ if (mp->shadow_info_dirty)
+ return true;
+
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ struct ovl_priv_data *op;
+
+ op = get_ovl_priv(ovl);
+
+ /*
+ * NOTE: we check extra_info flags even for
+ * disabled overlays, as extra_infos need to be
+ * always written.
+ */
+
+ /* to write new values to registers */
+ if (op->extra_info_dirty)
+ return true;
+
+ /* to set GO bit */
+ if (op->shadow_extra_info_dirty)
+ return true;
+
+ if (!op->enabled)
+ continue;
+
+ /* to write new values to registers */
+ if (op->info_dirty)
+ return true;
+
+ /* to set GO bit */
+ if (op->shadow_info_dirty)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool need_go(struct omap_overlay_manager *mgr)
+{
+ struct omap_overlay *ovl;
+ struct mgr_priv_data *mp;
+ struct ovl_priv_data *op;
+
+ mp = get_mgr_priv(mgr);
+
+ if (mp->shadow_info_dirty)
+ return true;
+
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ op = get_ovl_priv(ovl);
+ if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
+ return true;
+ }
+
+ return false;
+}
+
+/* returns true if an extra_info field is currently being updated */
+static bool extra_info_update_ongoing(void)
+{
+ const int num_ovls = omap_dss_get_num_overlays();
+ struct ovl_priv_data *op;
+ struct omap_overlay *ovl;
+ struct mgr_priv_data *mp;
+ int i;
+
+ for (i = 0; i < num_ovls; ++i) {
+ ovl = omap_dss_get_overlay(i);
+ op = get_ovl_priv(ovl);
+
+ if (!ovl->manager)
+ continue;
+
+ mp = get_mgr_priv(ovl->manager);
+
+ if (!mp->enabled)
+ continue;
+
+ if (!mp->updating)
+ continue;
+
+ if (op->extra_info_dirty || op->shadow_extra_info_dirty)
+ return true;
+ }
+
+ return false;
+}
+
+/* wait until no extra_info updates are pending */
+static void wait_pending_extra_info_updates(void)
+{
+ bool updating;
+ unsigned long flags;
+ unsigned long t;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ updating = extra_info_update_ongoing();
+
+ if (!updating) {
+ spin_unlock_irqrestore(&data_lock, flags);
+ return;
+ }
+
+ init_completion(&extra_updated_completion);
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ t = msecs_to_jiffies(500);
+ wait_for_completion_timeout(&extra_updated_completion, t);
+
+ updating = extra_info_update_ongoing();
+
+ WARN_ON(updating);
+}
+
+int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ struct mgr_priv_data *mp;
+ u32 irq;
+ int r;
+ int i;
+ struct omap_dss_device *dssdev = mgr->device;
+
+ if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ if (mgr_manual_update(mgr))
+ return 0;
+
+ irq = dispc_mgr_get_vsync_irq(mgr->id);
+
+ mp = get_mgr_priv(mgr);
+ i = 0;
+ while (1) {
+ unsigned long flags;
+ bool shadow_dirty, dirty;
+
+ spin_lock_irqsave(&data_lock, flags);
+ dirty = mp->info_dirty;
+ shadow_dirty = mp->shadow_info_dirty;
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ if (!dirty && !shadow_dirty) {
+ r = 0;
+ break;
+ }
+
+ /* 4 iterations is the worst case:
+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+ * 2 - first VSYNC, dirty = true
+ * 3 - dirty = false, shadow_dirty = true
+ * 4 - shadow_dirty = false */
+ if (i++ == 3) {
+ DSSERR("mgr(%d)->wait_for_go() not finishing\n",
+ mgr->id);
+ r = 0;
+ break;
+ }
+
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ if (r == -ERESTARTSYS)
+ break;
+
+ if (r) {
+ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
+ break;
+ }
+ }
+
+ return r;
+}
+
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ struct ovl_priv_data *op;
+ struct omap_dss_device *dssdev;
+ u32 irq;
+ int r;
+ int i;
+
+ if (!ovl->manager)
+ return 0;
+
+ dssdev = ovl->manager->device;
+
+ if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ if (ovl_manual_update(ovl))
+ return 0;
+
+ irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
+
+ op = get_ovl_priv(ovl);
+ i = 0;
+ while (1) {
+ unsigned long flags;
+ bool shadow_dirty, dirty;
+
+ spin_lock_irqsave(&data_lock, flags);
+ dirty = op->info_dirty;
+ shadow_dirty = op->shadow_info_dirty;
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ if (!dirty && !shadow_dirty) {
+ r = 0;
+ break;
+ }
+
+ /* 4 iterations is the worst case:
+ * 1 - initial iteration, dirty = true (between VFP and VSYNC)
+ * 2 - first VSYNC, dirty = true
+ * 3 - dirty = false, shadow_dirty = true
+ * 4 - shadow_dirty = false */
+ if (i++ == 3) {
+ DSSERR("ovl(%d)->wait_for_go() not finishing\n",
+ ovl->id);
+ r = 0;
+ break;
+ }
+
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+ if (r == -ERESTARTSYS)
+ break;
+
+ if (r) {
+ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
+ break;
+ }
+ }
+
+ return r;
+}
+
+static void dss_ovl_write_regs(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ struct omap_overlay_info *oi;
+ bool ilace, replication;
+ struct mgr_priv_data *mp;
+ int r;
+
+ DSSDBGF("%d", ovl->id);
+
+ if (!op->enabled || !op->info_dirty)
+ return;
+
+ oi = &op->info;
+
+ replication = dss_use_replication(ovl->manager->device, oi->color_mode);
+
+ ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;
+
+ r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
+ if (r) {
+ /*
+ * We can't do much here, as this function can be called from
+ * vsync interrupt.
+ */
+ DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
+
+ /* This will leave fifo configurations in a nonoptimal state */
+ op->enabled = false;
+ dispc_ovl_enable(ovl->id, false);
+ return;
+ }
+
+ mp = get_mgr_priv(ovl->manager);
+
+ op->info_dirty = false;
+ if (mp->updating)
+ op->shadow_info_dirty = true;
+}
+
+static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ struct mgr_priv_data *mp;
+
+ DSSDBGF("%d", ovl->id);
+
+ if (!op->extra_info_dirty)
+ return;
+
+ /* note: write also when op->enabled == false, so that the ovl gets
+ * disabled */
+
+ dispc_ovl_enable(ovl->id, op->enabled);
+ dispc_ovl_set_channel_out(ovl->id, op->channel);
+ dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
+
+ mp = get_mgr_priv(ovl->manager);
+
+ op->extra_info_dirty = false;
+ if (mp->updating)
+ op->shadow_extra_info_dirty = true;
+}
+
+static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ struct omap_overlay *ovl;
+
+ DSSDBGF("%d", mgr->id);
+
+ if (!mp->enabled)
+ return;
+
+ WARN_ON(mp->busy);
+
+ /* Commit overlay settings */
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ dss_ovl_write_regs(ovl);
+ dss_ovl_write_regs_extra(ovl);
+ }
+
+ if (mp->info_dirty) {
+ dispc_mgr_setup(mgr->id, &mp->info);
+
+ mp->info_dirty = false;
+ if (mp->updating)
+ mp->shadow_info_dirty = true;
+ }
+}
+
+static void dss_write_regs(void)
+{
+ const int num_mgrs = omap_dss_get_num_overlay_managers();
+ int i;
+
+ for (i = 0; i < num_mgrs; ++i) {
+ struct omap_overlay_manager *mgr;
+ struct mgr_priv_data *mp;
+ int r;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
+ continue;
+
+ r = dss_check_settings(mgr, mgr->device);
+ if (r) {
+ DSSERR("cannot write registers for manager %s: "
+ "illegal configuration\n", mgr->name);
+ continue;
+ }
+
+ dss_mgr_write_regs(mgr);
+ }
+}
+
+static void dss_set_go_bits(void)
+{
+ const int num_mgrs = omap_dss_get_num_overlay_managers();
+ int i;
+
+ for (i = 0; i < num_mgrs; ++i) {
+ struct omap_overlay_manager *mgr;
+ struct mgr_priv_data *mp;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
+ continue;
+
+ if (!need_go(mgr))
+ continue;
+
+ mp->busy = true;
+
+ if (!dss_data.irq_enabled && need_isr())
+ dss_register_vsync_isr();
+
+ dispc_mgr_go(mgr->id);
+ }
+
+}
+
+void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ unsigned long flags;
+ int r;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ WARN_ON(mp->updating);
+
+ r = dss_check_settings(mgr, mgr->device);
+ if (r) {
+ DSSERR("cannot start manual update: illegal configuration\n");
+ spin_unlock_irqrestore(&data_lock, flags);
+ return;
+ }
+
+ dss_mgr_write_regs(mgr);
+
+ mp->updating = true;
+
+ if (!dss_data.irq_enabled && need_isr())
+ dss_register_vsync_isr();
+
+ dispc_mgr_enable(mgr->id, true);
+
+ spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask);
+
+static void dss_register_vsync_isr(void)
+{
+ const int num_mgrs = dss_feat_get_num_mgrs();
+ u32 mask;
+ int r, i;
+
+ mask = 0;
+ for (i = 0; i < num_mgrs; ++i)
+ mask |= dispc_mgr_get_vsync_irq(i);
+
+ for (i = 0; i < num_mgrs; ++i)
+ mask |= dispc_mgr_get_framedone_irq(i);
+
+ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
+ WARN_ON(r);
+
+ dss_data.irq_enabled = true;
+}
+
+static void dss_unregister_vsync_isr(void)
+{
+ const int num_mgrs = dss_feat_get_num_mgrs();
+ u32 mask;
+ int r, i;
+
+ mask = 0;
+ for (i = 0; i < num_mgrs; ++i)
+ mask |= dispc_mgr_get_vsync_irq(i);
+
+ for (i = 0; i < num_mgrs; ++i)
+ mask |= dispc_mgr_get_framedone_irq(i);
+
+ r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
+ WARN_ON(r);
+
+ dss_data.irq_enabled = false;
+}
+
+static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
+{
+ struct omap_overlay *ovl;
+ struct mgr_priv_data *mp;
+ struct ovl_priv_data *op;
+
+ mp = get_mgr_priv(mgr);
+ mp->shadow_info_dirty = false;
+
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ op = get_ovl_priv(ovl);
+ op->shadow_info_dirty = false;
+ op->shadow_extra_info_dirty = false;
+ }
+}
+
+static void dss_apply_irq_handler(void *data, u32 mask)
+{
+ const int num_mgrs = dss_feat_get_num_mgrs();
+ int i;
+ bool extra_updating;
+
+ spin_lock(&data_lock);
+
+ /* clear busy, updating flags, shadow_dirty flags */
+ for (i = 0; i < num_mgrs; i++) {
+ struct omap_overlay_manager *mgr;
+ struct mgr_priv_data *mp;
+ bool was_updating;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->enabled)
+ continue;
+
+ was_updating = mp->updating;
+ mp->updating = dispc_mgr_is_enabled(i);
+
+ if (!mgr_manual_update(mgr)) {
+ bool was_busy = mp->busy;
+ mp->busy = dispc_mgr_go_busy(i);
+
+ if (was_busy && !mp->busy)
+ mgr_clear_shadow_dirty(mgr);
+ } else {
+ if (was_updating && !mp->updating)
+ mgr_clear_shadow_dirty(mgr);
+ }
+ }
+
+ dss_write_regs();
+ dss_set_go_bits();
+
+ extra_updating = extra_info_update_ongoing();
+ if (!extra_updating)
+ complete_all(&extra_updated_completion);
+
+ if (!need_isr())
+ dss_unregister_vsync_isr();
+
+ spin_unlock(&data_lock);
+}
+
+static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op;
+
+ op = get_ovl_priv(ovl);
+
+ if (!op->user_info_dirty)
+ return;
+
+ op->user_info_dirty = false;
+ op->info_dirty = true;
+ op->info = op->user_info;
+}
+
+static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
+{
+ struct mgr_priv_data *mp;
+
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->user_info_dirty)
+ return;
+
+ mp->user_info_dirty = false;
+ mp->info_dirty = true;
+ mp->info = mp->user_info;
+}
+
+int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+{
+ unsigned long flags;
+ struct omap_overlay *ovl;
+ int r;
+
+ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ r = dss_check_settings_apply(mgr, mgr->device);
+ if (r) {
+ spin_unlock_irqrestore(&data_lock, flags);
+ DSSERR("failed to apply settings: illegal configuration.\n");
+ return r;
+ }
+
+ /* Configure overlays */
+ list_for_each_entry(ovl, &mgr->overlays, list)
+ omap_dss_mgr_apply_ovl(ovl);
+
+ /* Configure manager */
+ omap_dss_mgr_apply_mgr(mgr);
+
+ dss_write_regs();
+ dss_set_go_bits();
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return 0;
+}
+
+static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
+{
+ struct ovl_priv_data *op;
+
+ op = get_ovl_priv(ovl);
+
+ if (op->enabled == enable)
+ return;
+
+ op->enabled = enable;
+ op->extra_info_dirty = true;
+}
+
+static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
+ u32 fifo_low, u32 fifo_high)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+ if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
+ return;
+
+ op->fifo_low = fifo_low;
+ op->fifo_high = fifo_high;
+ op->extra_info_dirty = true;
+}
+
+static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ struct omap_dss_device *dssdev;
+ u32 size, burst_size;
+ u32 fifo_low, fifo_high;
+
+ if (!op->enabled && !op->enabling)
+ return;
+
+ dssdev = ovl->manager->device;
+
+ size = dispc_ovl_get_fifo_size(ovl->id);
+
+ burst_size = dispc_ovl_get_burst_size(ovl->id);
+
+ switch (dssdev->type) {
+ case OMAP_DISPLAY_TYPE_DPI:
+ case OMAP_DISPLAY_TYPE_DBI:
+ case OMAP_DISPLAY_TYPE_SDI:
+ case OMAP_DISPLAY_TYPE_VENC:
+ case OMAP_DISPLAY_TYPE_HDMI:
+ default_get_overlay_fifo_thresholds(ovl->id, size,
+ burst_size, &fifo_low, &fifo_high);
+ break;
+#ifdef CONFIG_OMAP2_DSS_DSI
+ case OMAP_DISPLAY_TYPE_DSI:
+ dsi_get_overlay_fifo_thresholds(ovl->id, size,
+ burst_size, &fifo_low, &fifo_high);
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
+}
+
+static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
+{
+ struct omap_overlay *ovl;
+ struct mgr_priv_data *mp;
+
+ mp = get_mgr_priv(mgr);
+
+ if (!mp->enabled)
+ return;
+
+ list_for_each_entry(ovl, &mgr->overlays, list)
+ dss_ovl_setup_fifo(ovl);
+}
+
+static void dss_setup_fifos(void)
+{
+ const int num_mgrs = omap_dss_get_num_overlay_managers();
+ struct omap_overlay_manager *mgr;
+ int i;
+
+ for (i = 0; i < num_mgrs; ++i) {
+ mgr = omap_dss_get_overlay_manager(i);
+ dss_mgr_setup_fifos(mgr);
+ }
+}
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ unsigned long flags;
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (mp->enabled)
+ goto out;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ mp->enabled = true;
+
+ r = dss_check_settings(mgr, mgr->device);
+ if (r) {
+ DSSERR("failed to enable manager %d: check_settings failed\n",
+ mgr->id);
+ goto err;
+ }
+
+ dss_setup_fifos();
+
+ dss_write_regs();
+ dss_set_go_bits();
+
+ if (!mgr_manual_update(mgr))
+ mp->updating = true;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ if (!mgr_manual_update(mgr))
+ dispc_mgr_enable(mgr->id, true);
+
+out:
+ mutex_unlock(&apply_lock);
+
+ return 0;
+
+err:
+ mp->enabled = false;
+ spin_unlock_irqrestore(&data_lock, flags);
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+void dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ unsigned long flags;
+
+ mutex_lock(&apply_lock);
+
+ if (!mp->enabled)
+ goto out;
+
+ if (!mgr_manual_update(mgr))
+ dispc_mgr_enable(mgr->id, false);
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ mp->updating = false;
+ mp->enabled = false;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+out:
+ mutex_unlock(&apply_lock);
+}
+
+int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ unsigned long flags;
+ int r;
+
+ r = dss_mgr_simple_check(mgr, info);
+ if (r)
+ return r;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ mp->user_info = *info;
+ mp->user_info_dirty = true;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return 0;
+}
+
+void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ unsigned long flags;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ *info = mp->user_info;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+}
+
+int dss_mgr_set_device(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev)
+{
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (dssdev->manager) {
+ DSSERR("display '%s' already has a manager '%s'\n",
+ dssdev->name, dssdev->manager->name);
+ r = -EINVAL;
+ goto err;
+ }
+
+ if ((mgr->supported_displays & dssdev->type) == 0) {
+ DSSERR("display '%s' does not support manager '%s'\n",
+ dssdev->name, mgr->name);
+ r = -EINVAL;
+ goto err;
+ }
+
+ dssdev->manager = mgr;
+ mgr->device = dssdev;
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
+{
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (!mgr->device) {
+ DSSERR("failed to unset display, display not set.\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ /*
+ * Don't allow currently enabled displays to have the overlay manager
+ * pulled out from underneath them
+ */
+ if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ mgr->device->manager = NULL;
+ mgr->device = NULL;
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+
+int dss_ovl_set_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ int r;
+
+ r = dss_ovl_simple_check(ovl, info);
+ if (r)
+ return r;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ op->user_info = *info;
+ op->user_info_dirty = true;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return 0;
+}
+
+void dss_ovl_get_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ *info = op->user_info;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+}
+
+int dss_ovl_set_manager(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ int r;
+
+ if (!mgr)
+ return -EINVAL;
+
+ mutex_lock(&apply_lock);
+
+ if (ovl->manager) {
+ DSSERR("overlay '%s' already has a manager '%s'\n",
+ ovl->name, ovl->manager->name);
+ r = -EINVAL;
+ goto err;
+ }
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ if (op->enabled) {
+ spin_unlock_irqrestore(&data_lock, flags);
+ DSSERR("overlay has to be disabled to change the manager\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ op->channel = mgr->id;
+ op->extra_info_dirty = true;
+
+ ovl->manager = mgr;
+ list_add_tail(&ovl->list, &mgr->overlays);
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ /* XXX: When there is an overlay on a DSI manual update display, and
+ * the overlay is first disabled, then moved to tv, and enabled, we
+ * seem to get SYNC_LOST_DIGIT error.
+ *
+ * Waiting doesn't seem to help, but updating the manual update display
+ * after disabling the overlay seems to fix this. This hints that the
+ * overlay is perhaps somehow tied to the LCD output until the output
+ * is updated.
+ *
+ * Userspace workaround for this is to update the LCD after disabling
+ * the overlay, but before moving the overlay to TV.
+ */
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+int dss_ovl_unset_manager(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (!ovl->manager) {
+ DSSERR("failed to detach overlay: manager not set\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ if (op->enabled) {
+ spin_unlock_irqrestore(&data_lock, flags);
+ DSSERR("overlay has to be disabled to unset the manager\n");
+ r = -EINVAL;
+ goto err;
+ }
+
+ op->channel = -1;
+
+ ovl->manager = NULL;
+ list_del(&ovl->list);
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+bool dss_ovl_is_enabled(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ bool e;
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ e = op->enabled;
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ return e;
+}
+
+int dss_ovl_enable(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (op->enabled) {
+ r = 0;
+ goto err1;
+ }
+
+ if (ovl->manager == NULL || ovl->manager->device == NULL) {
+ r = -EINVAL;
+ goto err1;
+ }
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ op->enabling = true;
+
+ r = dss_check_settings(ovl->manager, ovl->manager->device);
+ if (r) {
+ DSSERR("failed to enable overlay %d: check_settings failed\n",
+ ovl->id);
+ goto err2;
+ }
+
+ dss_setup_fifos();
+
+ op->enabling = false;
+ dss_apply_ovl_enable(ovl, true);
+
+ dss_write_regs();
+ dss_set_go_bits();
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+err2:
+ op->enabling = false;
+ spin_unlock_irqrestore(&data_lock, flags);
+err1:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
+int dss_ovl_disable(struct omap_overlay *ovl)
+{
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+ unsigned long flags;
+ int r;
+
+ mutex_lock(&apply_lock);
+
+ if (!op->enabled) {
+ r = 0;
+ goto err;
+ }
+
+ if (ovl->manager == NULL || ovl->manager->device == NULL) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ spin_lock_irqsave(&data_lock, flags);
+
+ dss_apply_ovl_enable(ovl, false);
+ dss_write_regs();
+ dss_set_go_bits();
+
+ spin_unlock_irqrestore(&data_lock, flags);
+
+ mutex_unlock(&apply_lock);
+
+ return 0;
+
+err:
+ mutex_unlock(&apply_lock);
+ return r;
+}
+
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 86ec12e..8613f86 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -50,7 +50,7 @@ module_param_named(def_disp, def_disp_name, charp, 0);
MODULE_PARM_DESC(def_disp, "default display name");
#ifdef DEBUG
-unsigned int dss_debug;
+bool dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
@@ -178,6 +178,8 @@ static int omap_dss_probe(struct platform_device *pdev)
dss_features_init();
+ dss_apply_init();
+
dss_init_overlay_managers(pdev);
dss_init_overlays(pdev);
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5c81533..a5ec7f3 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -64,22 +64,6 @@ struct omap_dispc_isr_data {
u32 mask;
};
-struct dispc_h_coef {
- s8 hc4;
- s8 hc3;
- u8 hc2;
- s8 hc1;
- s8 hc0;
-};
-
-struct dispc_v_coef {
- s8 vc22;
- s8 vc2;
- u8 vc1;
- s8 vc0;
- s8 vc00;
-};
-
enum omap_burst_size {
BURST_SIZE_X2 = 0,
BURST_SIZE_X4 = 1,
@@ -438,6 +422,34 @@ static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
return mgr ? mgr->device : NULL;
}
+u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
+{
+ switch (channel) {
+ case OMAP_DSS_CHANNEL_LCD:
+ return DISPC_IRQ_VSYNC;
+ case OMAP_DSS_CHANNEL_LCD2:
+ return DISPC_IRQ_VSYNC2;
+ case OMAP_DSS_CHANNEL_DIGIT:
+ return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
+ default:
+ BUG();
+ }
+}
+
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
+{
+ switch (channel) {
+ case OMAP_DSS_CHANNEL_LCD:
+ return DISPC_IRQ_FRAMEDONE;
+ case OMAP_DSS_CHANNEL_LCD2:
+ return DISPC_IRQ_FRAMEDONE2;
+ case OMAP_DSS_CHANNEL_DIGIT:
+ return 0;
+ default:
+ BUG();
+ }
+}
+
bool dispc_mgr_go_busy(enum omap_channel channel)
{
int bit;
@@ -533,105 +545,27 @@ static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
}
-static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
- int vscaleup, int five_taps,
- enum omap_color_component color_comp)
-{
- /* Coefficients for horizontal up-sampling */
- static const struct dispc_h_coef coef_hup[8] = {
- { 0, 0, 128, 0, 0 },
- { -1, 13, 124, -8, 0 },
- { -2, 30, 112, -11, -1 },
- { -5, 51, 95, -11, -2 },
- { 0, -9, 73, 73, -9 },
- { -2, -11, 95, 51, -5 },
- { -1, -11, 112, 30, -2 },
- { 0, -8, 124, 13, -1 },
- };
-
- /* Coefficients for vertical up-sampling */
- static const struct dispc_v_coef coef_vup_3tap[8] = {
- { 0, 0, 128, 0, 0 },
- { 0, 3, 123, 2, 0 },
- { 0, 12, 111, 5, 0 },
- { 0, 32, 89, 7, 0 },
- { 0, 0, 64, 64, 0 },
- { 0, 7, 89, 32, 0 },
- { 0, 5, 111, 12, 0 },
- { 0, 2, 123, 3, 0 },
- };
-
- static const struct dispc_v_coef coef_vup_5tap[8] = {
- { 0, 0, 128, 0, 0 },
- { -1, 13, 124, -8, 0 },
- { -2, 30, 112, -11, -1 },
- { -5, 51, 95, -11, -2 },
- { 0, -9, 73, 73, -9 },
- { -2, -11, 95, 51, -5 },
- { -1, -11, 112, 30, -2 },
- { 0, -8, 124, 13, -1 },
- };
-
- /* Coefficients for horizontal down-sampling */
- static const struct dispc_h_coef coef_hdown[8] = {
- { 0, 36, 56, 36, 0 },
- { 4, 40, 55, 31, -2 },
- { 8, 44, 54, 27, -5 },
- { 12, 48, 53, 22, -7 },
- { -9, 17, 52, 51, 17 },
- { -7, 22, 53, 48, 12 },
- { -5, 27, 54, 44, 8 },
- { -2, 31, 55, 40, 4 },
- };
-
- /* Coefficients for vertical down-sampling */
- static const struct dispc_v_coef coef_vdown_3tap[8] = {
- { 0, 36, 56, 36, 0 },
- { 0, 40, 57, 31, 0 },
- { 0, 45, 56, 27, 0 },
- { 0, 50, 55, 23, 0 },
- { 0, 18, 55, 55, 0 },
- { 0, 23, 55, 50, 0 },
- { 0, 27, 56, 45, 0 },
- { 0, 31, 57, 40, 0 },
- };
-
- static const struct dispc_v_coef coef_vdown_5tap[8] = {
- { 0, 36, 56, 36, 0 },
- { 4, 40, 55, 31, -2 },
- { 8, 44, 54, 27, -5 },
- { 12, 48, 53, 22, -7 },
- { -9, 17, 52, 51, 17 },
- { -7, 22, 53, 48, 12 },
- { -5, 27, 54, 44, 8 },
- { -2, 31, 55, 40, 4 },
- };
-
- const struct dispc_h_coef *h_coef;
- const struct dispc_v_coef *v_coef;
+static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
+ int fir_vinc, int five_taps,
+ enum omap_color_component color_comp)
+{
+ const struct dispc_coef *h_coef, *v_coef;
int i;
- if (hscaleup)
- h_coef = coef_hup;
- else
- h_coef = coef_hdown;
-
- if (vscaleup)
- v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
- else
- v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
+ h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
+ v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
for (i = 0; i < 8; i++) {
u32 h, hv;
- h = FLD_VAL(h_coef[i].hc0, 7, 0)
- | FLD_VAL(h_coef[i].hc1, 15, 8)
- | FLD_VAL(h_coef[i].hc2, 23, 16)
- | FLD_VAL(h_coef[i].hc3, 31, 24);
- hv = FLD_VAL(h_coef[i].hc4, 7, 0)
- | FLD_VAL(v_coef[i].vc0, 15, 8)
- | FLD_VAL(v_coef[i].vc1, 23, 16)
- | FLD_VAL(v_coef[i].vc2, 31, 24);
+ h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
+ | FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
+ | FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
+ | FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
+ hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
+ | FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
+ | FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
+ | FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
dispc_ovl_write_firh_reg(plane, i, h);
@@ -646,8 +580,8 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
if (five_taps) {
for (i = 0; i < 8; i++) {
u32 v;
- v = FLD_VAL(v_coef[i].vc00, 7, 0)
- | FLD_VAL(v_coef[i].vc22, 15, 8);
+ v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
+ | FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
dispc_ovl_write_firv_reg(plane, i, v);
else
@@ -875,8 +809,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-static void dispc_ovl_set_channel_out(enum omap_plane plane,
- enum omap_channel channel)
+void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
{
int shift;
u32 val;
@@ -923,6 +856,39 @@ static void dispc_ovl_set_channel_out(enum omap_plane plane,
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
+static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
+{
+ int shift;
+ u32 val;
+ enum omap_channel channel;
+
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ shift = 8;
+ break;
+ case OMAP_DSS_VIDEO1:
+ case OMAP_DSS_VIDEO2:
+ case OMAP_DSS_VIDEO3:
+ shift = 16;
+ break;
+ default:
+ BUG();
+ }
+
+ val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
+
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
+ if (FLD_GET(val, 31, 30) == 0)
+ channel = FLD_GET(val, shift, shift);
+ else
+ channel = OMAP_DSS_CHANNEL_LCD2;
+ } else {
+ channel = FLD_GET(val, shift, shift);
+ }
+
+ return channel;
+}
+
static void dispc_ovl_set_burst_size(enum omap_plane plane,
enum omap_burst_size burst_size)
{
@@ -964,7 +930,7 @@ void dispc_enable_gamma_table(bool enable)
REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
}
-void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
{
u16 reg;
@@ -978,7 +944,7 @@ void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
REG_FLD_MOD(reg, enable, 15, 15);
}
-void dispc_mgr_set_cpr_coef(enum omap_channel channel,
+static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs)
{
u32 coef_r, coef_g, coef_b;
@@ -1057,8 +1023,7 @@ u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
return dispc.fifo_size[plane];
}
-static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low,
- u32 high)
+void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
{
u8 hi_start, hi_end, lo_start, lo_end;
u32 unit;
@@ -1169,17 +1134,12 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
enum omap_color_component color_comp)
{
int fir_hinc, fir_vinc;
- int hscaleup, vscaleup;
-
- hscaleup = orig_width <= out_width;
- vscaleup = orig_height <= out_height;
-
- dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
- color_comp);
fir_hinc = 1024 * orig_width / out_width;
fir_vinc = 1024 * orig_height / out_height;
+ dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
+ color_comp);
dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
}
@@ -1654,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
u32 fclk = 0;
u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
+ if (height <= out_height && width <= out_width)
+ return (unsigned long) pclk;
+
if (height > out_height) {
struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
unsigned int ppl = dssdev->panel.timings.x_res;
@@ -1708,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
else
vf = 1;
- return dispc_mgr_pclk_rate(channel) * vf * hf;
+ if (cpu_is_omap24xx()) {
+ if (vf > 1 && hf > 1)
+ return dispc_mgr_pclk_rate(channel) * 4;
+ else
+ return dispc_mgr_pclk_rate(channel) * 2;
+ } else if (cpu_is_omap34xx()) {
+ return dispc_mgr_pclk_rate(channel) * vf * hf;
+ } else {
+ return dispc_mgr_pclk_rate(channel) * hf;
+ }
}
static int dispc_ovl_calc_scaling(enum omap_plane plane,
@@ -1718,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
{
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
+ const int maxsinglelinewidth =
+ dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
unsigned long fclk = 0;
if (width == out_width && height == out_height)
@@ -1734,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
out_height > height * 8)
return -EINVAL;
- /* Must use 5-tap filter? */
- *five_taps = height > out_height * 2;
-
- if (!*five_taps) {
+ if (cpu_is_omap24xx()) {
+ if (width > maxsinglelinewidth)
+ DSSERR("Cannot scale max input width exceeded");
+ *five_taps = false;
+ fclk = calc_fclk(channel, width, height, out_width,
+ out_height);
+ } else if (cpu_is_omap34xx()) {
+ if (width > (maxsinglelinewidth * 2)) {
+ DSSERR("Cannot setup scaling");
+ DSSERR("width exceeds maximum width possible");
+ return -EINVAL;
+ }
+ fclk = calc_fclk_five_taps(channel, width, height, out_width,
+ out_height, color_mode);
+ if (width > maxsinglelinewidth) {
+ if (height > out_height && height < out_height * 2)
+ *five_taps = false;
+ else {
+ DSSERR("cannot setup scaling with five taps");
+ return -EINVAL;
+ }
+ }
+ if (!*five_taps)
+ fclk = calc_fclk(channel, width, height, out_width,
+ out_height);
+ } else {
+ if (width > maxsinglelinewidth) {
+ DSSERR("Cannot scale width exceeds max line width");
+ return -EINVAL;
+ }
fclk = calc_fclk(channel, width, height, out_width,
out_height);
-
- /* Try 5-tap filter if 3-tap fclk is too high */
- if (cpu_is_omap34xx() && height > out_height &&
- fclk > dispc_fclk_rate())
- *five_taps = true;
- }
-
- if (width > (2048 >> *five_taps)) {
- DSSERR("failed to set up scaling, fclk too low\n");
- return -EINVAL;
}
- if (*five_taps)
- fclk = calc_fclk_five_taps(channel, width, height,
- out_width, out_height, color_mode);
-
DSSDBG("required fclk rate = %lu Hz\n", fclk);
DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
@@ -1771,11 +1757,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
}
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
- bool ilace, enum omap_channel channel, bool replication,
- u32 fifo_low, u32 fifo_high)
+ bool ilace, bool replication)
{
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
- bool five_taps = false;
+ bool five_taps = true;
bool fieldmode = 0;
int r, cconv = 0;
unsigned offset0, offset1;
@@ -1783,36 +1768,43 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
s32 pix_inc;
u16 frame_height = oi->height;
unsigned int field_offset = 0;
+ u16 outw, outh;
+ enum omap_channel channel;
+
+ channel = dispc_ovl_get_channel_out(plane);
DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
- "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d "
- "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr,
+ "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
+ plane, oi->paddr, oi->p_uv_addr,
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
- oi->mirror, ilace, channel, replication, fifo_low, fifo_high);
+ oi->mirror, ilace, channel, replication);
if (oi->paddr == 0)
return -EINVAL;
- if (ilace && oi->height == oi->out_height)
+ outw = oi->out_width == 0 ? oi->width : oi->out_width;
+ outh = oi->out_height == 0 ? oi->height : oi->out_height;
+
+ if (ilace && oi->height == outh)
fieldmode = 1;
if (ilace) {
if (fieldmode)
oi->height /= 2;
oi->pos_y /= 2;
- oi->out_height /= 2;
+ outh /= 2;
DSSDBG("adjusting for ilace: height %d, pos_y %d, "
"out_height %d\n",
- oi->height, oi->pos_y, oi->out_height);
+ oi->height, oi->pos_y, outh);
}
if (!dss_feat_color_mode_supported(plane, oi->color_mode))
return -EINVAL;
r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
- oi->out_width, oi->out_height, oi->color_mode,
+ outw, outh, oi->color_mode,
&five_taps);
if (r)
return r;
@@ -1830,10 +1822,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
* so the integer part must be added to the base address of the
* bottom field.
*/
- if (!oi->height || oi->height == oi->out_height)
+ if (!oi->height || oi->height == outh)
field_offset = 0;
else
- field_offset = oi->height / oi->out_height / 2;
+ field_offset = oi->height / outh / 2;
}
/* Fields are independent but interleaved in memory. */
@@ -1869,7 +1861,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pix_inc(plane, pix_inc);
DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
- oi->height, oi->out_width, oi->out_height);
+ oi->height, outw, outh);
dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
@@ -1877,10 +1869,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
dispc_ovl_set_scaling(plane, oi->width, oi->height,
- oi->out_width, oi->out_height,
+ outw, outh,
ilace, five_taps, fieldmode,
oi->color_mode, oi->rotation);
- dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height);
+ dispc_ovl_set_vid_size(plane, outw, outh);
dispc_ovl_set_vid_color_conv(plane, cconv);
}
@@ -1891,10 +1883,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
- dispc_ovl_set_channel_out(plane, channel);
-
dispc_ovl_enable_replication(plane, replication);
- dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
return 0;
}
@@ -1916,10 +1905,14 @@ static void dispc_disable_isr(void *data, u32 mask)
static void _enable_lcd_out(enum omap_channel channel, bool enable)
{
- if (channel == OMAP_DSS_CHANNEL_LCD2)
+ if (channel == OMAP_DSS_CHANNEL_LCD2) {
REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
- else
+ /* flush posted write */
+ dispc_read_reg(DISPC_CONTROL2);
+ } else {
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
+ dispc_read_reg(DISPC_CONTROL);
+ }
}
static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
@@ -1967,6 +1960,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
static void _enable_digit_out(bool enable)
{
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
+ /* flush posted write */
+ dispc_read_reg(DISPC_CONTROL);
}
static void dispc_mgr_enable_digit_out(bool enable)
@@ -2124,25 +2119,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
}
-void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
+static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
{
dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
}
-u32 dispc_mgr_get_default_color(enum omap_channel channel)
-{
- u32 l;
-
- BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
- channel != OMAP_DSS_CHANNEL_LCD &&
- channel != OMAP_DSS_CHANNEL_LCD2);
-
- l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-
- return l;
-}
-
-void dispc_mgr_set_trans_key(enum omap_channel ch,
+static void dispc_mgr_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key)
{
@@ -2156,26 +2138,7 @@ void dispc_mgr_set_trans_key(enum omap_channel ch,
dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
}
-void dispc_mgr_get_trans_key(enum omap_channel ch,
- enum omap_dss_trans_key_type *type,
- u32 *trans_key)
-{
- if (type) {
- if (ch == OMAP_DSS_CHANNEL_LCD)
- *type = REG_GET(DISPC_CONFIG, 11, 11);
- else if (ch == OMAP_DSS_CHANNEL_DIGIT)
- *type = REG_GET(DISPC_CONFIG, 13, 13);
- else if (ch == OMAP_DSS_CHANNEL_LCD2)
- *type = REG_GET(DISPC_CONFIG2, 11, 11);
- else
- BUG();
- }
-
- if (trans_key)
- *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-}
-
-void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
+static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
{
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
@@ -2185,7 +2148,8 @@ void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
}
-void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
+static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
+ bool enable)
{
if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
return;
@@ -2196,40 +2160,20 @@ void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
}
-bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)
-{
- bool enabled;
-
- if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
- return false;
-
- if (ch == OMAP_DSS_CHANNEL_LCD)
- enabled = REG_GET(DISPC_CONFIG, 18, 18);
- else if (ch == OMAP_DSS_CHANNEL_DIGIT)
- enabled = REG_GET(DISPC_CONFIG, 19, 19);
- else
- BUG();
-
- return enabled;
-}
-
-bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
+void dispc_mgr_setup(enum omap_channel channel,
+ struct omap_overlay_manager_info *info)
{
- bool enabled;
-
- if (ch == OMAP_DSS_CHANNEL_LCD)
- enabled = REG_GET(DISPC_CONFIG, 10, 10);
- else if (ch == OMAP_DSS_CHANNEL_DIGIT)
- enabled = REG_GET(DISPC_CONFIG, 12, 12);
- else if (ch == OMAP_DSS_CHANNEL_LCD2)
- enabled = REG_GET(DISPC_CONFIG2, 10, 10);
- else
- BUG();
-
- return enabled;
+ dispc_mgr_set_default_color(channel, info->default_color);
+ dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
+ dispc_mgr_enable_trans_key(channel, info->trans_enabled);
+ dispc_mgr_enable_alpha_fixed_zorder(channel,
+ info->partial_alpha_enabled);
+ if (dss_has_feature(FEAT_CPR)) {
+ dispc_mgr_enable_cpr(channel, info->cpr_enable);
+ dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
+ }
}
-
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
{
int code;
@@ -3184,7 +3128,8 @@ static void dispc_error_worker(struct work_struct *work)
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
struct omap_overlay_manager *mgr;
mgr = omap_dss_get_overlay_manager(i);
- mgr->device->driver->disable(mgr->device);
+ if (mgr->device && mgr->device->driver)
+ mgr->device->driver->disable(mgr->device);
}
}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index c06efc3..5836bd1 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -97,6 +97,17 @@
#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
DISPC_PRELOAD_OFFSET(n))
+/* DISPC up/downsampling FIR filter coefficient structure */
+struct dispc_coef {
+ s8 hc4_vc22;
+ s8 hc3_vc2;
+ u8 hc2_vc1;
+ s8 hc1_vc0;
+ s8 hc0_vc00;
+};
+
+const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
+
/* DISPC manager/channel specific registers */
static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
{
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
new file mode 100644
index 0000000..069bccb
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc_coefs.c
@@ -0,0 +1,326 @@
+/*
+ * linux/drivers/video/omap2/dss/dispc_coefs.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Chandrabhanu Mahapatra <cmahapatra@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.
+ *
+ * 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 <video/omapdss.h>
+#include "dispc.h"
+
+#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
+
+static const struct dispc_coef coef3_M8[8] = {
+ { 0, 0, 128, 0, 0 },
+ { 0, -4, 123, 9, 0 },
+ { 0, -4, 108, 87, 0 },
+ { 0, -2, 87, 43, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 43, 87, -2, 0 },
+ { 0, 24, 108, -4, 0 },
+ { 0, 9, 123, -4, 0 },
+};
+
+static const struct dispc_coef coef3_M9[8] = {
+ { 0, 6, 116, 6, 0 },
+ { 0, 0, 112, 16, 0 },
+ { 0, -2, 100, 30, 0 },
+ { 0, -2, 83, 47, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 47, 83, -2, 0 },
+ { 0, 30, 100, -2, 0 },
+ { 0, 16, 112, 0, 0 },
+};
+
+static const struct dispc_coef coef3_M10[8] = {
+ { 0, 10, 108, 10, 0 },
+ { 0, 3, 104, 21, 0 },
+ { 0, 0, 94, 34, 0 },
+ { 0, -1, 80, 49, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 49, 80, -1, 0 },
+ { 0, 34, 94, 0, 0 },
+ { 0, 21, 104, 3, 0 },
+};
+
+static const struct dispc_coef coef3_M11[8] = {
+ { 0, 14, 100, 14, 0 },
+ { 0, 6, 98, 24, 0 },
+ { 0, 2, 90, 36, 0 },
+ { 0, 0, 78, 50, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 50, 78, 0, 0 },
+ { 0, 36, 90, 2, 0 },
+ { 0, 24, 98, 6, 0 },
+};
+
+static const struct dispc_coef coef3_M12[8] = {
+ { 0, 16, 96, 16, 0 },
+ { 0, 9, 93, 26, 0 },
+ { 0, 4, 86, 38, 0 },
+ { 0, 1, 76, 51, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 51, 76, 1, 0 },
+ { 0, 38, 86, 4, 0 },
+ { 0, 26, 93, 9, 0 },
+};
+
+static const struct dispc_coef coef3_M13[8] = {
+ { 0, 18, 92, 18, 0 },
+ { 0, 10, 90, 28, 0 },
+ { 0, 5, 83, 40, 0 },
+ { 0, 1, 75, 52, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 52, 75, 1, 0 },
+ { 0, 40, 83, 5, 0 },
+ { 0, 28, 90, 10, 0 },
+};
+
+static const struct dispc_coef coef3_M14[8] = {
+ { 0, 20, 88, 20, 0 },
+ { 0, 12, 86, 30, 0 },
+ { 0, 6, 81, 41, 0 },
+ { 0, 2, 74, 52, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 52, 74, 2, 0 },
+ { 0, 41, 81, 6, 0 },
+ { 0, 30, 86, 12, 0 },
+};
+
+static const struct dispc_coef coef3_M16[8] = {
+ { 0, 22, 84, 22, 0 },
+ { 0, 14, 82, 32, 0 },
+ { 0, 8, 78, 42, 0 },
+ { 0, 3, 72, 53, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 53, 72, 3, 0 },
+ { 0, 42, 78, 8, 0 },
+ { 0, 32, 82, 14, 0 },
+};
+
+static const struct dispc_coef coef3_M19[8] = {
+ { 0, 24, 80, 24, 0 },
+ { 0, 16, 79, 33, 0 },
+ { 0, 9, 76, 43, 0 },
+ { 0, 4, 70, 54, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 54, 70, 4, 0 },
+ { 0, 43, 76, 9, 0 },
+ { 0, 33, 79, 16, 0 },
+};
+
+static const struct dispc_coef coef3_M22[8] = {
+ { 0, 25, 78, 25, 0 },
+ { 0, 17, 77, 34, 0 },
+ { 0, 10, 74, 44, 0 },
+ { 0, 5, 69, 54, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 54, 69, 5, 0 },
+ { 0, 44, 74, 10, 0 },
+ { 0, 34, 77, 17, 0 },
+};
+
+static const struct dispc_coef coef3_M26[8] = {
+ { 0, 26, 76, 26, 0 },
+ { 0, 19, 74, 35, 0 },
+ { 0, 11, 72, 45, 0 },
+ { 0, 5, 69, 54, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 54, 69, 5, 0 },
+ { 0, 45, 72, 11, 0 },
+ { 0, 35, 74, 19, 0 },
+};
+
+static const struct dispc_coef coef3_M32[8] = {
+ { 0, 27, 74, 27, 0 },
+ { 0, 19, 73, 36, 0 },
+ { 0, 12, 71, 45, 0 },
+ { 0, 6, 68, 54, 0 },
+ { 0, 64, 64, 0, 0 },
+ { 0, 54, 68, 6, 0 },
+ { 0, 45, 71, 12, 0 },
+ { 0, 36, 73, 19, 0 },
+};
+
+static const struct dispc_coef coef5_M8[8] = {
+ { 0, 0, 128, 0, 0 },
+ { -2, 14, 125, -10, 1 },
+ { -6, 33, 114, -15, 2 },
+ { -10, 55, 98, -16, 1 },
+ { 0, -14, 78, 78, -14 },
+ { 1, -16, 98, 55, -10 },
+ { 2, -15, 114, 33, -6 },
+ { 1, -10, 125, 14, -2 },
+};
+
+static const struct dispc_coef coef5_M9[8] = {
+ { -3, 10, 114, 10, -3 },
+ { -6, 24, 110, 0, -1 },
+ { -8, 40, 103, -7, 0 },
+ { -11, 58, 91, -11, 1 },
+ { 0, -12, 76, 76, -12 },
+ { 1, -11, 91, 58, -11 },
+ { 0, -7, 103, 40, -8 },
+ { -1, 0, 111, 24, -6 },
+};
+
+static const struct dispc_coef coef5_M10[8] = {
+ { -4, 18, 100, 18, -4 },
+ { -6, 30, 99, 8, -3 },
+ { -8, 44, 93, 0, -1 },
+ { -9, 58, 84, -5, 0 },
+ { 0, -8, 72, 72, -8 },
+ { 0, -5, 84, 58, -9 },
+ { -1, 0, 93, 44, -8 },
+ { -3, 8, 99, 30, -6 },
+};
+
+static const struct dispc_coef coef5_M11[8] = {
+ { -5, 23, 92, 23, -5 },
+ { -6, 34, 90, 13, -3 },
+ { -6, 45, 85, 6, -2 },
+ { -6, 57, 78, 0, -1 },
+ { 0, -4, 68, 68, -4 },
+ { -1, 0, 78, 57, -6 },
+ { -2, 6, 85, 45, -6 },
+ { -3, 13, 90, 34, -6 },
+};
+
+static const struct dispc_coef coef5_M12[8] = {
+ { -4, 26, 84, 26, -4 },
+ { -5, 36, 82, 18, -3 },
+ { -4, 46, 78, 10, -2 },
+ { -3, 55, 72, 5, -1 },
+ { 0, 0, 64, 64, 0 },
+ { -1, 5, 72, 55, -3 },
+ { -2, 10, 78, 46, -4 },
+ { -3, 18, 82, 36, -5 },
+};
+
+static const struct dispc_coef coef5_M13[8] = {
+ { -3, 28, 78, 28, -3 },
+ { -3, 37, 76, 21, -3 },
+ { -2, 45, 73, 14, -2 },
+ { 0, 53, 68, 8, -1 },
+ { 0, 3, 61, 61, 3 },
+ { -1, 8, 68, 53, 0 },
+ { -2, 14, 73, 45, -2 },
+ { -3, 21, 76, 37, -3 },
+};
+
+static const struct dispc_coef coef5_M14[8] = {
+ { -2, 30, 72, 30, -2 },
+ { -1, 37, 71, 23, -2 },
+ { 0, 45, 69, 16, -2 },
+ { 3, 52, 64, 10, -1 },
+ { 0, 6, 58, 58, 6 },
+ { -1, 10, 64, 52, 3 },
+ { -2, 16, 69, 45, 0 },
+ { -2, 23, 71, 37, -1 },
+};
+
+static const struct dispc_coef coef5_M16[8] = {
+ { 0, 31, 66, 31, 0 },
+ { 1, 38, 65, 25, -1 },
+ { 3, 44, 62, 20, -1 },
+ { 6, 49, 59, 14, 0 },
+ { 0, 10, 54, 54, 10 },
+ { 0, 14, 59, 49, 6 },
+ { -1, 20, 62, 44, 3 },
+ { -1, 25, 65, 38, 1 },
+};
+
+static const struct dispc_coef coef5_M19[8] = {
+ { 3, 32, 58, 32, 3 },
+ { 4, 38, 58, 27, 1 },
+ { 7, 42, 55, 23, 1 },
+ { 10, 46, 54, 18, 0 },
+ { 0, 14, 50, 50, 14 },
+ { 0, 18, 54, 46, 10 },
+ { 1, 23, 55, 42, 7 },
+ { 1, 27, 58, 38, 4 },
+};
+
+static const struct dispc_coef coef5_M22[8] = {
+ { 4, 33, 54, 33, 4 },
+ { 6, 37, 54, 28, 3 },
+ { 9, 41, 53, 24, 1 },
+ { 12, 45, 51, 20, 0 },
+ { 0, 16, 48, 48, 16 },
+ { 0, 20, 51, 45, 12 },
+ { 1, 24, 53, 41, 9 },
+ { 3, 28, 54, 37, 6 },
+};
+
+static const struct dispc_coef coef5_M26[8] = {
+ { 6, 33, 50, 33, 6 },
+ { 8, 36, 51, 29, 4 },
+ { 11, 40, 50, 25, 2 },
+ { 14, 43, 48, 22, 1 },
+ { 0, 18, 46, 46, 18 },
+ { 1, 22, 48, 43, 14 },
+ { 2, 25, 50, 40, 11 },
+ { 4, 29, 51, 36, 8 },
+};
+
+static const struct dispc_coef coef5_M32[8] = {
+ { 7, 33, 48, 33, 7 },
+ { 10, 36, 48, 29, 5 },
+ { 13, 39, 47, 26, 3 },
+ { 16, 42, 46, 23, 1 },
+ { 0, 19, 45, 45, 19 },
+ { 1, 23, 46, 42, 16 },
+ { 3, 26, 47, 39, 13 },
+ { 5, 29, 48, 36, 10 },
+};
+
+const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
+{
+ int i;
+ static const struct {
+ int Mmin;
+ int Mmax;
+ const struct dispc_coef *coef_3;
+ const struct dispc_coef *coef_5;
+ } coefs[] = {
+ { 27, 32, coef3_M32, coef5_M32 },
+ { 23, 26, coef3_M26, coef5_M26 },
+ { 20, 22, coef3_M22, coef5_M22 },
+ { 17, 19, coef3_M19, coef5_M19 },
+ { 15, 16, coef3_M16, coef5_M16 },
+ { 14, 14, coef3_M14, coef5_M14 },
+ { 13, 13, coef3_M13, coef5_M13 },
+ { 12, 12, coef3_M12, coef5_M12 },
+ { 11, 11, coef3_M11, coef5_M11 },
+ { 10, 10, coef3_M10, coef5_M10 },
+ { 9, 9, coef3_M9, coef5_M9 },
+ { 4, 8, coef3_M8, coef5_M8 },
+ /*
+ * When upscaling more than two times, blockiness and outlines
+ * around the image are observed when M8 tables are used. M11,
+ * M16 and M19 tables are used to prevent this.
+ */
+ { 3, 3, coef3_M11, coef5_M11 },
+ { 2, 2, coef3_M16, coef5_M16 },
+ { 0, 1, coef3_M19, coef5_M19 },
+ };
+
+ inc /= 128;
+ for (i = 0; i < ARRAY_LEN(coefs); ++i)
+ if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
+ return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
+ return NULL;
+}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 976ac23..395d658 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -223,10 +223,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
mdelay(2);
- dssdev->manager->enable(dssdev->manager);
+ r = dss_mgr_enable(dssdev->manager);
+ if (r)
+ goto err_mgr_enable;
return 0;
+err_mgr_enable:
err_set_mode:
if (dpi_use_dsi_pll(dssdev))
dsi_pll_uninit(dpi.dsidev, true);
@@ -249,7 +252,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
{
- dssdev->manager->disable(dssdev->manager);
+ dss_mgr_disable(dssdev->manager);
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 5abf8e7e..d4d676c 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; };
typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
#define DSI_MAX_NR_ISRS 2
+#define DSI_MAX_NR_LANES 5
+
+enum dsi_lane_function {
+ DSI_LANE_UNUSED = 0,
+ DSI_LANE_CLK,
+ DSI_LANE_DATA1,
+ DSI_LANE_DATA2,
+ DSI_LANE_DATA3,
+ DSI_LANE_DATA4,
+};
+
+struct dsi_lane_config {
+ enum dsi_lane_function function;
+ u8 polarity;
+};
struct dsi_isr_data {
omap_dsi_isr_t isr;
@@ -223,24 +238,6 @@ enum dsi_vc_source {
DSI_VC_SOURCE_VP,
};
-enum dsi_lane {
- DSI_CLK_P = 1 << 0,
- DSI_CLK_N = 1 << 1,
- DSI_DATA1_P = 1 << 2,
- DSI_DATA1_N = 1 << 3,
- DSI_DATA2_P = 1 << 4,
- DSI_DATA2_N = 1 << 5,
- DSI_DATA3_P = 1 << 6,
- DSI_DATA3_N = 1 << 7,
- DSI_DATA4_P = 1 << 8,
- DSI_DATA4_N = 1 << 9,
-};
-
-struct dsi_update_region {
- u16 x, y, w, h;
- struct omap_dss_device *device;
-};
-
struct dsi_irq_stats {
unsigned long last_reset;
unsigned irq_count;
@@ -290,7 +287,9 @@ struct dsi_data {
struct dsi_isr_tables isr_tables_copy;
int update_channel;
- struct dsi_update_region update_region;
+#ifdef DEBUG
+ unsigned update_bytes;
+#endif
bool te_enabled;
bool ulps_enabled;
@@ -327,7 +326,10 @@ struct dsi_data {
unsigned long fint_min, fint_max;
unsigned long lpdiv_max;
- int num_data_lanes;
+ unsigned num_lanes_supported;
+
+ struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
+ unsigned num_lanes_used;
unsigned scp_clk_refcount;
};
@@ -340,8 +342,8 @@ struct dsi_packet_sent_handler_data {
static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
#ifdef DEBUG
-static unsigned int dsi_perf;
-module_param_named(dsi_perf, dsi_perf, bool, 0644);
+static bool dsi_perf;
+module_param(dsi_perf, bool, 0644);
#endif
static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
@@ -413,14 +415,29 @@ static void dsi_completion_handler(void *data, u32 mask)
static inline int wait_for_bit_change(struct platform_device *dsidev,
const struct dsi_reg idx, int bitnum, int value)
{
- int t = 100000;
+ unsigned long timeout;
+ ktime_t wait;
+ int t;
- while (REG_GET(dsidev, idx, bitnum, bitnum) != value) {
- if (--t == 0)
- return !value;
+ /* first busyloop to see if the bit changes right away */
+ t = 100;
+ while (t-- > 0) {
+ if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
+ return value;
}
- return value;
+ /* then loop for 500ms, sleeping for 1ms in between */
+ timeout = jiffies + msecs_to_jiffies(500);
+ while (time_before(jiffies, timeout)) {
+ if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
+ return value;
+
+ wait = ns_to_ktime(1000 * 1000);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+ }
+
+ return !value;
}
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
@@ -454,7 +471,6 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
static void dsi_perf_show(struct platform_device *dsidev, const char *name)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct omap_dss_device *dssdev = dsi->update_region.device;
ktime_t t, setup_time, trans_time;
u32 total_bytes;
u32 setup_us, trans_us, total_us;
@@ -476,9 +492,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
total_us = setup_us + trans_us;
- total_bytes = dsi->update_region.w *
- dsi->update_region.h *
- dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+ total_bytes = dsi->update_bytes;
printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
"%u bytes, %u kbytes/sec\n",
@@ -1720,17 +1734,19 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
cinfo->clkin4ddr, cinfo->regm);
- seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
- dss_get_generic_clk_source_name(dispc_clk_src),
- dss_feat_get_clk_source_name(dispc_clk_src),
+ seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
+ dss_feat_get_clk_source_name(dsi_module == 0 ?
+ OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+ OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
cinfo->dsi_pll_hsdiv_dispc_clk,
cinfo->regm_dispc,
dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
"off" : "on");
- seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
- dss_get_generic_clk_source_name(dsi_clk_src),
- dss_feat_get_clk_source_name(dsi_clk_src),
+ seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
+ dss_feat_get_clk_source_name(dsi_module == 0 ?
+ OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+ OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
cinfo->dsi_pll_hsdiv_dsi_clk,
cinfo->regm_dsi,
dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
@@ -2029,34 +2045,6 @@ static int dsi_cio_power(struct platform_device *dsidev,
return 0;
}
-/* Number of data lanes present on DSI interface */
-static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
-{
- /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
- * of data lanes as 2 by default */
- if (dss_has_feature(FEAT_DSI_GNQ))
- return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */
- else
- return 2;
-}
-
-/* Number of data lanes used by the dss device */
-static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
-{
- int num_data_lanes = 0;
-
- if (dssdev->phy.dsi.data1_lane != 0)
- num_data_lanes++;
- if (dssdev->phy.dsi.data2_lane != 0)
- num_data_lanes++;
- if (dssdev->phy.dsi.data3_lane != 0)
- num_data_lanes++;
- if (dssdev->phy.dsi.data4_lane != 0)
- num_data_lanes++;
-
- return num_data_lanes;
-}
-
static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
{
int val;
@@ -2088,59 +2076,112 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
}
}
-static void dsi_set_lane_config(struct omap_dss_device *dssdev)
+static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- u32 r;
- int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ u8 lanes[DSI_MAX_NR_LANES];
+ u8 polarities[DSI_MAX_NR_LANES];
+ int num_lanes, i;
+
+ static const enum dsi_lane_function functions[] = {
+ DSI_LANE_CLK,
+ DSI_LANE_DATA1,
+ DSI_LANE_DATA2,
+ DSI_LANE_DATA3,
+ DSI_LANE_DATA4,
+ };
+
+ lanes[0] = dssdev->phy.dsi.clk_lane;
+ lanes[1] = dssdev->phy.dsi.data1_lane;
+ lanes[2] = dssdev->phy.dsi.data2_lane;
+ lanes[3] = dssdev->phy.dsi.data3_lane;
+ lanes[4] = dssdev->phy.dsi.data4_lane;
+ polarities[0] = dssdev->phy.dsi.clk_pol;
+ polarities[1] = dssdev->phy.dsi.data1_pol;
+ polarities[2] = dssdev->phy.dsi.data2_pol;
+ polarities[3] = dssdev->phy.dsi.data3_pol;
+ polarities[4] = dssdev->phy.dsi.data4_pol;
- int clk_lane = dssdev->phy.dsi.clk_lane;
- int data1_lane = dssdev->phy.dsi.data1_lane;
- int data2_lane = dssdev->phy.dsi.data2_lane;
- int clk_pol = dssdev->phy.dsi.clk_pol;
- int data1_pol = dssdev->phy.dsi.data1_pol;
- int data2_pol = dssdev->phy.dsi.data2_pol;
+ num_lanes = 0;
+
+ for (i = 0; i < dsi->num_lanes_supported; ++i)
+ dsi->lanes[i].function = DSI_LANE_UNUSED;
+
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ int num;
+
+ if (lanes[i] == DSI_LANE_UNUSED)
+ break;
+
+ num = lanes[i] - 1;
+
+ if (num >= dsi->num_lanes_supported)
+ return -EINVAL;
+
+ if (dsi->lanes[num].function != DSI_LANE_UNUSED)
+ return -EINVAL;
+
+ dsi->lanes[num].function = functions[i];
+ dsi->lanes[num].polarity = polarities[i];
+ num_lanes++;
+ }
+
+ if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
+ return -EINVAL;
+
+ dsi->num_lanes_used = num_lanes;
+
+ return 0;
+}
+
+static int dsi_set_lane_config(struct omap_dss_device *dssdev)
+{
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ static const u8 offsets[] = { 0, 4, 8, 12, 16 };
+ static const enum dsi_lane_function functions[] = {
+ DSI_LANE_CLK,
+ DSI_LANE_DATA1,
+ DSI_LANE_DATA2,
+ DSI_LANE_DATA3,
+ DSI_LANE_DATA4,
+ };
+ u32 r;
+ int i;
r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
- r = FLD_MOD(r, clk_lane, 2, 0);
- r = FLD_MOD(r, clk_pol, 3, 3);
- r = FLD_MOD(r, data1_lane, 6, 4);
- r = FLD_MOD(r, data1_pol, 7, 7);
- r = FLD_MOD(r, data2_lane, 10, 8);
- r = FLD_MOD(r, data2_pol, 11, 11);
- if (num_data_lanes_dssdev > 2) {
- int data3_lane = dssdev->phy.dsi.data3_lane;
- int data3_pol = dssdev->phy.dsi.data3_pol;
-
- r = FLD_MOD(r, data3_lane, 14, 12);
- r = FLD_MOD(r, data3_pol, 15, 15);
+
+ for (i = 0; i < dsi->num_lanes_used; ++i) {
+ unsigned offset = offsets[i];
+ unsigned polarity, lane_number;
+ unsigned t;
+
+ for (t = 0; t < dsi->num_lanes_supported; ++t)
+ if (dsi->lanes[t].function == functions[i])
+ break;
+
+ if (t == dsi->num_lanes_supported)
+ return -EINVAL;
+
+ lane_number = t;
+ polarity = dsi->lanes[t].polarity;
+
+ r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
+ r = FLD_MOD(r, polarity, offset + 3, offset + 3);
}
- if (num_data_lanes_dssdev > 3) {
- int data4_lane = dssdev->phy.dsi.data4_lane;
- int data4_pol = dssdev->phy.dsi.data4_pol;
- r = FLD_MOD(r, data4_lane, 18, 16);
- r = FLD_MOD(r, data4_pol, 19, 19);
+ /* clear the unused lanes */
+ for (; i < dsi->num_lanes_supported; ++i) {
+ unsigned offset = offsets[i];
+
+ r = FLD_MOD(r, 0, offset + 2, offset);
+ r = FLD_MOD(r, 0, offset + 3, offset + 3);
}
- dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
- /* The configuration of the DSI complex I/O (number of data lanes,
- position, differential order) should not be changed while
- DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
- the hardware to take into account a new configuration of the complex
- I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
- follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
- then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
- DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
- DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
- DSI complex I/O configuration is unknown. */
+ dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
- /*
- REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
- REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
- REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
- REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
- */
+ return 0;
}
static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
@@ -2230,49 +2271,28 @@ static void dsi_cio_timings(struct platform_device *dsidev)
dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
}
+/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
- enum dsi_lane lanes)
+ unsigned mask_p, unsigned mask_n)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- int clk_lane = dssdev->phy.dsi.clk_lane;
- int data1_lane = dssdev->phy.dsi.data1_lane;
- int data2_lane = dssdev->phy.dsi.data2_lane;
- int data3_lane = dssdev->phy.dsi.data3_lane;
- int data4_lane = dssdev->phy.dsi.data4_lane;
- int clk_pol = dssdev->phy.dsi.clk_pol;
- int data1_pol = dssdev->phy.dsi.data1_pol;
- int data2_pol = dssdev->phy.dsi.data2_pol;
- int data3_pol = dssdev->phy.dsi.data3_pol;
- int data4_pol = dssdev->phy.dsi.data4_pol;
-
- u32 l = 0;
- u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26;
-
- if (lanes & DSI_CLK_P)
- l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
- if (lanes & DSI_CLK_N)
- l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
-
- if (lanes & DSI_DATA1_P)
- l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
- if (lanes & DSI_DATA1_N)
- l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
-
- if (lanes & DSI_DATA2_P)
- l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
- if (lanes & DSI_DATA2_N)
- l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
-
- if (lanes & DSI_DATA3_P)
- l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
- if (lanes & DSI_DATA3_N)
- l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
-
- if (lanes & DSI_DATA4_P)
- l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
- if (lanes & DSI_DATA4_N)
- l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
+ int i;
+ u32 l;
+ u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
+
+ l = 0;
+
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ unsigned p = dsi->lanes[i].polarity;
+
+ if (mask_p & (1 << i))
+ l |= 1 << (i * 2 + (p ? 0 : 1));
+
+ if (mask_n & (1 << i))
+ l |= 1 << (i * 2 + (p ? 1 : 0));
+ }
+
/*
* Bits in REGLPTXSCPDAT4TO0DXDY:
* 17: DY0 18: DX0
@@ -2305,51 +2325,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- int t;
- int bits[3];
- bool in_use[3];
-
- if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
- bits[0] = 28;
- bits[1] = 27;
- bits[2] = 26;
- } else {
- bits[0] = 24;
- bits[1] = 25;
- bits[2] = 26;
- }
-
- in_use[0] = false;
- in_use[1] = false;
- in_use[2] = false;
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ int t, i;
+ bool in_use[DSI_MAX_NR_LANES];
+ static const u8 offsets_old[] = { 28, 27, 26 };
+ static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
+ const u8 *offsets;
+
+ if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
+ offsets = offsets_old;
+ else
+ offsets = offsets_new;
- if (dssdev->phy.dsi.clk_lane != 0)
- in_use[dssdev->phy.dsi.clk_lane - 1] = true;
- if (dssdev->phy.dsi.data1_lane != 0)
- in_use[dssdev->phy.dsi.data1_lane - 1] = true;
- if (dssdev->phy.dsi.data2_lane != 0)
- in_use[dssdev->phy.dsi.data2_lane - 1] = true;
+ for (i = 0; i < dsi->num_lanes_supported; ++i)
+ in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
t = 100000;
while (true) {
u32 l;
- int i;
int ok;
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
ok = 0;
- for (i = 0; i < 3; ++i) {
- if (!in_use[i] || (l & (1 << bits[i])))
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ if (!in_use[i] || (l & (1 << offsets[i])))
ok++;
}
- if (ok == 3)
+ if (ok == dsi->num_lanes_supported)
break;
if (--t == 0) {
- for (i = 0; i < 3; ++i) {
- if (!in_use[i] || (l & (1 << bits[i])))
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ if (!in_use[i] || (l & (1 << offsets[i])))
continue;
DSSERR("CIO TXCLKESC%d domain not coming " \
@@ -2362,22 +2371,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
return 0;
}
+/* return bitmask of enabled lanes, lane0 being the lsb */
static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
{
- unsigned lanes = 0;
+ struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ unsigned mask = 0;
+ int i;
- if (dssdev->phy.dsi.clk_lane != 0)
- lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
- if (dssdev->phy.dsi.data1_lane != 0)
- lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
- if (dssdev->phy.dsi.data2_lane != 0)
- lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
- if (dssdev->phy.dsi.data3_lane != 0)
- lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
- if (dssdev->phy.dsi.data4_lane != 0)
- lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ if (dsi->lanes[i].function != DSI_LANE_UNUSED)
+ mask |= 1 << i;
+ }
- return lanes;
+ return mask;
}
static int dsi_cio_init(struct omap_dss_device *dssdev)
@@ -2385,7 +2392,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
int r;
- int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
u32 l;
DSSDBGF();
@@ -2407,7 +2413,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
goto err_scp_clk_dom;
}
- dsi_set_lane_config(dssdev);
+ r = dsi_set_lane_config(dssdev);
+ if (r)
+ goto err_scp_clk_dom;
/* set TX STOP MODE timer to maximum for this operation */
l = dsi_read_reg(dsidev, DSI_TIMING1);
@@ -2418,7 +2426,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
dsi_write_reg(dsidev, DSI_TIMING1, l);
if (dsi->ulps_enabled) {
- u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P;
+ unsigned mask_p;
+ int i;
DSSDBG("manual ulps exit\n");
@@ -2427,16 +2436,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
* ULPS exit sequence, as after reset the DSS HW thinks
* that we are not in ULPS mode, and refuses to send the
* sequence. So we need to send the ULPS exit sequence
- * manually.
+ * manually by setting positive lines high and negative lines
+ * low for 1ms.
*/
- if (num_data_lanes_dssdev > 2)
- lane_mask |= DSI_DATA3_P;
+ mask_p = 0;
- if (num_data_lanes_dssdev > 3)
- lane_mask |= DSI_DATA4_P;
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ if (dsi->lanes[i].function == DSI_LANE_UNUSED)
+ continue;
+ mask_p |= 1 << i;
+ }
- dsi_cio_enable_lane_override(dssdev, lane_mask);
+ dsi_cio_enable_lane_override(dssdev, mask_p, 0);
}
r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2913,6 +2925,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
+ /* flush posted write */
+ dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
+
return 0;
}
@@ -3513,7 +3528,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
DECLARE_COMPLETION_ONSTACK(completion);
- int r;
+ int r, i;
+ unsigned mask;
DSSDBGF();
@@ -3524,9 +3540,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
if (dsi->ulps_enabled)
return 0;
+ /* DDR_CLK_ALWAYS_ON */
if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
- DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
- return -EIO;
+ dsi_if_enable(dsidev, 0);
+ REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+ dsi_if_enable(dsidev, 1);
}
dsi_sync_vc(dsidev, 0);
@@ -3556,10 +3574,19 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
if (r)
return r;
+ mask = 0;
+
+ for (i = 0; i < dsi->num_lanes_supported; ++i) {
+ if (dsi->lanes[i].function == DSI_LANE_UNUSED)
+ continue;
+ mask |= 1 << i;
+ }
/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
/* LANEx_ULPS_SIG2 */
- REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2),
- 7, 5);
+ REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
+
+ /* flush posted write and wait for SCP interface to finish the write */
+ dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
if (wait_for_completion_timeout(&completion,
msecs_to_jiffies(1000)) == 0) {
@@ -3572,8 +3599,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
/* Reset LANEx_ULPS_SIG2 */
- REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
- 7, 5);
+ REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
+
+ /* flush posted write and wait for SCP interface to finish the write */
+ dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
@@ -3836,6 +3865,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
static void dsi_proto_timings(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
unsigned tclk_pre, tclk_post;
unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
@@ -3843,7 +3873,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
unsigned ddr_clk_pre, ddr_clk_post;
unsigned enter_hs_mode_lat, exit_hs_mode_lat;
unsigned ths_eot;
- int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
+ int ndl = dsi->num_lanes_used - 1;
u32 r;
r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -3945,68 +3975,82 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
}
}
-int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
+int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
u8 data_type;
u16 word_count;
+ int r;
- switch (dssdev->panel.dsi_pix_fmt) {
- case OMAP_DSS_DSI_FMT_RGB888:
- data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
- break;
- case OMAP_DSS_DSI_FMT_RGB666:
- data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
- break;
- case OMAP_DSS_DSI_FMT_RGB666_PACKED:
- data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
- break;
- case OMAP_DSS_DSI_FMT_RGB565:
- data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
- break;
- default:
- BUG();
- };
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ switch (dssdev->panel.dsi_pix_fmt) {
+ case OMAP_DSS_DSI_FMT_RGB888:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB666:
+ data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB666_PACKED:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
+ break;
+ case OMAP_DSS_DSI_FMT_RGB565:
+ data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
+ break;
+ default:
+ BUG();
+ };
- dsi_if_enable(dsidev, false);
- dsi_vc_enable(dsidev, channel, false);
+ dsi_if_enable(dsidev, false);
+ dsi_vc_enable(dsidev, channel, false);
- /* MODE, 1 = video mode */
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
+ /* MODE, 1 = video mode */
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
- word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+ word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
- dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
+ dsi_vc_write_long_header(dsidev, channel, data_type,
+ word_count, 0);
- dsi_vc_enable(dsidev, channel, true);
- dsi_if_enable(dsidev, true);
+ dsi_vc_enable(dsidev, channel, true);
+ dsi_if_enable(dsidev, true);
+ }
- dssdev->manager->enable(dssdev->manager);
+ r = dss_mgr_enable(dssdev->manager);
+ if (r) {
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ dsi_if_enable(dsidev, false);
+ dsi_vc_enable(dsidev, channel, false);
+ }
+
+ return r;
+ }
return 0;
}
-EXPORT_SYMBOL(dsi_video_mode_enable);
+EXPORT_SYMBOL(dsi_enable_video_output);
-void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
+void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- dsi_if_enable(dsidev, false);
- dsi_vc_enable(dsidev, channel, false);
+ if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
+ dsi_if_enable(dsidev, false);
+ dsi_vc_enable(dsidev, channel, false);
- /* MODE, 0 = command mode */
- REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
+ /* MODE, 0 = command mode */
+ REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
- dsi_vc_enable(dsidev, channel, true);
- dsi_if_enable(dsidev, true);
+ dsi_vc_enable(dsidev, channel, true);
+ dsi_if_enable(dsidev, true);
+ }
- dssdev->manager->disable(dssdev->manager);
+ dss_mgr_disable(dssdev->manager);
}
-EXPORT_SYMBOL(dsi_video_mode_disable);
+EXPORT_SYMBOL(dsi_disable_video_output);
static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
- u16 x, u16 y, u16 w, u16 h)
+ u16 w, u16 h)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4021,8 +4065,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
const unsigned channel = dsi->update_channel;
const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
- DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
- x, y, w, h);
+ DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
@@ -4070,7 +4113,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
msecs_to_jiffies(250));
BUG_ON(r == 0);
- dss_start_update(dssdev);
+ dss_mgr_start_update(dssdev->manager);
if (dsi->te_enabled) {
/* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4146,66 +4189,27 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
#endif
}
-int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
- u16 *x, u16 *y, u16 *w, u16 *h,
- bool enlarge_update_area)
+int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
+ void (*callback)(int, void *), void *data)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
u16 dw, dh;
- dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
- if (*x > dw || *y > dh)
- return -EINVAL;
-
- if (*x + *w > dw)
- return -EINVAL;
-
- if (*y + *h > dh)
- return -EINVAL;
-
- if (*w == 1)
- return -EINVAL;
-
- if (*w == 0 || *h == 0)
- return -EINVAL;
-
dsi_perf_mark_setup(dsidev);
- dss_setup_partial_planes(dssdev, x, y, w, h,
- enlarge_update_area);
- dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
-
- return 0;
-}
-EXPORT_SYMBOL(omap_dsi_prepare_update);
-
-int omap_dsi_update(struct omap_dss_device *dssdev,
- int channel,
- u16 x, u16 y, u16 w, u16 h,
- void (*callback)(int, void *), void *data)
-{
- struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
dsi->update_channel = channel;
- /* OMAP DSS cannot send updates of odd widths.
- * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
- * here to make sure we catch erroneous updates. Otherwise we'll only
- * see rather obscure HW error happening, as DSS halts. */
- BUG_ON(x % 2 == 1);
-
dsi->framedone_callback = callback;
dsi->framedone_data = data;
- dsi->update_region.x = x;
- dsi->update_region.y = y;
- dsi->update_region.w = w;
- dsi->update_region.h = h;
- dsi->update_region.device = dssdev;
+ dssdev->driver->get_resolution(dssdev, &dw, &dh);
- dsi_update_screen_dispc(dssdev, x, y, w, h);
+#ifdef DEBUG
+ dsi->update_bytes = dw * dh *
+ dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
+#endif
+ dsi_update_screen_dispc(dssdev, dw, dh);
return 0;
}
@@ -4218,6 +4222,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
int r;
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
+ u16 dw, dh;
u32 irq;
struct omap_video_timings timings = {
.hsw = 1,
@@ -4228,6 +4233,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
.vbp = 0,
};
+ dssdev->driver->get_resolution(dssdev, &dw, &dh);
+ timings.x_res = dw;
+ timings.y_res = dh;
+
irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
@@ -4330,6 +4339,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
int dsi_module = dsi_get_dsidev_id(dsidev);
int r;
+ r = dsi_parse_lane_config(dssdev);
+ if (r) {
+ DSSERR("illegal lane config");
+ goto err0;
+ }
+
r = dsi_pll_init(dsidev, true, true);
if (r)
goto err0;
@@ -4521,7 +4536,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- int dsi_module = dsi_get_dsidev_id(dsidev);
DSSDBG("DSI init\n");
@@ -4543,12 +4557,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
dsi->vdds_dsi_reg = vdds_dsi;
}
- if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
- DSSERR("DSI%d can't support more than %d data lanes\n",
- dsi_module + 1, dsi->num_data_lanes);
- return -EINVAL;
- }
-
return 0;
}
@@ -4771,7 +4779,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
- dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
+ /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
+ * of data to 3 by default */
+ if (dss_has_feature(FEAT_DSI_GNQ))
+ /* NB_DATA_LANES */
+ dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
+ else
+ dsi->num_lanes_supported = 3;
dsi_runtime_put(dsidev);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6308fc5..32ff69f 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -28,7 +28,7 @@
#endif
#ifdef DEBUG
-extern unsigned int dss_debug;
+extern bool dss_debug;
#ifdef DSS_SUBSYS_NAME
#define DSSDBG(format, ...) \
if (dss_debug) \
@@ -163,6 +163,34 @@ struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void);
struct regulator *dss_get_vdds_sdi(void);
+/* apply */
+void dss_apply_init(void);
+int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
+void dss_mgr_start_update(struct omap_overlay_manager *mgr);
+int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr);
+void dss_mgr_disable(struct omap_overlay_manager *mgr);
+int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+ struct omap_overlay_manager_info *info);
+int dss_mgr_set_device(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev);
+int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
+
+bool dss_ovl_is_enabled(struct omap_overlay *ovl);
+int dss_ovl_enable(struct omap_overlay *ovl);
+int dss_ovl_disable(struct omap_overlay *ovl);
+int dss_ovl_set_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+void dss_ovl_get_info(struct omap_overlay *ovl,
+ struct omap_overlay_info *info);
+int dss_ovl_set_manager(struct omap_overlay *ovl,
+ struct omap_overlay_manager *mgr);
+int dss_ovl_unset_manager(struct omap_overlay *ovl);
+
/* display */
int dss_suspend_all_devices(void);
int dss_resume_all_devices(void);
@@ -181,21 +209,22 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
/* manager */
int dss_init_overlay_managers(struct platform_device *pdev);
void dss_uninit_overlay_managers(struct platform_device *pdev);
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
-void dss_setup_partial_planes(struct omap_dss_device *dssdev,
- u16 *x, u16 *y, u16 *w, u16 *h,
- bool enlarge_update_area);
-void dss_start_update(struct omap_dss_device *dssdev);
+int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
+ const struct omap_overlay_manager_info *info);
+int dss_mgr_check(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev,
+ struct omap_overlay_manager_info *info,
+ struct omap_overlay_info **overlay_infos);
/* overlay */
void dss_init_overlays(struct platform_device *pdev);
void dss_uninit_overlays(struct platform_device *pdev);
-int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
-#ifdef L4_EXAMPLE
-void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
-#endif
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
+int dss_ovl_simple_check(struct omap_overlay *ovl,
+ const struct omap_overlay_info *info);
+int dss_ovl_check(struct omap_overlay *ovl,
+ struct omap_overlay_info *info, struct omap_dss_device *dssdev);
/* DSS */
int dss_init_platform_driver(void);
@@ -399,21 +428,22 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo);
+void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
u32 dispc_ovl_get_burst_size(enum omap_plane plane);
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
- bool ilace, enum omap_channel channel, bool replication,
- u32 fifo_low, u32 fifo_high);
+ bool ilace, bool replication);
int dispc_ovl_enable(enum omap_plane plane, bool enable);
-
+void dispc_ovl_set_channel_out(enum omap_plane plane,
+ enum omap_channel channel);
void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
-void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
-void dispc_mgr_set_cpr_coef(enum omap_channel channel,
- struct omap_dss_cpr_coefs *coefs);
+u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
bool dispc_mgr_go_busy(enum omap_channel channel);
void dispc_mgr_go(enum omap_channel channel);
+bool dispc_mgr_is_enabled(enum omap_channel channel);
void dispc_mgr_enable(enum omap_channel channel, bool enable);
bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
@@ -421,18 +451,6 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
enum omap_lcd_display_type type);
-void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
-u32 dispc_mgr_get_default_color(enum omap_channel channel);
-void dispc_mgr_set_trans_key(enum omap_channel ch,
- enum omap_dss_trans_key_type type,
- u32 trans_key);
-void dispc_mgr_get_trans_key(enum omap_channel ch,
- enum omap_dss_trans_key_type *type,
- u32 *trans_key);
-void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
-void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
-bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
-bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
void dispc_mgr_set_lcd_timings(enum omap_channel channel,
struct omap_video_timings *timings);
void dispc_mgr_set_pol_freq(enum omap_channel channel,
@@ -443,6 +461,8 @@ int dispc_mgr_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
int dispc_mgr_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
+void dispc_mgr_setup(enum omap_channel channel,
+ struct omap_overlay_manager_info *info);
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index b402699..afcb593 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
[FEAT_PARAM_DOWNSCALE] = { 1, 2 },
+ /*
+ * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
+ * scaler cannot scale a image with width more than 768.
+ */
+ [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
};
static const struct dss_param_range omap3_dss_param_range[] = {
@@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
+ [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
};
static const struct dss_param_range omap4_dss_param_range[] = {
@@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
+ [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
};
/* OMAP2 DSS Features */
@@ -465,6 +472,10 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.dump_core = ti_hdmi_4xxx_core_dump,
.dump_pll = ti_hdmi_4xxx_pll_dump,
.dump_phy = ti_hdmi_4xxx_phy_dump,
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+ .audio_enable = ti_hdmi_4xxx_wp_audio_enable,
+#endif
};
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 6a6c05d..cd833bb 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -86,6 +86,7 @@ enum dss_range_param {
FEAT_PARAM_DSIPLL_FINT,
FEAT_PARAM_DSIPLL_LPDIV,
FEAT_PARAM_DOWNSCALE,
+ FEAT_PARAM_LINEWIDTH,
};
/* DSS Feature Functions */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index c56378c..b4c270e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -333,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
if (r)
return r;
- dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
+ dss_mgr_disable(dssdev->manager);
p = &dssdev->panel.timings;
@@ -387,9 +387,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
- dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
+ r = dss_mgr_enable(dssdev->manager);
+ if (r)
+ goto err_mgr_enable;
return 0;
+
+err_mgr_enable:
+ hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
+ hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+ hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
err:
hdmi_runtime_put();
return -EIO;
@@ -397,7 +404,7 @@ err:
static void hdmi_power_off(struct omap_dss_device *dssdev)
{
- dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
+ dss_mgr_disable(dssdev->manager);
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
@@ -554,11 +561,44 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
- struct snd_pcm_substream *substream,
+static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct platform_device *pdev = to_platform_device(codec->dev);
+ struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
+ int err = 0;
+
+ if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) {
+ dev_err(&pdev->dev, "Cannot enable/disable audio\n");
+ return -ENODEV;
+ }
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ip_data->ops->audio_enable(ip_data, true);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ip_data->ops->audio_enable(ip_data, false);
+ break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
+static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
struct hdmi_audio_format audio_format;
struct hdmi_audio_dma audio_dma;
struct hdmi_core_audio_config core_cfg;
@@ -698,7 +738,16 @@ static int hdmi_audio_startup(struct snd_pcm_substream *substream,
return 0;
}
+static int hdmi_audio_codec_probe(struct snd_soc_codec *codec)
+{
+ struct hdmi_ip_data *priv = &hdmi.ip_data;
+
+ snd_soc_codec_set_drvdata(codec, priv);
+ return 0;
+}
+
static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
+ .probe = hdmi_audio_codec_probe,
};
static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 6e63845..d1858e7 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -26,17 +26,15 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
static int num_managers;
-static struct list_head manager_list;
+static struct omap_overlay_manager *managers;
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
{
@@ -106,7 +104,11 @@ put_device:
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
}
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -144,8 +146,11 @@ static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
char *buf)
{
enum omap_dss_trans_key_type key_type;
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
- key_type = mgr->info.trans_key_type;
+ key_type = info.trans_key_type;
BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
@@ -185,7 +190,11 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
}
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -217,7 +226,11 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
}
static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
@@ -249,10 +262,14 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
static ssize_t manager_alpha_blending_enabled_show(
struct omap_overlay_manager *mgr, char *buf)
{
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
return snprintf(buf, PAGE_SIZE, "%d\n",
- mgr->info.partial_alpha_enabled);
+ info.partial_alpha_enabled);
}
static ssize_t manager_alpha_blending_enabled_store(
@@ -287,7 +304,11 @@ static ssize_t manager_alpha_blending_enabled_store(
static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
+ struct omap_overlay_manager_info info;
+
+ mgr->get_manager_info(mgr, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
}
static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
@@ -469,143 +490,6 @@ static struct kobj_type manager_ktype = {
.default_attrs = manager_sysfs_attrs,
};
-/*
- * We have 4 levels of cache for the dispc settings. First two are in SW and
- * the latter two in HW.
- *
- * +--------------------+
- * |overlay/manager_info|
- * +--------------------+
- * v
- * apply()
- * v
- * +--------------------+
- * | dss_cache |
- * +--------------------+
- * v
- * configure()
- * v
- * +--------------------+
- * | shadow registers |
- * +--------------------+
- * v
- * VFP or lcd/digit_enable
- * v
- * +--------------------+
- * | registers |
- * +--------------------+
- */
-
-struct overlay_cache_data {
- /* If true, cache changed, but not written to shadow registers. Set
- * in apply(), cleared when registers written. */
- bool dirty;
- /* If true, shadow registers contain changed values not yet in real
- * registers. Set when writing to shadow registers, cleared at
- * VSYNC/EVSYNC */
- bool shadow_dirty;
-
- bool enabled;
-
- struct omap_overlay_info info;
-
- enum omap_channel channel;
- bool replication;
- bool ilace;
-
- u32 fifo_low;
- u32 fifo_high;
-};
-
-struct manager_cache_data {
- /* If true, cache changed, but not written to shadow registers. Set
- * in apply(), cleared when registers written. */
- bool dirty;
- /* If true, shadow registers contain changed values not yet in real
- * registers. Set when writing to shadow registers, cleared at
- * VSYNC/EVSYNC */
- bool shadow_dirty;
-
- struct omap_overlay_manager_info info;
-
- bool manual_update;
- bool do_manual_update;
-
- /* manual update region */
- u16 x, y, w, h;
-
- /* enlarge the update area if the update area contains scaled
- * overlays */
- bool enlarge_update_area;
-};
-
-static struct {
- spinlock_t lock;
- struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
- struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
-
- bool irq_enabled;
-} dss_cache;
-
-
-
-static int omap_dss_set_device(struct omap_overlay_manager *mgr,
- struct omap_dss_device *dssdev)
-{
- int i;
- int r;
-
- if (dssdev->manager) {
- DSSERR("display '%s' already has a manager '%s'\n",
- dssdev->name, dssdev->manager->name);
- return -EINVAL;
- }
-
- if ((mgr->supported_displays & dssdev->type) == 0) {
- DSSERR("display '%s' does not support manager '%s'\n",
- dssdev->name, mgr->name);
- return -EINVAL;
- }
-
- for (i = 0; i < mgr->num_overlays; i++) {
- struct omap_overlay *ovl = mgr->overlays[i];
-
- if (ovl->manager != mgr || !ovl->info.enabled)
- continue;
-
- r = dss_check_overlay(ovl, dssdev);
- if (r)
- return r;
- }
-
- dssdev->manager = mgr;
- mgr->device = dssdev;
- mgr->device_changed = true;
-
- return 0;
-}
-
-static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
-{
- if (!mgr->device) {
- DSSERR("failed to unset display, display not set.\n");
- return -EINVAL;
- }
-
- /*
- * Don't allow currently enabled displays to have the overlay manager
- * pulled out from underneath them
- */
- if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
- return -EINVAL;
-
- mgr->device->manager = NULL;
- mgr->device = NULL;
- mgr->device_changed = true;
-
- return 0;
-}
-
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
{
unsigned long timeout = msecs_to_jiffies(500);
@@ -624,1022 +508,169 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
}
-static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
-{
- unsigned long timeout = msecs_to_jiffies(500);
- struct manager_cache_data *mc;
- u32 irq;
- int r;
- int i;
- struct omap_dss_device *dssdev = mgr->device;
-
- if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- return 0;
-
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
- || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
- irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
- } else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
- }
-
- mc = &dss_cache.manager_cache[mgr->id];
- i = 0;
- while (1) {
- unsigned long flags;
- bool shadow_dirty, dirty;
-
- spin_lock_irqsave(&dss_cache.lock, flags);
- dirty = mc->dirty;
- shadow_dirty = mc->shadow_dirty;
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- if (!dirty && !shadow_dirty) {
- r = 0;
- break;
- }
-
- /* 4 iterations is the worst case:
- * 1 - initial iteration, dirty = true (between VFP and VSYNC)
- * 2 - first VSYNC, dirty = true
- * 3 - dirty = false, shadow_dirty = true
- * 4 - shadow_dirty = false */
- if (i++ == 3) {
- DSSERR("mgr(%d)->wait_for_go() not finishing\n",
- mgr->id);
- r = 0;
- break;
- }
-
- r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
- if (r == -ERESTARTSYS)
- break;
-
- if (r) {
- DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
- break;
- }
- }
-
- return r;
-}
-
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
-{
- unsigned long timeout = msecs_to_jiffies(500);
- struct overlay_cache_data *oc;
- struct omap_dss_device *dssdev;
- u32 irq;
- int r;
- int i;
-
- if (!ovl->manager)
- return 0;
-
- dssdev = ovl->manager->device;
-
- if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- return 0;
-
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
- || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
- irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
- } else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
- }
-
- oc = &dss_cache.overlay_cache[ovl->id];
- i = 0;
- while (1) {
- unsigned long flags;
- bool shadow_dirty, dirty;
-
- spin_lock_irqsave(&dss_cache.lock, flags);
- dirty = oc->dirty;
- shadow_dirty = oc->shadow_dirty;
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- if (!dirty && !shadow_dirty) {
- r = 0;
- break;
- }
-
- /* 4 iterations is the worst case:
- * 1 - initial iteration, dirty = true (between VFP and VSYNC)
- * 2 - first VSYNC, dirty = true
- * 3 - dirty = false, shadow_dirty = true
- * 4 - shadow_dirty = false */
- if (i++ == 3) {
- DSSERR("ovl(%d)->wait_for_go() not finishing\n",
- ovl->id);
- r = 0;
- break;
- }
-
- r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
- if (r == -ERESTARTSYS)
- break;
-
- if (r) {
- DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
- break;
- }
- }
-
- return r;
-}
-
-static int overlay_enabled(struct omap_overlay *ovl)
-{
- return ovl->info.enabled && ovl->manager && ovl->manager->device;
-}
-
-/* Is rect1 a subset of rect2? */
-static bool rectangle_subset(int x1, int y1, int w1, int h1,
- int x2, int y2, int w2, int h2)
-{
- if (x1 < x2 || y1 < y2)
- return false;
-
- if (x1 + w1 > x2 + w2)
- return false;
-
- if (y1 + h1 > y2 + h2)
- return false;
-
- return true;
-}
-
-/* Do rect1 and rect2 overlap? */
-static bool rectangle_intersects(int x1, int y1, int w1, int h1,
- int x2, int y2, int w2, int h2)
-{
- if (x1 >= x2 + w2)
- return false;
-
- if (x2 >= x1 + w1)
- return false;
-
- if (y1 >= y2 + h2)
- return false;
-
- if (y2 >= y1 + h1)
- return false;
-
- return true;
-}
-
-static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
-{
- struct omap_overlay_info *oi = &oc->info;
-
- if (oi->out_width != 0 && oi->width != oi->out_width)
- return true;
-
- if (oi->out_height != 0 && oi->height != oi->out_height)
- return true;
-
- return false;
-}
-
-static int configure_overlay(enum omap_plane plane)
+int dss_init_overlay_managers(struct platform_device *pdev)
{
- struct overlay_cache_data *c;
- struct manager_cache_data *mc;
- struct omap_overlay_info *oi, new_oi;
- struct omap_overlay_manager_info *mi;
- u16 outw, outh;
- u16 x, y, w, h;
- u32 paddr;
- int r;
- u16 orig_w, orig_h, orig_outw, orig_outh;
+ int i, r;
- DSSDBGF("%d", plane);
+ num_managers = dss_feat_get_num_mgrs();
- c = &dss_cache.overlay_cache[plane];
- oi = &c->info;
+ managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
+ GFP_KERNEL);
- if (!c->enabled) {
- dispc_ovl_enable(plane, 0);
- return 0;
- }
+ BUG_ON(managers == NULL);
- mc = &dss_cache.manager_cache[c->channel];
- mi = &mc->info;
-
- x = oi->pos_x;
- y = oi->pos_y;
- w = oi->width;
- h = oi->height;
- outw = oi->out_width == 0 ? oi->width : oi->out_width;
- outh = oi->out_height == 0 ? oi->height : oi->out_height;
- paddr = oi->paddr;
-
- orig_w = w;
- orig_h = h;
- orig_outw = outw;
- orig_outh = outh;
-
- if (mc->manual_update && mc->do_manual_update) {
- unsigned bpp;
- unsigned scale_x_m = w, scale_x_d = outw;
- unsigned scale_y_m = h, scale_y_d = outh;
-
- /* If the overlay is outside the update region, disable it */
- if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
- x, y, outw, outh)) {
- dispc_ovl_enable(plane, 0);
- return 0;
- }
+ for (i = 0; i < num_managers; ++i) {
+ struct omap_overlay_manager *mgr = &managers[i];
- switch (oi->color_mode) {
- case OMAP_DSS_COLOR_NV12:
- bpp = 8;
- break;
- case OMAP_DSS_COLOR_RGB16:
- case OMAP_DSS_COLOR_ARGB16:
- case OMAP_DSS_COLOR_YUV2:
- case OMAP_DSS_COLOR_UYVY:
- case OMAP_DSS_COLOR_RGBA16:
- case OMAP_DSS_COLOR_RGBX16:
- case OMAP_DSS_COLOR_ARGB16_1555:
- case OMAP_DSS_COLOR_XRGB16_1555:
- bpp = 16;
+ switch (i) {
+ case 0:
+ mgr->name = "lcd";
+ mgr->id = OMAP_DSS_CHANNEL_LCD;
break;
-
- case OMAP_DSS_COLOR_RGB24P:
- bpp = 24;
+ case 1:
+ mgr->name = "tv";
+ mgr->id = OMAP_DSS_CHANNEL_DIGIT;
break;
-
- case OMAP_DSS_COLOR_RGB24U:
- case OMAP_DSS_COLOR_ARGB32:
- case OMAP_DSS_COLOR_RGBA32:
- case OMAP_DSS_COLOR_RGBX32:
- bpp = 32;
+ case 2:
+ mgr->name = "lcd2";
+ mgr->id = OMAP_DSS_CHANNEL_LCD2;
break;
-
- default:
- BUG();
}
- if (mc->x > oi->pos_x) {
- x = 0;
- outw -= (mc->x - oi->pos_x);
- paddr += (mc->x - oi->pos_x) *
- scale_x_m / scale_x_d * bpp / 8;
- } else {
- x = oi->pos_x - mc->x;
- }
-
- if (mc->y > oi->pos_y) {
- y = 0;
- outh -= (mc->y - oi->pos_y);
- paddr += (mc->y - oi->pos_y) *
- scale_y_m / scale_y_d *
- oi->screen_width * bpp / 8;
- } else {
- y = oi->pos_y - mc->y;
- }
-
- if (mc->w < (x + outw))
- outw -= (x + outw) - (mc->w);
-
- if (mc->h < (y + outh))
- outh -= (y + outh) - (mc->h);
-
- w = w * outw / orig_outw;
- h = h * outh / orig_outh;
-
- /* YUV mode overlay's input width has to be even and the
- * algorithm above may adjust the width to be odd.
- *
- * Here we adjust the width if needed, preferring to increase
- * the width if the original width was bigger.
- */
- if ((w & 1) &&
- (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
- oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
- if (orig_w > w)
- w += 1;
- else
- w -= 1;
- }
- }
-
- new_oi = *oi;
-
- /* update new_oi members which could have been possibly updated */
- new_oi.pos_x = x;
- new_oi.pos_y = y;
- new_oi.width = w;
- new_oi.height = h;
- new_oi.out_width = outw;
- new_oi.out_height = outh;
- new_oi.paddr = paddr;
-
- r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
- c->replication, c->fifo_low, c->fifo_high);
- if (r) {
- /* this shouldn't happen */
- DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
- dispc_ovl_enable(plane, 0);
- return r;
- }
-
- dispc_ovl_enable(plane, 1);
-
- return 0;
-}
-
-static void configure_manager(enum omap_channel channel)
-{
- struct omap_overlay_manager_info *mi;
-
- DSSDBGF("%d", channel);
-
- /* picking info from the cache */
- mi = &dss_cache.manager_cache[channel].info;
-
- dispc_mgr_set_default_color(channel, mi->default_color);
- dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
- dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
- dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
- if (dss_has_feature(FEAT_CPR)) {
- dispc_mgr_enable_cpr(channel, mi->cpr_enable);
- dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
- }
-}
-
-/* configure_dispc() tries to write values from cache to shadow registers.
- * It writes only to those managers/overlays that are not busy.
- * returns 0 if everything could be written to shadow registers.
- * returns 1 if not everything could be written to shadow registers. */
-static int configure_dispc(void)
-{
- struct overlay_cache_data *oc;
- struct manager_cache_data *mc;
- const int num_ovls = dss_feat_get_num_ovls();
- const int num_mgrs = dss_feat_get_num_mgrs();
- int i;
- int r;
- bool mgr_busy[MAX_DSS_MANAGERS];
- bool mgr_go[MAX_DSS_MANAGERS];
- bool busy;
-
- r = 0;
- busy = false;
-
- for (i = 0; i < num_mgrs; i++) {
- mgr_busy[i] = dispc_mgr_go_busy(i);
- mgr_go[i] = false;
- }
-
- /* Commit overlay settings */
- for (i = 0; i < num_ovls; ++i) {
- oc = &dss_cache.overlay_cache[i];
- mc = &dss_cache.manager_cache[oc->channel];
+ mgr->set_device = &dss_mgr_set_device;
+ mgr->unset_device = &dss_mgr_unset_device;
+ mgr->apply = &omap_dss_mgr_apply;
+ mgr->set_manager_info = &dss_mgr_set_info;
+ mgr->get_manager_info = &dss_mgr_get_info;
+ mgr->wait_for_go = &dss_mgr_wait_for_go;
+ mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
- if (!oc->dirty)
- continue;
+ mgr->caps = 0;
+ mgr->supported_displays =
+ dss_feat_get_supported_displays(mgr->id);
- if (mc->manual_update && !mc->do_manual_update)
- continue;
+ INIT_LIST_HEAD(&mgr->overlays);
- if (mgr_busy[oc->channel]) {
- busy = true;
- continue;
- }
+ r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
+ &pdev->dev.kobj, "manager%d", i);
- r = configure_overlay(i);
if (r)
- DSSERR("configure_overlay %d failed\n", i);
-
- oc->dirty = false;
- oc->shadow_dirty = true;
- mgr_go[oc->channel] = true;
- }
-
- /* Commit manager settings */
- for (i = 0; i < num_mgrs; ++i) {
- mc = &dss_cache.manager_cache[i];
-
- if (!mc->dirty)
- continue;
-
- if (mc->manual_update && !mc->do_manual_update)
- continue;
-
- if (mgr_busy[i]) {
- busy = true;
- continue;
- }
-
- configure_manager(i);
- mc->dirty = false;
- mc->shadow_dirty = true;
- mgr_go[i] = true;
- }
-
- /* set GO */
- for (i = 0; i < num_mgrs; ++i) {
- mc = &dss_cache.manager_cache[i];
-
- if (!mgr_go[i])
- continue;
-
- /* We don't need GO with manual update display. LCD iface will
- * always be turned off after frame, and new settings will be
- * taken in to use at next update */
- if (!mc->manual_update)
- dispc_mgr_go(i);
- }
-
- if (busy)
- r = 1;
- else
- r = 0;
-
- return r;
-}
-
-/* Make the coordinates even. There are some strange problems with OMAP and
- * partial DSI update when the update widths are odd. */
-static void make_even(u16 *x, u16 *w)
-{
- u16 x1, x2;
-
- x1 = *x;
- x2 = *x + *w;
-
- x1 &= ~1;
- x2 = ALIGN(x2, 2);
-
- *x = x1;
- *w = x2 - x1;
-}
-
-/* Configure dispc for partial update. Return possibly modified update
- * area */
-void dss_setup_partial_planes(struct omap_dss_device *dssdev,
- u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
-{
- struct overlay_cache_data *oc;
- struct manager_cache_data *mc;
- struct omap_overlay_info *oi;
- const int num_ovls = dss_feat_get_num_ovls();
- struct omap_overlay_manager *mgr;
- int i;
- u16 x, y, w, h;
- unsigned long flags;
- bool area_changed;
-
- x = *xi;
- y = *yi;
- w = *wi;
- h = *hi;
-
- DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
- *xi, *yi, *wi, *hi);
-
- mgr = dssdev->manager;
-
- if (!mgr) {
- DSSDBG("no manager\n");
- return;
+ DSSERR("failed to create sysfs file\n");
}
- make_even(&x, &w);
-
- spin_lock_irqsave(&dss_cache.lock, flags);
-
- /*
- * Execute the outer loop until the inner loop has completed
- * once without increasing the update area. This will ensure that
- * all scaled overlays end up completely within the update area.
- */
- do {
- area_changed = false;
-
- /* We need to show the whole overlay if it is scaled. So look
- * for those, and make the update area larger if found.
- * Also mark the overlay cache dirty */
- for (i = 0; i < num_ovls; ++i) {
- unsigned x1, y1, x2, y2;
- unsigned outw, outh;
-
- oc = &dss_cache.overlay_cache[i];
- oi = &oc->info;
-
- if (oc->channel != mgr->id)
- continue;
-
- oc->dirty = true;
-
- if (!enlarge_update_area)
- continue;
-
- if (!oc->enabled)
- continue;
-
- if (!dispc_is_overlay_scaled(oc))
- continue;
-
- outw = oi->out_width == 0 ?
- oi->width : oi->out_width;
- outh = oi->out_height == 0 ?
- oi->height : oi->out_height;
-
- /* is the overlay outside the update region? */
- if (!rectangle_intersects(x, y, w, h,
- oi->pos_x, oi->pos_y,
- outw, outh))
- continue;
-
- /* if the overlay totally inside the update region? */
- if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
- x, y, w, h))
- continue;
-
- if (x > oi->pos_x)
- x1 = oi->pos_x;
- else
- x1 = x;
-
- if (y > oi->pos_y)
- y1 = oi->pos_y;
- else
- y1 = y;
-
- if ((x + w) < (oi->pos_x + outw))
- x2 = oi->pos_x + outw;
- else
- x2 = x + w;
-
- if ((y + h) < (oi->pos_y + outh))
- y2 = oi->pos_y + outh;
- else
- y2 = y + h;
-
- x = x1;
- y = y1;
- w = x2 - x1;
- h = y2 - y1;
-
- make_even(&x, &w);
-
- DSSDBG("changing upd area due to ovl(%d) "
- "scaling %d,%d %dx%d\n",
- i, x, y, w, h);
-
- area_changed = true;
- }
- } while (area_changed);
-
- mc = &dss_cache.manager_cache[mgr->id];
- mc->do_manual_update = true;
- mc->enlarge_update_area = enlarge_update_area;
- mc->x = x;
- mc->y = y;
- mc->w = w;
- mc->h = h;
-
- configure_dispc();
-
- mc->do_manual_update = false;
-
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- *xi = x;
- *yi = y;
- *wi = w;
- *hi = h;
+ return 0;
}
-void dss_start_update(struct omap_dss_device *dssdev)
+void dss_uninit_overlay_managers(struct platform_device *pdev)
{
- struct manager_cache_data *mc;
- struct overlay_cache_data *oc;
- const int num_ovls = dss_feat_get_num_ovls();
- const int num_mgrs = dss_feat_get_num_mgrs();
- struct omap_overlay_manager *mgr;
int i;
- mgr = dssdev->manager;
+ for (i = 0; i < num_managers; ++i) {
+ struct omap_overlay_manager *mgr = &managers[i];
- for (i = 0; i < num_ovls; ++i) {
- oc = &dss_cache.overlay_cache[i];
- if (oc->channel != mgr->id)
- continue;
-
- oc->shadow_dirty = false;
- }
-
- for (i = 0; i < num_mgrs; ++i) {
- mc = &dss_cache.manager_cache[i];
- if (mgr->id != i)
- continue;
-
- mc->shadow_dirty = false;
+ kobject_del(&mgr->kobj);
+ kobject_put(&mgr->kobj);
}
- dssdev->manager->enable(dssdev->manager);
+ kfree(managers);
+ managers = NULL;
+ num_managers = 0;
}
-static void dss_apply_irq_handler(void *data, u32 mask)
+int omap_dss_get_num_overlay_managers(void)
{
- struct manager_cache_data *mc;
- struct overlay_cache_data *oc;
- const int num_ovls = dss_feat_get_num_ovls();
- const int num_mgrs = dss_feat_get_num_mgrs();
- int i, r;
- bool mgr_busy[MAX_DSS_MANAGERS];
- u32 irq_mask;
-
- for (i = 0; i < num_mgrs; i++)
- mgr_busy[i] = dispc_mgr_go_busy(i);
-
- spin_lock(&dss_cache.lock);
-
- for (i = 0; i < num_ovls; ++i) {
- oc = &dss_cache.overlay_cache[i];
- if (!mgr_busy[oc->channel])
- oc->shadow_dirty = false;
- }
-
- for (i = 0; i < num_mgrs; ++i) {
- mc = &dss_cache.manager_cache[i];
- if (!mgr_busy[i])
- mc->shadow_dirty = false;
- }
-
- r = configure_dispc();
- if (r == 1)
- goto end;
-
- /* re-read busy flags */
- for (i = 0; i < num_mgrs; i++)
- mgr_busy[i] = dispc_mgr_go_busy(i);
-
- /* keep running as long as there are busy managers, so that
- * we can collect overlay-applied information */
- for (i = 0; i < num_mgrs; ++i) {
- if (mgr_busy[i])
- goto end;
- }
-
- irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
- DISPC_IRQ_EVSYNC_EVEN;
- if (dss_has_feature(FEAT_MGR_LCD2))
- irq_mask |= DISPC_IRQ_VSYNC2;
-
- omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask);
- dss_cache.irq_enabled = false;
-
-end:
- spin_unlock(&dss_cache.lock);
+ return num_managers;
}
+EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
-static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
{
- struct overlay_cache_data *oc;
- struct manager_cache_data *mc;
- int i;
- struct omap_overlay *ovl;
- int num_planes_enabled = 0;
- bool use_fifomerge;
- unsigned long flags;
- int r;
-
- DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
-
- r = dispc_runtime_get();
- if (r)
- return r;
-
- spin_lock_irqsave(&dss_cache.lock, flags);
-
- /* Configure overlays */
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_dss_device *dssdev;
-
- ovl = omap_dss_get_overlay(i);
-
- oc = &dss_cache.overlay_cache[ovl->id];
-
- if (ovl->manager_changed) {
- ovl->manager_changed = false;
- ovl->info_dirty = true;
- }
-
- if (!overlay_enabled(ovl)) {
- if (oc->enabled) {
- oc->enabled = false;
- oc->dirty = true;
- }
- continue;
- }
-
- if (!ovl->info_dirty) {
- if (oc->enabled)
- ++num_planes_enabled;
- continue;
- }
-
- dssdev = ovl->manager->device;
-
- if (dss_check_overlay(ovl, dssdev)) {
- if (oc->enabled) {
- oc->enabled = false;
- oc->dirty = true;
- }
- continue;
- }
-
- ovl->info_dirty = false;
- oc->dirty = true;
- oc->info = ovl->info;
-
- oc->replication =
- dss_use_replication(dssdev, ovl->info.color_mode);
-
- oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
-
- oc->channel = ovl->manager->id;
-
- oc->enabled = true;
-
- ++num_planes_enabled;
- }
-
- /* Configure managers */
- list_for_each_entry(mgr, &manager_list, list) {
- struct omap_dss_device *dssdev;
+ if (num >= num_managers)
+ return NULL;
- mc = &dss_cache.manager_cache[mgr->id];
-
- if (mgr->device_changed) {
- mgr->device_changed = false;
- mgr->info_dirty = true;
- }
-
- if (!mgr->info_dirty)
- continue;
-
- if (!mgr->device)
- continue;
-
- dssdev = mgr->device;
-
- mgr->info_dirty = false;
- mc->dirty = true;
- mc->info = mgr->info;
-
- mc->manual_update =
- dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
- }
-
- /* XXX TODO: Try to get fifomerge working. The problem is that it
- * affects both managers, not individually but at the same time. This
- * means the change has to be well synchronized. I guess the proper way
- * is to have a two step process for fifo merge:
- * fifomerge enable:
- * 1. disable other planes, leaving one plane enabled
- * 2. wait until the planes are disabled on HW
- * 3. config merged fifo thresholds, enable fifomerge
- * fifomerge disable:
- * 1. config unmerged fifo thresholds, disable fifomerge
- * 2. wait until fifo changes are in HW
- * 3. enable planes
- */
- use_fifomerge = false;
-
- /* Configure overlay fifos */
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_dss_device *dssdev;
- u32 size, burst_size;
-
- ovl = omap_dss_get_overlay(i);
-
- oc = &dss_cache.overlay_cache[ovl->id];
-
- if (!oc->enabled)
- continue;
-
- dssdev = ovl->manager->device;
-
- size = dispc_ovl_get_fifo_size(ovl->id);
- if (use_fifomerge)
- size *= 3;
-
- burst_size = dispc_ovl_get_burst_size(ovl->id);
-
- switch (dssdev->type) {
- case OMAP_DISPLAY_TYPE_DPI:
- case OMAP_DISPLAY_TYPE_DBI:
- case OMAP_DISPLAY_TYPE_SDI:
- case OMAP_DISPLAY_TYPE_VENC:
- case OMAP_DISPLAY_TYPE_HDMI:
- default_get_overlay_fifo_thresholds(ovl->id, size,
- burst_size, &oc->fifo_low,
- &oc->fifo_high);
- break;
-#ifdef CONFIG_OMAP2_DSS_DSI
- case OMAP_DISPLAY_TYPE_DSI:
- dsi_get_overlay_fifo_thresholds(ovl->id, size,
- burst_size, &oc->fifo_low,
- &oc->fifo_high);
- break;
-#endif
- default:
- BUG();
- }
- }
-
- r = 0;
- if (!dss_cache.irq_enabled) {
- u32 mask;
-
- mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
- DISPC_IRQ_EVSYNC_EVEN;
- if (dss_has_feature(FEAT_MGR_LCD2))
- mask |= DISPC_IRQ_VSYNC2;
-
- r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
- dss_cache.irq_enabled = true;
- }
- configure_dispc();
-
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- dispc_runtime_put();
-
- return r;
+ return &managers[num];
}
+EXPORT_SYMBOL(omap_dss_get_overlay_manager);
-static int dss_check_manager(struct omap_overlay_manager *mgr)
+int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
+ const struct omap_overlay_manager_info *info)
{
if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
/*
* OMAP3 supports only graphics source transparency color key
* and alpha blending simultaneously. See TRM 15.4.2.4.2.2
- * Alpha Mode
+ * Alpha Mode.
*/
- if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled
- && mgr->info.trans_key_type !=
- OMAP_DSS_COLOR_KEY_GFX_DST)
+ if (info->partial_alpha_enabled && info->trans_enabled
+ && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
+ DSSERR("check_manager: illegal transparency key\n");
return -EINVAL;
+ }
}
return 0;
}
-static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
- struct omap_overlay_manager_info *info)
-{
- int r;
- struct omap_overlay_manager_info old_info;
-
- old_info = mgr->info;
- mgr->info = *info;
-
- r = dss_check_manager(mgr);
- if (r) {
- mgr->info = old_info;
- return r;
- }
-
- mgr->info_dirty = true;
-
- return 0;
-}
-
-static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
- struct omap_overlay_manager_info *info)
+static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
+ struct omap_overlay_info **overlay_infos)
{
- *info = mgr->info;
-}
+ struct omap_overlay *ovl1, *ovl2;
+ struct omap_overlay_info *info1, *info2;
-static int dss_mgr_enable(struct omap_overlay_manager *mgr)
-{
- dispc_mgr_enable(mgr->id, 1);
- return 0;
-}
+ list_for_each_entry(ovl1, &mgr->overlays, list) {
+ info1 = overlay_infos[ovl1->id];
-static int dss_mgr_disable(struct omap_overlay_manager *mgr)
-{
- dispc_mgr_enable(mgr->id, 0);
- return 0;
-}
-
-static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
-{
- ++num_managers;
- list_add_tail(&manager->list, &manager_list);
-}
-
-int dss_init_overlay_managers(struct platform_device *pdev)
-{
- int i, r;
-
- spin_lock_init(&dss_cache.lock);
-
- INIT_LIST_HEAD(&manager_list);
-
- num_managers = 0;
-
- for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
- struct omap_overlay_manager *mgr;
- mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
-
- BUG_ON(mgr == NULL);
-
- switch (i) {
- case 0:
- mgr->name = "lcd";
- mgr->id = OMAP_DSS_CHANNEL_LCD;
- break;
- case 1:
- mgr->name = "tv";
- mgr->id = OMAP_DSS_CHANNEL_DIGIT;
- break;
- case 2:
- mgr->name = "lcd2";
- mgr->id = OMAP_DSS_CHANNEL_LCD2;
- break;
- }
-
- mgr->set_device = &omap_dss_set_device;
- mgr->unset_device = &omap_dss_unset_device;
- mgr->apply = &omap_dss_mgr_apply;
- mgr->set_manager_info = &omap_dss_mgr_set_info;
- mgr->get_manager_info = &omap_dss_mgr_get_info;
- mgr->wait_for_go = &dss_mgr_wait_for_go;
- mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
-
- mgr->enable = &dss_mgr_enable;
- mgr->disable = &dss_mgr_disable;
-
- mgr->caps = 0;
- mgr->supported_displays =
- dss_feat_get_supported_displays(mgr->id);
+ if (info1 == NULL)
+ continue;
- dss_overlay_setup_dispc_manager(mgr);
+ list_for_each_entry(ovl2, &mgr->overlays, list) {
+ if (ovl1 == ovl2)
+ continue;
- omap_dss_add_overlay_manager(mgr);
+ info2 = overlay_infos[ovl2->id];
- r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
- &pdev->dev.kobj, "manager%d", i);
+ if (info2 == NULL)
+ continue;
- if (r) {
- DSSERR("failed to create sysfs file\n");
- continue;
+ if (info1->zorder == info2->zorder) {
+ DSSERR("overlays %d and %d have the same "
+ "zorder %d\n",
+ ovl1->id, ovl2->id, info1->zorder);
+ return -EINVAL;
+ }
}
}
return 0;
}
-void dss_uninit_overlay_managers(struct platform_device *pdev)
+int dss_mgr_check(struct omap_overlay_manager *mgr,
+ struct omap_dss_device *dssdev,
+ struct omap_overlay_manager_info *info,
+ struct omap_overlay_info **overlay_infos)
{
- struct omap_overlay_manager *mgr;
+ struct omap_overlay *ovl;
+ int r;
- while (!list_empty(&manager_list)) {
- mgr = list_first_entry(&manager_list,
- struct omap_overlay_manager, list);
- list_del(&mgr->list);
- kobject_del(&mgr->kobj);
- kobject_put(&mgr->kobj);
- kfree(mgr);
+ if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
+ r = dss_mgr_check_zorder(mgr, overlay_infos);
+ if (r)
+ return r;
}
- num_managers = 0;
-}
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ struct omap_overlay_info *oi;
+ int r;
-int omap_dss_get_num_overlay_managers(void)
-{
- return num_managers;
-}
-EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
+ oi = overlay_infos[ovl->id];
-struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
-{
- int i = 0;
- struct omap_overlay_manager *mgr;
+ if (oi == NULL)
+ continue;
- list_for_each_entry(mgr, &manager_list, list) {
- if (i++ == num)
- return mgr;
+ r = dss_ovl_check(ovl, oi, dssdev);
+ if (r)
+ return r;
}
- return NULL;
+ return 0;
}
-EXPORT_SYMBOL(omap_dss_get_overlay_manager);
-
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index ab8e40e..6e82181 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -38,7 +38,7 @@
#include "dss_features.h"
static int num_overlays;
-static struct list_head overlay_list;
+static struct omap_overlay *overlays;
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
{
@@ -124,19 +124,31 @@ err:
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
- ovl->info.width, ovl->info.height);
+ info.width, info.height);
}
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
}
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
- ovl->info.pos_x, ovl->info.pos_y);
+ info.pos_x, info.pos_y);
}
static ssize_t overlay_position_store(struct omap_overlay *ovl,
@@ -170,8 +182,12 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
- ovl->info.out_width, ovl->info.out_height);
+ info.out_width, info.out_height);
}
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
@@ -205,7 +221,7 @@ static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
+ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
}
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
@@ -213,33 +229,30 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
{
int r;
bool enable;
- struct omap_overlay_info info;
-
- ovl->get_overlay_info(ovl, &info);
r = strtobool(buf, &enable);
if (r)
return r;
- info.enabled = enable;
+ if (enable)
+ r = ovl->enable(ovl);
+ else
+ r = ovl->disable(ovl);
- r = ovl->set_overlay_info(ovl, &info);
if (r)
return r;
- if (ovl->manager) {
- r = ovl->manager->apply(ovl->manager);
- if (r)
- return r;
- }
-
return size;
}
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
return snprintf(buf, PAGE_SIZE, "%d\n",
- ovl->info.global_alpha);
+ info.global_alpha);
}
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
@@ -276,8 +289,12 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
char *buf)
{
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
return snprintf(buf, PAGE_SIZE, "%d\n",
- ovl->info.pre_mult_alpha);
+ info.pre_mult_alpha);
}
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
@@ -313,7 +330,11 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
}
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
@@ -430,183 +451,6 @@ static struct kobj_type overlay_ktype = {
.default_attrs = overlay_sysfs_attrs,
};
-/* Check if overlay parameters are compatible with display */
-int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
-{
- struct omap_overlay_info *info;
- u16 outw, outh;
- u16 dw, dh;
- int i;
-
- if (!dssdev)
- return 0;
-
- if (!ovl->info.enabled)
- return 0;
-
- info = &ovl->info;
-
- if (info->paddr == 0) {
- DSSDBG("check_overlay failed: paddr 0\n");
- return -EINVAL;
- }
-
- dssdev->driver->get_resolution(dssdev, &dw, &dh);
-
- DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
- ovl->id,
- info->pos_x, info->pos_y,
- info->width, info->height,
- info->out_width, info->out_height,
- dw, dh);
-
- if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
- outw = info->width;
- outh = info->height;
- } else {
- if (info->out_width == 0)
- outw = info->width;
- else
- outw = info->out_width;
-
- if (info->out_height == 0)
- outh = info->height;
- else
- outh = info->out_height;
- }
-
- if (dw < info->pos_x + outw) {
- DSSDBG("check_overlay failed 1: %d < %d + %d\n",
- dw, info->pos_x, outw);
- return -EINVAL;
- }
-
- if (dh < info->pos_y + outh) {
- DSSDBG("check_overlay failed 2: %d < %d + %d\n",
- dh, info->pos_y, outh);
- return -EINVAL;
- }
-
- if ((ovl->supported_modes & info->color_mode) == 0) {
- DSSERR("overlay doesn't support mode %d\n", info->color_mode);
- return -EINVAL;
- }
-
- if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
- if (info->zorder < 0 || info->zorder > 3) {
- DSSERR("zorder out of range: %d\n",
- info->zorder);
- return -EINVAL;
- }
- /*
- * Check that zorder doesn't match with zorder of any other
- * overlay which is enabled and is also connected to the same
- * manager
- */
- for (i = 0; i < omap_dss_get_num_overlays(); i++) {
- struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
-
- if (tmp_ovl->id != ovl->id &&
- tmp_ovl->manager == ovl->manager &&
- tmp_ovl->info.enabled == true &&
- tmp_ovl->info.zorder == info->zorder) {
- DSSERR("%s and %s have same zorder: %d\n",
- ovl->name, tmp_ovl->name, info->zorder);
- return -EINVAL;
- }
- }
- }
-
- return 0;
-}
-
-static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
- struct omap_overlay_info *info)
-{
- int r;
- struct omap_overlay_info old_info;
-
- old_info = ovl->info;
- ovl->info = *info;
-
- if (ovl->manager) {
- r = dss_check_overlay(ovl, ovl->manager->device);
- if (r) {
- ovl->info = old_info;
- return r;
- }
- }
-
- ovl->info_dirty = true;
-
- return 0;
-}
-
-static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
- struct omap_overlay_info *info)
-{
- *info = ovl->info;
-}
-
-static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
-{
- return dss_mgr_wait_for_go_ovl(ovl);
-}
-
-static int omap_dss_set_manager(struct omap_overlay *ovl,
- struct omap_overlay_manager *mgr)
-{
- if (!mgr)
- return -EINVAL;
-
- if (ovl->manager) {
- DSSERR("overlay '%s' already has a manager '%s'\n",
- ovl->name, ovl->manager->name);
- return -EINVAL;
- }
-
- if (ovl->info.enabled) {
- DSSERR("overlay has to be disabled to change the manager\n");
- return -EINVAL;
- }
-
- ovl->manager = mgr;
- ovl->manager_changed = true;
-
- /* XXX: When there is an overlay on a DSI manual update display, and
- * the overlay is first disabled, then moved to tv, and enabled, we
- * seem to get SYNC_LOST_DIGIT error.
- *
- * Waiting doesn't seem to help, but updating the manual update display
- * after disabling the overlay seems to fix this. This hints that the
- * overlay is perhaps somehow tied to the LCD output until the output
- * is updated.
- *
- * Userspace workaround for this is to update the LCD after disabling
- * the overlay, but before moving the overlay to TV.
- */
-
- return 0;
-}
-
-static int omap_dss_unset_manager(struct omap_overlay *ovl)
-{
- if (!ovl->manager) {
- DSSERR("failed to detach overlay: manager not set\n");
- return -EINVAL;
- }
-
- if (ovl->info.enabled) {
- DSSERR("overlay has to be disabled to unset the manager\n");
- return -EINVAL;
- }
-
- ovl->manager = NULL;
- ovl->manager_changed = true;
-
- return 0;
-}
-
int omap_dss_get_num_overlays(void)
{
return num_overlays;
@@ -615,134 +459,65 @@ EXPORT_SYMBOL(omap_dss_get_num_overlays);
struct omap_overlay *omap_dss_get_overlay(int num)
{
- int i = 0;
- struct omap_overlay *ovl;
+ if (num >= num_overlays)
+ return NULL;
- list_for_each_entry(ovl, &overlay_list, list) {
- if (i++ == num)
- return ovl;
- }
-
- return NULL;
+ return &overlays[num];
}
EXPORT_SYMBOL(omap_dss_get_overlay);
-static void omap_dss_add_overlay(struct omap_overlay *overlay)
-{
- ++num_overlays;
- list_add_tail(&overlay->list, &overlay_list);
-}
-
-static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
-
-void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
-{
- mgr->num_overlays = dss_feat_get_num_ovls();
- mgr->overlays = dispc_overlays;
-}
-
-#ifdef L4_EXAMPLE
-static struct omap_overlay *l4_overlays[1];
-void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
-{
- mgr->num_overlays = 1;
- mgr->overlays = l4_overlays;
-}
-#endif
-
void dss_init_overlays(struct platform_device *pdev)
{
int i, r;
- INIT_LIST_HEAD(&overlay_list);
+ num_overlays = dss_feat_get_num_ovls();
- num_overlays = 0;
+ overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
+ GFP_KERNEL);
- for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
- struct omap_overlay *ovl;
- ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
+ BUG_ON(overlays == NULL);
- BUG_ON(ovl == NULL);
+ for (i = 0; i < num_overlays; ++i) {
+ struct omap_overlay *ovl = &overlays[i];
switch (i) {
case 0:
ovl->name = "gfx";
ovl->id = OMAP_DSS_GFX;
- ovl->info.global_alpha = 255;
- ovl->info.zorder = 0;
break;
case 1:
ovl->name = "vid1";
ovl->id = OMAP_DSS_VIDEO1;
- ovl->info.global_alpha = 255;
- ovl->info.zorder =
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
break;
case 2:
ovl->name = "vid2";
ovl->id = OMAP_DSS_VIDEO2;
- ovl->info.global_alpha = 255;
- ovl->info.zorder =
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
break;
case 3:
ovl->name = "vid3";
ovl->id = OMAP_DSS_VIDEO3;
- ovl->info.global_alpha = 255;
- ovl->info.zorder =
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
break;
}
- ovl->set_manager = &omap_dss_set_manager;
- ovl->unset_manager = &omap_dss_unset_manager;
- ovl->set_overlay_info = &dss_ovl_set_overlay_info;
- ovl->get_overlay_info = &dss_ovl_get_overlay_info;
- ovl->wait_for_go = &dss_ovl_wait_for_go;
+ ovl->is_enabled = &dss_ovl_is_enabled;
+ ovl->enable = &dss_ovl_enable;
+ ovl->disable = &dss_ovl_disable;
+ ovl->set_manager = &dss_ovl_set_manager;
+ ovl->unset_manager = &dss_ovl_unset_manager;
+ ovl->set_overlay_info = &dss_ovl_set_info;
+ ovl->get_overlay_info = &dss_ovl_get_info;
+ ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);
- omap_dss_add_overlay(ovl);
-
r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
&pdev->dev.kobj, "overlay%d", i);
- if (r) {
- DSSERR("failed to create sysfs file\n");
- continue;
- }
-
- dispc_overlays[i] = ovl;
- }
-
-#ifdef L4_EXAMPLE
- {
- struct omap_overlay *ovl;
- ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
-
- BUG_ON(ovl == NULL);
-
- ovl->name = "l4";
- ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
-
- ovl->set_manager = &omap_dss_set_manager;
- ovl->unset_manager = &omap_dss_unset_manager;
- ovl->set_overlay_info = &dss_ovl_set_overlay_info;
- ovl->get_overlay_info = &dss_ovl_get_overlay_info;
-
- omap_dss_add_overlay(ovl);
-
- r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
- &pdev->dev.kobj, "overlayl4");
-
if (r)
DSSERR("failed to create sysfs file\n");
-
- l4_overlays[0] = ovl;
}
-#endif
}
/* connect overlays to the new device, if not already connected. if force
@@ -795,8 +570,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
ovl = omap_dss_get_overlay(i);
if (!ovl->manager || force) {
if (ovl->manager)
- omap_dss_unset_manager(ovl);
- omap_dss_set_manager(ovl, mgr);
+ ovl->unset_manager(ovl);
+ ovl->set_manager(ovl, mgr);
}
}
@@ -806,17 +581,95 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
void dss_uninit_overlays(struct platform_device *pdev)
{
- struct omap_overlay *ovl;
+ int i;
+
+ for (i = 0; i < num_overlays; ++i) {
+ struct omap_overlay *ovl = &overlays[i];
- while (!list_empty(&overlay_list)) {
- ovl = list_first_entry(&overlay_list,
- struct omap_overlay, list);
- list_del(&ovl->list);
kobject_del(&ovl->kobj);
kobject_put(&ovl->kobj);
- kfree(ovl);
}
+ kfree(overlays);
+ overlays = NULL;
num_overlays = 0;
}
+int dss_ovl_simple_check(struct omap_overlay *ovl,
+ const struct omap_overlay_info *info)
+{
+ if (info->paddr == 0) {
+ DSSERR("check_overlay: paddr cannot be 0\n");
+ return -EINVAL;
+ }
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ if (info->out_width != 0 && info->width != info->out_width) {
+ DSSERR("check_overlay: overlay %d doesn't support "
+ "scaling\n", ovl->id);
+ return -EINVAL;
+ }
+
+ if (info->out_height != 0 && info->height != info->out_height) {
+ DSSERR("check_overlay: overlay %d doesn't support "
+ "scaling\n", ovl->id);
+ return -EINVAL;
+ }
+ }
+
+ if ((ovl->supported_modes & info->color_mode) == 0) {
+ DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
+ ovl->id, info->color_mode);
+ return -EINVAL;
+ }
+
+ if (info->zorder >= omap_dss_get_num_overlays()) {
+ DSSERR("check_overlay: zorder %d too high\n", info->zorder);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int dss_ovl_check(struct omap_overlay *ovl,
+ struct omap_overlay_info *info, struct omap_dss_device *dssdev)
+{
+ u16 outw, outh;
+ u16 dw, dh;
+
+ if (dssdev == NULL)
+ return 0;
+
+ dssdev->driver->get_resolution(dssdev, &dw, &dh);
+
+ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
+ outw = info->width;
+ outh = info->height;
+ } else {
+ if (info->out_width == 0)
+ outw = info->width;
+ else
+ outw = info->out_width;
+
+ if (info->out_height == 0)
+ outh = info->height;
+ else
+ outh = info->out_height;
+ }
+
+ if (dw < info->pos_x + outw) {
+ DSSERR("overlay %d horizontally not inside the display area "
+ "(%d + %d >= %d)\n",
+ ovl->id, info->pos_x, outw, dw);
+ return -EINVAL;
+ }
+
+ if (dh < info->pos_y + outh) {
+ DSSERR("overlay %d vertically not inside the display area "
+ "(%d + %d >= %d)\n",
+ ovl->id, info->pos_y, outh, dh);
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 1130c60..814bb95 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
if (*w == 0 || *h == 0)
return -EINVAL;
- dss_setup_partial_planes(dssdev, x, y, w, h, true);
dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
return 0;
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 40305ad..8266ca0 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -123,10 +123,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
goto err_sdi_enable;
mdelay(2);
- dssdev->manager->enable(dssdev->manager);
+ r = dss_mgr_enable(dssdev->manager);
+ if (r)
+ goto err_mgr_enable;
return 0;
+err_mgr_enable:
+ dss_sdi_disable();
err_sdi_enable:
err_set_dispc_clock_div:
err_set_dss_clock_div:
@@ -145,7 +149,7 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
{
- dssdev->manager->disable(dssdev->manager);
+ dss_mgr_disable(dssdev->manager);
dss_sdi_disable();
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 2c3443d..7503f7f 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -110,6 +110,11 @@ struct ti_hdmi_ip_ops {
void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+ void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start);
+#endif
+
};
struct hdmi_ip_data {
@@ -134,5 +139,8 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
-
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable);
+#endif
#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index e1a6ce5..9af81f1 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -1204,36 +1204,13 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
return 0;
}
-int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
- struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable)
{
- int err = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- REG_FLD_MOD(hdmi_av_base(ip_data),
- HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
- REG_FLD_MOD(hdmi_wp_base(ip_data),
- HDMI_WP_AUDIO_CTRL, 1, 31, 31);
- REG_FLD_MOD(hdmi_wp_base(ip_data),
- HDMI_WP_AUDIO_CTRL, 1, 30, 30);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- REG_FLD_MOD(hdmi_av_base(ip_data),
- HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
- REG_FLD_MOD(hdmi_wp_base(ip_data),
- HDMI_WP_AUDIO_CTRL, 0, 30, 30);
- REG_FLD_MOD(hdmi_wp_base(ip_data),
- HDMI_WP_AUDIO_CTRL, 0, 31, 31);
- break;
- default:
- err = -EINVAL;
- }
- return err;
+ REG_FLD_MOD(hdmi_av_base(ip_data),
+ HDMI_CORE_AV_AUD_MODE, enable, 0, 0);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, enable, 31, 31);
+ REG_FLD_MOD(hdmi_wp_base(ip_data),
+ HDMI_WP_AUDIO_CTRL, enable, 30, 30);
}
#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index 2040956..a442998 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -576,9 +576,6 @@ struct hdmi_core_audio_config {
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
- struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai);
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
u32 sample_freq, u32 *n, u32 *cts);
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 7533458..b3e9f90 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -417,9 +417,10 @@ static const struct venc_config *venc_timings_to_config(
BUG();
}
-static void venc_power_on(struct omap_dss_device *dssdev)
+static int venc_power_on(struct omap_dss_device *dssdev)
{
u32 l;
+ int r;
venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
@@ -447,7 +448,22 @@ static void venc_power_on(struct omap_dss_device *dssdev)
if (dssdev->platform_enable)
dssdev->platform_enable(dssdev);
- dssdev->manager->enable(dssdev->manager);
+ r = dss_mgr_enable(dssdev->manager);
+ if (r)
+ goto err;
+
+ return 0;
+
+err:
+ venc_write_reg(VENC_OUTPUT_CONTROL, 0);
+ dss_set_dac_pwrdn_bgz(0);
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ regulator_disable(venc.vdda_dac_reg);
+
+ return r;
}
static void venc_power_off(struct omap_dss_device *dssdev)
@@ -455,7 +471,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
dss_set_dac_pwrdn_bgz(0);
- dssdev->manager->disable(dssdev->manager);
+ dss_mgr_disable(dssdev->manager);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
@@ -504,7 +520,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
if (r)
goto err1;
- venc_power_on(dssdev);
+ r = venc_power_on(dssdev);
+ if (r)
+ goto err2;
venc.wss_data = 0;
@@ -512,6 +530,8 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
mutex_unlock(&venc.venc_lock);
return 0;
+err2:
+ venc_runtime_put();
err1:
omap_dss_stop_device(dssdev);
err0:
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index df7bcce..16ba619 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -111,28 +111,22 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
set_fb_fix(fbi);
}
- if (pi->enabled) {
- struct omap_overlay_info info;
+ if (!pi->enabled) {
+ r = ovl->disable(ovl);
+ if (r)
+ goto undo;
+ }
+ if (pi->enabled) {
r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
pi->out_width, pi->out_height);
if (r)
goto undo;
-
- ovl->get_overlay_info(ovl, &info);
-
- if (!info.enabled) {
- info.enabled = pi->enabled;
- r = ovl->set_overlay_info(ovl, &info);
- if (r)
- goto undo;
- }
} else {
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
- info.enabled = pi->enabled;
info.pos_x = pi->pos_x;
info.pos_y = pi->pos_y;
info.out_width = pi->out_width;
@@ -146,6 +140,12 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
if (ovl->manager)
ovl->manager->apply(ovl->manager);
+ if (pi->enabled) {
+ r = ovl->enable(ovl);
+ if (r)
+ goto undo;
+ }
+
/* Release the locks in a specific order to keep lockdep happy */
if (old_rg->id > new_rg->id) {
omapfb_put_mem_region(old_rg);
@@ -189,19 +189,19 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
memset(pi, 0, sizeof(*pi));
} else {
struct omap_overlay *ovl;
- struct omap_overlay_info *ovli;
+ struct omap_overlay_info ovli;
ovl = ofbi->overlays[0];
- ovli = &ovl->info;
+ ovl->get_overlay_info(ovl, &ovli);
- pi->pos_x = ovli->pos_x;
- pi->pos_y = ovli->pos_y;
- pi->enabled = ovli->enabled;
+ pi->pos_x = ovli.pos_x;
+ pi->pos_y = ovli.pos_y;
+ pi->enabled = ovl->is_enabled(ovl);
pi->channel_out = 0; /* xxx */
pi->mirror = 0;
pi->mem_idx = get_mem_idx(ofbi);
- pi->out_width = ovli->out_width;
- pi->out_height = ovli->out_height;
+ pi->out_width = ovli.out_width;
+ pi->out_height = ovli.out_height;
}
return 0;
@@ -238,7 +238,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
continue;
for (j = 0; j < ofbi2->num_overlays; j++) {
- if (ofbi2->overlays[j]->info.enabled) {
+ struct omap_overlay *ovl;
+ ovl = ofbi2->overlays[j];
+ if (ovl->is_enabled(ovl)) {
r = -EBUSY;
goto out;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 70aa47d..ce15831 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -43,18 +43,18 @@
static char *def_mode;
static char *def_vram;
-static int def_vrfb;
+static bool def_vrfb;
static int def_rotate;
-static int def_mirror;
+static bool def_mirror;
static bool auto_update;
static unsigned int auto_update_freq;
module_param(auto_update, bool, 0);
module_param(auto_update_freq, uint, 0644);
#ifdef DEBUG
-unsigned int omapfb_debug;
+bool omapfb_debug;
module_param_named(debug, omapfb_debug, bool, 0644);
-static unsigned int omapfb_test_pattern;
+static bool omapfb_test_pattern;
module_param_named(test, omapfb_test_pattern, bool, 0644);
#endif
@@ -970,16 +970,20 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
outh = var->yres;
}
} else {
- outw = ovl->info.out_width;
- outh = ovl->info.out_height;
+ struct omap_overlay_info info;
+ ovl->get_overlay_info(ovl, &info);
+ outw = info.out_width;
+ outh = info.out_height;
}
if (init) {
posx = 0;
posy = 0;
} else {
- posx = ovl->info.pos_x;
- posy = ovl->info.pos_y;
+ struct omap_overlay_info info;
+ ovl->get_overlay_info(ovl, &info);
+ posx = info.pos_x;
+ posy = info.pos_y;
}
r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
@@ -2067,6 +2071,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
if (ofbi->num_overlays > 0) {
struct omap_overlay *ovl = ofbi->overlays[0];
+ ovl->manager->apply(ovl->manager);
+
r = omapfb_overlay_enable(ovl, 1);
if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 1694d51..e8d8cc7 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -473,7 +473,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
continue;
for (j = 0; j < ofbi2->num_overlays; j++) {
- if (ofbi2->overlays[j]->info.enabled) {
+ struct omap_overlay *ovl;
+ ovl = ofbi2->overlays[j];
+ if (ovl->is_enabled(ovl)) {
r = -EBUSY;
goto out;
}
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index fdf0ede..c0bdc9b 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -32,7 +32,7 @@
#include <video/omapdss.h>
#ifdef DEBUG
-extern unsigned int omapfb_debug;
+extern bool omapfb_debug;
#define DBG(format, ...) \
do { \
if (omapfb_debug) \
@@ -181,13 +181,10 @@ static inline void omapfb_unlock(struct omapfb2_device *fbdev)
static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
int enable)
{
- struct omap_overlay_info info;
-
- ovl->get_overlay_info(ovl, &info);
- if (info.enabled == enable)
- return 0;
- info.enabled = enable;
- return ovl->set_overlay_info(ovl, &info);
+ if (enable)
+ return ovl->enable(ovl);
+ else
+ return ovl->disable(ovl);
}
static inline struct omapfb2_mem_region *
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index dc7bfa9..df31a24 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -78,12 +78,12 @@ static char *mode_option __devinitdata;
* these flags allow the user to specify that requests for +ve sync
* should be silently turned in -ve sync.
*/
-static int lowhsync;
-static int lowvsync;
-static int noaccel __devinitdata;
+static bool lowhsync;
+static bool lowvsync;
+static bool noaccel __devinitdata;
/* mtrr option */
#ifdef CONFIG_MTRR
-static int nomtrr __devinitdata;
+static bool nomtrr __devinitdata;
#endif
/*
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 6632ee5..055e527 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -57,11 +57,11 @@
*/
static int hwcursor = 1;
static char *mode_option __devinitdata;
-static int noaccel __devinitdata;
+static bool noaccel __devinitdata;
/* mtrr option */
#ifdef CONFIG_MTRR
-static int nomtrr __devinitdata;
+static bool nomtrr __devinitdata;
#endif
/*
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
index b2252fe..6d30428 100644
--- a/drivers/video/pnx4008/pnxrgbfb.c
+++ b/drivers/video/pnx4008/pnxrgbfb.c
@@ -193,17 +193,6 @@ static struct platform_driver rgbfb_driver = {
.remove = rgbfb_remove,
};
-static int __init rgbfb_init(void)
-{
- return platform_driver_register(&rgbfb_driver);
-}
-
-static void __exit rgbfb_exit(void)
-{
- platform_driver_unregister(&rgbfb_driver);
-}
-
-module_init(rgbfb_init);
-module_exit(rgbfb_exit);
+module_platform_driver(rgbfb_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index 50e0039..c5c7414 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -856,17 +856,6 @@ static struct platform_driver sdum_driver = {
.resume = sdum_resume,
};
-int __init sdum_init(void)
-{
- return platform_driver_register(&sdum_driver);
-}
-
-static void __exit sdum_exit(void)
-{
- platform_driver_unregister(&sdum_driver);
-};
-
-module_init(sdum_init);
-module_exit(sdum_exit);
+module_platform_driver(sdum_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 18ead6f..8384b94 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -832,17 +832,7 @@ static struct platform_driver pxa168fb_driver = {
.remove = __devexit_p(pxa168fb_remove),
};
-static int __init pxa168fb_init(void)
-{
- return platform_driver_register(&pxa168fb_driver);
-}
-module_init(pxa168fb_init);
-
-static void __exit pxa168fb_exit(void)
-{
- platform_driver_unregister(&pxa168fb_driver);
-}
-module_exit(pxa168fb_exit);
+module_platform_driver(pxa168fb_driver);
MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
"Green Wan <gwan@marvell.com>");
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 1ed8b36..1d71c08 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -747,20 +747,7 @@ static struct platform_driver pxa3xx_gcu_driver = {
},
};
-static int __init
-pxa3xx_gcu_init(void)
-{
- return platform_driver_register(&pxa3xx_gcu_driver);
-}
-
-static void __exit
-pxa3xx_gcu_exit(void)
-{
- platform_driver_unregister(&pxa3xx_gcu_driver);
-}
-
-module_init(pxa3xx_gcu_init);
-module_exit(pxa3xx_gcu_exit);
+module_platform_driver(pxa3xx_gcu_driver);
MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index d8ab7be..2f58cf9 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -207,9 +207,9 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
/* command line data, set in rivafb_setup() */
static int flatpanel __devinitdata = -1; /* Autodetect later */
static int forceCRTC __devinitdata = -1;
-static int noaccel __devinitdata = 0;
+static bool noaccel __devinitdata = 0;
#ifdef CONFIG_MTRR
-static int nomtrr __devinitdata = 0;
+static bool nomtrr __devinitdata = 0;
#endif
#ifdef CONFIG_PMAC_BACKLIGHT
static int backlight __devinitdata = 1;
@@ -218,7 +218,7 @@ static int backlight __devinitdata = 0;
#endif
static char *mode_option __devinitdata = NULL;
-static int strictmode = 0;
+static bool strictmode = 0;
static struct fb_fix_screeninfo __devinitdata rivafb_fix = {
.type = FB_TYPE_PACKED_PIXELS,
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0753b1c..0c63b69 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -192,6 +192,7 @@ struct s3c_fb_vsync {
* @regs: The mapped hardware registers.
* @variant: Variant information for this hardware.
* @enabled: A bitmask of enabled hardware windows.
+ * @output_on: Flag if the physical output is enabled.
* @pdata: The platform configuration data passed with the device.
* @windows: The hardware windows that have been claimed.
* @irq_no: IRQ line number
@@ -208,6 +209,7 @@ struct s3c_fb {
struct s3c_fb_variant variant;
unsigned char enabled;
+ bool output_on;
struct s3c_fb_platdata *pdata;
struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
@@ -441,6 +443,39 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
}
/**
+ * s3c_fb_enable() - Set the state of the main LCD output
+ * @sfb: The main framebuffer state.
+ * @enable: The state to set.
+ */
+static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
+{
+ u32 vidcon0 = readl(sfb->regs + VIDCON0);
+
+ if (enable && !sfb->output_on)
+ pm_runtime_get_sync(sfb->dev);
+
+ if (enable) {
+ vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
+ } else {
+ /* see the note in the framebuffer datasheet about
+ * why you cannot take both of these bits down at the
+ * same time. */
+
+ if (vidcon0 & VIDCON0_ENVID) {
+ vidcon0 |= VIDCON0_ENVID;
+ vidcon0 &= ~VIDCON0_ENVID_F;
+ }
+ }
+
+ writel(vidcon0, sfb->regs + VIDCON0);
+
+ if (!enable && sfb->output_on)
+ pm_runtime_put_sync(sfb->dev);
+
+ sfb->output_on = enable;
+}
+
+/**
* s3c_fb_set_par() - framebuffer request to set new framebuffer state.
* @info: The framebuffer to change.
*
@@ -461,6 +496,8 @@ static int s3c_fb_set_par(struct fb_info *info)
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
+ pm_runtime_get_sync(sfb->dev);
+
shadow_protect_win(win, 1);
switch (var->bits_per_pixel) {
@@ -510,9 +547,10 @@ static int s3c_fb_set_par(struct fb_info *info)
if (sfb->variant.is_2443)
data |= (1 << 5);
- data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
writel(data, regs + VIDCON0);
+ s3c_fb_enable(sfb, 1);
+
data = VIDTCON0_VBPD(var->upper_margin - 1) |
VIDTCON0_VFPD(var->lower_margin - 1) |
VIDTCON0_VSPW(var->vsync_len - 1);
@@ -574,6 +612,7 @@ static int s3c_fb_set_par(struct fb_info *info)
}
data = WINCONx_ENWIN;
+ sfb->enabled |= (1 << win->index);
/* note, since we have to round up the bits-per-pixel, we end up
* relying on the bitfield information for r/g/b/a to work out
@@ -621,7 +660,8 @@ static int s3c_fb_set_par(struct fb_info *info)
} else if (var->transp.length == 1)
data |= WINCON1_BPPMODE_25BPP_A1888
| WINCON1_BLD_PIX;
- else if (var->transp.length == 4)
+ else if ((var->transp.length == 4) ||
+ (var->transp.length == 8))
data |= WINCON1_BPPMODE_28BPP_A4888
| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
else
@@ -654,6 +694,8 @@ static int s3c_fb_set_par(struct fb_info *info)
shadow_protect_win(win, 0);
+ pm_runtime_put_sync(sfb->dev);
+
return 0;
}
@@ -725,6 +767,8 @@ static int s3c_fb_setcolreg(unsigned regno,
dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
__func__, win->index, regno, red, green, blue);
+ pm_runtime_get_sync(sfb->dev);
+
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
/* true-colour, use pseudo-palette */
@@ -752,39 +796,15 @@ static int s3c_fb_setcolreg(unsigned regno,
break;
default:
+ pm_runtime_put_sync(sfb->dev);
return 1; /* unknown type */
}
+ pm_runtime_put_sync(sfb->dev);
return 0;
}
/**
- * s3c_fb_enable() - Set the state of the main LCD output
- * @sfb: The main framebuffer state.
- * @enable: The state to set.
- */
-static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
-{
- u32 vidcon0 = readl(sfb->regs + VIDCON0);
-
- if (enable)
- vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
- else {
- /* see the note in the framebuffer datasheet about
- * why you cannot take both of these bits down at the
- * same time. */
-
- if (!(vidcon0 & VIDCON0_ENVID))
- return;
-
- vidcon0 |= VIDCON0_ENVID;
- vidcon0 &= ~VIDCON0_ENVID_F;
- }
-
- writel(vidcon0, sfb->regs + VIDCON0);
-}
-
-/**
* s3c_fb_blank() - blank or unblank the given window
* @blank_mode: The blank state from FB_BLANK_*
* @info: The framebuffer to blank.
@@ -800,6 +820,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
+ pm_runtime_get_sync(sfb->dev);
+
wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
switch (blank_mode) {
@@ -810,12 +832,16 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_NORMAL:
/* disable the DMA and display 0x0 (black) */
+ shadow_protect_win(win, 1);
writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
sfb->regs + sfb->variant.winmap + (index * 4));
+ shadow_protect_win(win, 0);
break;
case FB_BLANK_UNBLANK:
+ shadow_protect_win(win, 1);
writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
+ shadow_protect_win(win, 0);
wincon |= WINCONx_ENWIN;
sfb->enabled |= (1 << index);
break;
@@ -823,10 +849,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
default:
+ pm_runtime_put_sync(sfb->dev);
return 1;
}
+ shadow_protect_win(win, 1);
writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
+ shadow_protect_win(win, 0);
/* Check the enabled state to see if we need to be running the
* main LCD interface, as if there are no active windows then
@@ -845,8 +874,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
/* we're stuck with this until we can do something about overriding
* the power control using the blanking event for a single fb.
*/
- if (index == sfb->pdata->default_win)
+ if (index == sfb->pdata->default_win) {
+ shadow_protect_win(win, 1);
s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
+ shadow_protect_win(win, 0);
+ }
+
+ pm_runtime_put_sync(sfb->dev);
return 0;
}
@@ -870,6 +904,8 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
void __iomem *buf = sfb->regs + win->index * 8;
unsigned int start_boff, end_boff;
+ pm_runtime_get_sync(sfb->dev);
+
/* Offset in bytes to the start of the displayed area */
start_boff = var->yoffset * info->fix.line_length;
/* X offset depends on the current bpp */
@@ -888,6 +924,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
break;
default:
dev_err(sfb->dev, "invalid bpp\n");
+ pm_runtime_put_sync(sfb->dev);
return -EINVAL;
}
}
@@ -903,6 +940,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
shadow_protect_win(win, 0);
+ pm_runtime_put_sync(sfb->dev);
return 0;
}
@@ -992,11 +1030,16 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
if (crtc != 0)
return -ENODEV;
+ pm_runtime_get_sync(sfb->dev);
+
count = sfb->vsync_info.count;
s3c_fb_enable_irq(sfb);
ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
count != sfb->vsync_info.count,
msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
+
+ pm_runtime_put_sync(sfb->dev);
+
if (ret == 0)
return -ETIMEDOUT;
@@ -1027,30 +1070,8 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
return ret;
}
-static int s3c_fb_open(struct fb_info *info, int user)
-{
- struct s3c_fb_win *win = info->par;
- struct s3c_fb *sfb = win->parent;
-
- pm_runtime_get_sync(sfb->dev);
-
- return 0;
-}
-
-static int s3c_fb_release(struct fb_info *info, int user)
-{
- struct s3c_fb_win *win = info->par;
- struct s3c_fb *sfb = win->parent;
-
- pm_runtime_put_sync(sfb->dev);
-
- return 0;
-}
-
static struct fb_ops s3c_fb_ops = {
.owner = THIS_MODULE,
- .fb_open = s3c_fb_open,
- .fb_release = s3c_fb_release,
.fb_check_var = s3c_fb_check_var,
.fb_set_par = s3c_fb_set_par,
.fb_blank = s3c_fb_blank,
@@ -1452,7 +1473,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
dev_err(dev, "failed to create window %d\n", win);
for (; win >= 0; win--)
s3c_fb_release_win(sfb, sfb->windows[win]);
- goto err_irq;
+ goto err_pm_runtime;
}
}
@@ -1461,7 +1482,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
return 0;
-err_irq:
+err_pm_runtime:
+ pm_runtime_put_sync(sfb->dev);
free_irq(sfb->irq_no, sfb);
err_ioremap:
@@ -1471,6 +1493,8 @@ err_req_region:
release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
err_lcd_clk:
+ pm_runtime_disable(sfb->dev);
+
if (!sfb->variant.has_clksel) {
clk_disable(sfb->lcd_clk);
clk_put(sfb->lcd_clk);
@@ -1524,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int s3c_fb_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1571,10 +1595,15 @@ static int s3c_fb_resume(struct device *dev)
for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
void __iomem *regs = sfb->regs + sfb->variant.keycon;
+ win = sfb->windows[win_no];
+ if (!win)
+ continue;
+ shadow_protect_win(win, 1);
regs += (win_no * 8);
writel(0xffffff, regs + WKEYCON0);
writel(0xffffff, regs + WKEYCON1);
+ shadow_protect_win(win, 0);
}
/* restore framebuffers */
@@ -1589,27 +1618,19 @@ static int s3c_fb_resume(struct device *dev)
return 0;
}
+#endif
+#ifdef CONFIG_PM_RUNTIME
static int s3c_fb_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c_fb *sfb = platform_get_drvdata(pdev);
- struct s3c_fb_win *win;
- int win_no;
-
- for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
- win = sfb->windows[win_no];
- if (!win)
- continue;
-
- /* use the blank function to push into power-down */
- s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
- }
if (!sfb->variant.has_clksel)
clk_disable(sfb->lcd_clk);
clk_disable(sfb->bus_clk);
+
return 0;
}
@@ -1618,8 +1639,6 @@ static int s3c_fb_runtime_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct s3c_fb *sfb = platform_get_drvdata(pdev);
struct s3c_fb_platdata *pd = sfb->pdata;
- struct s3c_fb_win *win;
- int win_no;
clk_enable(sfb->bus_clk);
@@ -1630,39 +1649,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
- /* zero all windows before we do anything */
- for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
- s3c_fb_clear_win(sfb, win_no);
-
- for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
- void __iomem *regs = sfb->regs + sfb->variant.keycon;
-
- regs += (win_no * 8);
- writel(0xffffff, regs + WKEYCON0);
- writel(0xffffff, regs + WKEYCON1);
- }
-
- /* restore framebuffers */
- for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
- win = sfb->windows[win_no];
- if (!win)
- continue;
-
- dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
- s3c_fb_set_par(win->fbinfo);
- }
-
return 0;
}
-
-#else
-#define s3c_fb_suspend NULL
-#define s3c_fb_resume NULL
-#define s3c_fb_runtime_suspend NULL
-#define s3c_fb_runtime_resume NULL
#endif
-
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1985,10 +1975,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
static const struct dev_pm_ops s3cfb_pm_ops = {
- .suspend = s3c_fb_suspend,
- .resume = s3c_fb_resume,
- .runtime_suspend = s3c_fb_runtime_suspend,
- .runtime_resume = s3c_fb_runtime_resume,
+ SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
+ SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
+ NULL)
};
static struct platform_driver s3c_fb_driver = {
@@ -2002,18 +1991,7 @@ static struct platform_driver s3c_fb_driver = {
},
};
-static int __init s3c_fb_init(void)
-{
- return platform_driver_register(&s3c_fb_driver);
-}
-
-static void __exit s3c_fb_cleanup(void)
-{
- platform_driver_unregister(&s3c_fb_driver);
-}
-
-module_init(s3c_fb_init);
-module_exit(s3c_fb_cleanup);
+module_platform_driver(s3c_fb_driver);
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ee4c0df..77f34c6 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -26,8 +26,8 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/div64.h>
#include <asm/mach/map.h>
@@ -45,10 +45,10 @@
#ifdef CONFIG_FB_S3C2410_DEBUG
static int debug = 1;
#else
-static int debug = 0;
+static int debug;
#endif
-#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
+#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
/* useful functions */
@@ -567,11 +567,10 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
- if (blank_mode == FB_BLANK_POWERDOWN) {
+ if (blank_mode == FB_BLANK_POWERDOWN)
s3c2410fb_lcd_enable(fbi, 0);
- } else {
+ else
s3c2410fb_lcd_enable(fbi, 1);
- }
if (blank_mode == FB_BLANK_UNBLANK)
writel(0x0, tpal_reg);
@@ -812,7 +811,7 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
#endif
-static char driver_name[] = "s3c2410fb";
+static const char driver_name[] = "s3c2410fb";
static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
enum s3c_drv_type drv_type)
@@ -881,7 +880,10 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
goto release_mem;
}
- info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
+ if (drv_type == DRV_S3C2412)
+ info->irq_base = info->io + S3C2412_LCDINTBASE;
+ else
+ info->irq_base = info->io + S3C2410_LCDINTBASE;
dprintk("devinit\n");
@@ -927,7 +929,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
clk_enable(info->clk);
dprintk("got and enabled clock\n");
- msleep(1);
+ usleep_range(1000, 1000);
info->clk_rate = clk_get_rate(info->clk);
@@ -975,9 +977,8 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
/* create device files */
ret = device_create_file(&pdev->dev, &dev_attr_debug);
- if (ret) {
+ if (ret)
printk(KERN_ERR "failed to add debug attribute\n");
- }
printk(KERN_INFO "fb%d: %s frame buffer device\n",
fbinfo->node, fbinfo->fix.id);
@@ -1027,7 +1028,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
s3c2410fb_cpufreq_deregister(info);
s3c2410fb_lcd_enable(info, 0);
- msleep(1);
+ usleep_range(1000, 1000);
s3c2410fb_unmap_video_memory(fbinfo);
@@ -1064,7 +1065,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
* the LCD DMA engine is not going to get back on the bus
* before the clock goes off again (bjd) */
- msleep(1);
+ usleep_range(1000, 1000);
clk_disable(info->clk);
return 0;
@@ -1076,7 +1077,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
struct s3c2410fb_info *info = fbinfo->par;
clk_enable(info->clk);
- msleep(1);
+ usleep_range(1000, 1000);
s3c2410fb_init_registers(fbinfo);
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 946a949..2c80246 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -727,7 +727,7 @@ static int s3fb_set_par(struct fb_info *info)
if (par->chip == CHIP_988_VIRGE_VX) {
vga_wcrt(par->state.vgabase, 0x50, 0x00);
vga_wcrt(par->state.vgabase, 0x67, 0x50);
-
+ msleep(10); /* screen remains blank sometimes without this */
vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
vga_wcrt(par->state.vgabase, 0x66, 0x90);
}
@@ -901,7 +901,8 @@ static int s3fb_set_par(struct fb_info *info)
/* Set Data Transfer Position */
hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
- value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1);
+ /* + 2 is needed for Virge/VX, does no harm on other cards */
+ value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
memset_io(info->screen_base, 0x00, screen_size);
@@ -1216,6 +1217,31 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
info->screen_size = 2 << 20;
break;
}
+ } else if (par->chip == CHIP_988_VIRGE_VX) {
+ switch ((regval & 0x60) >> 5) {
+ case 0: /* 2MB */
+ info->screen_size = 2 << 20;
+ break;
+ case 1: /* 4MB */
+ info->screen_size = 4 << 20;
+ break;
+ case 2: /* 6MB */
+ info->screen_size = 6 << 20;
+ break;
+ case 3: /* 8MB */
+ info->screen_size = 8 << 20;
+ break;
+ }
+ /* off-screen memory */
+ regval = vga_rcrt(par->state.vgabase, 0x37);
+ switch ((regval & 0x60) >> 5) {
+ case 1: /* 4MB */
+ info->screen_size -= 4 << 20;
+ break;
+ case 2: /* 2MB */
+ info->screen_size -= 2 << 20;
+ break;
+ }
} else
info->screen_size = s3_memsizes[regval >> 5] << 10;
info->fix.smem_len = info->screen_size;
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 37d764a..3c1de98 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -76,7 +76,7 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
map_offset = (physbase + map[i].poff) & POFF_MASK;
break;
}
- if (!map_size){
+ if (!map_size) {
page += PAGE_SIZE;
continue;
}
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 45e47d8..83b16e2 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -585,18 +585,7 @@ static struct platform_driver sh7760_lcdc_driver = {
.remove = __devexit_p(sh7760fb_remove),
};
-static int __init sh7760fb_init(void)
-{
- return platform_driver_register(&sh7760_lcdc_driver);
-}
-
-static void __exit sh7760fb_exit(void)
-{
- platform_driver_unregister(&sh7760_lcdc_driver);
-}
-
-module_init(sh7760fb_init);
-module_exit(sh7760fb_exit);
+module_platform_driver(sh7760_lcdc_driver);
MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 72ee96b..05151b8 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/bitmap.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -41,6 +42,7 @@
#define VMCTR1 0x0020
#define VMCTR2 0x0024
#define VMLEN1 0x0028
+#define VMLEN2 0x002c
#define CMTSRTREQ 0x0070
#define CMTSRTCTR 0x00d0
@@ -51,8 +53,7 @@ struct sh_mipi {
void __iomem *base;
void __iomem *linkbase;
struct clk *dsit_clk;
- struct clk *dsip_clk;
- struct device *dev;
+ struct platform_device *pdev;
void *next_board_data;
void (*next_display_on)(void *board_data, struct fb_info *info);
@@ -124,35 +125,15 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
sh_mipi_dsi_enable(mipi, false);
}
-static void mipi_display_on(void *arg, struct fb_info *info)
-{
- struct sh_mipi *mipi = arg;
-
- pm_runtime_get_sync(mipi->dev);
- sh_mipi_dsi_enable(mipi, true);
-
- if (mipi->next_display_on)
- mipi->next_display_on(mipi->next_board_data, info);
-}
-
-static void mipi_display_off(void *arg)
-{
- struct sh_mipi *mipi = arg;
-
- if (mipi->next_display_off)
- mipi->next_display_off(mipi->next_board_data);
-
- sh_mipi_dsi_enable(mipi, false);
- pm_runtime_put(mipi->dev);
-}
-
static int __init sh_mipi_setup(struct sh_mipi *mipi,
struct sh_mipi_dsi_info *pdata)
{
void __iomem *base = mipi->base;
struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
- u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000;
+ u32 pctype, datatype, pixfmt, linelength, vmctr2;
+ u32 tmp, top, bottom, delay, div;
bool yuv;
+ int bpp;
/*
* Select data format. MIPI DSI is not hot-pluggable, so, we just use
@@ -253,6 +234,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
(!yuv && ch->interface_type != RGB24))
return -EINVAL;
+ if (!pdata->lane)
+ return -EINVAL;
+
/* reset DSI link */
iowrite32(0x00000001, base + SYSCTRL);
/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
@@ -262,15 +246,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
/* setup DSI link */
/*
- * Default = ULPS enable |
- * Contention detection enabled |
- * EoT packet transmission enable |
- * CRC check enable |
- * ECC check enable
- * additionally enable first two lanes
- */
- iowrite32(0x00003703, base + SYSCONF);
- /*
* T_wakeup = 0x7000
* T_hs-trail = 3
* T_hs-prepare = 3
@@ -290,15 +265,24 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
iowrite32(0x0fffffff, base + TATOVSET);
/* Peripheral reset timeout, default 0xffffffff */
iowrite32(0x0fffffff, base + PRTOVSET);
- /* Enable timeout counters */
- iowrite32(0x00000f00, base + DSICTRL);
/* Interrupts not used, disable all */
iowrite32(0, base + DSIINTE);
/* DSI-Tx bias on */
iowrite32(0x00000001, base + PHYCTRL);
udelay(200);
- /* Deassert resets, power on, set multiplier */
- iowrite32(0x03070b01, base + PHYCTRL);
+ /* Deassert resets, power on */
+ iowrite32(0x03070001, base + PHYCTRL);
+
+ /*
+ * Default = ULPS enable |
+ * Contention detection enabled |
+ * EoT packet transmission enable |
+ * CRC check enable |
+ * ECC check enable
+ */
+ bitmap_fill((unsigned long *)&tmp, pdata->lane);
+ tmp |= 0x00003700;
+ iowrite32(tmp, base + SYSCONF);
/* setup l-bridge */
@@ -316,18 +300,68 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
* Non-burst mode with sync pulses: VSE and HSE are output,
* HSA period allowed, no commands in LP
*/
+ vmctr2 = 0;
+ if (pdata->flags & SH_MIPI_DSI_VSEE)
+ vmctr2 |= 1 << 23;
+ if (pdata->flags & SH_MIPI_DSI_HSEE)
+ vmctr2 |= 1 << 22;
+ if (pdata->flags & SH_MIPI_DSI_HSAE)
+ vmctr2 |= 1 << 21;
+ if (pdata->flags & SH_MIPI_DSI_BL2E)
+ vmctr2 |= 1 << 17;
if (pdata->flags & SH_MIPI_DSI_HSABM)
- vmctr2 |= 0x20;
- if (pdata->flags & SH_MIPI_DSI_HSPBM)
- vmctr2 |= 0x10;
+ vmctr2 |= 1 << 5;
+ if (pdata->flags & SH_MIPI_DSI_HBPBM)
+ vmctr2 |= 1 << 4;
+ if (pdata->flags & SH_MIPI_DSI_HFPBM)
+ vmctr2 |= 1 << 3;
iowrite32(vmctr2, mipi->linkbase + VMCTR2);
/*
- * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
- * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
- * (unused if VMCTR2[HSABM] = 0)
+ * VMLEN1 = RGBLEN | HSALEN
+ *
+ * see
+ * Video mode - Blanking Packet setting
+ */
+ top = linelength << 16; /* RGBLEN */
+ bottom = 0x00000001;
+ if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
+ bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10;
+ iowrite32(top | bottom , mipi->linkbase + VMLEN1);
+
+ /*
+ * VMLEN2 = HBPLEN | HFPLEN
+ *
+ * see
+ * Video mode - Blanking Packet setting
*/
- iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1);
+ top = 0x00010000;
+ bottom = 0x00000001;
+ delay = 0;
+
+ div = 1; /* HSbyteCLK is calculation base
+ * HS4divCLK = HSbyteCLK/2
+ * HS6divCLK is not supported for now */
+ if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
+ div = 2;
+
+ if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
+ top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin;
+ top = ((pdata->lane * top / div) - 10) << 16;
+ }
+ if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
+ bottom = ch->lcd_cfg[0].right_margin;
+ bottom = (pdata->lane * bottom / div) - 12;
+ }
+
+ bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */
+ if ((pdata->lane / div) > bpp) {
+ tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */
+ tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */
+ delay = (pdata->lane * tmp);
+ }
+
+ iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
msleep(5);
@@ -352,9 +386,56 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
pixfmt << 4);
sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
+ /* Enable timeout counters */
+ iowrite32(0x00000f00, base + DSICTRL);
+
return 0;
}
+static void mipi_display_on(void *arg, struct fb_info *info)
+{
+ struct sh_mipi *mipi = arg;
+ struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
+ int ret;
+
+ pm_runtime_get_sync(&mipi->pdev->dev);
+
+ ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
+ if (ret < 0)
+ goto mipi_display_on_fail1;
+
+ ret = sh_mipi_setup(mipi, pdata);
+ if (ret < 0)
+ goto mipi_display_on_fail2;
+
+ sh_mipi_dsi_enable(mipi, true);
+
+ if (mipi->next_display_on)
+ mipi->next_display_on(mipi->next_board_data, info);
+
+ return;
+
+mipi_display_on_fail1:
+ pm_runtime_put_sync(&mipi->pdev->dev);
+mipi_display_on_fail2:
+ pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
+}
+
+static void mipi_display_off(void *arg)
+{
+ struct sh_mipi *mipi = arg;
+ struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
+
+ if (mipi->next_display_off)
+ mipi->next_display_off(mipi->next_board_data);
+
+ sh_mipi_dsi_enable(mipi, false);
+
+ pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
+
+ pm_runtime_put_sync(&mipi->pdev->dev);
+}
+
static int __init sh_mipi_probe(struct platform_device *pdev)
{
struct sh_mipi *mipi;
@@ -363,11 +444,13 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
unsigned long rate, f_current;
int idx = pdev->id, ret;
- char dsip_clk[] = "dsi.p_clk";
if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
return -ENODEV;
+ if (!pdata->set_dot_clock)
+ return -EINVAL;
+
mutex_lock(&array_lock);
if (idx < 0)
for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
@@ -408,7 +491,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
goto emap2;
}
- mipi->dev = &pdev->dev;
+ mipi->pdev = pdev;
mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
if (IS_ERR(mipi->dsit_clk)) {
@@ -428,44 +511,15 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
- sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
- mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
- if (IS_ERR(mipi->dsip_clk)) {
- ret = PTR_ERR(mipi->dsip_clk);
- goto eclkpget;
- }
-
- f_current = clk_get_rate(mipi->dsip_clk);
- /* Between 10 and 50MHz */
- rate = clk_round_rate(mipi->dsip_clk, 24000000);
- if (rate > 0 && rate != f_current)
- ret = clk_set_rate(mipi->dsip_clk, rate);
- else
- ret = rate;
- if (ret < 0)
- goto esetprate;
-
- dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
-
- msleep(10);
-
ret = clk_enable(mipi->dsit_clk);
if (ret < 0)
goto eclkton;
- ret = clk_enable(mipi->dsip_clk);
- if (ret < 0)
- goto eclkpon;
-
mipi_dsi[idx] = mipi;
pm_runtime_enable(&pdev->dev);
pm_runtime_resume(&pdev->dev);
- ret = sh_mipi_setup(mipi, pdata);
- if (ret < 0)
- goto emipisetup;
-
mutex_unlock(&array_lock);
platform_set_drvdata(pdev, mipi);
@@ -482,16 +536,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
return 0;
-emipisetup:
- mipi_dsi[idx] = NULL;
- pm_runtime_disable(&pdev->dev);
- clk_disable(mipi->dsip_clk);
-eclkpon:
- clk_disable(mipi->dsit_clk);
eclkton:
-esetprate:
- clk_put(mipi->dsip_clk);
-eclkpget:
esettrate:
clk_put(mipi->dsit_clk);
eclktget:
@@ -542,10 +587,9 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
pdata->lcd_chan->board_cfg.board_data = NULL;
pm_runtime_disable(&pdev->dev);
- clk_disable(mipi->dsip_clk);
clk_disable(mipi->dsit_clk);
clk_put(mipi->dsit_clk);
- clk_put(mipi->dsip_clk);
+
iounmap(mipi->linkbase);
if (res2)
release_mem_region(res2->start, resource_size(res2));
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index facffc2..aac5b36 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
@@ -102,7 +103,7 @@ struct sh_mobile_lcdc_priv {
struct sh_mobile_lcdc_chan ch[2];
struct notifier_block notifier;
int started;
- int forced_bpp; /* 2 channel LCDC must share bpp setting */
+ int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
struct sh_mobile_meram_info *meram_dev;
};
@@ -215,6 +216,47 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
lcdc_sys_read_data,
};
+static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
+{
+ if (var->grayscale > 1)
+ return var->grayscale;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ return V4L2_PIX_FMT_RGB565;
+ case 24:
+ return V4L2_PIX_FMT_BGR24;
+ case 32:
+ return V4L2_PIX_FMT_BGR32;
+ default:
+ return 0;
+ }
+}
+
+static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
+{
+ return var->grayscale > 1;
+}
+
+static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
+{
+ if (var->grayscale <= 1)
+ return false;
+
+ switch (var->grayscale) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
{
if (atomic_inc_and_test(&priv->hw_usecnt)) {
@@ -420,7 +462,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
tmp = ((display_var->xres & 7) << 24) |
((display_h_total & 7) << 16) |
((display_var->hsync_len & 7) << 8) |
- hsync_pos;
+ (hsync_pos & 7);
lcdc_write_chan(ch, LDHAJR, tmp);
}
@@ -435,7 +477,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
{
struct sh_mobile_lcdc_chan *ch;
unsigned long tmp;
- int bpp = 0;
int k, m;
/* Enable LCDC channels. Read data from external memory, avoid using the
@@ -454,9 +495,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
if (!ch->enabled)
continue;
- if (!bpp)
- bpp = ch->info->var.bits_per_pixel;
-
/* Power supply */
lcdc_write_chan(ch, LDPMR, 0);
@@ -487,31 +525,37 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
sh_mobile_lcdc_geometry(ch);
- if (ch->info->var.nonstd) {
- tmp = (ch->info->var.nonstd << 16);
- switch (ch->info->var.bits_per_pixel) {
- case 12:
- tmp |= LDDFR_YF_420;
- break;
- case 16:
- tmp |= LDDFR_YF_422;
- break;
- case 24:
- default:
- tmp |= LDDFR_YF_444;
- break;
- }
- } else {
- switch (ch->info->var.bits_per_pixel) {
- case 16:
- tmp = LDDFR_PKF_RGB16;
- break;
- case 24:
- tmp = LDDFR_PKF_RGB24;
+ switch (sh_mobile_format_fourcc(&ch->info->var)) {
+ case V4L2_PIX_FMT_RGB565:
+ tmp = LDDFR_PKF_RGB16;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ tmp = LDDFR_PKF_RGB24;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ tmp = LDDFR_PKF_ARGB32;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ tmp = LDDFR_CC | LDDFR_YF_420;
+ break;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ tmp = LDDFR_CC | LDDFR_YF_422;
+ break;
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ tmp = LDDFR_CC | LDDFR_YF_444;
+ break;
+ }
+
+ if (sh_mobile_format_is_yuv(&ch->info->var)) {
+ switch (ch->info->var.colorspace) {
+ case V4L2_COLORSPACE_REC709:
+ tmp |= LDDFR_CF1;
break;
- case 32:
- default:
- tmp = LDDFR_PKF_ARGB32;
+ case V4L2_COLORSPACE_JPEG:
+ tmp |= LDDFR_CF0;
break;
}
}
@@ -519,7 +563,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
lcdc_write_chan(ch, LDDFR, tmp);
lcdc_write_chan(ch, LDMLSR, ch->pitch);
lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
- if (ch->info->var.nonstd)
+ if (sh_mobile_format_is_yuv(&ch->info->var))
lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
/* When using deferred I/O mode, configure the LCDC for one-shot
@@ -536,21 +580,23 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
}
/* Word and long word swap. */
- if (priv->ch[0].info->var.nonstd)
+ switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) {
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV42:
+ tmp = LDDDSR_LS | LDDDSR_WS;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV24:
tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
- else {
- switch (bpp) {
- case 16:
- tmp = LDDDSR_LS | LDDDSR_WS;
- break;
- case 24:
- tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
- break;
- case 32:
- default:
- tmp = LDDDSR_LS;
- break;
- }
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ default:
+ tmp = LDDDSR_LS;
+ break;
}
lcdc_write(priv, _LDDDSR, tmp);
@@ -622,12 +668,24 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
ch->meram_enabled = 0;
}
- if (!ch->info->var.nonstd)
- pixelformat = SH_MOBILE_MERAM_PF_RGB;
- else if (ch->info->var.bits_per_pixel == 24)
- pixelformat = SH_MOBILE_MERAM_PF_NV24;
- else
+ switch (sh_mobile_format_fourcc(&ch->info->var)) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
pixelformat = SH_MOBILE_MERAM_PF_NV;
+ break;
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ pixelformat = SH_MOBILE_MERAM_PF_NV24;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_BGR32:
+ default:
+ pixelformat = SH_MOBILE_MERAM_PF_RGB;
+ break;
+ }
ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
ch->info->var.yres, pixelformat,
@@ -845,6 +903,7 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
.xpanstep = 0,
.ypanstep = 1,
.ywrapstep = 0,
+ .capabilities = FB_CAP_FOURCC,
};
static void sh_mobile_lcdc_fillrect(struct fb_info *info,
@@ -877,8 +936,9 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
unsigned long new_pan_offset;
unsigned long base_addr_y, base_addr_c;
unsigned long c_offset;
+ bool yuv = sh_mobile_format_is_yuv(&info->var);
- if (!info->var.nonstd)
+ if (!yuv)
new_pan_offset = var->yoffset * info->fix.line_length
+ var->xoffset * (info->var.bits_per_pixel / 8);
else
@@ -892,7 +952,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
/* Set the source address for the next refresh */
base_addr_y = ch->dma_handle + new_pan_offset;
- if (info->var.nonstd) {
+ if (yuv) {
/* Set y offset */
c_offset = var->yoffset * info->fix.line_length
* (info->var.bits_per_pixel - 8) / 8;
@@ -900,7 +960,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+ info->var.xres * info->var.yres_virtual
+ c_offset;
/* Set x offset */
- if (info->var.bits_per_pixel == 24)
+ if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24)
base_addr_c += 2 * var->xoffset;
else
base_addr_c += var->xoffset;
@@ -924,7 +984,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
ch->base_addr_c = base_addr_c;
lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
- if (info->var.nonstd)
+ if (yuv)
lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
if (lcdc_chan_is_sublcd(ch))
@@ -1100,51 +1160,84 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
- if (var->bits_per_pixel <= 16) { /* RGB 565 */
- var->bits_per_pixel = 16;
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
- var->bits_per_pixel = 24;
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
- var->bits_per_pixel = 32;
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- } else
- return -EINVAL;
+ if (sh_mobile_format_is_fourcc(var)) {
+ switch (var->grayscale) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ var->bits_per_pixel = 12;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ var->bits_per_pixel = 16;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ var->bits_per_pixel = 24;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ var->bits_per_pixel = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
+ /* Default to RGB and JPEG color-spaces for RGB and YUV formats
+ * respectively.
+ */
+ if (!sh_mobile_format_is_yuv(var))
+ var->colorspace = V4L2_COLORSPACE_SRGB;
+ else if (var->colorspace != V4L2_COLORSPACE_REC709)
+ var->colorspace = V4L2_COLORSPACE_JPEG;
+ } else {
+ if (var->bits_per_pixel <= 16) { /* RGB 565 */
+ var->bits_per_pixel = 16;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
+ var->bits_per_pixel = 24;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
+ var->bits_per_pixel = 32;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ } else
+ return -EINVAL;
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ }
/* Make sure we don't exceed our allocated memory. */
if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
info->fix.smem_len)
return -EINVAL;
- /* only accept the forced_bpp for dual channel configurations */
- if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
+ /* only accept the forced_fourcc for dual channel configurations */
+ if (p->forced_fourcc &&
+ p->forced_fourcc != sh_mobile_format_fourcc(var))
return -EINVAL;
return 0;
@@ -1158,7 +1251,7 @@ static int sh_mobile_set_par(struct fb_info *info)
sh_mobile_lcdc_stop(ch->lcdc);
- if (info->var.nonstd)
+ if (sh_mobile_format_is_yuv(&info->var))
info->fix.line_length = info->var.xres;
else
info->fix.line_length = info->var.xres
@@ -1170,6 +1263,14 @@ static int sh_mobile_set_par(struct fb_info *info)
info->fix.line_length = line_length;
}
+ if (sh_mobile_format_is_fourcc(&info->var)) {
+ info->fix.type = FB_TYPE_FOURCC;
+ info->fix.visual = FB_VISUAL_FOURCC;
+ } else {
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ }
+
return ret;
}
@@ -1464,9 +1565,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
unsigned int size = mode->yres * mode->xres;
- /* NV12 buffers must have even number of lines */
- if ((cfg->nonstd) && cfg->bpp == 12 &&
- (mode->yres & 0x1)) {
+ /* NV12/NV21 buffers must have even number of lines */
+ if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
+ cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
"mode.\n");
return -EINVAL;
@@ -1484,14 +1585,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
dev_dbg(dev, "Found largest videomode %ux%u\n",
max_mode->xres, max_mode->yres);
- /* Initialize fixed screen information. Restrict pan to 2 lines steps
- * for NV12.
- */
- info->fix = sh_mobile_lcdc_fix;
- info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
- if (cfg->nonstd && cfg->bpp == 12)
- info->fix.ypanstep = 2;
-
/* Create the mode list. */
if (cfg->lcd_cfg == NULL) {
mode = &default_720p;
@@ -1509,19 +1602,38 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
*/
var = &info->var;
fb_videomode_to_var(var, mode);
- var->bits_per_pixel = cfg->bpp;
var->width = cfg->lcd_size_cfg.width;
var->height = cfg->lcd_size_cfg.height;
var->yres_virtual = var->yres * 2;
var->activate = FB_ACTIVATE_NOW;
+ switch (cfg->fourcc) {
+ case V4L2_PIX_FMT_RGB565:
+ var->bits_per_pixel = 16;
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ var->bits_per_pixel = 24;
+ break;
+ case V4L2_PIX_FMT_BGR32:
+ var->bits_per_pixel = 32;
+ break;
+ default:
+ var->grayscale = cfg->fourcc;
+ break;
+ }
+
+ /* Make sure the memory size check won't fail. smem_len is initialized
+ * later based on var.
+ */
+ info->fix.smem_len = UINT_MAX;
ret = sh_mobile_check_var(var, info);
if (ret)
return ret;
+ max_size = max_size * var->bits_per_pixel / 8 * 2;
+
/* Allocate frame buffer memory and color map. */
- buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
- GFP_KERNEL);
+ buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL);
if (!buf) {
dev_err(dev, "unable to allocate buffer\n");
return -ENOMEM;
@@ -1530,16 +1642,27 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
if (ret < 0) {
dev_err(dev, "unable to allocate cmap\n");
- dma_free_coherent(dev, info->fix.smem_len,
- buf, ch->dma_handle);
+ dma_free_coherent(dev, max_size, buf, ch->dma_handle);
return ret;
}
+ /* Initialize fixed screen information. Restrict pan to 2 lines steps
+ * for NV12 and NV21.
+ */
+ info->fix = sh_mobile_lcdc_fix;
info->fix.smem_start = ch->dma_handle;
- if (var->nonstd)
+ info->fix.smem_len = max_size;
+ if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
+ cfg->fourcc == V4L2_PIX_FMT_NV21)
+ info->fix.ypanstep = 2;
+
+ if (sh_mobile_format_is_yuv(var)) {
info->fix.line_length = var->xres;
- else
- info->fix.line_length = var->xres * (cfg->bpp / 8);
+ info->fix.visual = FB_VISUAL_FOURCC;
+ } else {
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ }
info->screen_base = buf;
info->device = dev;
@@ -1626,9 +1749,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
goto err1;
}
- /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
+ /* for dual channel LCDC (MAIN + SUB) force shared format setting */
if (num_channels == 2)
- priv->forced_bpp = pdata->ch[0].bpp;
+ priv->forced_fourcc = pdata->ch[0].fourcc;
priv->base = ioremap_nocache(res->start, resource_size(res));
if (!priv->base)
@@ -1675,13 +1798,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
if (error < 0)
goto err1;
- dev_info(info->dev,
- "registered %s/%s as %dx%d %dbpp.\n",
- pdev->name,
- (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
- "mainlcd" : "sublcd",
- info->var.xres, info->var.yres,
- ch->cfg.bpp);
+ dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
+ pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
+ "mainlcd" : "sublcd", info->var.xres, info->var.yres,
+ info->var.bits_per_pixel);
/* deferred io mode: disable clock to save power */
if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
@@ -1709,18 +1829,7 @@ static struct platform_driver sh_mobile_lcdc_driver = {
.remove = sh_mobile_lcdc_remove,
};
-static int __init sh_mobile_lcdc_init(void)
-{
- return platform_driver_register(&sh_mobile_lcdc_driver);
-}
-
-static void __exit sh_mobile_lcdc_exit(void)
-{
- platform_driver_unregister(&sh_mobile_lcdc_driver);
-}
-
-module_init(sh_mobile_lcdc_init);
-module_exit(sh_mobile_lcdc_exit);
+module_platform_driver(sh_mobile_lcdc_driver);
MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 4d63490..f45d83e 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -679,18 +679,7 @@ static struct platform_driver sh_mobile_meram_driver = {
.remove = sh_mobile_meram_remove,
};
-static int __init sh_mobile_meram_init(void)
-{
- return platform_driver_register(&sh_mobile_meram_driver);
-}
-
-static void __exit sh_mobile_meram_exit(void)
-{
- platform_driver_unregister(&sh_mobile_meram_driver);
-}
-
-module_init(sh_mobile_meram_init);
-module_exit(sh_mobile_meram_exit);
+module_platform_driver(sh_mobile_meram_driver);
MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index a78254c..3690eff 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -2230,18 +2230,7 @@ static struct platform_driver sm501fb_driver = {
},
};
-static int __devinit sm501fb_init(void)
-{
- return platform_driver_register(&sm501fb_driver);
-}
-
-static void __exit sm501fb_cleanup(void)
-{
- platform_driver_unregister(&sm501fb_driver);
-}
-
-module_init(sm501fb_init);
-module_exit(sm501fb_cleanup);
+module_platform_driver(sm501fb_driver);
module_param_named(mode, fb_mode, charp, 0);
MODULE_PARM_DESC(mode,
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
index 3c22994..ccbfef5 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/smscufx.c
@@ -130,8 +130,8 @@ static struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
/* module options */
-static int console; /* Optionally allow fbcon to consume first framebuffer */
-static int fb_defio = true; /* Optionally enable fb_defio mmap support */
+static bool console; /* Optionally allow fbcon to consume first framebuffer */
+static bool fb_defio = true; /* Optionally enable fb_defio mmap support */
/* ufx keeps a list of urbs for efficient bulk transfers */
static void ufx_urb_completion(struct urb *urb);
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 2301c27..111fb32 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -93,11 +93,11 @@
/* initialized by setup */
-static int vgapass; /* enable VGA passthrough cable */
+static bool vgapass; /* enable VGA passthrough cable */
static int mem; /* mem size in MB, 0 = autodetect */
-static int clipping = 1; /* use clipping (slower, safer) */
+static bool clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* force FBI freq in Mhz . Dangerous */
-static int slowpci; /* slow PCI settings */
+static bool slowpci; /* slow PCI settings */
/*
Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index a99b994..e026724 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -169,7 +169,7 @@ static int nowrap = 1; /* not implemented (yet) */
static int hwcursor = 1;
static char *mode_option __devinitdata;
/* mtrr option */
-static int nomtrr __devinitdata;
+static bool nomtrr __devinitdata;
/* -------------------------------------------------------------------------
* Hardware-specific funcions
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 1f868d0..a197731 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -69,9 +69,9 @@ static struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
/* module options */
-static int console = 1; /* Allow fbcon to open framebuffer */
-static int fb_defio = 1; /* Detect mmap writes using page faults */
-static int shadow = 1; /* Optionally disable shadow framebuffer */
+static bool console = 1; /* Allow fbcon to open framebuffer */
+static bool fb_defio = 1; /* Detect mmap writes using page faults */
+static bool shadow = 1; /* Optionally disable shadow framebuffer */
/* dlfb keeps a list of urbs for efficient bulk transfers */
static void dlfb_urb_completion(struct urb *urb);
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 7f8472cc..e7f69ef 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -44,11 +44,11 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
};
static int mtrr __devinitdata = 3; /* enable mtrr by default */
-static int blank = 1; /* enable blanking by default */
+static bool blank = 1; /* enable blanking by default */
static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */
static bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */
-static int nocrtc __devinitdata; /* ignore CRTC settings */
-static int noedid __devinitdata; /* don't try DDC transfers */
+static bool nocrtc __devinitdata; /* ignore CRTC settings */
+static bool noedid __devinitdata; /* don't try DDC transfers */
static int vram_remap __devinitdata; /* set amt. of memory to be used */
static int vram_total __devinitdata; /* set total amount of memory */
static u16 maxclk __devinitdata; /* maximum pixel clock */
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index bf2f780..501a922 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -110,7 +110,7 @@ static struct fb_fix_screeninfo vfb_fix __devinitdata = {
.accel = FB_ACCEL_NONE,
};
-static int vfb_enable __initdata = 0; /* disabled by default */
+static bool vfb_enable __initdata = 0; /* disabled by default */
module_param(vfb_enable, bool, 0);
static int vfb_check_var(struct fb_var_screeninfo *var,
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 777c21d..2a5fe6e 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -457,18 +457,7 @@ static struct platform_driver vt8500lcd_driver = {
},
};
-static int __init vt8500lcd_init(void)
-{
- return platform_driver_register(&vt8500lcd_driver);
-}
-
-static void __exit vt8500lcd_exit(void)
-{
- platform_driver_unregister(&vt8500lcd_driver);
-}
-
-module_init(vt8500lcd_init);
-module_exit(vt8500lcd_exit);
+module_platform_driver(vt8500lcd_driver);
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2375e5b..90a2e30 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -1620,18 +1620,7 @@ static struct platform_driver w100fb_driver = {
},
};
-int __init w100fb_init(void)
-{
- return platform_driver_register(&w100fb_driver);
-}
-
-void __exit w100fb_cleanup(void)
-{
- platform_driver_unregister(&w100fb_driver);
-}
-
-module_init(w100fb_init);
-module_exit(w100fb_cleanup);
+module_platform_driver(w100fb_driver);
MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 96e34a5..c8703bd 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -404,18 +404,7 @@ static struct platform_driver wm8505fb_driver = {
},
};
-static int __init wm8505fb_init(void)
-{
- return platform_driver_register(&wm8505fb_driver);
-}
-
-static void __exit wm8505fb_exit(void)
-{
- platform_driver_unregister(&wm8505fb_driver);
-}
-
-module_init(wm8505fb_init);
-module_exit(wm8505fb_exit);
+module_platform_driver(wm8505fb_driver);
MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
index 45832b7..55be386 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/wmt_ge_rops.c
@@ -167,18 +167,7 @@ static struct platform_driver wmt_ge_rops_driver = {
},
};
-static int __init wmt_ge_rops_init(void)
-{
- return platform_driver_register(&wmt_ge_rops_driver);
-}
-
-static void __exit wmt_ge_rops_exit(void)
-{
- platform_driver_unregister(&wmt_ge_rops_driver);
-}
-
-module_init(wmt_ge_rops_init);
-module_exit(wmt_ge_rops_exit);
+module_platform_driver(wmt_ge_rops_driver);
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
MODULE_DESCRIPTION("Accelerators for raster operations using "
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index fcb6cd9..1808452 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -511,25 +511,7 @@ static struct platform_driver xilinxfb_of_driver = {
},
};
-
-/* ---------------------------------------------------------------------
- * Module setup and teardown
- */
-
-static int __init
-xilinxfb_init(void)
-{
- return platform_driver_register(&xilinxfb_of_driver);
-}
-
-static void __exit
-xilinxfb_cleanup(void)
-{
- platform_driver_unregister(&xilinxfb_of_driver);
-}
-
-module_init(xilinxfb_init);
-module_exit(xilinxfb_cleanup);
+module_platform_driver(xilinxfb_of_driver);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 94fd738..95aeedf 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -1,4 +1,5 @@
-/* Virtio balloon implementation, inspired by Dor Loar and Marcelo
+/*
+ * Virtio balloon implementation, inspired by Dor Laor and Marcelo
* Tosatti's implementations.
*
* Copyright 2008 Rusty Russell IBM Corporation
@@ -17,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-//#define DEBUG
+
#include <linux/virtio.h>
#include <linux/virtio_balloon.h>
#include <linux/swap.h>
@@ -87,7 +88,7 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
init_completion(&vb->acked);
/* We should always be able to add one buffer to an empty queue. */
- if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0)
+ if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
BUG();
virtqueue_kick(vq);
@@ -149,7 +150,6 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
vb->num_pages--;
}
-
/*
* Note that if
* virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
@@ -220,7 +220,7 @@ static void stats_handle_request(struct virtio_balloon *vb)
vq = vb->stats_vq;
sg_init_one(&sg, vb->stats, sizeof(vb->stats));
- if (virtqueue_add_buf(vq, &sg, 1, 0, vb) < 0)
+ if (virtqueue_add_buf(vq, &sg, 1, 0, vb, GFP_KERNEL) < 0)
BUG();
virtqueue_kick(vq);
}
@@ -275,32 +275,21 @@ static int balloon(void *_vballoon)
return 0;
}
-static int virtballoon_probe(struct virtio_device *vdev)
+static int init_vqs(struct virtio_balloon *vb)
{
- struct virtio_balloon *vb;
struct virtqueue *vqs[3];
vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request };
const char *names[] = { "inflate", "deflate", "stats" };
int err, nvqs;
- vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
- if (!vb) {
- err = -ENOMEM;
- goto out;
- }
-
- INIT_LIST_HEAD(&vb->pages);
- vb->num_pages = 0;
- init_waitqueue_head(&vb->config_change);
- vb->vdev = vdev;
- vb->need_stats_update = 0;
-
- /* We expect two virtqueues: inflate and deflate,
- * and optionally stat. */
+ /*
+ * We expect two virtqueues: inflate and deflate, and
+ * optionally stat.
+ */
nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2;
- err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
+ err = vb->vdev->config->find_vqs(vb->vdev, nvqs, vqs, callbacks, names);
if (err)
- goto out_free_vb;
+ return err;
vb->inflate_vq = vqs[0];
vb->deflate_vq = vqs[1];
@@ -313,10 +302,34 @@ static int virtballoon_probe(struct virtio_device *vdev)
* use it to signal us later.
*/
sg_init_one(&sg, vb->stats, sizeof vb->stats);
- if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb) < 0)
+ if (virtqueue_add_buf(vb->stats_vq, &sg, 1, 0, vb, GFP_KERNEL)
+ < 0)
BUG();
virtqueue_kick(vb->stats_vq);
}
+ return 0;
+}
+
+static int virtballoon_probe(struct virtio_device *vdev)
+{
+ struct virtio_balloon *vb;
+ int err;
+
+ vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
+ if (!vb) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&vb->pages);
+ vb->num_pages = 0;
+ init_waitqueue_head(&vb->config_change);
+ vb->vdev = vdev;
+ vb->need_stats_update = 0;
+
+ err = init_vqs(vb);
+ if (err)
+ goto out_free_vb;
vb->thread = kthread_run(balloon, vb, "vballoon");
if (IS_ERR(vb->thread)) {
@@ -351,6 +364,48 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev)
kfree(vb);
}
+#ifdef CONFIG_PM
+static int virtballoon_freeze(struct virtio_device *vdev)
+{
+ /*
+ * The kthread is already frozen by the PM core before this
+ * function is called.
+ */
+
+ /* Ensure we don't get any more requests from the host */
+ vdev->config->reset(vdev);
+ vdev->config->del_vqs(vdev);
+ return 0;
+}
+
+static int virtballoon_thaw(struct virtio_device *vdev)
+{
+ return init_vqs(vdev->priv);
+}
+
+static int virtballoon_restore(struct virtio_device *vdev)
+{
+ struct virtio_balloon *vb = vdev->priv;
+ struct page *page, *page2;
+
+ /* We're starting from a clean slate */
+ vb->num_pages = 0;
+
+ /*
+ * If a request wasn't complete at the time of freezing, this
+ * could have been set.
+ */
+ vb->need_stats_update = 0;
+
+ /* We don't have these pages in the balloon anymore! */
+ list_for_each_entry_safe(page, page2, &vb->pages, lru) {
+ list_del(&page->lru);
+ totalram_pages++;
+ }
+ return init_vqs(vdev->priv);
+}
+#endif
+
static unsigned int features[] = {
VIRTIO_BALLOON_F_MUST_TELL_HOST,
VIRTIO_BALLOON_F_STATS_VQ,
@@ -365,6 +420,11 @@ static struct virtio_driver virtio_balloon_driver = {
.probe = virtballoon_probe,
.remove = __devexit_p(virtballoon_remove),
.config_changed = virtballoon_changed,
+#ifdef CONFIG_PM
+ .freeze = virtballoon_freeze,
+ .restore = virtballoon_restore,
+ .thaw = virtballoon_thaw,
+#endif
};
static int __init init(void)
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 0269717..01d6dc2 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -310,8 +310,8 @@ 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, info->queue, vm_notify, callback, name);
+ vq = vring_new_virtqueue(info->num, VIRTIO_MMIO_VRING_ALIGN, vdev,
+ true, info->queue, vm_notify, callback, name);
if (!vq) {
err = -ENOMEM;
goto error_new_virtqueue;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index baabb79..635e1ef 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -55,6 +55,10 @@ struct virtio_pci_device
unsigned msix_vectors;
/* Vectors allocated, excluding per-vq vectors if any */
unsigned msix_used_vectors;
+
+ /* Status saved during hibernate/restore */
+ u8 saved_status;
+
/* Whether we have vector per vq */
bool per_vq_vectors;
};
@@ -414,8 +418,8 @@ 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, info->queue, vp_notify, callback, name);
+ vq = vring_new_virtqueue(info->num, VIRTIO_PCI_VRING_ALIGN, vdev,
+ true, info->queue, vp_notify, callback, name);
if (!vq) {
err = -ENOMEM;
goto out_activate_queue;
@@ -716,19 +720,114 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
-static int virtio_pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
+static int virtio_pci_suspend(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+
pci_save_state(pci_dev);
pci_set_power_state(pci_dev, PCI_D3hot);
return 0;
}
-static int virtio_pci_resume(struct pci_dev *pci_dev)
+static int virtio_pci_resume(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+
pci_restore_state(pci_dev);
pci_set_power_state(pci_dev, PCI_D0);
return 0;
}
+
+static int virtio_pci_freeze(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ struct virtio_driver *drv;
+ int ret;
+
+ drv = container_of(vp_dev->vdev.dev.driver,
+ struct virtio_driver, driver);
+
+ ret = 0;
+ vp_dev->saved_status = vp_get_status(&vp_dev->vdev);
+ if (drv && drv->freeze)
+ ret = drv->freeze(&vp_dev->vdev);
+
+ if (!ret)
+ pci_disable_device(pci_dev);
+ return ret;
+}
+
+static int restore_common(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ int ret;
+
+ ret = pci_enable_device(pci_dev);
+ if (ret)
+ return ret;
+ pci_set_master(pci_dev);
+ vp_finalize_features(&vp_dev->vdev);
+
+ return ret;
+}
+
+static int virtio_pci_thaw(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ struct virtio_driver *drv;
+ int ret;
+
+ ret = restore_common(dev);
+ if (ret)
+ return ret;
+
+ drv = container_of(vp_dev->vdev.dev.driver,
+ struct virtio_driver, driver);
+
+ if (drv && drv->thaw)
+ ret = drv->thaw(&vp_dev->vdev);
+ else if (drv && drv->restore)
+ ret = drv->restore(&vp_dev->vdev);
+
+ /* Finally, tell the device we're all set */
+ if (!ret)
+ vp_set_status(&vp_dev->vdev, vp_dev->saved_status);
+
+ return ret;
+}
+
+static int virtio_pci_restore(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ struct virtio_driver *drv;
+ int ret;
+
+ drv = container_of(vp_dev->vdev.dev.driver,
+ struct virtio_driver, driver);
+
+ ret = restore_common(dev);
+ if (!ret && drv && drv->restore)
+ ret = drv->restore(&vp_dev->vdev);
+
+ /* Finally, tell the device we're all set */
+ if (!ret)
+ vp_set_status(&vp_dev->vdev, vp_dev->saved_status);
+
+ return ret;
+}
+
+static const struct dev_pm_ops virtio_pci_pm_ops = {
+ .suspend = virtio_pci_suspend,
+ .resume = virtio_pci_resume,
+ .freeze = virtio_pci_freeze,
+ .thaw = virtio_pci_thaw,
+ .restore = virtio_pci_restore,
+ .poweroff = virtio_pci_suspend,
+};
#endif
static struct pci_driver virtio_pci_driver = {
@@ -737,8 +836,7 @@ static struct pci_driver virtio_pci_driver = {
.probe = virtio_pci_probe,
.remove = __devexit_p(virtio_pci_remove),
#ifdef CONFIG_PM
- .suspend = virtio_pci_suspend,
- .resume = virtio_pci_resume,
+ .driver.pm = &virtio_pci_pm_ops,
#endif
};
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index c7a2c20..79e1b29 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -22,23 +22,27 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/hrtimer.h>
/* virtio guest is communicating with a virtual "device" that actually runs on
* a host processor. Memory barriers are used to control SMP effects. */
#ifdef CONFIG_SMP
/* Where possible, use SMP barriers which are more lightweight than mandatory
* barriers, because mandatory barriers control MMIO effects on accesses
- * through relaxed memory I/O windows (which virtio does not use). */
-#define virtio_mb() smp_mb()
-#define virtio_rmb() smp_rmb()
-#define virtio_wmb() smp_wmb()
+ * through relaxed memory I/O windows (which virtio-pci does not use). */
+#define virtio_mb(vq) \
+ do { if ((vq)->weak_barriers) smp_mb(); else mb(); } while(0)
+#define virtio_rmb(vq) \
+ do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
+#define virtio_wmb(vq) \
+ do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
#else
/* We must force memory ordering even if guest is UP since host could be
* running on another CPU, but SMP barriers are defined to barrier() in that
* configuration. So fall back to mandatory barriers instead. */
-#define virtio_mb() mb()
-#define virtio_rmb() rmb()
-#define virtio_wmb() wmb()
+#define virtio_mb(vq) mb()
+#define virtio_rmb(vq) rmb()
+#define virtio_wmb(vq) wmb()
#endif
#ifdef DEBUG
@@ -77,6 +81,9 @@ struct vring_virtqueue
/* Actual memory layout for this queue */
struct vring vring;
+ /* Can we use weak barriers? */
+ bool weak_barriers;
+
/* Other side has made a mess, don't try any more. */
bool broken;
@@ -102,6 +109,10 @@ struct vring_virtqueue
#ifdef DEBUG
/* They're supposed to lock for us. */
unsigned int in_use;
+
+ /* Figure out if their kicks are too delayed. */
+ bool last_add_time_valid;
+ ktime_t last_add_time;
#endif
/* Tokens for callbacks. */
@@ -160,12 +171,29 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
return head;
}
-int virtqueue_add_buf_gfp(struct virtqueue *_vq,
- struct scatterlist sg[],
- unsigned int out,
- unsigned int in,
- void *data,
- gfp_t gfp)
+/**
+ * virtqueue_add_buf - expose buffer to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: the description of the buffer(s).
+ * @out_num: the number of sg readable by other side
+ * @in_num: the number of sg which are writable (after readable ones)
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns remaining capacity of queue or a negative error
+ * (ie. ENOSPC). Note that it only really makes sense to treat all
+ * positive return values as "available": indirect buffers mean that
+ * we can put an entire sg[] array inside a single queue entry.
+ */
+int virtqueue_add_buf(struct virtqueue *_vq,
+ struct scatterlist sg[],
+ unsigned int out,
+ unsigned int in,
+ void *data,
+ gfp_t gfp)
{
struct vring_virtqueue *vq = to_vvq(_vq);
unsigned int i, avail, uninitialized_var(prev);
@@ -175,6 +203,19 @@ int virtqueue_add_buf_gfp(struct virtqueue *_vq,
BUG_ON(data == NULL);
+#ifdef DEBUG
+ {
+ ktime_t now = ktime_get();
+
+ /* No kick or get, with .1 second between? Warn. */
+ if (vq->last_add_time_valid)
+ WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time))
+ > 100);
+ vq->last_add_time = now;
+ vq->last_add_time_valid = true;
+ }
+#endif
+
/* If the host supports indirect descriptor tables, and we have multiple
* buffers, then go indirect. FIXME: tune this threshold */
if (vq->indirect && (out + in) > 1 && vq->num_free) {
@@ -227,40 +268,102 @@ add_head:
vq->data[head] = data;
/* Put entry in available array (but don't update avail->idx until they
- * do sync). FIXME: avoid modulus here? */
- avail = (vq->vring.avail->idx + vq->num_added++) % vq->vring.num;
+ * do sync). */
+ avail = (vq->vring.avail->idx & (vq->vring.num-1));
vq->vring.avail->ring[avail] = head;
+ /* Descriptors and available array need to be set before we expose the
+ * new available array entries. */
+ virtio_wmb(vq);
+ vq->vring.avail->idx++;
+ vq->num_added++;
+
+ /* This is very unlikely, but theoretically possible. Kick
+ * just in case. */
+ if (unlikely(vq->num_added == (1 << 16) - 1))
+ virtqueue_kick(_vq);
+
pr_debug("Added buffer head %i to %p\n", head, vq);
END_USE(vq);
return vq->num_free;
}
-EXPORT_SYMBOL_GPL(virtqueue_add_buf_gfp);
+EXPORT_SYMBOL_GPL(virtqueue_add_buf);
-void virtqueue_kick(struct virtqueue *_vq)
+/**
+ * virtqueue_kick_prepare - first half of split virtqueue_kick call.
+ * @vq: the struct virtqueue
+ *
+ * Instead of virtqueue_kick(), you can do:
+ * if (virtqueue_kick_prepare(vq))
+ * virtqueue_notify(vq);
+ *
+ * This is sometimes useful because the virtqueue_kick_prepare() needs
+ * to be serialized, but the actual virtqueue_notify() call does not.
+ */
+bool virtqueue_kick_prepare(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
u16 new, old;
+ bool needs_kick;
+
START_USE(vq);
/* Descriptors and available array need to be set before we expose the
* new available array entries. */
- virtio_wmb();
+ virtio_wmb(vq);
- old = vq->vring.avail->idx;
- new = vq->vring.avail->idx = old + vq->num_added;
+ old = vq->vring.avail->idx - vq->num_added;
+ new = vq->vring.avail->idx;
vq->num_added = 0;
- /* Need to update avail index before checking if we should notify */
- virtio_mb();
-
- if (vq->event ?
- vring_need_event(vring_avail_event(&vq->vring), new, old) :
- !(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY))
- /* Prod other side to tell it about changes. */
- vq->notify(&vq->vq);
+#ifdef DEBUG
+ if (vq->last_add_time_valid) {
+ WARN_ON(ktime_to_ms(ktime_sub(ktime_get(),
+ vq->last_add_time)) > 100);
+ }
+ vq->last_add_time_valid = false;
+#endif
+ if (vq->event) {
+ needs_kick = vring_need_event(vring_avail_event(&vq->vring),
+ new, old);
+ } else {
+ needs_kick = !(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY);
+ }
END_USE(vq);
+ return needs_kick;
+}
+EXPORT_SYMBOL_GPL(virtqueue_kick_prepare);
+
+/**
+ * virtqueue_notify - second half of split virtqueue_kick call.
+ * @vq: the struct virtqueue
+ *
+ * This does not need to be serialized.
+ */
+void virtqueue_notify(struct virtqueue *_vq)
+{
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ /* Prod other side to tell it about changes. */
+ vq->notify(_vq);
+}
+EXPORT_SYMBOL_GPL(virtqueue_notify);
+
+/**
+ * virtqueue_kick - update after add_buf
+ * @vq: the struct virtqueue
+ *
+ * After one or more virtqueue_add_buf calls, invoke this to kick
+ * the other side.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+void virtqueue_kick(struct virtqueue *vq)
+{
+ if (virtqueue_kick_prepare(vq))
+ virtqueue_notify(vq);
}
EXPORT_SYMBOL_GPL(virtqueue_kick);
@@ -294,11 +397,28 @@ static inline bool more_used(const struct vring_virtqueue *vq)
return vq->last_used_idx != vq->vring.used->idx;
}
+/**
+ * virtqueue_get_buf - get the next used buffer
+ * @vq: the struct virtqueue we're talking about.
+ * @len: the length written into the buffer
+ *
+ * If the driver wrote data into the buffer, @len will be set to the
+ * amount written. This means you don't need to clear the buffer
+ * beforehand to ensure there's no data leakage in the case of short
+ * writes.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ *
+ * Returns NULL if there are no used buffers, or the "data" token
+ * handed to virtqueue_add_buf().
+ */
void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
{
struct vring_virtqueue *vq = to_vvq(_vq);
void *ret;
unsigned int i;
+ u16 last_used;
START_USE(vq);
@@ -314,10 +434,11 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
}
/* Only get used array entries after they have been exposed by host. */
- virtio_rmb();
+ virtio_rmb(vq);
- i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
- *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;
+ last_used = (vq->last_used_idx & (vq->vring.num - 1));
+ i = vq->vring.used->ring[last_used].id;
+ *len = vq->vring.used->ring[last_used].len;
if (unlikely(i >= vq->vring.num)) {
BAD_RING(vq, "id %u out of range\n", i);
@@ -337,14 +458,27 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
* the read in the next get_buf call. */
if (!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
vring_used_event(&vq->vring) = vq->last_used_idx;
- virtio_mb();
+ virtio_mb(vq);
}
+#ifdef DEBUG
+ vq->last_add_time_valid = false;
+#endif
+
END_USE(vq);
return ret;
}
EXPORT_SYMBOL_GPL(virtqueue_get_buf);
+/**
+ * virtqueue_disable_cb - disable callbacks
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * Note that this is not necessarily synchronous, hence unreliable and only
+ * useful as an optimization.
+ *
+ * Unlike other operations, this need not be serialized.
+ */
void virtqueue_disable_cb(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
@@ -353,6 +487,17 @@ void virtqueue_disable_cb(struct virtqueue *_vq)
}
EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
+/**
+ * virtqueue_enable_cb - restart callbacks after disable_cb.
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * This re-enables callbacks; it returns "false" if there are pending
+ * buffers in the queue, to detect a possible race between the driver
+ * checking for more work, and enabling callbacks.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
bool virtqueue_enable_cb(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
@@ -366,7 +511,7 @@ bool virtqueue_enable_cb(struct virtqueue *_vq)
* entry. Always do both to keep code simple. */
vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
vring_used_event(&vq->vring) = vq->last_used_idx;
- virtio_mb();
+ virtio_mb(vq);
if (unlikely(more_used(vq))) {
END_USE(vq);
return false;
@@ -377,6 +522,19 @@ bool virtqueue_enable_cb(struct virtqueue *_vq)
}
EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
+/**
+ * virtqueue_enable_cb_delayed - restart callbacks after disable_cb.
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * This re-enables callbacks but hints to the other side to delay
+ * interrupts until most of the available buffers have been processed;
+ * it returns "false" if there are many pending buffers in the queue,
+ * to detect a possible race between the driver checking for more work,
+ * and enabling callbacks.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
@@ -393,7 +551,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
/* TODO: tune this threshold */
bufs = (u16)(vq->vring.avail->idx - vq->last_used_idx) * 3 / 4;
vring_used_event(&vq->vring) = vq->last_used_idx + bufs;
- virtio_mb();
+ virtio_mb(vq);
if (unlikely((u16)(vq->vring.used->idx - vq->last_used_idx) > bufs)) {
END_USE(vq);
return false;
@@ -404,6 +562,14 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
}
EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
+/**
+ * virtqueue_detach_unused_buf - detach first unused buffer
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * Returns NULL or the "data" token handed to virtqueue_add_buf().
+ * This is not valid on an active queue; it is useful only for device
+ * shutdown.
+ */
void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
@@ -453,6 +619,7 @@ EXPORT_SYMBOL_GPL(vring_interrupt);
struct virtqueue *vring_new_virtqueue(unsigned int num,
unsigned int vring_align,
struct virtio_device *vdev,
+ bool weak_barriers,
void *pages,
void (*notify)(struct virtqueue *),
void (*callback)(struct virtqueue *),
@@ -476,12 +643,14 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
vq->vq.vdev = vdev;
vq->vq.name = name;
vq->notify = notify;
+ vq->weak_barriers = weak_barriers;
vq->broken = false;
vq->last_used_idx = 0;
vq->num_added = 0;
list_add_tail(&vq->vq.list, &vdev->vqs);
#ifdef DEBUG
vq->in_use = false;
+ vq->last_add_time_valid = false;
#endif
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC);
@@ -530,7 +699,13 @@ void vring_transport_features(struct virtio_device *vdev)
}
EXPORT_SYMBOL_GPL(vring_transport_features);
-/* return the size of the vring within the virtqueue */
+/**
+ * virtqueue_get_vring_size - return the size of the virtqueue's vring
+ * @vq: the struct virtqueue containing the vring of interest.
+ *
+ * Returns the size of the vring. This is mainly used for boasting to
+ * userspace. Unlike other operations, this need not be serialized.
+ */
unsigned int virtqueue_get_vring_size(struct virtqueue *_vq)
{
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index d4d8d1f..e45ca2b 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -100,7 +100,7 @@ MODULE_PARM_DESC(f71862fg_pin,
"Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63"
" (default=" __MODULE_STRING(WATCHDOG_F71862FG_PIN)")");
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0444);
MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index eed5436f..20feb4d 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -55,7 +55,7 @@ module_param(timeout, ushort, 0);
MODULE_PARM_DESC(timeout,
"Watchdog timeout in ticks. (0<timeout<65536, default=65535)");
-static int reset = 1;
+static bool reset = 1;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset,
"Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c
index ba6eda4..18c1bb6 100644
--- a/drivers/xen/biomerge.c
+++ b/drivers/xen/biomerge.c
@@ -11,3 +11,4 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&
((mfn1 == mfn2) || ((mfn1+1) == mfn2));
}
+EXPORT_SYMBOL(xen_biovec_phys_mergeable);
diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
index 3832e30..596e6a7 100644
--- a/drivers/xen/xen-balloon.c
+++ b/drivers/xen/xen-balloon.c
@@ -221,7 +221,7 @@ static int register_balloon(struct device *dev)
{
int i, error;
- error = bus_register(&balloon_subsys);
+ error = subsys_system_register(&balloon_subsys, NULL);
if (error)
return error;
diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c
index 52fed16..30d7be0 100644
--- a/drivers/xen/xen-pciback/conf_space.c
+++ b/drivers/xen/xen-pciback/conf_space.c
@@ -16,7 +16,7 @@
#include "conf_space.h"
#include "conf_space_quirks.h"
-static int permissive;
+static bool permissive;
module_param(permissive, bool, 0644);
/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index 8e1c44d..d5dcf8d 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -16,7 +16,7 @@
#define INVALID_EVTCHN_IRQ (-1)
struct workqueue_struct *xen_pcibk_wq;
-static int __read_mostly passthrough;
+static bool __read_mostly passthrough;
module_param(passthrough, bool, S_IRUGO);
MODULE_PARM_DESC(passthrough,
"Option to specify how to export PCI topology to guest:\n"\
OpenPOWER on IntegriCloud